RegCreateKeyEx()和GetLastError()

RegCreateKeyEx()和GetLastError(),c,windows,visual-studio,winapi,registry,C,Windows,Visual Studio,Winapi,Registry,为什么RegCreateKeyEx()返回LONG,而不是通过SetLastError()设置DWORD错误代码 我是否可以安全地将其LONG返回值转换为DWORD,然后使用SetLastError()将其设置为全局错误代码 为什么RegCreateKeyEx()返回一个LONG,而不是通过SetLastError()设置DWORD错误代码 可能是因为注册表API在Windows仍为16位时开始使用,而当时SetLastError()/GetLastError()函数不存在。无论是谁添加了32

为什么
RegCreateKeyEx()
返回
LONG
,而不是通过
SetLastError()设置
DWORD
错误代码

我是否可以安全地将其
LONG
返回值转换为
DWORD
,然后使用
SetLastError()
将其设置为全局错误代码

为什么RegCreateKeyEx()返回一个LONG,而不是通过SetLastError()设置DWORD错误代码

可能是因为注册表API在Windows仍为16位时开始使用,而当时
SetLastError()
/
GetLastError()
函数不存在。无论是谁添加了32位版本的注册表函数,都认为保持调用样式向后兼容比更新使用
SetLastError()
更重要

查看陈雷蒙的精彩博客(和精彩书籍)和相关信息

是否可以安全地将其长返回值转换为DWORD,然后使用SetLastError()将其设置为全局错误代码

没有理由不。只要你对每个值都这样做,包括错误和成功

为什么RegCreateKeyEx()返回一个LONG,而不是通过SetLastError()设置DWORD错误代码

可能是因为注册表API在Windows仍为16位时开始使用,而当时
SetLastError()
/
GetLastError()
函数不存在。无论是谁添加了32位版本的注册表函数,都认为保持调用样式向后兼容比更新使用
SetLastError()
更重要

查看陈雷蒙的精彩博客(和精彩书籍)和相关信息

是否可以安全地将其长返回值转换为DWORD,然后使用SetLastError()将其设置为全局错误代码

没有理由不。只要你对每个值都这样做,包括错误和成功

为什么RegCreateKeyEx()返回一个LONG,而不是通过SetLastError()设置DWORD错误代码

很难说清楚,如果没有成为设计这些API的开发团队的一员的话

是否可以安全地将其长返回值转换为DWORD,然后使用SetLastError()将其设置为全局错误代码

安全,但毫无意义。对于使用
SetLastError
返回错误代码的API,调用方必须在API调用返回后立即调用
GetLastError
。否则,执行的任何其他代码都有调用
SetLastError
并销毁原始错误代码的强烈风险

因此,考虑到您必须立即调用
GetLastError
,您的代码将如下所示:

LONG retval = RegCreateKeyEx(...);
SetLastError((DWORD)err);
DWORD err := GetLastError();
这有点毫无意义。你应该写:

DWORD err := (DWORD)RegCreateKeyEx(...);
为什么RegCreateKeyEx()返回一个LONG,而不是通过SetLastError()设置DWORD错误代码

很难说清楚,如果没有成为设计这些API的开发团队的一员的话

是否可以安全地将其长返回值转换为DWORD,然后使用SetLastError()将其设置为全局错误代码

安全,但毫无意义。对于使用
SetLastError
返回错误代码的API,调用方必须在API调用返回后立即调用
GetLastError
。否则,执行的任何其他代码都有调用
SetLastError
并销毁原始错误代码的强烈风险

因此,考虑到您必须立即调用
GetLastError
,您的代码将如下所示:

LONG retval = RegCreateKeyEx(...);
SetLastError((DWORD)err);
DWORD err := GetLastError();
这有点毫无意义。你应该写:

DWORD err := (DWORD)RegCreateKeyEx(...);

不一定是毫无意义的——我以前就必须这样做过一次。假设您要进行一长串API调用,并且每个调用的失败都会掉到一个常见的错误记录例程中,那么如果错误记录器能够以相同的方式检索所有Win32 API的错误代码,就更整洁了。在这种情况下,不会有其他内容覆盖错误代码的风险。@snowcrash09在这种情况下,尽管我只有两种方法调用记录器。一个传递错误代码,一个不传递。未传递错误代码的变量调用
GetLastError
,然后将其交给另一个变量。这样你就有了一个统一的编码,同时也避免了SetLastError/GetLastError的往返,以找出你已经知道的东西。这不一定是毫无意义的——我以前曾经做过一次。假设您要进行一长串API调用,并且每个调用的失败都会掉到一个常见的错误记录例程中,那么如果错误记录器能够以相同的方式检索所有Win32 API的错误代码,就更整洁了。在这种情况下,不会有其他内容覆盖错误代码的风险。@snowcrash09在这种情况下,尽管我只有两种方法调用记录器。一个传递错误代码,一个不传递。未传递错误代码的变量调用
GetLastError
,然后将其交给另一个变量。这样你就有了一个统一的编码,也避免了SetLastError/GetLastError往返于你已经知道的东西。