调用Windows函数时,它会先验证我们传给它的参数,然后再开始执行任务,如果传入的参数无效,或者由于其他原因导致操作无法执行,则函数的返回值将指出函数的失败原因。以下为大多数Windows函数使用的返回值的数据类型。
数据类型 | 指出函数调用失败的值 |
VOID | 这个函数不可能失败 |
BOOL | 如果失败,返回0;否则,返回非0 |
HANDLE | 如果失败,返回NULL;否则,HANDLE将标识一个可操纵的对象。 注意:某些函数会返回INVALID_HANDLE_VALUE的一个句柄,它被定义为-1 |
PVOID | 如果失败,返回NULL;否则,PVOID将标识一个数据块的内存地址 |
LONG/DWORD | 返回计数的函数通常会返回一个LONG或DWORD,如果函数出于某种原因不能对我们想要计数的东西进行计数,它通常会返回0或-1。 |
在内部,当Windows函数检测到错误时,它会使用一种名为“线程本地存储区”的机制将响应的错误代码与“主调线程”关联到一起,这种机制使不同的线程能够独立运行,不会出现相互干扰对方的错误代码的情况。
此函数使用很简单,返回上一个函数调用设置的线程的32位错误代码。
以下是在#include
- //
- // MessageId: ERROR_HANDLE_EOF
- //
- // MessageText:
- //
- // Reached the end of the file.
- //
- #define ERROR_HANDLE_EOF 38L
-
- //
- // MessageId: ERROR_HANDLE_DISK_FULL
- //
- // MessageText:
- //
- // The disk is full.
- //
- #define ERROR_HANDLE_DISK_FULL 39L
可以看见每个错误有MessageId和MessageText。
MessageId主要用于与GetLastError()的返回值做比较。
Windows函数失败之后,应该马上调用GetLastError(),因为如果又调用了另一个函数,则此值会被改写。
按F5调试的过程中,我们在watch窗口中选择一行,然后输入$err,hr。如下图所示:
这里测试一个打开存在的文件,本地文件时不存在的。
HANDLE hfile = CreateFile(TEXT("C:\\123"), 0, 0, NULL, OPEN_EXISTING, 0, NULL);
查看错误,如下图所示:报错,找不到指定的文件。
使用FormatMessage函数,可以获取到具体的错误信息。
- HANDLE hfile = CreateFile(TEXT("C:\\123"), 0, 0, NULL, OPEN_EXISTING, 0, NULL);
-
- DWORD dw = GetLastError();
-
- LPVOID msgBuf = NULL;
-
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
- NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&msgBuf,
- 0, NULL);
-
- PCTSTR msgStr = (PCTSTR)LocalLock(msgBuf);
-
- LocalFree(msgBuf);