ProxyRegisterWaitLoadLibrary

typedef NTSTATUS(NTAPI* NTWAITFORSINGLEOBJECT)(HANDLE, BOOL, PLARGE_INTEGER);
typedef NTSTATUS(NTAPI* RTLREGISTERWAIT)(PHANDLE, HANDLE, WORKERCALLBACKFUNC, PVOID, ULONG, ULONG);
typedef NTSTATUS(NTAPI* RTLDEREGISTERWAITEX)(HANDLE, HANDLE);

HMODULE ProxyRegisterWaitLoadLibraryW(_In_ LPCWSTR lpModuleName)
{
	RTLREGISTERWAIT RtlRegisterWait = NULL;
	RTLDEREGISTERWAITEX RtlDeregisterWaitEx = NULL;
	NTWAITFORSINGLEOBJECT NtWaitForSingleObject = NULL;
	HANDLE WaitObject = NULL, EventObject = NULL;
	HMODULE hReturn = NULL;
	LARGE_INTEGER Timeout = { 0 };
	Timeout.QuadPart = 500;

	NtWaitForSingleObject = (NTWAITFORSINGLEOBJECT)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtWaitForSingleObject");
	RtlRegisterWait = (RTLREGISTERWAIT)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlRegisterWait");
	RtlDeregisterWaitEx = (RTLDEREGISTERWAITEX)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlDeregisterWaitEx");

	if (!RtlRegisterWait || !NtWaitForSingleObject || !RtlDeregisterWaitEx)
		goto EXIT_ROUTINE;

	EventObject = CreateEventW(NULL, FALSE, FALSE, NULL);
	if (EventObject == NULL)
		goto EXIT_ROUTINE;

	if (RtlRegisterWait(&WaitObject, EventObject, (WORKERCALLBACKFUNC)LoadLibraryW, (PVOID)lpModuleName, 0, WT_EXECUTEDEFAULT) != STATUS_SUCCESS)
		goto EXIT_ROUTINE;
	else
		NtWaitForSingleObject(EventObject, FALSE, &Timeout);

	hReturn = GetModuleHandleW(lpModuleName);

EXIT_ROUTINE:

	if (EventObject)
		CloseHandle(EventObject);

	if(WaitObject)
		RtlDeregisterWaitEx(WaitObject, NULL);

	return hReturn;
}

HMODULE ProxyRegisterWaitLoadLibraryA(_In_ LPCSTR lpModuleName)
{
	RTLREGISTERWAIT RtlRegisterWait = NULL;
	RTLDEREGISTERWAITEX RtlDeregisterWaitEx = NULL;
	NTWAITFORSINGLEOBJECT NtWaitForSingleObject = NULL;
	HANDLE WaitObject = NULL, EventObject = NULL;
	HMODULE hReturn = NULL;
	LARGE_INTEGER Timeout = { 0 };
	Timeout.QuadPart = 500;

	NtWaitForSingleObject = (NTWAITFORSINGLEOBJECT)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtWaitForSingleObject");
	RtlRegisterWait = (RTLREGISTERWAIT)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlRegisterWait");
	RtlDeregisterWaitEx = (RTLDEREGISTERWAITEX)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlDeregisterWaitEx");

	if (!RtlRegisterWait || !NtWaitForSingleObject || !RtlDeregisterWaitEx)
		goto EXIT_ROUTINE;

	EventObject = CreateEventW(NULL, FALSE, FALSE, NULL);
	if (EventObject == NULL)
		goto EXIT_ROUTINE;

	if (RtlRegisterWait(&WaitObject, EventObject, (WORKERCALLBACKFUNC)LoadLibraryA, (PVOID)lpModuleName, 0, WT_EXECUTEDEFAULT) != STATUS_SUCCESS)
		goto EXIT_ROUTINE;
	else
		NtWaitForSingleObject(EventObject, FALSE, &Timeout);

	hReturn = GetModuleHandleA(lpModuleName);

EXIT_ROUTINE:

	if (EventObject)
		CloseHandle(EventObject);

	if (WaitObject)
		RtlDeregisterWaitEx(WaitObject, NULL);

	return hReturn;
}

Last updated