VOID SetupShowUninstallDialog( VOID ) { PVOID context; TASKDIALOGCONFIG config; PH_AUTO_POOL autoPool; memset(&config, 0, sizeof(TASKDIALOGCONFIG)); PhInitializeAutoPool(&autoPool); context = (PPH_SETUP_CONTEXT)PhCreateAlloc(sizeof(PH_SETUP_CONTEXT)); memset(context, 0, sizeof(PH_SETUP_CONTEXT)); config.cbSize = sizeof(TASKDIALOGCONFIG); config.dwFlags = TDF_POSITION_RELATIVE_TO_WINDOW; config.dwCommonButtons = TDCBF_CANCEL_BUTTON; config.pszWindowTitle = PhApplicationName; config.pfCallback = TaskDialogUninstallBootstrapCallback; config.lpCallbackData = (LONG_PTR)context; TaskDialogIndirect(&config, NULL, NULL, NULL); PhDereferenceObject(context); PhDeleteAutoPool(&autoPool); }
NTSTATUS ShowUpdateDialogThread( _In_ PVOID Parameter ) { PH_AUTO_POOL autoPool; PPH_UPDATER_CONTEXT context; TASKDIALOGCONFIG config = { sizeof(TASKDIALOGCONFIG) }; if (Parameter) context = (PPH_UPDATER_CONTEXT)Parameter; else context = CreateUpdateContext(FALSE); PhInitializeAutoPool(&autoPool); // Start TaskDialog bootstrap config.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION | TDF_CAN_BE_MINIMIZED; config.pszContent = L"Initializing..."; config.lpCallbackData = (LONG_PTR)context; config.pfCallback = TaskDialogBootstrapCallback; TaskDialogIndirect(&config, NULL, NULL, NULL); FreeUpdateContext(context); PhDeleteAutoPool(&autoPool); if (UpdateDialogThreadHandle) { NtClose(UpdateDialogThreadHandle); UpdateDialogThreadHandle = NULL; } PhResetEvent(&InitializedEvent); return STATUS_SUCCESS; }
static NTSTATUS WindowThreadStart( __in PVOID Parameter ) { PH_AUTO_POOL autoPool; BOOL result; MSG message; PhInitializeAutoPool(&autoPool); GfxWindowHandle = CreateDialog( PluginInstance->DllBase, MAKEINTRESOURCE(IDD_SYSGFX), NULL, MainWndProc ); PhSetEvent(&InitializedEvent); while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!IsDialogMessage(GfxWindowHandle, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); PhResetEvent(&InitializedEvent); NtClose(GfxThreadHandle); GfxWindowHandle = NULL; GfxPanelWindowHandle = NULL; GfxThreadHandle = NULL; return STATUS_SUCCESS; }
static NTSTATUS PhNetworkOutputDialogThreadStart( _In_ PVOID Parameter ) { BOOL result; MSG message; HWND windowHandle; PH_AUTO_POOL autoPool; PNETWORK_OUTPUT_CONTEXT context = (PNETWORK_OUTPUT_CONTEXT)Parameter; PhInitializeAutoPool(&autoPool); windowHandle = CreateDialogParam( (HINSTANCE)PluginInstance->DllBase, MAKEINTRESOURCE(IDD_OUTPUT), PhMainWndHandle, NetworkOutputDlgProc, (LPARAM)Parameter ); ShowWindow(windowHandle, SW_SHOW); SetForegroundWindow(windowHandle); while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!IsDialogMessage(context->WindowHandle, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); DestroyWindow(windowHandle); return STATUS_SUCCESS; }
NTSTATUS PhNetworkPingDialogThreadStart( _In_ PVOID Parameter ) { BOOL result; MSG message; HWND windowHandle; PH_AUTO_POOL autoPool; PhInitializeAutoPool(&autoPool); windowHandle = CreateDialogParam( (HINSTANCE)PluginInstance->DllBase, MAKEINTRESOURCE(IDD_PINGDIALOG), NULL, NetworkPingWndProc, (LPARAM)Parameter ); ShowWindow(windowHandle, SW_SHOW); SetForegroundWindow(windowHandle); while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!IsDialogMessage(windowHandle, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); return STATUS_SUCCESS; }
VOID SetupShowUpdateDialog( VOID ) { PVOID context; TASKDIALOGCONFIG config; PH_AUTO_POOL autoPool; memset(&config, 0, sizeof(TASKDIALOGCONFIG)); PhInitializeAutoPool(&autoPool); context = CreateUpdateContext(); config.cbSize = sizeof(TASKDIALOGCONFIG); config.dwFlags = TDF_POSITION_RELATIVE_TO_WINDOW; config.dwCommonButtons = TDCBF_CANCEL_BUTTON; config.pszWindowTitle = PhApplicationName; config.pfCallback = TaskDialogBootstrapCallback; config.lpCallbackData = (LONG_PTR)context; TaskDialogIndirect(&config, NULL, NULL, NULL); PhDeleteAutoPool(&autoPool); }
NTSTATUS PhpWorkQueueThreadStart( _In_ PVOID Parameter ) { PH_AUTO_POOL autoPool; PPH_WORK_QUEUE workQueue = (PPH_WORK_QUEUE)Parameter; PhInitializeAutoPool(&autoPool); while (TRUE) { NTSTATUS status; HANDLE semaphoreHandle; LARGE_INTEGER timeout; PPH_WORK_QUEUE_ITEM workQueueItem = NULL; // Check if we have more threads than the limit. if (workQueue->CurrentThreads > workQueue->MaximumThreads) { BOOLEAN terminate = FALSE; // Lock and re-check. PhAcquireQueuedLockExclusive(&workQueue->StateLock); // Check the minimum as well. if (workQueue->CurrentThreads > workQueue->MaximumThreads && workQueue->CurrentThreads > workQueue->MinimumThreads) { workQueue->CurrentThreads--; terminate = TRUE; } PhReleaseQueuedLockExclusive(&workQueue->StateLock); if (terminate) break; } semaphoreHandle = PhpGetSemaphoreWorkQueue(workQueue); if (!workQueue->Terminating) { // Wait for work. status = NtWaitForSingleObject( semaphoreHandle, FALSE, PhTimeoutFromMilliseconds(&timeout, workQueue->NoWorkTimeout) ); } else { status = STATUS_UNSUCCESSFUL; } if (status == STATUS_WAIT_0 && !workQueue->Terminating) { PLIST_ENTRY listEntry; // Dequeue the work item. PhAcquireQueuedLockExclusive(&workQueue->QueueLock); listEntry = RemoveHeadList(&workQueue->QueueListHead); if (IsListEmpty(&workQueue->QueueListHead)) PhPulseCondition(&workQueue->QueueEmptyCondition); PhReleaseQueuedLockExclusive(&workQueue->QueueLock); // Make sure we got work. if (listEntry != &workQueue->QueueListHead) { workQueueItem = CONTAINING_RECORD(listEntry, PH_WORK_QUEUE_ITEM, ListEntry); PhpExecuteWorkQueueItem(workQueueItem); _InterlockedDecrement(&workQueue->BusyCount); PhpDestroyWorkQueueItem(workQueueItem); } } else { BOOLEAN terminate = FALSE; // No work arrived before the timeout passed, or we are terminating, or some error // occurred. Terminate the thread. PhAcquireQueuedLockExclusive(&workQueue->StateLock); if (workQueue->Terminating || workQueue->CurrentThreads > workQueue->MinimumThreads) { workQueue->CurrentThreads--; terminate = TRUE; } PhReleaseQueuedLockExclusive(&workQueue->StateLock); if (terminate) break; } PhDrainAutoPool(&autoPool); } PhReleaseRundownProtection(&workQueue->RundownProtect); PhDeleteAutoPool(&autoPool); return STATUS_SUCCESS; }
static NTSTATUS ShowUpdateDialogThreadStart( __in PVOID Parameter ) { BOOL result; MSG message; PH_AUTO_POOL autoPool; PhInitializeAutoPool(&autoPool); UpdateDialogHandle = CreateDialog( (HINSTANCE)PluginInstance->DllBase, MAKEINTRESOURCE(IDD_UPDATE), PhMainWndHandle, UpdaterWndProc ); PhSetEvent(&InitializedEvent); while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!IsDialogMessage(UpdateDialogHandle, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); PhResetEvent(&InitializedEvent); // Ensure global objects are disposed and reset when window closes. if (SetupFilePath) { PhDereferenceObject(SetupFilePath); SetupFilePath = NULL; } if (UpdateCheckThreadHandle) { NtClose(UpdateCheckThreadHandle); UpdateCheckThreadHandle = NULL; } if (DownloadThreadHandle) { NtClose(DownloadThreadHandle); DownloadThreadHandle = NULL; } if (UpdaterDialogThreadHandle) { NtClose(UpdaterDialogThreadHandle); UpdaterDialogThreadHandle = NULL; } if (FontHandle) { DeleteObject(FontHandle); FontHandle = NULL; } FreeXmlData(); if (UpdateDialogHandle) { DestroyWindow(UpdateDialogHandle); UpdateDialogHandle = NULL; } return STATUS_SUCCESS; }
NTSTATUS PhSvcApiRequestThreadStart( _In_ PVOID Parameter ) { PH_AUTO_POOL autoPool; NTSTATUS status; PHSVC_THREAD_CONTEXT threadContext; HANDLE portHandle; PVOID portContext; SIZE_T messageSize; PPORT_MESSAGE receiveMessage; PPORT_MESSAGE replyMessage; CSHORT messageType; PPHSVC_CLIENT client; PPHSVC_API_PAYLOAD payload; PhInitializeAutoPool(&autoPool); threadContext.CurrentClient = NULL; threadContext.OldClient = NULL; TlsSetValue(PhSvcApiThreadContextTlsIndex, &threadContext); portHandle = PhSvcApiPortHandle; messageSize = PhIsExecutingInWow64() ? sizeof(PHSVC_API_MSG64) : sizeof(PHSVC_API_MSG); receiveMessage = PhAllocate(messageSize); replyMessage = NULL; while (TRUE) { status = NtReplyWaitReceivePort( portHandle, &portContext, replyMessage, receiveMessage ); portHandle = PhSvcApiPortHandle; replyMessage = NULL; if (!NT_SUCCESS(status)) { // Client probably died. continue; } messageType = receiveMessage->u2.s2.Type; if (messageType == LPC_CONNECTION_REQUEST) { PhSvcHandleConnectionRequest(receiveMessage); continue; } if (!portContext) continue; client = portContext; threadContext.CurrentClient = client; PhWaitForEvent(&client->ReadyEvent, NULL); if (messageType == LPC_REQUEST) { if (PhIsExecutingInWow64()) payload = &((PPHSVC_API_MSG64)receiveMessage)->p; else payload = &((PPHSVC_API_MSG)receiveMessage)->p; PhSvcDispatchApiCall(client, payload, &portHandle); replyMessage = receiveMessage; } else if (messageType == LPC_PORT_CLOSED) { PhDereferenceObject(client); if (_InterlockedDecrement(&PhSvcApiNumberOfClients) == 0) { NtSetEvent(PhSvcTimeoutStandbyEventHandle, NULL); } } assert(!threadContext.OldClient); PhDrainAutoPool(&autoPool); } PhDeleteAutoPool(&autoPool); }
PPH_LIST PhGetGenericTreeNewLines( __in HWND TreeNewHandle, __in ULONG Mode ) { PH_AUTO_POOL autoPool; PPH_LIST lines; ULONG rows; ULONG columns; ULONG numberOfNodes; PULONG displayToId; PWSTR *displayToText; PPH_STRING **table; ULONG i; ULONG j; PhInitializeAutoPool(&autoPool); numberOfNodes = TreeNew_GetFlatNodeCount(TreeNewHandle); rows = numberOfNodes + 1; PhMapDisplayIndexTreeNew(TreeNewHandle, &displayToId, &displayToText, &columns); PhaCreateTextTable(&table, rows, columns); for (i = 0; i < columns; i++) table[0][i] = PhaCreateString(displayToText[i]); for (i = 0; i < numberOfNodes; i++) { PPH_TREENEW_NODE node; node = TreeNew_GetFlatNode(TreeNewHandle, i); if (node) { for (j = 0; j < columns; j++) { PH_TREENEW_GET_CELL_TEXT getCellText; getCellText.Node = node; getCellText.Id = displayToId[j]; PhInitializeEmptyStringRef(&getCellText.Text); TreeNew_GetCellText(TreeNewHandle, &getCellText); table[i + 1][j] = PhaCreateStringEx(getCellText.Text.Buffer, getCellText.Text.Length); } } else { for (j = 0; j < columns; j++) { table[i + 1][j] = PHA_DEREFERENCE(PhReferenceEmptyString()); } } } PhFree(displayToText); PhFree(displayToId); lines = PhaFormatTextTable(table, rows, columns, Mode); PhDeleteAutoPool(&autoPool); return lines; }
NTSTATUS SaveDb( VOID ) { PH_AUTO_POOL autoPool; NTSTATUS status; HANDLE fileHandle; mxml_node_t *topNode; ULONG enumerationKey = 0; PDB_OBJECT *object; PhInitializeAutoPool(&autoPool); topNode = mxmlNewElement(MXML_NO_PARENT, "objects"); LockDb(); while (PhEnumHashtable(ObjectDb, (PVOID*)&object, &enumerationKey)) { CreateObjectElement( topNode, &UInt64ToBase10String((*object)->Tag)->sr, &(*object)->Name->sr, &UInt64ToBase10String((*object)->PriorityClass)->sr, &UInt64ToBase10String((*object)->IoPriorityPlusOne)->sr, &(*object)->Comment->sr, &UInt64ToBase10String((*object)->BackColor)->sr, &UInt64ToBase10String((*object)->Collapse)->sr, &UInt64ToBase10String((*object)->AffinityMask)->sr ); PhDrainAutoPool(&autoPool); } UnlockDb(); // Create the directory if it does not exist. { PPH_STRING fullPath; ULONG indexOfFileName; if (fullPath = PH_AUTO(PhGetFullPath(ObjectDbPath->Buffer, &indexOfFileName))) { if (indexOfFileName != -1) SHCreateDirectoryEx(NULL, PhaSubstring(fullPath, 0, indexOfFileName)->Buffer, NULL); } } PhDeleteAutoPool(&autoPool); status = PhCreateFileWin32( &fileHandle, ObjectDbPath->Buffer, FILE_GENERIC_WRITE, 0, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) { mxmlDelete(topNode); return status; } mxmlSaveFd(topNode, fileHandle, MXML_NO_CALLBACK); mxmlDelete(topNode); NtClose(fileHandle); return STATUS_SUCCESS; }
BOOLEAN PhModalPropertySheet( _Inout_ PROPSHEETHEADER *Header ) { // PropertySheet incorrectly discards WM_QUIT messages in certain cases, so we will use our own // message loop. An example of this is when GetMessage (called by PropertySheet's message loop) // dispatches a message directly from kernel-mode that causes the property sheet to close. // In that case PropertySheet will retrieve the WM_QUIT message but will ignore it because of // its buggy logic. // This is also a good opportunity to introduce an auto-pool. PH_AUTO_POOL autoPool; HWND oldFocus; HWND topLevelOwner; HWND hwnd; BOOL result; MSG message; PhInitializeAutoPool(&autoPool); oldFocus = GetFocus(); topLevelOwner = Header->hwndParent; while (topLevelOwner && (GetWindowLong(topLevelOwner, GWL_STYLE) & WS_CHILD)) topLevelOwner = GetParent(topLevelOwner); if (topLevelOwner && (topLevelOwner == GetDesktopWindow() || EnableWindow(topLevelOwner, FALSE))) topLevelOwner = NULL; Header->dwFlags |= PSH_MODELESS; hwnd = (HWND)PropertySheet(Header); if (!hwnd) { if (topLevelOwner) EnableWindow(topLevelOwner, TRUE); return FALSE; } while (result = GetMessage(&message, NULL, 0, 0)) { if (result == -1) break; if (!PropSheet_IsDialogMessage(hwnd, &message)) { TranslateMessage(&message); DispatchMessage(&message); } PhDrainAutoPool(&autoPool); // Destroy the window when necessary. if (!PropSheet_GetCurrentPageHwnd(hwnd)) break; } if (result == 0) PostQuitMessage((INT)message.wParam); if (Header->hwndParent && GetActiveWindow() == hwnd) SetActiveWindow(Header->hwndParent); if (topLevelOwner) EnableWindow(topLevelOwner, TRUE); if (oldFocus && IsWindow(oldFocus)) SetFocus(oldFocus); DestroyWindow(hwnd); PhDeleteAutoPool(&autoPool); return TRUE; }
static NTSTATUS PhpRefreshThreadStackThreadStart( _In_ PVOID Parameter ) { PH_AUTO_POOL autoPool; NTSTATUS status; PTHREAD_STACK_CONTEXT threadStackContext = Parameter; CLIENT_ID clientId; BOOLEAN defaultWalk; PhInitializeAutoPool(&autoPool); PhLoadSymbolsThreadProvider(threadStackContext->ThreadProvider); clientId.UniqueProcess = threadStackContext->ProcessId; clientId.UniqueThread = threadStackContext->ThreadId; defaultWalk = TRUE; if (threadStackContext->CustomWalk) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.Type = PluginThreadStackWalkStack; control.UniqueKey = threadStackContext; control.u.WalkStack.Status = STATUS_UNSUCCESSFUL; control.u.WalkStack.ThreadHandle = threadStackContext->ThreadHandle; control.u.WalkStack.ProcessHandle = threadStackContext->SymbolProvider->ProcessHandle; control.u.WalkStack.ClientId = &clientId; control.u.WalkStack.Flags = PH_WALK_I386_STACK | PH_WALK_AMD64_STACK | PH_WALK_KERNEL_STACK; control.u.WalkStack.Callback = PhpWalkThreadStackCallback; control.u.WalkStack.CallbackContext = threadStackContext; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); status = control.u.WalkStack.Status; if (NT_SUCCESS(status)) defaultWalk = FALSE; } if (defaultWalk) { PH_PLUGIN_THREAD_STACK_CONTROL control; control.UniqueKey = threadStackContext; if (PhPluginsEnabled) { control.Type = PluginThreadStackBeginDefaultWalkStack; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); } status = PhWalkThreadStack( threadStackContext->ThreadHandle, threadStackContext->SymbolProvider->ProcessHandle, &clientId, threadStackContext->SymbolProvider, PH_WALK_I386_STACK | PH_WALK_AMD64_STACK | PH_WALK_KERNEL_STACK, PhpWalkThreadStackCallback, threadStackContext ); if (PhPluginsEnabled) { control.Type = PluginThreadStackEndDefaultWalkStack; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackThreadStackControl), &control); } } if (threadStackContext->NewList->Count != 0) status = STATUS_SUCCESS; threadStackContext->WalkStatus = status; PostMessage(threadStackContext->ProgressWindowHandle, WM_PH_COMPLETED, 0, 0); PhDeleteAutoPool(&autoPool); return STATUS_SUCCESS; }