VOID PhpRegisterSymbolProvider( _In_opt_ PPH_SYMBOL_PROVIDER SymbolProvider ) { if (PhBeginInitOnce(&PhSymInitOnce)) { PhInvokeCallback(&PhSymInitCallback, NULL); PhEndInitOnce(&PhSymInitOnce); } if (!SymbolProvider) return; #ifdef PH_SYMBOL_PROVIDER_DELAY_INIT if (PhBeginInitOnce(&SymbolProvider->InitOnce)) { #endif if (SymInitialize_I) { PH_LOCK_SYMBOLS(); SymInitialize_I(SymbolProvider->ProcessHandle, NULL, FALSE); if (SymRegisterCallbackW64_I) SymRegisterCallbackW64_I(SymbolProvider->ProcessHandle, PhpSymbolCallbackFunction, (ULONG64)SymbolProvider); PH_UNLOCK_SYMBOLS(); SymbolProvider->IsRegistered = TRUE; } #ifdef PH_SYMBOL_PROVIDER_DELAY_INIT PhEndInitOnce(&SymbolProvider->InitOnce); } #endif }
HRESULT CreateXCLRDataProcess( __in HANDLE ProcessId, __in ICLRDataTarget *Target, __out struct IXCLRDataProcess **DataProcess ) { ULONG flags; BOOLEAN clrV4; HMODULE dllBase; HRESULT (__stdcall *clrDataCreateInstance)(REFIID, ICLRDataTarget *, void **); clrV4 = FALSE; if (NT_SUCCESS(PhGetProcessIsDotNetEx(ProcessId, NULL, 0, NULL, &flags))) { if (flags & PH_CLR_VERSION_4_ABOVE) clrV4 = TRUE; } // Load the correct version of mscordacwks.dll. if (clrV4) { static PH_INITONCE initOnce = PH_INITONCE_INIT; static HMODULE mscordacwksDllBase; if (PhBeginInitOnce(&initOnce)) { mscordacwksDllBase = LoadMscordacwks(TRUE); PhEndInitOnce(&initOnce); } dllBase = mscordacwksDllBase; } else { static PH_INITONCE initOnce = PH_INITONCE_INIT; static HMODULE mscordacwksDllBase; if (PhBeginInitOnce(&initOnce)) { mscordacwksDllBase = LoadMscordacwks(FALSE); PhEndInitOnce(&initOnce); } dllBase = mscordacwksDllBase; } if (!dllBase) return E_FAIL; clrDataCreateInstance = (PVOID)GetProcAddress(dllBase, "CLRDataCreateInstance"); if (!clrDataCreateInstance) return E_FAIL; return clrDataCreateInstance(&IID_IXCLRDataProcess, Target, DataProcess); }
PPH_PROCESS_PROPCONTEXT PhCreateProcessPropContext( _In_ HWND ParentWindowHandle, _In_ PPH_PROCESS_ITEM ProcessItem ) { static PH_INITONCE initOnce = PH_INITONCE_INIT; PPH_PROCESS_PROPCONTEXT propContext; PROPSHEETHEADER propSheetHeader; if (PhBeginInitOnce(&initOnce)) { PhpProcessPropContextType = PhCreateObjectType(L"ProcessPropContext", 0, PhpProcessPropContextDeleteProcedure); PhpProcessPropPageContextType = PhCreateObjectType(L"ProcessPropPageContext", 0, PhpProcessPropPageContextDeleteProcedure); PhEndInitOnce(&initOnce); } propContext = PhCreateObjectZero(sizeof(PH_PROCESS_PROPCONTEXT), PhpProcessPropContextType); propContext->PropSheetPages = PhAllocateZero(sizeof(HPROPSHEETPAGE) * PH_PROCESS_PROPCONTEXT_MAXPAGES); if (!PH_IS_FAKE_PROCESS_ID(ProcessItem->ProcessId)) { propContext->Title = PhFormatString( L"%s (%u)", ProcessItem->ProcessName->Buffer, HandleToUlong(ProcessItem->ProcessId) ); } else { PhSetReference(&propContext->Title, ProcessItem->ProcessName); } memset(&propSheetHeader, 0, sizeof(PROPSHEETHEADER)); propSheetHeader.dwSize = sizeof(PROPSHEETHEADER); propSheetHeader.dwFlags = PSH_MODELESS | PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP | PSH_PROPTITLE | PSH_USECALLBACK | PSH_USEHICON; propSheetHeader.hInstance = PhInstanceHandle; propSheetHeader.hwndParent = ParentWindowHandle; propSheetHeader.hIcon = ProcessItem->SmallIcon; propSheetHeader.pszCaption = propContext->Title->Buffer; propSheetHeader.pfnCallback = PhpPropSheetProc; propSheetHeader.nPages = 0; propSheetHeader.nStartPage = 0; propSheetHeader.phpage = propContext->PropSheetPages; if (PhCsForceNoParent) propSheetHeader.hwndParent = NULL; memcpy(&propContext->PropSheetHeader, &propSheetHeader, sizeof(PROPSHEETHEADER)); PhSetReference(&propContext->ProcessItem, ProcessItem); return propContext; }
VOID PhpViewSignerInfo( _In_ PPH_VERIFY_FILE_INFO Information, _In_ HANDLE StateData ) { static PH_INITONCE initOnce = PH_INITONCE_INIT; static _CryptUIDlgViewSignerInfo cryptUIDlgViewSignerInfo; if (PhBeginInitOnce(&initOnce)) { HMODULE cryptui = LoadLibrary(L"cryptui.dll"); cryptUIDlgViewSignerInfo = (PVOID)GetProcAddress(cryptui, "CryptUIDlgViewSignerInfoW"); PhEndInitOnce(&initOnce); } if (cryptUIDlgViewSignerInfo) { CRYPTUI_VIEWSIGNERINFO_STRUCT viewSignerInfo = { sizeof(CRYPTUI_VIEWSIGNERINFO_STRUCT) }; PCRYPT_PROVIDER_DATA provData; PCRYPT_PROVIDER_SGNR sgnr; if (!(provData = WTHelperProvDataFromStateData_I(StateData))) return; if (!(sgnr = WTHelperGetProvSignerFromChain_I(provData, 0, FALSE, 0))) return; viewSignerInfo.hwndParent = Information->hWnd; viewSignerInfo.pSignerInfo = sgnr->psSigner; viewSignerInfo.hMsg = provData->hMsg; viewSignerInfo.pszOID = szOID_PKIX_KP_CODE_SIGNING; cryptUIDlgViewSignerInfo(&viewSignerInfo); } }
static VOID QueueDnsCacheUpdateThread( VOID ) { if (PhBeginInitOnce(&DnsUpdateQueueInitOnce)) { PhInitializeWorkQueue(&DnsUpdateQueue, 0, 1, 500); PhEndInitOnce(&DnsUpdateQueueInitOnce); } if (DnsUpdateQueue.BusyCount < 1) // One update at a time PhQueueItemWorkQueue(&DnsUpdateQueue, DnsCacheUpdateThread, 0); }
VOID PhpQueueThreadWorkQueueItem( __in PTHREAD_START_ROUTINE Function, __in_opt PVOID Context ) { if (PhBeginInitOnce(&PhThreadProviderWorkQueueInitOnce)) { PhInitializeWorkQueue(&PhThreadProviderWorkQueue, 0, 1, 1000); PhEndInitOnce(&PhThreadProviderWorkQueueInitOnce); } PhQueueItemWorkQueue(&PhThreadProviderWorkQueue, Function, Context); }
FORCEINLINE VOID PhpSecurityEditorInitialization( VOID ) { if (PhBeginInitOnce(&SecurityEditorInitOnce)) { HMODULE aclui; aclui = LoadLibrary(L"aclui.dll"); CreateSecurityPage_I = (PVOID)GetProcAddress(aclui, "CreateSecurityPage"); EditSecurity_I = (PVOID)GetProcAddress(aclui, "EditSecurity"); PhEndInitOnce(&SecurityEditorInitOnce); } }
/** * Queues a work item to the global work queue. * * \param Function A function to execute. * \param Context A user-defined value to pass to the function. */ VOID PhQueueItemGlobalWorkQueue( _In_ PUSER_THREAD_START_ROUTINE Function, _In_opt_ PVOID Context ) { if (PhBeginInitOnce(&PhGlobalWorkQueueInitOnce)) { PhInitializeWorkQueue( &PhGlobalWorkQueue, 0, 3, 1000 ); PhEndInitOnce(&PhGlobalWorkQueueInitOnce); } PhQueueItemWorkQueue( &PhGlobalWorkQueue, Function, Context ); }
static ULONG PhpGetCurrentScale( VOID ) { static PH_INITONCE initOnce; static ULONG dpi = 96; if (PhBeginInitOnce(&initOnce)) { HDC hdc; if (hdc = CreateIC(L"DISPLAY", NULL, NULL, NULL)) { dpi = GetDeviceCaps(hdc, LOGPIXELSY); DeleteDC(hdc); } PhEndInitOnce(&initOnce); } return dpi; }
HRESULT PkpCreateSevenZipObject( __in PGUID ClassId, __in PGUID InterfaceId, __out PVOID *Object ) { if (PhBeginInitOnce(&SevenZipInitOnce)) { SevenZipHandle = LoadLibrary(L"7z.dll"); if (SevenZipHandle) { CreateObject_I = (_CreateObject)GetProcAddress(SevenZipHandle, "CreateObject"); } PhEndInitOnce(&SevenZipInitOnce); } if (!CreateObject_I) return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); return CreateObject_I(ClassId, InterfaceId, Object); }
/** * Verifies a file's digital signature. * * \param FileName A file name. * \param SignerName A variable which receives a pointer * to a string containing the signer name. You must free * the string using PhDereferenceObject() when you no * longer need it. Note that the signer name may be NULL * if it is not valid. * * \return A VERIFY_RESULT value. */ VERIFY_RESULT PhVerifyFile( __in PWSTR FileName, __out_opt PPH_STRING *SignerName ) { VERIFY_RESULT result; if (PhBeginInitOnce(&PhpVerifyInitOnce)) { PhpVerifyInitialization(); PhEndInitOnce(&PhpVerifyInitOnce); } // Make sure we have successfully imported // the required functions. if ( !CryptCATAdminCalcHashFromFileHandle || !CryptCATAdminAcquireContext || !CryptCATAdminEnumCatalogFromHash || !CryptCATCatalogInfoFromContext || !CryptCATAdminReleaseCatalogContext || !CryptCATAdminReleaseContext || !WinVerifyTrust_I || !WTHelperProvDataFromStateData_I || !WTHelperGetProvSignerFromChain_I || !CertNameToStr_I ) return VrUnknown; result = PhpVerifyFileBasic(FileName, SignerName); if (result == VrNoSignature) result = PhpVerifyFileFromCatalog(FileName, SignerName); return result; }
static NTSTATUS PhpFindObjectsThreadStart( _In_ PVOID Parameter ) { NTSTATUS status = STATUS_SUCCESS; PSYSTEM_HANDLE_INFORMATION_EX handles; PPH_HASHTABLE processHandleHashtable; PVOID processes; PSYSTEM_PROCESS_INFORMATION process; ULONG i; // Refuse to search with no filter. if (SearchString->Length == 0) goto Exit; // Try to get a search pointer from the search string. UseSearchPointer = PhStringToInteger64(&SearchString->sr, 0, &SearchPointer); _wcsupr(SearchString->Buffer); if (NT_SUCCESS(status = PhEnumHandlesEx(&handles))) { static PH_INITONCE initOnce = PH_INITONCE_INIT; static ULONG fileObjectTypeIndex = -1; BOOLEAN useWorkQueue = FALSE; PH_WORK_QUEUE workQueue; processHandleHashtable = PhCreateSimpleHashtable(8); if (!KphIsConnected() && WindowsVersion >= WINDOWS_VISTA) { useWorkQueue = TRUE; PhInitializeWorkQueue(&workQueue, 1, 20, 1000); if (PhBeginInitOnce(&initOnce)) { UNICODE_STRING fileTypeName; RtlInitUnicodeString(&fileTypeName, L"File"); fileObjectTypeIndex = PhGetObjectTypeNumber(&fileTypeName); PhEndInitOnce(&initOnce); } } for (i = 0; i < handles->NumberOfHandles; i++) { PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo = &handles->Handles[i]; PVOID *processHandlePtr; HANDLE processHandle; if (SearchStop) break; // Open a handle to the process if we don't already have one. processHandlePtr = PhFindItemSimpleHashtable( processHandleHashtable, (PVOID)handleInfo->UniqueProcessId ); if (processHandlePtr) { processHandle = (HANDLE)*processHandlePtr; } else { if (NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_DUP_HANDLE, (HANDLE)handleInfo->UniqueProcessId ))) { PhAddItemSimpleHashtable( processHandleHashtable, (PVOID)handleInfo->UniqueProcessId, processHandle ); } else { continue; } } if (useWorkQueue && handleInfo->ObjectTypeIndex == (USHORT)fileObjectTypeIndex) { PSEARCH_HANDLE_CONTEXT searchHandleContext; searchHandleContext = PhAllocate(sizeof(SEARCH_HANDLE_CONTEXT)); searchHandleContext->NeedToFree = TRUE; searchHandleContext->HandleInfo = handleInfo; searchHandleContext->ProcessHandle = processHandle; PhQueueItemWorkQueue(&workQueue, SearchHandleFunction, searchHandleContext); } else { SEARCH_HANDLE_CONTEXT searchHandleContext; searchHandleContext.NeedToFree = FALSE; searchHandleContext.HandleInfo = handleInfo; searchHandleContext.ProcessHandle = processHandle; SearchHandleFunction(&searchHandleContext); } } if (useWorkQueue) { PhWaitForWorkQueue(&workQueue); PhDeleteWorkQueue(&workQueue); } { PPH_KEY_VALUE_PAIR entry; i = 0; while (PhEnumHashtable(processHandleHashtable, &entry, &i)) NtClose((HANDLE)entry->Value); } PhDereferenceObject(processHandleHashtable); PhFree(handles); } if (NT_SUCCESS(PhEnumProcesses(&processes))) { process = PH_FIRST_PROCESS(processes); do { PhEnumGenericModules( process->UniqueProcessId, NULL, PH_ENUM_GENERIC_MAPPED_FILES | PH_ENUM_GENERIC_MAPPED_IMAGES, EnumModulesCallback, (PVOID)process->UniqueProcessId ); } while (process = PH_NEXT_PROCESS(process)); PhFree(processes); } Exit: PostMessage(PhFindObjectsWindowHandle, WM_PH_SEARCH_FINISHED, status, 0); return STATUS_SUCCESS; }
/** * Gets the default icon used for executable files. * * \param SmallIcon A variable which receives the small default executable icon. * Do not destroy the icon using DestroyIcon(); it is shared between callers. * \param LargeIcon A variable which receives the large default executable icon. * Do not destroy the icon using DestroyIcon(); it is shared between callers. */ VOID PhGetStockApplicationIcon( _Out_opt_ HICON *SmallIcon, _Out_opt_ HICON *LargeIcon ) { static PH_INITONCE initOnce = PH_INITONCE_INIT; static HICON smallIcon = NULL; static HICON largeIcon = NULL; // This no longer uses SHGetFileInfo because it is *very* slow and causes // many other DLLs to be loaded, increasing memory usage. The worst thing // about it, however, is that it is horribly incompatible with multi-threading. // The first time it is called, it tries to perform some one-time initialization. // It guards this with a lock, but when multiple threads try to call the function // at the same time, instead of waiting for initialization to finish it simply // fails the other threads. if (PhBeginInitOnce(&initOnce)) { PPH_STRING systemDirectory; PPH_STRING dllFileName; // imageres,11 (Windows 10 and above), user32,0 (Vista and above) or shell32,2 (XP) contains the default application icon. if (systemDirectory = PhGetSystemDirectory()) { PH_STRINGREF dllBaseName; ULONG index; // TODO: Find a better solution. if (WindowsVersion >= WINDOWS_10) { PhInitializeStringRef(&dllBaseName, L"\\imageres.dll"); index = 11; } else if (WindowsVersion >= WINDOWS_VISTA) { PhInitializeStringRef(&dllBaseName, L"\\user32.dll"); index = 0; } else { PhInitializeStringRef(&dllBaseName, L"\\shell32.dll"); index = 2; } dllFileName = PhConcatStringRef2(&systemDirectory->sr, &dllBaseName); PhDereferenceObject(systemDirectory); ExtractIconEx(dllFileName->Buffer, index, &largeIcon, &smallIcon, 1); PhDereferenceObject(dllFileName); } // Fallback icons - this is bad, because the icon isn't scaled correctly. if (!smallIcon) smallIcon = LoadIcon(NULL, IDI_APPLICATION); if (!largeIcon) largeIcon = LoadIcon(NULL, IDI_APPLICATION); PhEndInitOnce(&initOnce); } if (SmallIcon) *SmallIcon = smallIcon; if (LargeIcon) *LargeIcon = largeIcon; }
NTSTATUS PhVerifyFileEx( _In_ PPH_VERIFY_FILE_INFO Information, _Out_ VERIFY_RESULT *VerifyResult, _Out_opt_ PCERT_CONTEXT **Signatures, _Out_opt_ PULONG NumberOfSignatures ) { NTSTATUS status; HANDLE fileHandle; VERIFY_RESULT verifyResult; PCERT_CONTEXT *signatures; ULONG numberOfSignatures; WINTRUST_FILE_INFO fileInfo = { 0 }; if (PhBeginInitOnce(&PhpVerifyInitOnce)) { PhpVerifyInitialization(); PhEndInitOnce(&PhpVerifyInitOnce); } // Make sure we have successfully imported // the required functions. if ( !CryptCATAdminCalcHashFromFileHandle || !CryptCATAdminAcquireContext || !CryptCATAdminEnumCatalogFromHash || !CryptCATCatalogInfoFromContext || !CryptCATAdminReleaseCatalogContext || !CryptCATAdminReleaseContext || !WinVerifyTrust_I || !WTHelperProvDataFromStateData_I || !WTHelperGetProvSignerFromChain_I || !CertNameToStr_I || !CertDuplicateCertificateContext_I || !CertFreeCertificateContext_I ) return STATUS_NOT_SUPPORTED; if (!NT_SUCCESS(status = PhCreateFileWin32( &fileHandle, Information->FileName, FILE_GENERIC_READ, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) return status; fileInfo.cbStruct = sizeof(WINTRUST_FILE_INFO); fileInfo.pcwszFilePath = Information->FileName; fileInfo.hFile = fileHandle; verifyResult = PhpVerifyFile(Information, fileHandle, WTD_CHOICE_FILE, &fileInfo, &WinTrustActionGenericVerifyV2, NULL, &signatures, &numberOfSignatures); if (verifyResult == VrNoSignature) { if (CryptCATAdminAcquireContext2 && CryptCATAdminCalcHashFromFileHandle2) { PhFreeVerifySignatures(signatures, numberOfSignatures); verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, BCRYPT_SHA256_ALGORITHM, &signatures, &numberOfSignatures); } if (verifyResult != VrTrusted) { PhFreeVerifySignatures(signatures, numberOfSignatures); verifyResult = PhpVerifyFileFromCatalog(Information, fileHandle, NULL, &signatures, &numberOfSignatures); } } *VerifyResult = verifyResult; if (Signatures) *Signatures = signatures; else PhFreeVerifySignatures(signatures, numberOfSignatures); if (NumberOfSignatures) *NumberOfSignatures = numberOfSignatures; NtClose(fileHandle); return STATUS_SUCCESS; }
PPH_STRING PhFormatNativeKeyName( __in PPH_STRING Name ) { static PH_STRINGREF hklmPrefix = PH_STRINGREF_INIT(L"\\Registry\\Machine"); static PH_STRINGREF hkcrPrefix = PH_STRINGREF_INIT(L"\\Registry\\Machine\\Software\\Classes"); static PH_STRINGREF hkuPrefix = PH_STRINGREF_INIT(L"\\Registry\\User"); static PPH_STRING hkcuPrefix; static PPH_STRING hkcucrPrefix; static PH_STRINGREF hklmString = PH_STRINGREF_INIT(L"HKLM"); static PH_STRINGREF hkcrString = PH_STRINGREF_INIT(L"HKCR"); static PH_STRINGREF hkuString = PH_STRINGREF_INIT(L"HKU"); static PH_STRINGREF hkcuString = PH_STRINGREF_INIT(L"HKCU"); static PH_STRINGREF hkcucrString = PH_STRINGREF_INIT(L"HKCU\\Software\\Classes"); static PH_INITONCE initOnce = PH_INITONCE_INIT; PPH_STRING newName; PH_STRINGREF name; if (PhBeginInitOnce(&initOnce)) { PTOKEN_USER tokenUser; PPH_STRING stringSid = NULL; if (PhCurrentTokenQueryHandle) { if (NT_SUCCESS(PhGetTokenUser( PhCurrentTokenQueryHandle, &tokenUser ))) { stringSid = PhSidToStringSid(tokenUser->User.Sid); PhFree(tokenUser); } } if (stringSid) { static PH_STRINGREF registryUserPrefix = PH_STRINGREF_INIT(L"\\Registry\\User\\"); static PH_STRINGREF classesString = PH_STRINGREF_INIT(L"_Classes"); hkcuPrefix = PhConcatStringRef2(®istryUserPrefix, &stringSid->sr); hkcucrPrefix = PhConcatStringRef2(&hkcuPrefix->sr, &classesString); PhDereferenceObject(stringSid); } else { hkcuPrefix = PhCreateString(L"..."); // some random string that won't ever get matched hkcucrPrefix = PhCreateString(L"..."); } PhEndInitOnce(&initOnce); } name = Name->sr; if (PhStartsWithStringRef(&name, &hkcrPrefix, TRUE)) { name.Buffer += hkcrPrefix.Length / sizeof(WCHAR); name.Length -= hkcrPrefix.Length; newName = PhConcatStringRef2(&hkcrString, &name); } else if (PhStartsWithStringRef(&name, &hklmPrefix, TRUE)) { name.Buffer += hklmPrefix.Length / sizeof(WCHAR); name.Length -= hklmPrefix.Length; newName = PhConcatStringRef2(&hklmString, &name); } else if (PhStartsWithStringRef(&name, &hkcucrPrefix->sr, TRUE)) { name.Buffer += hkcucrPrefix->Length / sizeof(WCHAR); name.Length -= hkcucrPrefix->Length; newName = PhConcatStringRef2(&hkcucrString, &name); } else if (PhStartsWithStringRef(&name, &hkcuPrefix->sr, TRUE)) { name.Buffer += hkcuPrefix->Length / sizeof(WCHAR); name.Length -= hkcuPrefix->Length; newName = PhConcatStringRef2(&hkcuString, &name); } else if (PhStartsWithStringRef(&name, &hkuPrefix, TRUE)) { name.Buffer += hkuPrefix.Length / sizeof(WCHAR); name.Length -= hkuPrefix.Length; newName = PhConcatStringRef2(&hkuString, &name); } else { newName = Name; PhReferenceObject(Name); } return newName; }
static VOID PhpInitializeServiceNumbers( VOID ) { if (PhBeginInitOnce(&ServiceNumbersInitOnce)) { NTSTATUS status; HANDLE eventHandle; HANDLE threadHandle; HANDLE pipeReadHandle; HANDLE pipeWriteHandle; // The ThreadLastSystemCall info class only works when the thread is in the Waiting // state. We'll create a thread which blocks on an event object we create, then wait // until it is in the Waiting state. Only then can we query the thread using // ThreadLastSystemCall. // NtWaitForSingleObject status = NtCreateEvent(&eventHandle, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); if (NT_SUCCESS(status)) { if (NT_SUCCESS(PhCreateThreadEx(&threadHandle, PhpWfsoThreadStart, eventHandle))) { if (PhpWaitUntilThreadIsWaiting(threadHandle)) { PhpGetThreadLastSystemCallNumber(threadHandle, &NumberForWfso); } // Allow the thread to exit. NtSetEvent(eventHandle, NULL); NtClose(threadHandle); } NtClose(eventHandle); } // NtWaitForMultipleObjects status = NtCreateEvent(&eventHandle, EVENT_ALL_ACCESS, NULL, NotificationEvent, FALSE); if (NT_SUCCESS(status)) { if (NT_SUCCESS(PhCreateThreadEx(&threadHandle, PhpWfmoThreadStart, eventHandle))) { if (PhpWaitUntilThreadIsWaiting(threadHandle)) { PhpGetThreadLastSystemCallNumber(threadHandle, &NumberForWfmo); } NtSetEvent(eventHandle, NULL); NtClose(threadHandle); } NtClose(eventHandle); } // NtReadFile status = PhCreatePipe(&pipeReadHandle, &pipeWriteHandle); if (NT_SUCCESS(status)) { if (NT_SUCCESS(PhCreateThreadEx(&threadHandle, PhpRfThreadStart, pipeReadHandle))) { ULONG data = 0; IO_STATUS_BLOCK isb; if (PhpWaitUntilThreadIsWaiting(threadHandle)) { PhpGetThreadLastSystemCallNumber(threadHandle, &NumberForRf); } NtWriteFile(pipeWriteHandle, NULL, NULL, NULL, &isb, &data, sizeof(data), NULL, NULL); NtClose(threadHandle); } NtClose(pipeReadHandle); NtClose(pipeWriteHandle); } PhEndInitOnce(&ServiceNumbersInitOnce); } }