How to call GetLastError in the win32 API

 

Hi, I have an expert which imports some win32 API functions. One of the functions, WriteFile, returns 0 on error and you have to call GetLastError() in the win32 API to get the error code. However there is a conflict, because mql4 has its own GetLastError. If you call mql4's GetLastError when there is a win32 API error, it returns 0. At the same time, you can't import GetLastError from the win32 API as you get an error at compile time as it conflicts with mql4's built in version.

Is there any way I can call GetLastError in the win32API to get the error code of a win32 API function call?

int result = WriteFile(....); // win32 API call, returns 0 if there's an error and stores the error code in GetLastError()

if(result == 0)

Print("GetLastError()=", GetLastError()); // always prints 0, because this is calling mql4's GetLastError function not the win32 API's

 
mbritton:

Is there any way I can call GetLastError in the win32API to get the error code of a win32 API function call?

Even if you could import GetLastError() there's a strong chance that it wouldn't help.

The value of GetLastError() will be overwritten by any Win32 calls which MT4 itself makes internally between your call to WriteFile() and your call to GetLastError(). You would only be able to retrieve the Win32 last-error value if MT4 wasn't making any use of the Win32 API itself between the calls from your code. That's possible, but not very likely. For example, if MT4 does GetProcAddress() every time that you call an imported function, rather than caching the values on first use, then the last-error code would be overwritten before you could query it.

[EDIT: actually, it's quite rare for Win32 functions to do SetLastError(0) if they succeed. But it's still a possibility, and you'd still be relying on MT4 not doing any internal Win32 calls which fail in between your calls. If you could import the GetLastError() function, which you can't.]

The question which is worth considering instead is why this is failing, or why you feel the need to check it. If you have successfully opened a file handle with GENERIC_WRITE, then there's only a very limited number of reasons why WriteFile() can then subsequently fail, and most of them are to do with critical situations such as very low free disk space. As a result, there's huge amounts of code out there - including Microsoft examples - which don't even bother to check the return value from WriteFile(); the assumption is that if WriteFile() fails, it's going to be for reasons which mean that the user has more pressing problems to deal with...

 
jjc:

Even if you could import GetLastError() there's a strong chance that it wouldn't help.

Just to let you know there may be other interested readers getting value from your response, including me of course :-)

Thanks!

 
dabbler:

Just to let you know there may be other interested readers getting value from your response, including me of course :-)

I've just checked, and I'm in fact wrong about the last-error getting overwritten. Let's say that you have a custom DLL whose sole purpose is to return the Win32 last-error. You then do something like the following:

#import "MyWin32Wrapper.dll"
   int GetLastError_Win32();
#import

void start()
{
   GetLastError_Win32();	// Dummy call
   
   int okay = WriteFile(-1, other dummy params...); // Call WriteFile() with invalid handle
   int err = GetLastError_Win32();
}

In this scenario, err does correctly contain 6: i.e. invalid handle. But you have to have the dummy call at the top, because otherwise, the first time that you use GetLastError_Win32(), there's all sorts of internal stuff within MT4 where it does LoadLibrary(), GetProcAddress() etc, and this does indeed wipe the last-error code.

But there's still no way of importing the GetLastError() function directly, and I'm sticking to the original point that it's hard to see a reason why you'd need to. If a file-write fails on a valid writeable handle and with valid parameters, then you're probably dealing with a system-wide rather than application-specific problem.

 

I consider the given responses as "off topic" because none is answering the thread openers question. Instead you make assumptions about what people write code for and what this code needs to work. You can't. There are limitless examples of API functions setting an error code you *need* to proceed, WriteFile() is not the only library function.

To answer the question:

#import "ntdll.dll"
   int  RtlGetLastWin32Error();
#import

kernel32::GetLastError() maps to ntdll. It's that simple.

Now what I'd like to know: Is there a way to set the last MQL error status, ie. the MQL equivalent to SetLastError(). This would be really helpful for us.

Maybe somebody with better Russian than mine can shed some light onto the conclusions of https://www.mql5.com/ru/forum/133499.

pp

 
paulepanke:

Maybe somebody with better Russian than mine can shed some light onto the conclusions of https://www.mql5.com/ru/forum/133499.

pp

Seems quite readable with Google translate

http://translate.google.com/translate?sl=auto&tl=en&js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&u=http%3A%2F%2Fforum.mql4.com%2Fru%2F40916