仅在现代 Windows NT 系统上,我能否在运行时确定句柄是指套接字句柄还是对象句柄?

On modern Windows NT systems only, can I determine at runtime whether a handle refers to a socket or an object handle?

我完全知道,在过去 Windows 套接字仅作为第三方用户模式 ​​DLL 实现,套接字和对象句柄是不相关的。然而,在现代 Windows NT 系统上,套接字是完整的内核对象,尽管也有一些用户模式状态。

遗憾的是,该特定查询没有单个 API。您必须直接访问 NT 对象管理器并在其已知句柄列表中找到所需的句柄,然后您可以检索句柄的对象类型(以及其他内容)。

Inside NT's Object Manager

Pushing the Limits of Windows: Handles

HOWTO: Enumerate handles

WinObj: The ultimate Object Manager namespace viewer

更新:我忘了NtQueryObject()。您可以查询 HANDLEObjectTypeInformation class,其中 returns 一个 PUBLIC_OBJECT_TYPE_INFORMATION 结构:

typedef struct __PUBLIC_OBJECT_TYPE_INFORMATION {
    UNICODE_STRING TypeName;
    ULONG Reserved [22];    // reserved for internal use
} PUBLIC_OBJECT_TYPE_INFORMATION, *PPUBLIC_OBJECT_TYPE_INFORMATION;

例如:

std::wstring GetHandleTypeName(HANDLE hHandle)
{
    typedef NTSTATUS (NTAPI *NtQueryObjectPtr)(
          HANDLE Handle,
          OBJECT_INFORMATION_CLASS ObjectInformationClass,
          PVOID ObjectInformation,
          ULONG ObjectInformationLength,
          PULONG ReturnLength);

    HMODULE hMod = LoadLibrary(_T("NtDll.dll"));
    NtQueryObjectPtr QueryObj = (NtQueryObjectPtr) ::GetProcAddress(hMod, "NtQueryObject");
    ASSERT(QueryObj);

    ULONG OutSize = 0;
    NTSTATUS NtStatus = QueryObj(hHandle, ObjectTypeInformation, NULL, 0, &OutSize);
    std::vector<BYTE> buffer(OutSize);
    PPUBLIC_OBJECT_TYPE_INFORMATION TypeInfo = (PPUBLIC_OBJECT_TYPE_INFORMATION) &buffer[0];
    ULONG InSize = OutSize;
    NtStatus = QueryObj(hHandle, ObjectTypeInformation, TypeInfo, InSize, &OutSize);
    return std::wstring(TypeInfo->TypeName.Buffer, TypeInfo->TypeName.Length);
}

std::wstring cs = GetHandleTypeName((HANDLE)TheDesiredSocket);
MessageBoxW(cs.c_str());

有关将 NtQueryObject() 与套接字一起使用的更多信息,请参阅这些内容:

C++ Get Handle of Open Sockets of a Program

socket handles