WinDbg : Getting The Last Error
One of the most used Windows APIs is perhaps GetLastError(). It returns us the error code of the last error encountered. However, many a times, we do not query for the last error while writing the code, and while debugging later on, we have no idea why it failed, we just know that it did. Here is an example:
HANDLE hVol = INVALID_HANDLE_VALUE;
hVol = CreateFile( csDrvName,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0, // FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS
NULL);
if( hVol == INVALID_HANDLE_VALUE )
{
return E_FAIL;
}
Now this function never queried the last error and if it had logging, then it never printed it to the logs.
Which brings us to the question, if we had called GetLastError(), where does it get the info from, and if it did, then can we also get the same information from the debugger in cases when we wrote code like the above. The answer is Yes, we can, and here is how...
Commands Used:
- !teb
- !error
Before we proceed, all error codes are thread specific, so being in the context of the thread you are debugging is important. To know know more about changing thread contexts this link might be helpful.
Note : The fields of !teb sometimes vary between operating system versions. So if your output is slightly different from mine, there is no need to be concerned.
0:002> !teb
TEB at 7efd7000
ExceptionList: 00b8fdf0
StackBase: 00b90000
StackLimit: 00b8e000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 7efd7000
EnvironmentPointer: 00000000
ClientId: 0000099c . 00001d48
RpcHandle: 00000000
Tls Storage: 7efd702c
PEB Address: 7efde000
LastErrorValue: 2
LastStatusValue: 0
Count Owned Locks: 0
HardErrorMode: 0
The value in LastErrorValue field is what GetLastError reports to us. It lives in the thread level, and that is why we can be multi threaded, and each thread can be calling a different API and the error codes don't get mangled.
Coming to the interpretation part. The !error command can interpret all errors and status messages in Windows.
0:001> !error 0n2
Error code: (Win32) 0x2 (2) - The system cannot find the file specified.
Note : Please be careful to use the right numeric base for !error. That is, if the value shown in !teb is in decimal, we should append a 0n to ensure it is not interpreted as hexadecimal.
Similarly, the LastStatusValue field will have the NTSTATUS codes.