You're doing the error checking a bit late since you call CloseHandle after the call to LogonUser. CloseHandle can very well change the error number, which it most likely do if LogonUser fails you don't get a handle to close and when you try to do that the CloseHandle will fail and set its own error number. You should check the GetLastWin32Error value directly after the call to LogonUser.