blob: 7781673a4077f3f20018a49e01e59639fe02d2c2 [file] [log] [blame]
#include "internal.h"
typedef void (WINAPI *_precise_time_fn_t)(PULONGLONG);
DISPATCH_STATIC_GLOBAL(dispatch_once_t _dispatch_precise_time_pred);
DISPATCH_STATIC_GLOBAL(_precise_time_fn_t _dispatch_QueryInterruptTimePrecise_ptr);
DISPATCH_STATIC_GLOBAL(_precise_time_fn_t _dispatch_QueryUnbiasedInterruptTimePrecise_ptr);
typedef NTSTATUS (NTAPI *_NtQueryInformationFile_fn_t)(HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass);
DISPATCH_STATIC_GLOBAL(dispatch_once_t _dispatch_ntdll_pred);
DISPATCH_STATIC_GLOBAL(_NtQueryInformationFile_fn_t _dispatch_NtQueryInformationFile_ptr);
bool
_dispatch_handle_is_socket(HANDLE hFile)
{
// GetFileType() returns FILE_TYPE_PIPE for both pipes and sockets. We can
// disambiguate by checking if PeekNamedPipe() fails with
// ERROR_INVALID_FUNCTION.
if (GetFileType(hFile) == FILE_TYPE_PIPE &&
!PeekNamedPipe(hFile, NULL, 0, NULL, NULL, NULL)) {
return GetLastError() == ERROR_INVALID_FUNCTION;
}
return false;
}
static void
_dispatch_init_precise_time(void *context DISPATCH_UNUSED)
{
HMODULE kernelbase = LoadLibraryW(L"KernelBase.dll");
if (!kernelbase) {
DISPATCH_INTERNAL_CRASH(0, "failed to load KernelBase.dll");
}
_dispatch_QueryInterruptTimePrecise_ptr = (_precise_time_fn_t)
GetProcAddress(kernelbase, "QueryInterruptTimePrecise");
_dispatch_QueryUnbiasedInterruptTimePrecise_ptr = (_precise_time_fn_t)
GetProcAddress(kernelbase, "QueryUnbiasedInterruptTimePrecise");
if (!_dispatch_QueryInterruptTimePrecise_ptr) {
DISPATCH_INTERNAL_CRASH(0, "could not locate QueryInterruptTimePrecise");
}
if (!_dispatch_QueryUnbiasedInterruptTimePrecise_ptr) {
DISPATCH_INTERNAL_CRASH(0, "could not locate QueryUnbiasedInterruptTimePrecise");
}
}
void
_dispatch_QueryInterruptTimePrecise(PULONGLONG lpInterruptTimePrecise)
{
dispatch_once_f(&_dispatch_precise_time_pred, NULL, _dispatch_init_precise_time);
return _dispatch_QueryInterruptTimePrecise_ptr(lpInterruptTimePrecise);
}
void
_dispatch_QueryUnbiasedInterruptTimePrecise(PULONGLONG lpUnbiasedInterruptTimePrecise)
{
dispatch_once_f(&_dispatch_precise_time_pred, NULL, _dispatch_init_precise_time);
return _dispatch_QueryUnbiasedInterruptTimePrecise_ptr(lpUnbiasedInterruptTimePrecise);
}
static void
_dispatch_init_ntdll(void *context DISPATCH_UNUSED)
{
HMODULE ntdll = LoadLibraryW(L"ntdll.dll");
if (!ntdll) {
// ntdll is not required.
return;
}
_dispatch_NtQueryInformationFile_ptr = (_NtQueryInformationFile_fn_t)
GetProcAddress(ntdll, "NtQueryInformationFile");
}
NTSTATUS _dispatch_NtQueryInformationFile(HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length,
FILE_INFORMATION_CLASS FileInformationClass)
{
dispatch_once_f(&_dispatch_ntdll_pred, NULL, _dispatch_init_ntdll);
if (!_dispatch_NtQueryInformationFile_ptr) {
return STATUS_NOT_SUPPORTED;
}
return _dispatch_NtQueryInformationFile_ptr(FileHandle, IoStatusBlock,
FileInformation, Length, FileInformationClass);
}