winpty/misc/buffer-tests/harness/NtHandleQuery.cc
Ryan Prichard 5917ff60a7 On Win10, replace NtQuerySystemInformation with CompareObjectHandles
* CompareObjectHandles is a documented API, and presumably it could be
   faster.  The tests actually do run a little faster now on Win10,
   dropping from 6.5sec to 3.6sec or so.

 * Also make the NtQuerySystemInformation buffer static so we don't have to
   repeat the double-buffer-in-a-loop process on every ntHandlePointer
   call.
2015-10-24 04:14:25 -05:00

61 lines
2.0 KiB
C++
Executable File

#include "NtHandleQuery.h"
#include <DebugClient.h>
#include <OsModule.h>
// internal definitions copied from mingw-w64's winternl.h and ntstatus.h.
#define STATUS_SUCCESS ((NTSTATUS)0x00000000)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004)
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation = 0,
SystemProcessorInformation = 1,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemProcessInformation = 5,
SystemProcessorPerformanceInformation = 8,
SystemHandleInformation = 16,
SystemPagefileInformation = 18,
SystemInterruptInformation = 23,
SystemExceptionInformation = 33,
SystemRegistryQuotaInformation = 37,
SystemLookasideInformation = 45
} SYSTEM_INFORMATION_CLASS;
typedef NTSTATUS NTAPI NtQuerySystemInformation_Type(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength);
std::vector<SYSTEM_HANDLE_ENTRY> queryNtHandles() {
OsModule ntdll(L"ntdll.dll");
auto funcPtr = ntdll.proc("NtQuerySystemInformation");
ASSERT(funcPtr != NULL && "NtQuerySystemInformation API is missing");
auto func = reinterpret_cast<NtQuerySystemInformation_Type*>(funcPtr);
static std::vector<char> buf(1024);
while (true) {
ULONG returnLength = 0;
auto ret = func(
SystemHandleInformation,
buf.data(),
buf.size(),
&returnLength);
if (ret == STATUS_INFO_LENGTH_MISMATCH) {
buf.resize(buf.size() * 2);
continue;
} else if (ret == STATUS_SUCCESS) {
break;
} else {
trace("Could not query NT handles, status was 0x%x",
static_cast<unsigned>(ret));
return {};
}
}
auto &info = *reinterpret_cast<SYSTEM_HANDLE_INFORMATION*>(buf.data());
std::vector<SYSTEM_HANDLE_ENTRY> ret(info.Count);
std::copy(info.Handle, info.Handle + info.Count, ret.begin());
return ret;
}