For this post: GetLastError: how does it work with DECLARE DLL ?, I received this question:


I was sent here by someone from UT regarding a problem I'm having with GetLastError API call.  It always returns 0 even if I enter a bogus password to LogonUser().

Base on what I read above, are you saying that GetLastError will never properly work in VFP 8.0?



“Never” is a strong word. I don’t see any code showing how the user is calling any APIs, so I can’t tell what is happening for the user, so I can’t propose a way to make it work. Perhaps the user can try it in VFP9 and see if their code behaves differently. If so, then the the GetLastError fix that I implemented for VFP9 probably helps in this scenario.



So I had to figure out how to call LogonUser:




#define LOGON32_LOGON_NETWORK           3

#define LOGON32_LOGON_BATCH             4

#define LOGON32_LOGON_SERVICE           5

#define LOGON32_LOGON_UNLOCK            7


#define ERROR_LOGON_FAILURE              1326


DECLARE integer LogonUser IN WIN32API string lpszUsername,string lpszDomain,;

      string lpszPassword,integer dwLogonType,integer dwLogonProvider, integer @ phToken

DECLARE integer CloseHandle IN  WIN32API integer

DECLARE integer GetLastError IN  WIN32API


IF LogonUser("calvinh","redmond","",LOGON32_LOGON_BATCH,LOGON32_PROVIDER_DEFAULT,@hToken) != 0

      ?"Login success",hToken

      IF hToken!= 0




*     MESSAGEBOX("This is a Win32API call")

      ?"Login failed",GetLastError()





I tried running the code I n both VFP8 and VFP9, with and without my password as the 3rd parameter, and I received the same results: success with the correct password, and “Login failed   1326” with the incorrect password.


Thus, in this case, GetLastError was correct in VFP8.

Because GetLastError means to get the single global last error code, if there are any intervening API calls, they will change the last error code. So, if you uncomment the MessageBox and run the code in VFP8, the intervening call causes the GetLastError to return 0, because there was no error in calling the MessageBox.

Run the modified code in VFP9 and the error code is preserved, because of the changes I made in VFP9.


Wait a minute, you say. Didn’t the MessageBox call reset the global last error code in VFP9 as well? Yes it did, but it wasn’t called via DECLARE DLL , which is where the GetLastError code was preserved.