GetConsoleCharType不支持的WinAPI错误代码
我决定探索WinAPI undocumented函数,因为其中一些函数仍然可以使用,并且可以做没有它们不可能做的事情(例如:GetConsoleCharType不支持的WinAPI错误代码,c,winapi,C,Winapi,我决定探索WinAPI undocumented函数,因为其中一些函数仍然可以使用,并且可以做没有它们不可能做的事情(例如:GetConsoleCommand和History或MessageBoxTimeout) 当我试图从kernel32.dll导入GetConsoleCharType时,我在互联网上找到了一个声明。当我运行它时,我从GetLastError中得到了错误代码16385。我试图在FormatMessage中运行它以检索错误消息,但是FormatMessage失败,代码15100来
GetConsoleCommand和History
或MessageBoxTimeout
)
当我试图从kernel32.dll导入GetConsoleCharType
时,我在互联网上找到了一个声明。当我运行它时,我从GetLastError
中得到了错误代码16385
。我试图在FormatMessage
中运行它以检索错误消息,但是FormatMessage
失败,代码15100
来自GetLastError
。我进入页面,看到它们只支持0到15999之间的错误代码。有人能帮我理解这个错误吗
函数声明来自
我的代码:
HMODULE hModule = LoadLibraryA("kernel32.dll");
if (hModule)
{
puts("Kernel32 loaded!");
BOOL(WINAPI * GetConsoleCharType)(HANDLE hConsole, COORD Coord, PDWORD Type);
GetConsoleCharType = (decltype(GetConsoleCharType))GetProcAddress(hModule, "GetConsoleCharType");
if(GetConsoleCharType)
{
puts("Function loaded!");
DWORD type = 0;
if (GetConsoleCharType(GetStdHandle(STD_OUTPUT_HANDLE), { 0, 0 }, &type))
puts("Function worked!");
else
{
printf("Function failed with code %lu\n", GetLastError());
char* msg;
if(FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&msg, 0, NULL))
{
printf("Error: %s", msg);
LocalFree(msg);
}
else
{
printf("FormatMessage failed with code %lu\n", GetLastError());
}
}
FreeLibrary(hModule);
}
}
输出:
Kernel32 loaded!
Function loaded!
Function failed with code 16385
FormatMessage failed with code 15100
GetConsoleCharType
returnC0074001
-您可以通过RtlGetLastNtStatus()
获取它。真正在conhost.exe内部处理调用。如果将调试器附加到它,则可以查看下一次调试打印:
onecore\windows\core\console\open\src\server\apidispatchersinternal.cpp(23)\ConhostV2.dll!00007FFFB6D35863: (caller: 00007FFFB6D35681) ReturnHr(5) tid(ae4) 80004001 Not implemented
Msg:[Deprecated API attempted: 0x00000007]
内部处理呼叫
HRESULT ApiDispatchers::ServerDeprecatedApi(_CONSOLE_API_MSG * const,int * const)
{
return wil::details::in1diag3::Return_HrMsg(*,E_NOTIMPL,
"onecore\windows\core\console\open\src\server\apidispatchersinternal.cpp");
}
它返回E_NOTIMPL(0x80004001)
,然后进行转换
80004001 -> 4001 -> 4001 | c0070000 = c0074001
最后,
RtlNtStatusToDosError
将其转换为0x4001=16385
是什么让您认为GetConsoleCharType()
使用GetLastError()
报告错误?它是未记录的,您甚至不知道它是否报告了错误。例如,您链接到的不会调用SetLastError()
,因此GetLastError()
的返回值将毫无意义。对于获取,可以实现此目的:“设置最后一个错误代码的每个函数的文档的返回值部分会记录函数设置最后一个错误代码的条件。“如果没有文档,您就不知道这些情况。因此,在调用一个没有文档的函数后调用GetLastError
是不安全的。我曾尝试在此代码之前使用SetLastError
检查它是否更改。事实上,调用线程的最后一个错误代码发生了变化,这并不表明它的值是契约的一部分。任何变化都不是任何迹象。合同不是你可以从观察中得出的东西。合同是一种书面文件。当然,未记录的库函数并不附带契约。换句话说:未记录API调用的契约是:不要使用。