在文档中
如果剪贴板格式不可用,则返回值为零。要获取扩展错误信息,请调用 GetLastError。 IsClipboardFormatAvailable 函数 (winuser.h)
但是这段代码的输出是0:
#include <Windows.h>
#include <cstdio>
#include <winerror.h>
int main()
{
//I copied an image to the clipboard before running the program
if(!IsClipboardFormatAvailable(CF_UNICODETEXT))
{
printf("%lu", GetLastError());
}
}
为什么IsClipboardFormatAvailable函数没有设置最后一个错误?
内核中的
IsClipboardFormatAvailable
调用 NtUserIsClipboardFormatAvailable
。
功能如下
WINDOWSTATION * CheckClipboardAccess();
CLIP * FindClipFormat(WINDOWSTATION * pWinSta, UINT format, ULONG);
BOOLEAN NtUserIsClipboardFormatAvailable(_In_ UINT format)
{
BOOLEAN fOk = FALSE;
EnterSharedCrit();
if (WINDOWSTATION * pWinSta = CheckClipboardAccess())
{
if (pWinSta == <some global data>)
{
if (grpdeskLogon != <thread desktop>)
{
fOk = (0 != FindClipFormat(pWinSta, format, 1));
}
}
}
UserSessionSwitchLeaveCrit();
return fOk;
}
CheckClipboardAccess
在某些情况下有设置最后一个错误的迹象 - 它调用NTSTATUS ReferenceWindowStation(..)
并且如果api失败 - 调用
status = ReferenceWindowStation(..)
if (0 > status) UserSetLastError(RtlNtStatusToDosError(status))
但如果线程桌面也等于
grpdeskLogon
(这是Winlogon桌面)可见,现在设置了任何错误。如果查找 FindClipFormat
也可见,如果未找到格式,该函数不会设置任何错误。
因此,如果我们在返回时得到 0 (FALSE) - 我们无法知道真正的原因 - 或者因为在剪贴板中找不到请求的格式,或者因为我们在 winlogon 桌面上,或者错误的窗口站,或者其他原因。
以及 Windows 的工作原理。
如果我们请求某个对象(或检查它是否存在)但它不存在 - 这是设计错误。当然可以做另一种设计。但窗户是按设计设计的。如果没有返回请求的对象(或检查) - 这是错误,错误代码必须解释原因 - 访问被拒绝,或未找到对象,或共享冲突,或其他原因。这是任何 Windows 对象的通用规则 - 文件、注册表项、命名事件等。
如果我们尝试打开对象(或检查)但不能 - 这是错误,它必须是直接或间接(通过最后一个错误)返回。 windows 对于这种情况有特殊的状态。例如
STATUS_OBJECT_NAME_NOT_FOUND
STATUS_OBJECT_PATH_NOT_FOUND
STATUS_NOT_FOUND
STATUS_OBJECTID_NOT_FOUND
...
所以在当前情况下我们只是有一些小的 Windows 错误