Path: blob/master/external/source/HostingCLR_inject/HostingCLR/ReflectiveFree.cpp
19812 views
#include "stdafx.h"1#include "ReflectiveFree.h"2#include <Windows.h>34typedef NTSTATUS5(NTAPI *NtQueueApcThread)(6HANDLE ThreadHandle,7PVOID ApcRoutine,8ULONG_PTR SystemArgument1,9ULONG_PTR SystemArgument2,10ULONG_PTR SystemArgument311);1213VOID ReflectiveFree(HINSTANCE hAppInstance) {14NtQueueApcThread pNtQueueApcThread = (NtQueueApcThread)GetProcAddress(GetModuleHandle(TEXT("ntdll")), "NtQueueApcThread");15HANDLE hThread = NULL;16HANDLE hThisThread = NULL;17do {18if (!pNtQueueApcThread)19break;2021// create a suspended thread that will just exit once the APCs have executed22hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ExitThread, 0, CREATE_SUSPENDED, NULL);23if (!hThread)24break;2526// open a real handle to this thread to pass in the APC so it operates on this thread and not itself27hThisThread = OpenThread(THREAD_QUERY_INFORMATION | SYNCHRONIZE, FALSE, GetCurrentThreadId());28if (!hThisThread)29{30break;31}323334// The other thread will:35// - Wait for us: WaitForSingleObjectEx(hThisThread, INFINITE, FALSE);36// - Close the handle we opened: CloseHandle(hThisThread);37// - Free the memory: VirtualFree(hAppInstance, 0, MEM_RELEASE);3839// tell that thread to wait on this thread, ensures VirtualFree isn't called until this thread has exited40NTSTATUS status = pNtQueueApcThread(hThread, WaitForSingleObjectEx, (ULONG_PTR)hThisThread, INFINITE, FALSE);4142// then close the handle so it's not leaked43QueueUserAPC((PAPCFUNC)CloseHandle, hThread, (ULONG_PTR)hThisThread);44// then free the memory45status = pNtQueueApcThread(hThread, VirtualFree, (ULONG_PTR)hAppInstance, 0, MEM_RELEASE);46ResumeThread(hThread);47} while (FALSE);4849if (hThread)50{51CloseHandle(hThread);52}53}5455VOID ReflectiveFreeAndExitThread(HINSTANCE hAppInstance, DWORD dwExitCode) {56ReflectiveFree(hAppInstance);5758ExitThread(dwExitCode);59return;60}6162