static VOID PhpAnalyzeWaitFallbacks( _In_ PANALYZE_WAIT_CONTEXT Context ) { PPH_STRING info; // We didn't detect NtUserMessageCall, but this may still apply due to another // win32k system call (e.g. from EnableWindow). if (!Context->Found && (info = PhpaGetSendMessageReceiver(Context->ThreadId))) { PhAppendStringBuilder2( &Context->StringBuilder, L"Thread is sending a USER message:\r\n" ); PhAppendStringBuilder(&Context->StringBuilder, &info->sr); PhAppendStringBuilder2(&Context->StringBuilder, L"\r\n"); Context->Found = TRUE; } // Nt(Alpc)ConnectPort doesn't get detected anywhere else. if (!Context->Found && (info = PhpaGetAlpcInformation(Context->ThreadId))) { PhAppendStringBuilder2( &Context->StringBuilder, L"Thread is waiting for an ALPC port:\r\n" ); PhAppendStringBuilder(&Context->StringBuilder, &info->sr); PhAppendStringBuilder2(&Context->StringBuilder, L"\r\n"); Context->Found = TRUE; } }
PPH_STRING FlagsToString( __in ULONG Flags, __in PFLAG_DEFINITION Map, __in ULONG SizeOfMap ) { PH_STRING_BUILDER sb; ULONG i; PhInitializeStringBuilder(&sb, 100); for (i = 0; i < SizeOfMap / sizeof(FLAG_DEFINITION); i++) { if (Flags & Map[i].Flag) { PhAppendStringBuilder2(&sb, Map[i].Name); PhAppendStringBuilder2(&sb, L", "); } } if (sb.String->Length != 0) PhRemoveStringBuilder(&sb, sb.String->Length / 2 - 2, 2); return PhFinalStringBuilderString(&sb); }
/** * Creates a string representation of an access mask. * * \param Access The access mask. * \param AccessEntries An array of access entry structures. You can * call PhGetAccessEntries() to retrieve the access entry structures * for a standard object type. * \param NumberOfAccessEntries The number of elements in \a AccessEntries. * * \return The string representation of \a Access. */ PPH_STRING PhGetAccessString( _In_ ACCESS_MASK Access, _In_ PPH_ACCESS_ENTRY AccessEntries, _In_ ULONG NumberOfAccessEntries ) { PH_STRING_BUILDER stringBuilder; PPH_ACCESS_ENTRY accessEntries; PBOOLEAN matched; ULONG i; ULONG j; PhInitializeStringBuilder(&stringBuilder, 32); // Sort the access entries according to how many access rights they // include. accessEntries = PhAllocateCopy(AccessEntries, NumberOfAccessEntries * sizeof(PH_ACCESS_ENTRY)); qsort(accessEntries, NumberOfAccessEntries, sizeof(PH_ACCESS_ENTRY), PhpAccessEntryCompare); matched = PhAllocate(NumberOfAccessEntries * sizeof(BOOLEAN)); memset(matched, 0, NumberOfAccessEntries * sizeof(BOOLEAN)); for (i = 0; i < NumberOfAccessEntries; i++) { // We make sure we haven't matched this access entry yet. // This ensures that we won't get duplicates, e.g. // FILE_GENERIC_READ includes FILE_READ_DATA, and we // don't want to display both to the user. if ( !matched[i] && ((Access & accessEntries[i].Access) == accessEntries[i].Access) ) { if (accessEntries[i].ShortName) PhAppendStringBuilder2(&stringBuilder, accessEntries[i].ShortName); else PhAppendStringBuilder2(&stringBuilder, accessEntries[i].Name); PhAppendStringBuilder2(&stringBuilder, L", "); // Disable equal or more specific entries. for (j = i; j < NumberOfAccessEntries; j++) { if ((accessEntries[i].Access | accessEntries[j].Access) == accessEntries[i].Access) matched[j] = TRUE; } } } // Remove the trailing ", ". if (PhEndsWithString2(stringBuilder.String, L", ", FALSE)) PhRemoveEndStringBuilder(&stringBuilder, 2); PhFree(matched); PhFree(accessEntries); return PhFinalStringBuilderString(&stringBuilder); }
static PPH_STRING PhpGetStringForSelectedLogEntries( __in BOOLEAN All ) { PH_STRING_BUILDER stringBuilder; ULONG i; if (ListViewCount == 0) return PhReferenceEmptyString(); PhInitializeStringBuilder(&stringBuilder, 0x100); i = ListViewCount - 1; while (TRUE) { PPH_LOG_ENTRY entry; SYSTEMTIME systemTime; PPH_STRING temp; if (!All) { // The list view displays the items in reverse order... if (!(ListView_GetItemState(ListViewHandle, ListViewCount - i - 1, LVIS_SELECTED) & LVIS_SELECTED)) { goto ContinueLoop; } } entry = PhGetItemCircularBuffer_PVOID(&PhLogBuffer, i); if (!entry) goto ContinueLoop; PhLargeIntegerToLocalSystemTime(&systemTime, &entry->Time); temp = PhFormatDateTime(&systemTime); PhAppendStringBuilder(&stringBuilder, temp); PhDereferenceObject(temp); PhAppendStringBuilder2(&stringBuilder, L": "); temp = PhFormatLogEntry(entry); PhAppendStringBuilder(&stringBuilder, temp); PhDereferenceObject(temp); PhAppendStringBuilder2(&stringBuilder, L"\r\n"); ContinueLoop: if (i == 0) break; i--; } return PhFinalStringBuilderString(&stringBuilder); }
PPH_STRING PhGetTreeNewText( __in HWND TreeNewHandle, __reserved ULONG Reserved ) { PH_STRING_BUILDER stringBuilder; PULONG displayToId; ULONG rows; ULONG columns; ULONG i; ULONG j; PhMapDisplayIndexTreeNew(TreeNewHandle, &displayToId, NULL, &columns); rows = TreeNew_GetFlatNodeCount(TreeNewHandle); PhInitializeStringBuilder(&stringBuilder, 0x100); for (i = 0; i < rows; i++) { PH_TREENEW_GET_CELL_TEXT getCellText; getCellText.Node = TreeNew_GetFlatNode(TreeNewHandle, i); assert(getCellText.Node); if (!getCellText.Node->Selected) continue; for (j = 0; j < columns; j++) { getCellText.Id = displayToId[j]; PhInitializeEmptyStringRef(&getCellText.Text); TreeNew_GetCellText(TreeNewHandle, &getCellText); PhAppendStringBuilderEx(&stringBuilder, getCellText.Text.Buffer, getCellText.Text.Length); PhAppendStringBuilder2(&stringBuilder, L", "); } // Remove the trailing comma and space. if (stringBuilder.String->Length != 0) PhRemoveStringBuilder(&stringBuilder, stringBuilder.String->Length / 2 - 2, 2); PhAppendStringBuilder2(&stringBuilder, L"\r\n"); } PhFree(displayToId); return PhFinalStringBuilderString(&stringBuilder); }
VOID PhpEscapeStringForCsv( __inout PPH_STRING_BUILDER StringBuilder, __in PPH_STRING String ) { SIZE_T i; SIZE_T length; PWCHAR runStart; ULONG runLength; length = String->Length / sizeof(WCHAR); runStart = NULL; for (i = 0; i < length; i++) { switch (String->Buffer[i]) { case '\"': if (runStart) { PhAppendStringBuilderEx(StringBuilder, runStart, runLength * sizeof(WCHAR)); runStart = NULL; } PhAppendStringBuilder2(StringBuilder, L"\"\""); break; default: if (runStart) { runLength++; } else { runStart = &String->Buffer[i]; runLength = 1; } break; } } if (runStart) PhAppendStringBuilderEx(StringBuilder, runStart, runLength * sizeof(WCHAR)); }
PPH_STRING EtpGetGpuNameString( VOID ) { ULONG i; ULONG count; PH_STRING_BUILDER sb; count = EtGetGpuAdapterCount(); PhInitializeStringBuilder(&sb, 100); for (i = 0; i < count; i++) { PPH_STRING description; description = EtGetGpuAdapterDescription(i); if (!PhIsNullOrEmptyString(description)) { // Ignore "Microsoft Basic Render Driver" unless we don't have any other adapters. // This does not take into account localization. if (count == 1 || !PhEqualString2(description, L"Microsoft Basic Render Driver", TRUE)) { PhAppendStringBuilder(&sb, &description->sr); PhAppendStringBuilder2(&sb, L", "); } } if (description) PhDereferenceObject(description); } if (sb.String->Length != 0) PhRemoveEndStringBuilder(&sb, 2); return PhFinalStringBuilderString(&sb); }
INT_PTR CALLBACK PhpChoiceDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PCHOICE_DIALOG_CONTEXT context = (PCHOICE_DIALOG_CONTEXT)lParam; ULONG type; SIZE_T i; HWND comboBoxHandle; HWND checkBoxHandle; RECT checkBoxRect; RECT rect; ULONG diff; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); SetWindowText(hwndDlg, context->Title); SetWindowText(GetDlgItem(hwndDlg, IDC_MESSAGE), context->Message); type = context->Flags & PH_CHOICE_DIALOG_TYPE_MASK; // Select the control to show, depending on the type. This is // because it is impossible to change the style of the combo box // after it is created. switch (type) { case PH_CHOICE_DIALOG_USER_CHOICE: comboBoxHandle = GetDlgItem(hwndDlg, IDC_CHOICEUSER); ShowWindow(GetDlgItem(hwndDlg, IDC_CHOICEUSER), SW_SHOW); break; case PH_CHOICE_DIALOG_PASSWORD: comboBoxHandle = GetDlgItem(hwndDlg, IDC_CHOICESIMPLE); ShowWindow(GetDlgItem(hwndDlg, IDC_CHOICESIMPLE), SW_SHOW); // Disable combo box features since it isn't a combo box. context->SavedChoicesSettingName = NULL; break; case PH_CHOICE_DIALOG_CHOICE: default: comboBoxHandle = GetDlgItem(hwndDlg, IDC_CHOICE); ShowWindow(GetDlgItem(hwndDlg, IDC_CHOICE), SW_SHOW); break; } context->ComboBoxHandle = comboBoxHandle; checkBoxHandle = GetDlgItem(hwndDlg, IDC_OPTION); if (type == PH_CHOICE_DIALOG_PASSWORD) { // Nothing } else if (type == PH_CHOICE_DIALOG_USER_CHOICE && context->SavedChoicesSettingName) { PPH_STRING savedChoices = PhGetStringSetting(context->SavedChoicesSettingName); ULONG_PTR indexOfDelim; PPH_STRING savedChoice; i = 0; // Split the saved choices using the delimiter. while (i < savedChoices->Length / 2) { // BUG BUG BUG - what if the user saves "\s"? indexOfDelim = PhFindStringInString(savedChoices, i, L"\\s"); if (indexOfDelim == -1) indexOfDelim = savedChoices->Length / 2; savedChoice = PhSubstring(savedChoices, i, indexOfDelim - i); if (savedChoice->Length != 0) { PPH_STRING unescaped; unescaped = PhUnescapeStringForDelimiter(savedChoice, '\\'); ComboBox_InsertString(comboBoxHandle, -1, unescaped->Buffer); PhDereferenceObject(unescaped); } PhDereferenceObject(savedChoice); i = indexOfDelim + 2; } PhDereferenceObject(savedChoices); } else { for (i = 0; i < context->NumberOfChoices; i++) { ComboBox_AddString(comboBoxHandle, context->Choices[i]); } context->SavedChoicesSettingName = NULL; // make sure we don't try to save the choices } if (type == PH_CHOICE_DIALOG_PASSWORD) { if (*context->SelectedChoice) SetWindowText(comboBoxHandle, (*context->SelectedChoice)->Buffer); Edit_SetSel(comboBoxHandle, 0, -1); } else if (type == PH_CHOICE_DIALOG_USER_CHOICE || type == PH_CHOICE_DIALOG_CHOICE) { // If we failed to choose a default choice based on what was specified, // select the first one if possible, or set the text directly. if (!(*context->SelectedChoice) || PhSelectComboBoxString( comboBoxHandle, (*context->SelectedChoice)->Buffer, FALSE) == CB_ERR) { if (type == PH_CHOICE_DIALOG_USER_CHOICE && *context->SelectedChoice) { SetWindowText(comboBoxHandle, (*context->SelectedChoice)->Buffer); } else if (type == PH_CHOICE_DIALOG_CHOICE && context->NumberOfChoices != 0) { ComboBox_SetCurSel(comboBoxHandle, 0); } } if (type == PH_CHOICE_DIALOG_USER_CHOICE) ComboBox_SetEditSel(comboBoxHandle, 0, -1); } if (context->Option) { SetWindowText(checkBoxHandle, context->Option); if (context->SelectedOption) Button_SetCheck(checkBoxHandle, *context->SelectedOption ? BST_CHECKED : BST_UNCHECKED); } else { // Hide the check box and move the buttons up. ShowWindow(checkBoxHandle, SW_HIDE); GetWindowRect(checkBoxHandle, &checkBoxRect); MapWindowPoints(NULL, hwndDlg, (POINT *)&checkBoxRect, 2); GetWindowRect(GetDlgItem(hwndDlg, IDOK), &rect); MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2); diff = rect.top - checkBoxRect.top; // OK rect.top -= diff; rect.bottom -= diff; SetWindowPos(GetDlgItem(hwndDlg, IDOK), NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOZORDER); // Cancel GetWindowRect(GetDlgItem(hwndDlg, IDCANCEL), &rect); MapWindowPoints(NULL, hwndDlg, (POINT *)&rect, 2); rect.top -= diff; rect.bottom -= diff; SetWindowPos(GetDlgItem(hwndDlg, IDCANCEL), NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOZORDER); // Window GetWindowRect(hwndDlg, &rect); rect.bottom -= diff; SetWindowPos(hwndDlg, NULL, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOZORDER); } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)comboBoxHandle, TRUE); } break; case WM_DESTROY: { RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { PCHOICE_DIALOG_CONTEXT context = (PCHOICE_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); PPH_STRING selectedChoice; if ((context->Flags & PH_CHOICE_DIALOG_TYPE_MASK) != PH_CHOICE_DIALOG_PASSWORD) { selectedChoice = PH_AUTO(PhGetWindowText(context->ComboBoxHandle)); *context->SelectedChoice = selectedChoice; } else { // Password values are never auto-dereferenced. selectedChoice = PhGetWindowText(context->ComboBoxHandle); *context->SelectedChoice = selectedChoice; } if (context->Option && context->SelectedOption) *context->SelectedOption = Button_GetCheck(GetDlgItem(hwndDlg, IDC_OPTION)) == BST_CHECKED; if (context->SavedChoicesSettingName) { PH_STRING_BUILDER savedChoices; ULONG i; ULONG choicesToSave = PH_CHOICE_DIALOG_SAVED_CHOICES; PPH_STRING choice; PPH_STRING escaped; PhInitializeStringBuilder(&savedChoices, 100); // Push the selected choice to the top, then save the others. if (selectedChoice->Length != 0) { escaped = PhEscapeStringForDelimiter(selectedChoice, '\\'); PhAppendStringBuilder(&savedChoices, &escaped->sr); PhDereferenceObject(escaped); PhAppendStringBuilder2(&savedChoices, L"\\s"); } for (i = 1; i < choicesToSave; i++) { choice = PhGetComboBoxString(context->ComboBoxHandle, i - 1); if (!choice) break; // Don't save the choice if it's the same as the one // entered by the user (since we already saved it above). if (PhEqualString(choice, selectedChoice, FALSE)) { PhDereferenceObject(choice); choicesToSave++; // useless for now, but may be needed in the future continue; } escaped = PhEscapeStringForDelimiter(choice, '\\'); PhAppendStringBuilder(&savedChoices, &escaped->sr); PhDereferenceObject(escaped); PhDereferenceObject(choice); PhAppendStringBuilder2(&savedChoices, L"\\s"); } if (PhEndsWithString2(savedChoices.String, L"\\s", FALSE)) PhRemoveEndStringBuilder(&savedChoices, 2); PhSetStringSetting2(context->SavedChoicesSettingName, &savedChoices.String->sr); PhDeleteStringBuilder(&savedChoices); } EndDialog(hwndDlg, IDOK); } break; } } break; } return FALSE; }
PPH_STRING PhGetProcessTooltipText( __in PPH_PROCESS_ITEM Process ) { PH_STRING_BUILDER stringBuilder; PPH_STRING tempString; PhInitializeStringBuilder(&stringBuilder, 200); // Command line if (Process->CommandLine) { PhAppendStringBuilder(&stringBuilder, Process->CommandLine); PhAppendCharStringBuilder(&stringBuilder, '\n'); } // File information tempString = PhFormatImageVersionInfo( Process->FileName, &Process->VersionInfo, L" ", 0 ); if (!PhIsNullOrEmptyString(tempString)) { PhAppendStringBuilder2(&stringBuilder, L"File:\n"); PhAppendStringBuilder(&stringBuilder, tempString); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (tempString) PhDereferenceObject(tempString); // Known command line information if (Process->CommandLine && Process->QueryHandle) { PH_KNOWN_PROCESS_TYPE knownProcessType; PH_KNOWN_PROCESS_COMMAND_LINE knownCommandLine; if (NT_SUCCESS(PhGetProcessKnownType( Process->QueryHandle, &knownProcessType )) && PhaGetProcessKnownCommandLine( Process->CommandLine, knownProcessType, &knownCommandLine )) { switch (knownProcessType & KnownProcessTypeMask) { case ServiceHostProcessType: PhAppendStringBuilder2(&stringBuilder, L"Service group name:\n "); PhAppendStringBuilder(&stringBuilder, knownCommandLine.ServiceHost.GroupName); PhAppendCharStringBuilder(&stringBuilder, '\n'); break; case RunDllAsAppProcessType: { PH_IMAGE_VERSION_INFO versionInfo; if (PhInitializeImageVersionInfo( &versionInfo, knownCommandLine.RunDllAsApp.FileName->Buffer )) { tempString = PhFormatImageVersionInfo( knownCommandLine.RunDllAsApp.FileName, &versionInfo, L" ", 0 ); if (!PhIsNullOrEmptyString(tempString)) { PhAppendStringBuilder2(&stringBuilder, L"Run DLL target file:\n"); PhAppendStringBuilder(&stringBuilder, tempString); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (tempString) PhDereferenceObject(tempString); PhDeleteImageVersionInfo(&versionInfo); } } break; case ComSurrogateProcessType: { PH_IMAGE_VERSION_INFO versionInfo; PPH_STRING guidString; PhAppendStringBuilder2(&stringBuilder, L"COM target:\n"); if (knownCommandLine.ComSurrogate.Name) { PhAppendStringBuilder2(&stringBuilder, L" "); PhAppendStringBuilder(&stringBuilder, knownCommandLine.ComSurrogate.Name); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (guidString = PhFormatGuid(&knownCommandLine.ComSurrogate.Guid)) { PhAppendStringBuilder2(&stringBuilder, L" "); PhAppendStringBuilder(&stringBuilder, guidString); PhDereferenceObject(guidString); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (knownCommandLine.ComSurrogate.FileName && PhInitializeImageVersionInfo( &versionInfo, knownCommandLine.ComSurrogate.FileName->Buffer )) { tempString = PhFormatImageVersionInfo( knownCommandLine.ComSurrogate.FileName, &versionInfo, L" ", 0 ); if (!PhIsNullOrEmptyString(tempString)) { PhAppendStringBuilder2(&stringBuilder, L"COM target file:\n"); PhAppendStringBuilder(&stringBuilder, tempString); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (tempString) PhDereferenceObject(tempString); PhDeleteImageVersionInfo(&versionInfo); } } break; } } } // Services if (Process->ServiceList && Process->ServiceList->Count != 0) { ULONG enumerationKey = 0; PPH_SERVICE_ITEM serviceItem; PPH_LIST serviceList; ULONG i; // Copy the service list into our own list so we can sort it. serviceList = PhCreateList(Process->ServiceList->Count); PhAcquireQueuedLockShared(&Process->ServiceListLock); while (PhEnumPointerList( Process->ServiceList, &enumerationKey, &serviceItem )) { PhReferenceObject(serviceItem); PhAddItemList(serviceList, serviceItem); } PhReleaseQueuedLockShared(&Process->ServiceListLock); qsort(serviceList->Items, serviceList->Count, sizeof(PPH_SERVICE_ITEM), ServiceForTooltipCompare); PhAppendStringBuilder2(&stringBuilder, L"Services:\n"); // Add the services. for (i = 0; i < serviceList->Count; i++) { serviceItem = serviceList->Items[i]; PhAppendStringBuilder2(&stringBuilder, L" "); PhAppendStringBuilder(&stringBuilder, serviceItem->Name); PhAppendStringBuilder2(&stringBuilder, L" ("); PhAppendStringBuilder(&stringBuilder, serviceItem->DisplayName); PhAppendStringBuilder2(&stringBuilder, L")\n"); } PhDereferenceObjects(serviceList->Items, serviceList->Count); PhDereferenceObject(serviceList); } // Tasks if (PhEqualString2(Process->ProcessName, L"taskeng.exe", TRUE) || PhEqualString2(Process->ProcessName, L"taskhost.exe", TRUE)) { PH_STRING_BUILDER tasks; PhInitializeStringBuilder(&tasks, 40); PhpFillRunningTasks(Process, &tasks); if (tasks.String->Length != 0) { PhAppendStringBuilder2(&stringBuilder, L"Tasks:\n"); PhAppendStringBuilder(&stringBuilder, tasks.String); } PhDeleteStringBuilder(&tasks); } // Plugin if (PhPluginsEnabled) { PH_PLUGIN_GET_TOOLTIP_TEXT getTooltipText; getTooltipText.Parameter = Process; getTooltipText.StringBuilder = &stringBuilder; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackGetProcessTooltipText), &getTooltipText); } // Notes { PH_STRING_BUILDER notes; PhInitializeStringBuilder(¬es, 40); if (Process->FileName) { if (Process->VerifyResult == VrTrusted) { if (!PhIsNullOrEmptyString(Process->VerifySignerName)) PhAppendFormatStringBuilder(¬es, L" Signer: %s\n", Process->VerifySignerName->Buffer); else PhAppendStringBuilder2(¬es, L" Signed.\n"); } else if (Process->VerifyResult == VrUnknown) { // Nothing } else if (Process->VerifyResult != VrNoSignature) { PhAppendStringBuilder2(¬es, L" Signature invalid.\n"); } } if (Process->IsPacked) { PhAppendFormatStringBuilder( ¬es, L" Image is probably packed (%u imports over %u modules).\n", Process->ImportFunctions, Process->ImportModules ); } if (Process->ConsoleHostProcessId) { CLIENT_ID clientId; PPH_STRING clientIdString; clientId.UniqueProcess = Process->ConsoleHostProcessId; clientId.UniqueThread = NULL; clientIdString = PhGetClientIdName(&clientId); PhAppendFormatStringBuilder(¬es, L" Console host: %s\n", clientIdString->Buffer); PhDereferenceObject(clientIdString); } if (Process->IsDotNet) PhAppendStringBuilder2(¬es, L" Process is managed (.NET).\n"); if (Process->IsElevated) PhAppendStringBuilder2(¬es, L" Process is elevated.\n"); if (Process->IsInJob) PhAppendStringBuilder2(¬es, L" Process is in a job.\n"); if (Process->IsPosix) PhAppendStringBuilder2(¬es, L" Process is POSIX.\n"); if (Process->IsWow64) PhAppendStringBuilder2(¬es, L" Process is 32-bit (WOW64).\n"); if (notes.String->Length != 0) { PhAppendStringBuilder2(&stringBuilder, L"Notes:\n"); PhAppendStringBuilder(&stringBuilder, notes.String); } PhDeleteStringBuilder(¬es); } // Remove the trailing newline. if (stringBuilder.String->Length != 0) PhRemoveStringBuilder(&stringBuilder, stringBuilder.String->Length / 2 - 1, 1); return PhFinalStringBuilderString(&stringBuilder); }
VOID PhpFillRunningTasks( __in PPH_PROCESS_ITEM Process, __inout PPH_STRING_BUILDER Tasks ) { static CLSID CLSID_TaskScheduler_I = { 0x0f87369f, 0xa4e5, 0x4cfc, { 0xbd, 0x3e, 0x73, 0xe6, 0x15, 0x45, 0x72, 0xdd } }; static IID IID_ITaskService_I = { 0x2faba4c7, 0x4da9, 0x4013, { 0x96, 0x97, 0x20, 0xcc, 0x3f, 0xd4, 0x0f, 0x85 } }; ITaskService *taskService; if (SUCCEEDED(CoCreateInstance( &CLSID_TaskScheduler_I, NULL, CLSCTX_INPROC_SERVER, &IID_ITaskService_I, &taskService ))) { VARIANT empty = { 0 }; if (SUCCEEDED(ITaskService_Connect(taskService, empty, empty, empty, empty))) { IRunningTaskCollection *runningTasks; if (SUCCEEDED(ITaskService_GetRunningTasks( taskService, TASK_ENUM_HIDDEN, &runningTasks ))) { LONG count; LONG i; VARIANT index; index.vt = VT_INT; if (SUCCEEDED(IRunningTaskCollection_get_Count(runningTasks, &count))) { for (i = 1; i <= count; i++) // collections are 1-based { IRunningTask *runningTask; index.lVal = i; if (SUCCEEDED(IRunningTaskCollection_get_Item(runningTasks, index, &runningTask))) { ULONG pid; BSTR action = NULL; BSTR path = NULL; if ( SUCCEEDED(IRunningTask_get_EnginePID(runningTask, &pid)) && pid == (ULONG)Process->ProcessId ) { IRunningTask_get_CurrentAction(runningTask, &action); IRunningTask_get_Path(runningTask, &path); PhAppendStringBuilder2(Tasks, L" "); PhAppendStringBuilder2(Tasks, action ? action : L"Unknown Action"); PhAppendStringBuilder2(Tasks, L" ("); PhAppendStringBuilder2(Tasks, path ? path : L"Unknown Path"); PhAppendStringBuilder2(Tasks, L")\n"); if (action) SysFreeString(action); if (path) SysFreeString(path); } IRunningTask_Release(runningTask); } } } IRunningTaskCollection_Release(runningTasks); } } ITaskService_Release(taskService); } }
BOOLEAN PhShellProcessHacker( __in HWND hWnd, __in_opt PWSTR Parameters, __in ULONG ShowWindowType, __in ULONG Flags, __in ULONG AppFlags, __in_opt ULONG Timeout, __out_opt PHANDLE ProcessHandle ) { BOOLEAN result; PH_STRING_BUILDER sb; PWSTR parameters; PPH_STRING temp; if (AppFlags & PH_SHELL_APP_PROPAGATE_PARAMETERS) { PhInitializeStringBuilder(&sb, 128); if (Parameters) PhAppendStringBuilder2(&sb, Parameters); // Propagate parameters. if (PhStartupParameters.NoSettings) { PhAppendStringBuilder2(&sb, L" -nosettings"); } else if (PhStartupParameters.SettingsFileName && PhSettingsFileName) { PhAppendStringBuilder2(&sb, L" -settings \""); temp = PhEscapeCommandLinePart(&PhSettingsFileName->sr); PhAppendStringBuilder(&sb, temp); PhDereferenceObject(temp); PhAppendCharStringBuilder(&sb, '\"'); } if (PhStartupParameters.NoKph) { PhAppendStringBuilder2(&sb, L" -nokph"); } if (PhStartupParameters.NoPlugins) { PhAppendStringBuilder2(&sb, L" -noplugins"); } if (PhStartupParameters.NewInstance) { PhAppendStringBuilder2(&sb, L" -newinstance"); } if (!(AppFlags & PH_SHELL_APP_PROPAGATE_PARAMETERS_IGNORE_VISIBILITY)) { if (PhStartupParameters.ShowVisible) { PhAppendStringBuilder2(&sb, L" -v"); } if (PhStartupParameters.ShowHidden) { PhAppendStringBuilder2(&sb, L" -hide"); } } parameters = sb.String->Buffer; } else { parameters = Parameters; } result = PhShellExecuteEx( hWnd, PhApplicationFileName->Buffer, parameters, ShowWindowType, Flags, Timeout, ProcessHandle ); if (AppFlags & PH_SHELL_APP_PROPAGATE_PARAMETERS) PhDeleteStringBuilder(&sb); return result; }
VOID PhpAnalyzeWaitPassive( _In_ HWND hWnd, _In_ HANDLE ProcessId, _In_ HANDLE ThreadId ) { NTSTATUS status; HANDLE processHandle; HANDLE threadHandle; THREAD_LAST_SYSCALL_INFORMATION lastSystemCall; PH_STRING_BUILDER stringBuilder; PPH_STRING string; PhpInitializeServiceNumbers(); if (!NT_SUCCESS(status = PhOpenThread(&threadHandle, THREAD_GET_CONTEXT, ThreadId))) { PhShowStatus(hWnd, L"Unable to open the thread.", status, 0); return; } if (!NT_SUCCESS(status = PhGetThreadLastSystemCall(threadHandle, &lastSystemCall))) { NtClose(threadHandle); PhShowStatus(hWnd, L"Unable to determine whether the thread is waiting.", status, 0); return; } if (!NT_SUCCESS(status = PhOpenProcess(&processHandle, PROCESS_DUP_HANDLE, ProcessId))) { NtClose(threadHandle); PhShowStatus(hWnd, L"Unable to open the process.", status, 0); return; } PhInitializeStringBuilder(&stringBuilder, 100); if (lastSystemCall.SystemCallNumber == NumberForWfso) { string = PhpaGetHandleString(processHandle, lastSystemCall.FirstArgument); PhAppendFormatStringBuilder(&stringBuilder, L"Thread is waiting for:\r\n"); PhAppendStringBuilder(&stringBuilder, &string->sr); } else if (lastSystemCall.SystemCallNumber == NumberForWfmo) { PhAppendFormatStringBuilder(&stringBuilder, L"Thread is waiting for multiple (%lu) objects.", PtrToUlong(lastSystemCall.FirstArgument)); } else if (lastSystemCall.SystemCallNumber == NumberForRf) { string = PhpaGetHandleString(processHandle, lastSystemCall.FirstArgument); PhAppendFormatStringBuilder(&stringBuilder, L"Thread is waiting for file I/O:\r\n"); PhAppendStringBuilder(&stringBuilder, &string->sr); } else { string = PhpaGetSendMessageReceiver(ThreadId); if (string) { PhAppendStringBuilder2(&stringBuilder, L"Thread is sending a USER message:\r\n"); PhAppendStringBuilder(&stringBuilder, &string->sr); } else { string = PhpaGetAlpcInformation(ThreadId); if (string) { PhAppendStringBuilder2(&stringBuilder, L"Thread is waiting for an ALPC port:\r\n"); PhAppendStringBuilder(&stringBuilder, &string->sr); } } } if (stringBuilder.String->Length == 0) PhAppendStringBuilder2(&stringBuilder, L"Unable to determine why the thread is waiting."); PhShowInformationDialog(hWnd, stringBuilder.String->Buffer, 0); PhDeleteStringBuilder(&stringBuilder); NtClose(processHandle); NtClose(threadHandle); }
PPH_STRING PhGetProcessTooltipText( _In_ PPH_PROCESS_ITEM Process, _Out_opt_ PULONG ValidToTickCount ) { PH_STRING_BUILDER stringBuilder; ULONG validForMs = 60 * 60 * 1000; // 1 hour PPH_STRING tempString; PH_KNOWN_PROCESS_TYPE knownProcessType = UnknownProcessType; PhInitializeStringBuilder(&stringBuilder, 200); // Command line if (Process->CommandLine) { tempString = PhEllipsisString(Process->CommandLine, 100 * 10); // This is necessary because the tooltip control seems to use some kind of O(n^9999) word-wrapping // algorithm. PhpAppendStringWithLineBreaks(&stringBuilder, &tempString->sr, 100, NULL); PhAppendCharStringBuilder(&stringBuilder, '\n'); PhDereferenceObject(tempString); } // File information tempString = PhFormatImageVersionInfo( Process->FileName, &Process->VersionInfo, &StandardIndent, 0 ); if (!PhIsNullOrEmptyString(tempString)) { PhAppendStringBuilder2(&stringBuilder, L"File:\n"); PhAppendStringBuilder(&stringBuilder, &tempString->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (tempString) PhDereferenceObject(tempString); // Known command line information if (Process->QueryHandle) PhGetProcessKnownType(Process->QueryHandle, &knownProcessType); if (Process->CommandLine && Process->QueryHandle) { PH_KNOWN_PROCESS_COMMAND_LINE knownCommandLine; if (knownProcessType != UnknownProcessType && PhaGetProcessKnownCommandLine( Process->CommandLine, knownProcessType, &knownCommandLine )) { switch (knownProcessType & KnownProcessTypeMask) { case ServiceHostProcessType: PhAppendStringBuilder2(&stringBuilder, L"Service group name:\n "); PhAppendStringBuilder(&stringBuilder, &knownCommandLine.ServiceHost.GroupName->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); break; case RunDllAsAppProcessType: { PH_IMAGE_VERSION_INFO versionInfo; if (PhInitializeImageVersionInfo( &versionInfo, knownCommandLine.RunDllAsApp.FileName->Buffer )) { tempString = PhFormatImageVersionInfo( knownCommandLine.RunDllAsApp.FileName, &versionInfo, &StandardIndent, 0 ); if (!PhIsNullOrEmptyString(tempString)) { PhAppendStringBuilder2(&stringBuilder, L"Run DLL target file:\n"); PhAppendStringBuilder(&stringBuilder, &tempString->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (tempString) PhDereferenceObject(tempString); PhDeleteImageVersionInfo(&versionInfo); } } break; case ComSurrogateProcessType: { PH_IMAGE_VERSION_INFO versionInfo; PPH_STRING guidString; PhAppendStringBuilder2(&stringBuilder, L"COM target:\n"); if (knownCommandLine.ComSurrogate.Name) { PhAppendStringBuilder(&stringBuilder, &StandardIndent); PhAppendStringBuilder(&stringBuilder, &knownCommandLine.ComSurrogate.Name->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (guidString = PhFormatGuid(&knownCommandLine.ComSurrogate.Guid)) { PhAppendStringBuilder(&stringBuilder, &StandardIndent); PhAppendStringBuilder(&stringBuilder, &guidString->sr); PhDereferenceObject(guidString); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (knownCommandLine.ComSurrogate.FileName && PhInitializeImageVersionInfo( &versionInfo, knownCommandLine.ComSurrogate.FileName->Buffer )) { tempString = PhFormatImageVersionInfo( knownCommandLine.ComSurrogate.FileName, &versionInfo, &StandardIndent, 0 ); if (!PhIsNullOrEmptyString(tempString)) { PhAppendStringBuilder2(&stringBuilder, L"COM target file:\n"); PhAppendStringBuilder(&stringBuilder, &tempString->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } if (tempString) PhDereferenceObject(tempString); PhDeleteImageVersionInfo(&versionInfo); } } break; } } } // Services if (Process->ServiceList && Process->ServiceList->Count != 0) { ULONG enumerationKey = 0; PPH_SERVICE_ITEM serviceItem; PPH_LIST serviceList; ULONG i; // Copy the service list into our own list so we can sort it. serviceList = PhCreateList(Process->ServiceList->Count); PhAcquireQueuedLockShared(&Process->ServiceListLock); while (PhEnumPointerList( Process->ServiceList, &enumerationKey, &serviceItem )) { PhReferenceObject(serviceItem); PhAddItemList(serviceList, serviceItem); } PhReleaseQueuedLockShared(&Process->ServiceListLock); qsort(serviceList->Items, serviceList->Count, sizeof(PPH_SERVICE_ITEM), ServiceForTooltipCompare); PhAppendStringBuilder2(&stringBuilder, L"Services:\n"); // Add the services. for (i = 0; i < serviceList->Count; i++) { serviceItem = serviceList->Items[i]; PhAppendStringBuilder(&stringBuilder, &StandardIndent); PhAppendStringBuilder(&stringBuilder, &serviceItem->Name->sr); PhAppendStringBuilder2(&stringBuilder, L" ("); PhAppendStringBuilder(&stringBuilder, &serviceItem->DisplayName->sr); PhAppendStringBuilder2(&stringBuilder, L")\n"); } PhDereferenceObjects(serviceList->Items, serviceList->Count); PhDereferenceObject(serviceList); } // Tasks, Drivers switch (knownProcessType & KnownProcessTypeMask) { case TaskHostProcessType: { PH_STRING_BUILDER tasks; PhInitializeStringBuilder(&tasks, 40); PhpFillRunningTasks(Process, &tasks); if (tasks.String->Length != 0) { PhAppendStringBuilder2(&stringBuilder, L"Tasks:\n"); PhAppendStringBuilder(&stringBuilder, &tasks.String->sr); } PhDeleteStringBuilder(&tasks); } break; case UmdfHostProcessType: { PH_STRING_BUILDER drivers; PhInitializeStringBuilder(&drivers, 40); PhpFillUmdfDrivers(Process, &drivers); if (drivers.String->Length != 0) { PhAppendStringBuilder2(&stringBuilder, L"Drivers:\n"); PhAppendStringBuilder(&stringBuilder, &drivers.String->sr); } PhDeleteStringBuilder(&drivers); validForMs = 10 * 1000; // 10 seconds } break; } // Plugin if (PhPluginsEnabled) { PH_PLUGIN_GET_TOOLTIP_TEXT getTooltipText; getTooltipText.Parameter = Process; getTooltipText.StringBuilder = &stringBuilder; getTooltipText.ValidForMs = validForMs; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackGetProcessTooltipText), &getTooltipText); validForMs = getTooltipText.ValidForMs; } // Notes { PH_STRING_BUILDER notes; PhInitializeStringBuilder(¬es, 40); if (Process->FileName) { if (Process->VerifyResult == VrTrusted) { if (!PhIsNullOrEmptyString(Process->VerifySignerName)) PhAppendFormatStringBuilder(¬es, L" Signer: %s\n", Process->VerifySignerName->Buffer); else PhAppendStringBuilder2(¬es, L" Signed.\n"); } else if (Process->VerifyResult == VrUnknown) { // Nothing } else if (Process->VerifyResult != VrNoSignature) { PhAppendStringBuilder2(¬es, L" Signature invalid.\n"); } } if (Process->IsPacked) { PhAppendFormatStringBuilder( ¬es, L" Image is probably packed (%u imports over %u modules).\n", Process->ImportFunctions, Process->ImportModules ); } if ((ULONG_PTR)Process->ConsoleHostProcessId & ~3) { CLIENT_ID clientId; PWSTR description = L"Console host"; PPH_STRING clientIdString; clientId.UniqueProcess = (HANDLE)((ULONG_PTR)Process->ConsoleHostProcessId & ~3); clientId.UniqueThread = NULL; if ((ULONG_PTR)Process->ConsoleHostProcessId & 2) description = L"Console application"; clientIdString = PhGetClientIdName(&clientId); PhAppendFormatStringBuilder(¬es, L" %s: %s\n", description, clientIdString->Buffer); PhDereferenceObject(clientIdString); } if (Process->PackageFullName) { PhAppendFormatStringBuilder(¬es, L" Package name: %s\n", Process->PackageFullName->Buffer); } if (Process->IsDotNet) PhAppendStringBuilder2(¬es, L" Process is managed (.NET).\n"); if (Process->IsElevated) PhAppendStringBuilder2(¬es, L" Process is elevated.\n"); if (Process->IsImmersive) PhAppendStringBuilder2(¬es, L" Process is a Modern UI app.\n"); if (Process->IsInJob) PhAppendStringBuilder2(¬es, L" Process is in a job.\n"); if (Process->IsPosix) PhAppendStringBuilder2(¬es, L" Process is POSIX.\n"); if (Process->IsWow64) PhAppendStringBuilder2(¬es, L" Process is 32-bit (WOW64).\n"); if (notes.String->Length != 0) { PhAppendStringBuilder2(&stringBuilder, L"Notes:\n"); PhAppendStringBuilder(&stringBuilder, ¬es.String->sr); } PhDeleteStringBuilder(¬es); } if (ValidToTickCount) *ValidToTickCount = GetTickCount() + validForMs; // Remove the trailing newline. if (stringBuilder.String->Length != 0) PhRemoveEndStringBuilder(&stringBuilder, 1); return PhFinalStringBuilderString(&stringBuilder); }
PPH_STRING PhGetServiceTooltipText( _In_ PPH_SERVICE_ITEM Service ) { PH_STRING_BUILDER stringBuilder; SC_HANDLE serviceHandle; PhInitializeStringBuilder(&stringBuilder, 200); if (serviceHandle = PhOpenService(Service->Name->Buffer, SERVICE_QUERY_CONFIG)) { PPH_STRING fileName; PPH_STRING description; // File information if (fileName = PhGetServiceRelevantFileName(&Service->Name->sr, serviceHandle)) { PH_IMAGE_VERSION_INFO versionInfo; PPH_STRING versionInfoText; if (PhInitializeImageVersionInfo( &versionInfo, fileName->Buffer )) { versionInfoText = PhFormatImageVersionInfo( fileName, &versionInfo, &StandardIndent, 0 ); if (!PhIsNullOrEmptyString(versionInfoText)) { PhAppendStringBuilder2(&stringBuilder, L"File:\n"); PhAppendStringBuilder(&stringBuilder, &versionInfoText->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); } PhClearReference(&versionInfoText); PhDeleteImageVersionInfo(&versionInfo); } PhDereferenceObject(fileName); } // Description if (description = PhGetServiceDescription(serviceHandle)) { PhAppendStringBuilder2(&stringBuilder, L"Description:\n "); PhAppendStringBuilder(&stringBuilder, &description->sr); PhAppendCharStringBuilder(&stringBuilder, '\n'); PhDereferenceObject(description); } CloseServiceHandle(serviceHandle); } // Remove the trailing newline. if (stringBuilder.String->Length != 0) PhRemoveEndStringBuilder(&stringBuilder, 1); return PhFinalStringBuilderString(&stringBuilder); }
VOID PhpFillUmdfDrivers( _In_ PPH_PROCESS_ITEM Process, _Inout_ PPH_STRING_BUILDER Drivers ) { static PH_STRINGREF activeDevices = PH_STRINGREF_INIT(L"ACTIVE_DEVICES"); static PH_STRINGREF currentControlSetEnum = PH_STRINGREF_INIT(L"System\\CurrentControlSet\\Enum\\"); HANDLE processHandle; ULONG flags = 0; PVOID environment; ULONG environmentLength; ULONG enumerationKey; PH_ENVIRONMENT_VARIABLE variable; if (!NT_SUCCESS(PhOpenProcess( &processHandle, PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, Process->ProcessId ))) return; #ifdef _WIN64 // Just in case. if (Process->IsWow64) flags |= PH_GET_PROCESS_ENVIRONMENT_WOW64; #endif if (NT_SUCCESS(PhGetProcessEnvironment( processHandle, flags, &environment, &environmentLength ))) { enumerationKey = 0; while (PhEnumProcessEnvironmentVariables(environment, environmentLength, &enumerationKey, &variable)) { PH_STRINGREF part; PH_STRINGREF remainingPart; if (!PhEqualStringRef(&variable.Name, &activeDevices, TRUE)) continue; remainingPart = variable.Value; while (remainingPart.Length != 0) { PhSplitStringRefAtChar(&remainingPart, ';', &part, &remainingPart); if (part.Length != 0) { HANDLE driverKeyHandle; PPH_STRING driverKeyPath; driverKeyPath = PhConcatStringRef2(¤tControlSetEnum, &part); if (NT_SUCCESS(PhOpenKey( &driverKeyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &driverKeyPath->sr, 0 ))) { PPH_STRING deviceDesc; PH_STRINGREF deviceName; PPH_STRING hardwareId; if (deviceDesc = PhQueryRegistryString(driverKeyHandle, L"DeviceDesc")) { PH_STRINGREF firstPart; PH_STRINGREF secondPart; if (PhSplitStringRefAtLastChar(&deviceDesc->sr, ';', &firstPart, &secondPart)) deviceName = secondPart; else deviceName = deviceDesc->sr; } else { PhInitializeStringRef(&deviceName, L"Unknown Device"); } hardwareId = PhQueryRegistryString(driverKeyHandle, L"HardwareID"); PhAppendStringBuilder(Drivers, &StandardIndent); PhAppendStringBuilder(Drivers, &deviceName); if (hardwareId) { PhTrimToNullTerminatorString(hardwareId); if (hardwareId->Length != 0) { PhAppendStringBuilder2(Drivers, L" ("); PhAppendStringBuilder(Drivers, &hardwareId->sr); PhAppendCharStringBuilder(Drivers, ')'); } } PhAppendCharStringBuilder(Drivers, '\n'); PhClearReference(&hardwareId); PhClearReference(&deviceDesc); NtClose(driverKeyHandle); } PhDereferenceObject(driverKeyPath); } } } PhFreePage(environment); } NtClose(processHandle); }
BOOLEAN QueryUpdateData( _Inout_ PPH_UPDATER_CONTEXT Context ) { BOOLEAN success = FALSE; PPH_HTTP_CONTEXT httpContext = NULL; PPH_BYTES jsonString = NULL; PVOID jsonObject = NULL; if (!PhHttpSocketCreate(&httpContext, NULL)) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketConnect( httpContext, L"wj32.org", PH_HTTP_DEFAULT_HTTPS_PORT )) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketBeginRequest( httpContext, NULL, L"/processhacker/nightly.php?phupdater", PH_HTTP_FLAG_REFRESH | PH_HTTP_FLAG_SECURE )) { Context->ErrorCode = GetLastError(); goto CleanupExit; } { PPH_STRING versionHeader; PPH_STRING windowsHeader; if (versionHeader = UpdateVersionString()) { PhHttpSocketAddRequestHeaders(httpContext, versionHeader->Buffer, (ULONG)versionHeader->Length / sizeof(WCHAR)); PhDereferenceObject(versionHeader); } if (windowsHeader = UpdateWindowsString()) { PhHttpSocketAddRequestHeaders(httpContext, windowsHeader->Buffer, (ULONG)windowsHeader->Length / sizeof(WCHAR)); PhDereferenceObject(windowsHeader); } } if (!PhHttpSocketSendRequest(httpContext, NULL, 0)) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!PhHttpSocketEndRequest(httpContext)) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!(jsonString = PhHttpSocketDownloadString(httpContext, FALSE))) { Context->ErrorCode = GetLastError(); goto CleanupExit; } if (!(jsonObject = PhCreateJsonParser(jsonString->Buffer))) goto CleanupExit; Context->Version = PhGetJsonValueAsString(jsonObject, "version"); Context->RelDate = PhGetJsonValueAsString(jsonObject, "updated"); Context->SetupFileDownloadUrl = PhGetJsonValueAsString(jsonObject, "setup_url"); Context->SetupFileLength = PhFormatSize(PhGetJsonValueAsLong64(jsonObject, "setup_length"), 2); Context->SetupFileHash = PhGetJsonValueAsString(jsonObject, "setup_hash"); Context->SetupFileSignature = PhGetJsonValueAsString(jsonObject, "setup_sig"); Context->BuildMessage = PhGetJsonValueAsString(jsonObject, "changelog"); PhFreeJsonParser(jsonObject); if (PhIsNullOrEmptyString(Context->Version)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->RelDate)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileDownloadUrl)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileLength)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileHash)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->SetupFileSignature)) goto CleanupExit; if (PhIsNullOrEmptyString(Context->BuildMessage)) goto CleanupExit; success = TRUE; CleanupExit: if (httpContext) PhHttpSocketDestroy(httpContext); if (jsonString) PhDereferenceObject(jsonString); if (success && !PhIsNullOrEmptyString(Context->BuildMessage)) { PH_STRING_BUILDER sb; PhInitializeStringBuilder(&sb, 0x100); for (SIZE_T i = 0; i < Context->BuildMessage->Length / sizeof(WCHAR); i++) { if (Context->BuildMessage->Data[i] == '\n') PhAppendStringBuilder2(&sb, L"\r\n"); else PhAppendCharStringBuilder(&sb, Context->BuildMessage->Data[i]); } PhMoveReference(&Context->BuildMessage, PhFinalStringBuilderString(&sb)); } return success; }
static VOID PhpGetWfmoInformation( _In_ HANDLE ProcessHandle, _In_ BOOLEAN IsWow64, _In_ ULONG NumberOfHandles, _In_ PHANDLE AddressOfHandles, _In_ WAIT_TYPE WaitType, _In_ BOOLEAN Alertable, _Inout_ PPH_STRING_BUILDER StringBuilder ) { NTSTATUS status; HANDLE handles[MAXIMUM_WAIT_OBJECTS]; ULONG i; status = STATUS_SUCCESS; if (NumberOfHandles <= MAXIMUM_WAIT_OBJECTS) { #ifdef _WIN64 if (IsWow64) { ULONG handles32[MAXIMUM_WAIT_OBJECTS]; if (NT_SUCCESS(status = NtReadVirtualMemory( ProcessHandle, AddressOfHandles, handles32, NumberOfHandles * sizeof(ULONG), NULL ))) { for (i = 0; i < NumberOfHandles; i++) handles[i] = UlongToHandle(handles32[i]); } } else { #endif status = NtReadVirtualMemory( ProcessHandle, AddressOfHandles, handles, NumberOfHandles * sizeof(HANDLE), NULL ); #ifdef _WIN64 } #endif if (NT_SUCCESS(status)) { PhAppendFormatStringBuilder( StringBuilder, L"Thread is waiting (%s, %s) for:\r\n", Alertable ? L"alertable" : L"non-alertable", WaitType == WaitAll ? L"wait all" : L"wait any" ); for (i = 0; i < NumberOfHandles; i++) { PhAppendStringBuilder( StringBuilder, &PhpaGetHandleString(ProcessHandle, handles[i])->sr ); PhAppendStringBuilder2( StringBuilder, L"\r\n" ); } } } if (!NT_SUCCESS(status) || NumberOfHandles > MAXIMUM_WAIT_OBJECTS) { PhAppendStringBuilder2( StringBuilder, L"Thread is waiting for multiple objects." ); } }
static BOOLEAN NTAPI PhpWalkThreadStackAnalyzeCallback( _In_ PPH_THREAD_STACK_FRAME StackFrame, _In_opt_ PVOID Context ) { PANALYZE_WAIT_CONTEXT context = (PANALYZE_WAIT_CONTEXT)Context; PPH_STRING name; name = PhGetSymbolFromAddress( context->SymbolProvider, (ULONG64)StackFrame->PcAddress, NULL, NULL, NULL, NULL ); if (!name) return TRUE; context->Found = TRUE; #define FUNC_MATCH(Name) PhStartsWithString2(name, L##Name, TRUE) #define NT_FUNC_MATCH(Name) ( \ PhStartsWithString2(name, L"ntdll.dll!Nt" L##Name, TRUE) || \ PhStartsWithString2(name, L"ntdll.dll!Zw" L##Name, TRUE) \ ) if (!name) { // Dummy } else if (FUNC_MATCH("kernel32.dll!Sleep")) { PhAppendFormatStringBuilder( &context->StringBuilder, L"Thread is sleeping. Timeout: %lu milliseconds.", PtrToUlong(StackFrame->Params[0]) ); } else if (NT_FUNC_MATCH("DelayExecution")) { BOOLEAN alertable = !!StackFrame->Params[0]; PVOID timeoutAddress = StackFrame->Params[1]; LARGE_INTEGER timeout; if (NT_SUCCESS(NtReadVirtualMemory( context->ProcessHandle, timeoutAddress, &timeout, sizeof(LARGE_INTEGER), NULL ))) { if (timeout.QuadPart < 0) { PhAppendFormatStringBuilder( &context->StringBuilder, L"Thread is sleeping. Timeout: %I64u milliseconds.", -timeout.QuadPart / PH_TIMEOUT_MS ); } else { // TODO } } else { PhAppendStringBuilder2( &context->StringBuilder, L"Thread is sleeping." ); } } else if (NT_FUNC_MATCH("DeviceIoControlFile")) { HANDLE handle = (HANDLE)StackFrame->Params[0]; PhAppendStringBuilder2( &context->StringBuilder, L"Thread is waiting for an I/O control request:\r\n" ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else if (NT_FUNC_MATCH("FsControlFile")) { HANDLE handle = StackFrame->Params[0]; PhAppendStringBuilder2( &context->StringBuilder, L"Thread is waiting for a FS control request:\r\n" ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else if (NT_FUNC_MATCH("QueryObject")) { HANDLE handle = StackFrame->Params[0]; // Use the KiFastSystemCall args if the handle we have is wrong. if ((ULONG_PTR)handle % 4 != 0 || !handle) handle = context->PrevParams[1]; PhAppendStringBuilder2( &context->StringBuilder, L"Thread is querying an object:\r\n" ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else if (NT_FUNC_MATCH("ReadFile") || NT_FUNC_MATCH("WriteFile")) { HANDLE handle = StackFrame->Params[0]; PhAppendStringBuilder2( &context->StringBuilder, L"Thread is waiting for file I/O:\r\n" ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else if (NT_FUNC_MATCH("RemoveIoCompletion")) { HANDLE handle = StackFrame->Params[0]; PhAppendStringBuilder2( &context->StringBuilder, L"Thread is waiting for an I/O completion port:\r\n" ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else if ( NT_FUNC_MATCH("ReplyWaitReceivePort") || NT_FUNC_MATCH("RequestWaitReplyPort") || NT_FUNC_MATCH("AlpcSendWaitReceivePort") ) { HANDLE handle = StackFrame->Params[0]; PPH_STRING alpcInfo; PhAppendStringBuilder2( &context->StringBuilder, L"Thread is waiting for an ALPC port:\r\n" ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); if (alpcInfo = PhpaGetAlpcInformation(context->ThreadId)) { PhAppendStringBuilder2( &context->StringBuilder, L"\r\n" ); PhAppendStringBuilder( &context->StringBuilder, &alpcInfo->sr ); } } else if ( NT_FUNC_MATCH("SetHighWaitLowEventPair") || NT_FUNC_MATCH("SetLowWaitHighEventPair") || NT_FUNC_MATCH("WaitHighEventPair") || NT_FUNC_MATCH("WaitLowEventPair") ) { HANDLE handle = StackFrame->Params[0]; if ((ULONG_PTR)handle % 4 != 0 || !handle) handle = context->PrevParams[1]; PhAppendFormatStringBuilder( &context->StringBuilder, L"Thread is waiting (%s) for an event pair:\r\n", name->Buffer ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else if ( FUNC_MATCH("user32.dll!NtUserGetMessage") || FUNC_MATCH("user32.dll!NtUserWaitMessage") ) { PhAppendStringBuilder2( &context->StringBuilder, L"Thread is waiting for a USER message.\r\n" ); } else if (FUNC_MATCH("user32.dll!NtUserMessageCall")) { PPH_STRING receiverString; PhAppendStringBuilder2( &context->StringBuilder, L"Thread is sending a USER message:\r\n" ); receiverString = PhpaGetSendMessageReceiver(context->ThreadId); if (receiverString) { PhAppendStringBuilder(&context->StringBuilder, &receiverString->sr); PhAppendStringBuilder2(&context->StringBuilder, L"\r\n"); } else { PhAppendStringBuilder2(&context->StringBuilder, L"Unknown.\r\n"); } } else if (NT_FUNC_MATCH("WaitForDebugEvent")) { HANDLE handle = StackFrame->Params[0]; PhAppendStringBuilder2( &context->StringBuilder, L"Thread is waiting for a debug event:\r\n" ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else if ( NT_FUNC_MATCH("WaitForKeyedEvent") || NT_FUNC_MATCH("ReleaseKeyedEvent") ) { HANDLE handle = StackFrame->Params[0]; PVOID key = StackFrame->Params[1]; PhAppendFormatStringBuilder( &context->StringBuilder, L"Thread is waiting (%s) for a keyed event (key 0x%Ix):\r\n", name->Buffer, key ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else if ( NT_FUNC_MATCH("WaitForMultipleObjects") || FUNC_MATCH("kernel32.dll!WaitForMultipleObjects") ) { ULONG numberOfHandles = PtrToUlong(StackFrame->Params[0]); PVOID addressOfHandles = StackFrame->Params[1]; WAIT_TYPE waitType = (WAIT_TYPE)StackFrame->Params[2]; BOOLEAN alertable = !!StackFrame->Params[3]; if (numberOfHandles > MAXIMUM_WAIT_OBJECTS) { numberOfHandles = PtrToUlong(context->PrevParams[1]); addressOfHandles = context->PrevParams[2]; waitType = (WAIT_TYPE)context->PrevParams[3]; alertable = FALSE; } PhpGetWfmoInformation( context->ProcessHandle, TRUE, // on x64 this function is only called for WOW64 processes numberOfHandles, addressOfHandles, waitType, alertable, &context->StringBuilder ); } else if ( NT_FUNC_MATCH("WaitForSingleObject") || FUNC_MATCH("kernel32.dll!WaitForSingleObject") ) { HANDLE handle = StackFrame->Params[0]; BOOLEAN alertable = !!StackFrame->Params[1]; if ((ULONG_PTR)handle % 4 != 0 || !handle) { handle = context->PrevParams[1]; alertable = !!context->PrevParams[2]; } PhAppendFormatStringBuilder( &context->StringBuilder, L"Thread is waiting (%s) for:\r\n", alertable ? L"alertable" : L"non-alertable" ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else if (NT_FUNC_MATCH("WaitForWorkViaWorkerFactory")) { HANDLE handle = StackFrame->Params[0]; PhAppendStringBuilder2( &context->StringBuilder, L"Thread is waiting for work from a worker factory:\r\n" ); PhAppendStringBuilder( &context->StringBuilder, &PhpaGetHandleString(context->ProcessHandle, handle)->sr ); } else { context->Found = FALSE; } PhDereferenceObject(name); memcpy(&context->PrevParams, StackFrame->Params, sizeof(StackFrame->Params)); return !context->Found; }
static INT_PTR CALLBACK NetworkOutputDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PNETWORK_OUTPUT_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = (PNETWORK_OUTPUT_CONTEXT)lParam; SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PNETWORK_OUTPUT_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) { PhSaveWindowPlacementToSetting(SETTING_NAME_TRACERT_WINDOW_POSITION, SETTING_NAME_TRACERT_WINDOW_SIZE, hwndDlg); PhDeleteLayoutManager(&context->LayoutManager); if (context->ProcessHandle) { // Terminate the child process. PhTerminateProcess(context->ProcessHandle, STATUS_SUCCESS); // Close the child process handle. NtClose(context->ProcessHandle); } // Close the pipe handle. if (context->PipeReadHandle) NtClose(context->PipeReadHandle); RemoveProp(hwndDlg, L"Context"); PhFree(context); } } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { PH_RECTANGLE windowRectangle; context->WindowHandle = hwndDlg; context->OutputHandle = GetDlgItem(hwndDlg, IDC_NETOUTPUTEDIT); PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); PhAddLayoutItem(&context->LayoutManager, context->OutputHandle, NULL, PH_ANCHOR_ALL); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_MORE_INFO), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_RIGHT); windowRectangle.Position = PhGetIntegerPairSetting(SETTING_NAME_TRACERT_WINDOW_POSITION); windowRectangle.Size = PhGetIntegerPairSetting(SETTING_NAME_TRACERT_WINDOW_SIZE); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 190; rect.bottom = 120; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } // Check for first-run default position. if (windowRectangle.Position.X == 0 || windowRectangle.Position.Y == 0) { PhCenterWindow(hwndDlg, GetParent(hwndDlg)); } else { PhLoadWindowPlacementFromSetting(SETTING_NAME_TRACERT_WINDOW_POSITION, SETTING_NAME_TRACERT_WINDOW_SIZE, hwndDlg); } if (context->IpAddress.Type == PH_IPV4_NETWORK_TYPE) { RtlIpv4AddressToString(&context->IpAddress.InAddr, context->IpAddressString); } else { RtlIpv6AddressToString(&context->IpAddress.In6Addr, context->IpAddressString); } switch (context->Action) { case NETWORK_ACTION_TRACEROUTE: { HANDLE dialogThread = INVALID_HANDLE_VALUE; Static_SetText(context->WindowHandle, PhaFormatString(L"Tracing route to %s...", context->IpAddressString)->Buffer ); if (dialogThread = PhCreateThread(0, NetworkTracertThreadStart, (PVOID)context)) NtClose(dialogThread); } break; case NETWORK_ACTION_WHOIS: { HANDLE dialogThread = INVALID_HANDLE_VALUE; Static_SetText(context->WindowHandle, PhaFormatString(L"Whois %s...", context->IpAddressString)->Buffer ); ShowWindow(GetDlgItem(hwndDlg, IDC_MORE_INFO), SW_SHOW); if (dialogThread = PhCreateThread(0, NetworkWhoisThreadStart, (PVOID)context)) NtClose(dialogThread); } break; } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: PostQuitMessage(0); break; } } break; case WM_SIZE: PhLayoutManagerLayout(&context->LayoutManager); break; case WM_SIZING: PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); break; case WM_CTLCOLORDLG: case WM_CTLCOLORSTATIC: { HDC hDC = (HDC)wParam; HWND hwndChild = (HWND)lParam; // Check if old graph colors are enabled. if (!PhGetIntegerSetting(L"GraphColorMode")) break; // Set a transparent background for the control backcolor. SetBkMode(hDC, TRANSPARENT); // Check for our edit control and change the color. if (hwndChild == context->OutputHandle) { // Set text color as the Green PH graph text color. SetTextColor(hDC, RGB(124, 252, 0)); // Set a black control backcolor. return (INT_PTR)GetStockBrush(BLACK_BRUSH); } } break; case WM_NOTIFY: { switch (((LPNMHDR)lParam)->code) { case NM_CLICK: case NM_RETURN: { PNMLINK syslink = (PNMLINK)lParam; if (syslink->hdr.idFrom == IDC_MORE_INFO) { PhShellExecute( PhMainWndHandle, PhaConcatStrings2(L"http://wq.apnic.net/apnic-bin/whois.pl?searchtext=", context->IpAddressString)->Buffer, NULL ); } } break; } } break; case NTM_RECEIVEDTRACE: { OEM_STRING inputString; UNICODE_STRING convertedString; PH_STRING_BUILDER receivedString; if (wParam != 0) { inputString.Buffer = (PCHAR)lParam; inputString.Length = (USHORT)wParam; if (NT_SUCCESS(RtlOemStringToUnicodeString(&convertedString, &inputString, TRUE))) { PPH_STRING windowText = NULL; PhInitializeStringBuilder(&receivedString, PAGE_SIZE); // Get the current output text. windowText = PhGetWindowText(context->OutputHandle); // Append the current output text to the New string. if (!PhIsNullOrEmptyString(windowText)) PhAppendStringBuilder(&receivedString, &windowText->sr); PhAppendFormatStringBuilder(&receivedString, L"%s", convertedString.Buffer); // Remove leading newlines. if (receivedString.String->Length >= 2 * 2 && receivedString.String->Buffer[0] == '\r' && receivedString.String->Buffer[1] == '\n') { PhRemoveStringBuilder(&receivedString, 0, 2); } SetWindowText(context->OutputHandle, receivedString.String->Buffer); SendMessage( context->OutputHandle, EM_SETSEL, receivedString.String->Length / 2 - 1, receivedString.String->Length / 2 - 1 ); SendMessage(context->OutputHandle, WM_VSCROLL, SB_BOTTOM, 0); PhDereferenceObject(windowText); PhDeleteStringBuilder(&receivedString); RtlFreeUnicodeString(&convertedString); } } } break; case NTM_RECEIVEDWHOIS: { OEM_STRING inputString; UNICODE_STRING convertedString; PH_STRING_BUILDER receivedString; if (lParam != 0) { inputString.Buffer = (PCHAR)lParam; inputString.Length = (USHORT)wParam; if (NT_SUCCESS(RtlOemStringToUnicodeString(&convertedString, &inputString, TRUE))) { USHORT i; PhInitializeStringBuilder(&receivedString, PAGE_SIZE); // Convert carriage returns. for (i = 0; i < convertedString.Length; i++) { if (convertedString.Buffer[i] == '\n') { PhAppendStringBuilder2(&receivedString, L"\r\n"); } else { PhAppendCharStringBuilder(&receivedString, convertedString.Buffer[i]); } } // Remove leading newlines. if (receivedString.String->Length >= 2 * 2 && receivedString.String->Buffer[0] == '\r' && receivedString.String->Buffer[1] == '\n') { PhRemoveStringBuilder(&receivedString, 0, 2); } SetWindowText(context->OutputHandle, receivedString.String->Buffer); SendMessage( context->OutputHandle, EM_SETSEL, receivedString.String->Length / 2 - 1, receivedString.String->Length / 2 - 1 ); SendMessage(context->OutputHandle, WM_VSCROLL, SB_TOP, 0); PhDeleteStringBuilder(&receivedString); RtlFreeUnicodeString(&convertedString); } PhFree((PVOID)lParam); } } break; case NTM_RECEIVEDFINISH: { PPH_STRING windowText = PhGetWindowText(context->WindowHandle); if (windowText) { Static_SetText( context->WindowHandle, PhaFormatString(L"%s Finished.", windowText->Buffer)->Buffer ); PhDereferenceObject(windowText); } } break; } return FALSE; }
/** * Loads plugins from the default plugins directory. */ VOID PhLoadPlugins( VOID ) { HANDLE pluginsDirectoryHandle; PPH_STRING pluginsDirectory; pluginsDirectory = PhGetStringSetting(L"PluginsDirectory"); if (RtlDetermineDosPathNameType_U(pluginsDirectory->Buffer) == RtlPathTypeRelative) { // Not absolute. Make sure it is. PluginsDirectory = PhConcatStrings(4, PhApplicationDirectory->Buffer, L"\\", pluginsDirectory->Buffer, L"\\"); PhDereferenceObject(pluginsDirectory); } else { PluginsDirectory = pluginsDirectory; } if (NT_SUCCESS(PhCreateFileWin32( &pluginsDirectoryHandle, PluginsDirectory->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))) { UNICODE_STRING pattern = RTL_CONSTANT_STRING(L"*.dll"); PhEnumDirectoryFile(pluginsDirectoryHandle, &pattern, EnumPluginsDirectoryCallback, NULL); NtClose(pluginsDirectoryHandle); } // Handle load errors. // In certain startup modes we want to ignore all plugin load errors. if (LoadErrors && LoadErrors->Count != 0 && !PhStartupParameters.PhSvc) { PH_STRING_BUILDER sb; ULONG i; PPHP_PLUGIN_LOAD_ERROR loadError; PPH_STRING baseName; PhInitializeStringBuilder(&sb, 100); PhAppendStringBuilder2(&sb, L"Unable to load the following plugin(s):\n\n"); for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhAppendFormatStringBuilder(&sb, L"%s: %s\n", baseName->Buffer, PhGetStringOrDefault(loadError->ErrorMessage, L"An unknown error occurred.")); PhDereferenceObject(baseName); } PhAppendStringBuilder2(&sb, L"\nDo you want to disable the above plugin(s)?"); if (PhShowMessage( NULL, MB_ICONERROR | MB_YESNO, sb.String->Buffer ) == IDYES) { ULONG i; for (i = 0; i < LoadErrors->Count; i++) { loadError = LoadErrors->Items[i]; baseName = PhGetBaseName(loadError->FileName); PhSetPluginDisabled(&baseName->sr, TRUE); PhDereferenceObject(baseName); } } PhDeleteStringBuilder(&sb); } // When we loaded settings before, we didn't know about plugin settings, so they // went into the ignored settings list. Now that they've had a chance to add // settings, we should scan the ignored settings list and move the settings to // the right places. if (PhSettingsFileName) PhConvertIgnoredSettings(); PhpExecuteCallbackForAllPlugins(PluginCallbackLoad, TRUE); }