GetConsoleCharType不支持的WinAPI错误代码

GetConsoleCharType不支持的WinAPI错误代码,c,winapi,C,Winapi,我决定探索WinAPI undocumented函数,因为其中一些函数仍然可以使用,并且可以做没有它们不可能做的事情(例如:GetConsoleCommand和History或MessageBoxTimeout) 当我试图从kernel32.dll导入GetConsoleCharType时,我在互联网上找到了一个声明。当我运行它时,我从GetLastError中得到了错误代码16385。我试图在FormatMessage中运行它以检索错误消息,但是FormatMessage失败,代码15100来

我决定探索WinAPI undocumented函数,因为其中一些函数仍然可以使用,并且可以做没有它们不可能做的事情(例如:
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
return
C0074001
-您可以通过
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调用的契约是:不要使用。