VOID ReBarLoadLayoutSettings( VOID ) { UINT index = 0; UINT count = 0; PPH_STRING settingsString; PH_STRINGREF remaining; settingsString = PhGetStringSetting(SETTING_NAME_REBAR_CONFIG); remaining = settingsString->sr; if (remaining.Length == 0) return; count = (UINT)SendMessage(RebarHandle, RB_GETBANDCOUNT, 0, 0); for (index = 0; index < count; index++) { PH_STRINGREF idPart; PH_STRINGREF cxPart; PH_STRINGREF stylePart; ULONG64 idInteger; ULONG64 cxInteger; ULONG64 styleInteger; UINT oldBandIndex; REBARBANDINFO rebarBandInfo = { sizeof(REBARBANDINFO), RBBIM_STYLE | RBBIM_SIZE }; if (remaining.Length == 0) break; PhSplitStringRefAtChar(&remaining, '|', &idPart, &remaining); PhSplitStringRefAtChar(&remaining, '|', &cxPart, &remaining); PhSplitStringRefAtChar(&remaining, '|', &stylePart, &remaining); PhStringToInteger64(&idPart, 10, &idInteger); PhStringToInteger64(&cxPart, 10, &cxInteger); PhStringToInteger64(&stylePart, 10, &styleInteger); if ((oldBandIndex = (UINT)SendMessage(RebarHandle, RB_IDTOINDEX, (UINT)idInteger, 0)) == UINT_MAX) continue; if (oldBandIndex != index) { SendMessage(RebarHandle, RB_MOVEBAND, oldBandIndex, index); } if (SendMessage(RebarHandle, RB_GETBANDINFO, index, (LPARAM)&rebarBandInfo)) { rebarBandInfo.cx = (UINT)cxInteger; rebarBandInfo.fStyle |= (UINT)styleInteger; SendMessage(RebarHandle, RB_SETBANDINFO, index, (LPARAM)&rebarBandInfo); } } }
static BOOLEAN ParseVersionString( _Inout_ PPH_UPDATER_CONTEXT Context ) { PH_STRINGREF sr, majorPart, minorPart, revisionPart; ULONG64 majorInteger = 0, minorInteger = 0, revisionInteger = 0; PhInitializeStringRef(&sr, Context->Version->Buffer); PhInitializeStringRef(&revisionPart, Context->RevVersion->Buffer); if (PhSplitStringRefAtChar(&sr, '.', &majorPart, &minorPart)) { PhStringToInteger64(&majorPart, 10, &majorInteger); PhStringToInteger64(&minorPart, 10, &minorInteger); PhStringToInteger64(&revisionPart, 10, &revisionInteger); Context->MajorVersion = (ULONG)majorInteger; Context->MinorVersion = (ULONG)minorInteger; Context->RevisionVersion = (ULONG)revisionInteger; return TRUE; } return FALSE; }
VOID StatusBarLoadSettings( VOID ) { ULONG64 buttonCount = 0; PPH_STRING settingsString; PH_STRINGREF remaining; PH_STRINGREF part; settingsString = PhaGetStringSetting(SETTING_NAME_STATUSBAR_CONFIG); remaining = settingsString->sr; if (remaining.Length == 0) { // Load default settings StatusBarLoadDefault(); return; } // Query the number of buttons to insert if (!PhSplitStringRefAtChar(&remaining, '|', &part, &remaining)) { // Load default settings StatusBarLoadDefault(); return; } if (!PhStringToInteger64(&part, 10, &buttonCount)) { // Load default settings StatusBarLoadDefault(); return; } StatusBarItemList = PhCreateList((ULONG)buttonCount); for (ULONG i = 0; i < (ULONG)buttonCount; i++) { PH_STRINGREF idPart; ULONG64 idInteger; if (remaining.Length == 0) break; PhSplitStringRefAtChar(&remaining, '|', &idPart, &remaining); if (PhStringToInteger64(&idPart, 10, &idInteger)) { PSTATUSBAR_ITEM statusItem; statusItem = PhAllocate(sizeof(STATUSBAR_ITEM)); memset(statusItem, 0, sizeof(STATUSBAR_ITEM)); statusItem->Id = (ULONG)idInteger; PhInsertItemList(StatusBarItemList, i, statusItem); } } }
/** * Parses an application name and sub-ID pair. * * \param CompoundId The compound identifier. * \param AppName A variable which receives the application name. * \param SubId A variable which receives the sub-ID. */ BOOLEAN PhEmParseCompoundId( _In_ PPH_STRINGREF CompoundId, _Out_ PPH_STRINGREF AppName, _Out_ PULONG SubId ) { PH_STRINGREF firstPart; PH_STRINGREF secondPart; ULONG64 integer; firstPart = *CompoundId; if (firstPart.Length == 0) return FALSE; if (firstPart.Buffer[0] != '+') return FALSE; PhSkipStringRef(&firstPart, sizeof(WCHAR)); PhSplitStringRefAtChar(&firstPart, '+', &firstPart, &secondPart); if (firstPart.Length == 0 || secondPart.Length == 0) return FALSE; if (!PhStringToInteger64(&secondPart, 10, &integer)) return FALSE; *AppName = firstPart; *SubId = (ULONG)integer; return TRUE; }
BOOLEAN LastUpdateCheckExpired( VOID ) { ULONG64 lastUpdateTimeTicks = 0; LARGE_INTEGER currentUpdateTimeTicks; PPH_STRING lastUpdateTimeString; PhQuerySystemTime(¤tUpdateTimeTicks); lastUpdateTimeString = PhGetStringSetting(SETTING_NAME_LAST_CHECK); PhStringToInteger64(&lastUpdateTimeString->sr, 0, &lastUpdateTimeTicks); if (currentUpdateTimeTicks.QuadPart - lastUpdateTimeTicks >= 7 * PH_TICKS_PER_DAY) { PPH_STRING currentUpdateTimeString; currentUpdateTimeString = PhFormatUInt64(currentUpdateTimeTicks.QuadPart, FALSE); PhSetStringSetting2(SETTING_NAME_LAST_CHECK, ¤tUpdateTimeString->sr); PhDereferenceObject(currentUpdateTimeString); PhDereferenceObject(lastUpdateTimeString); return TRUE; } PhDereferenceObject(lastUpdateTimeString); return FALSE; }
static BOOLEAN NTAPI PhpPreviousInstancesCallback( _In_ PPH_STRINGREF Name, _In_ PPH_STRINGREF TypeName, _In_opt_ PVOID Context ) { ULONG64 processId64; PH_STRINGREF firstPart; PH_STRINGREF secondPart; if ( PhStartsWithStringRef2(Name, L"PhMutant_", TRUE) && PhSplitStringRefAtChar(Name, L'_', &firstPart, &secondPart) && PhStringToInteger64(&secondPart, 10, &processId64) ) { HANDLE processHandle; if (NT_SUCCESS(PhOpenProcess( &processHandle, SYNCHRONIZE | PROCESS_TERMINATE, ULongToHandle((ULONG)processId64) ))) { NtTerminateProcess(processHandle, 1); NtClose(processHandle); } } return TRUE; }
static BOOLEAN LastUpdateCheckExpired( VOID ) { ULONG64 lastUpdateTimeTicks = 0; LARGE_INTEGER currentUpdateTimeTicks; PPH_STRING lastUpdateTimeString; // Get the last update check time lastUpdateTimeString = PhGetStringSetting(SETTING_NAME_LAST_CHECK); PhStringToInteger64(&lastUpdateTimeString->sr, 0, &lastUpdateTimeTicks); // Query the current time PhQuerySystemTime(¤tUpdateTimeTicks); // Check if the last update check was more than 7 days ago if (currentUpdateTimeTicks.QuadPart - lastUpdateTimeTicks >= 7 * PH_TICKS_PER_DAY) { PPH_STRING currentUpdateTimeString = PhFormatUInt64(currentUpdateTimeTicks.QuadPart, FALSE); // Save the current time PhSetStringSetting2(SETTING_NAME_LAST_CHECK, ¤tUpdateTimeString->sr); // Cleanup PhDereferenceObject(currentUpdateTimeString); PhDereferenceObject(lastUpdateTimeString); return TRUE; } // Cleanup PhDereferenceObject(lastUpdateTimeString); return FALSE; }
VOID NetAdaptersLoadList( VOID ) { PPH_STRING settingsString; PH_STRINGREF remaining; settingsString = PhaGetStringSetting(SETTING_NAME_INTERFACE_LIST); remaining = settingsString->sr; while (remaining.Length != 0) { ULONG64 ifindex; ULONG64 luid64; PH_STRINGREF part1; PH_STRINGREF part2; PH_STRINGREF part3; IF_LUID ifLuid; DV_NETADAPTER_ID id; PDV_NETADAPTER_ENTRY entry; if (remaining.Length == 0) break; PhSplitStringRefAtChar(&remaining, ',', &part1, &remaining); PhSplitStringRefAtChar(&remaining, ',', &part2, &remaining); PhSplitStringRefAtChar(&remaining, ',', &part3, &remaining); PhStringToInteger64(&part1, 10, &ifindex); PhStringToInteger64(&part2, 10, &luid64); ifLuid.Value = luid64; InitializeNetAdapterId(&id, (IF_INDEX)ifindex, ifLuid, PhCreateString2(&part3)); entry = CreateNetAdapterEntry(&id); DeleteNetAdapterId(&id); entry->UserReference = TRUE; } }
PPH_LIST PhInitializeColumnSetList( _In_ PWSTR SettingName ) { PPH_LIST columnSetList; PPH_STRING settingsString; ULONG64 count; ULONG64 index; PH_STRINGREF remaining; PH_STRINGREF part; columnSetList = PhCreateList(10); settingsString = PhaGetStringSetting(SettingName); remaining = settingsString->sr; if (remaining.Length == 0) goto CleanupExit; if (!PhSplitStringRefAtChar(&remaining, '-', &part, &remaining)) goto CleanupExit; if (!PhStringToInteger64(&part, 10, &count)) goto CleanupExit; for (index = 0; index < count; index++) { PH_STRINGREF columnSetNamePart; PH_STRINGREF columnSetSettingPart; PH_STRINGREF columnSetSortPart; if (remaining.Length == 0) break; PhSplitStringRefAtChar(&remaining, '-', &columnSetNamePart, &remaining); PhSplitStringRefAtChar(&remaining, '-', &columnSetSettingPart, &remaining); PhSplitStringRefAtChar(&remaining, '-', &columnSetSortPart, &remaining); { PPH_COLUMN_SET_ENTRY entry; entry = PhAllocate(sizeof(PH_COLUMN_SET_ENTRY)); entry->Name = PhCreateString2(&columnSetNamePart); entry->Setting = PhCreateString2(&columnSetSettingPart); entry->Sorting = PhCreateString2(&columnSetSortPart); PhAddItemList(columnSetList, entry); } } CleanupExit: return columnSetList; }
ULONG64 ParseVersionString( _Inout_ PPH_STRING VersionString ) { PH_STRINGREF remaining, majorPart, minorPart, revisionPart; ULONG64 majorInteger = 0, minorInteger = 0, revisionInteger = 0; PhInitializeStringRef(&remaining, PhGetString(VersionString)); PhSplitStringRefAtChar(&remaining, '.', &majorPart, &remaining); PhSplitStringRefAtChar(&remaining, '.', &minorPart, &remaining); PhSplitStringRefAtChar(&remaining, '.', &revisionPart, &remaining); PhStringToInteger64(&majorPart, 10, &majorInteger); PhStringToInteger64(&minorPart, 10, &minorInteger); PhStringToInteger64(&revisionPart, 10, &revisionInteger); return MAKE_VERSION_ULONGLONG( (ULONG)majorInteger, (ULONG)minorInteger, (ULONG)revisionInteger, 0 ); }
static BOOLEAN NTAPI FiCommandLineCallback( _In_opt_ PPH_COMMAND_LINE_OPTION Option, _In_opt_ PPH_STRING Value, _In_opt_ PVOID Context ) { if (Option) { switch (Option->Id) { case FI_ARG_HELP: FiArgHelp = TRUE; break; case FI_ARG_ACTION: PhSwapReference(&FiArgAction, Value); break; case FI_ARG_NATIVE: FiArgNative = TRUE; break; case FI_ARG_PATTERN: PhSwapReference(&FiArgPattern, Value); break; case FI_ARG_CASESENSITIVE: FiArgCaseSensitive = TRUE; break; case FI_ARG_OUTPUT: PhSwapReference(&FiArgOutput, Value); break; case FI_ARG_FORCE: FiArgForce = TRUE; break; case FI_ARG_LENGTH: PhStringToInteger64(&Value->sr, 0, (PLONG64)&FiArgLength); break; } } else { if (!FiArgAction) PhSwapReference(&FiArgAction, Value); else if (!FiArgFileName) PhSwapReference(&FiArgFileName, Value); } return TRUE; }
BOOLEAN NTAPI PhpCommandModeOptionCallback( _In_opt_ PPH_COMMAND_LINE_OPTION Option, _In_opt_ PPH_STRING Value, _In_opt_ PVOID Context ) { ULONG64 integer; if (Option) { switch (Option->Id) { case PH_COMMAND_OPTION_HWND: if (PhStringToInteger64(&Value->sr, 10, &integer)) CommandModeWindowHandle = (HWND)integer; break; } } return TRUE; }
BOOLEAN PhLoadListViewColumnSettings( _In_ HWND ListViewHandle, _In_ PPH_STRING Settings ) { #define ORDER_LIMIT 50 PH_STRINGREF remainingPart; ULONG columnIndex; ULONG orderArray[ORDER_LIMIT]; // HACK, but reasonable limit ULONG maxOrder; ULONG scale; if (Settings->Length == 0) return FALSE; remainingPart = Settings->sr; columnIndex = 0; memset(orderArray, 0, sizeof(orderArray)); maxOrder = 0; if (remainingPart.Length != 0 && remainingPart.Buffer[0] == '@') { PH_STRINGREF scalePart; ULONG64 integer; PhSkipStringRef(&remainingPart, sizeof(WCHAR)); PhSplitStringRefAtChar(&remainingPart, '|', &scalePart, &remainingPart); if (scalePart.Length == 0 || !PhStringToInteger64(&scalePart, 10, &integer)) return FALSE; scale = (ULONG)integer; } else { scale = PhGlobalDpi; } while (remainingPart.Length != 0) { PH_STRINGREF columnPart; PH_STRINGREF orderPart; PH_STRINGREF widthPart; ULONG64 integer; ULONG order; ULONG width; LVCOLUMN lvColumn; PhSplitStringRefAtChar(&remainingPart, '|', &columnPart, &remainingPart); if (columnPart.Length == 0) return FALSE; PhSplitStringRefAtChar(&columnPart, ',', &orderPart, &widthPart); if (orderPart.Length == 0 || widthPart.Length == 0) return FALSE; // Order if (!PhStringToInteger64(&orderPart, 10, &integer)) return FALSE; order = (ULONG)integer; if (order < ORDER_LIMIT) { orderArray[order] = columnIndex; if (maxOrder < order + 1) maxOrder = order + 1; } // Width if (!PhStringToInteger64(&widthPart, 10, &integer)) return FALSE; width = (ULONG)integer; if (scale != PhGlobalDpi && scale != 0) width = PhMultiplyDivide(width, PhGlobalDpi, scale); lvColumn.mask = LVCF_WIDTH; lvColumn.cx = width; ListView_SetColumn(ListViewHandle, columnIndex, &lvColumn); columnIndex++; } ListView_SetColumnOrderArray(ListViewHandle, maxOrder, orderArray); return TRUE; }
NTSTATUS PhpGetMappedArchiveMemberFromHeader( _In_ PPH_MAPPED_ARCHIVE MappedArchive, _In_ PIMAGE_ARCHIVE_MEMBER_HEADER Header, _Out_ PPH_MAPPED_ARCHIVE_MEMBER Member ) { WCHAR integerString[11]; ULONG64 size; PH_STRINGREF string; PWSTR digit; PSTR slash; if ((ULONG_PTR)Header >= (ULONG_PTR)MappedArchive->ViewBase + MappedArchive->Size) return STATUS_NO_MORE_ENTRIES; __try { PhpMappedArchiveProbe(MappedArchive, Header, sizeof(IMAGE_ARCHIVE_MEMBER_HEADER)); } __except (EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } Member->MappedArchive = MappedArchive; Member->Header = Header; Member->Data = PTR_ADD_OFFSET(Header, sizeof(IMAGE_ARCHIVE_MEMBER_HEADER)); Member->Type = NormalArchiveMemberType; // Read the size string, terminate it after the last digit and parse it. if (!PhCopyStringZFromBytes(Header->Size, 10, integerString, 11, NULL)) return STATUS_INVALID_PARAMETER; string.Buffer = integerString; string.Length = 0; digit = string.Buffer; while (iswdigit(*digit++)) string.Length += sizeof(WCHAR); if (!PhStringToInteger64(&string, 10, &size)) return STATUS_INVALID_PARAMETER; Member->Size = (ULONG)size; __try { PhpMappedArchiveProbe(MappedArchive, Member->Data, Member->Size); } __except (EXCEPTION_EXECUTE_HANDLER) { return GetExceptionCode(); } // Parse the name. if (!PhCopyBytesZ(Header->Name, 16, Member->NameBuffer, 20, NULL)) return STATUS_INVALID_PARAMETER; Member->Name = Member->NameBuffer; slash = strchr(Member->NameBuffer, '/'); if (!slash) return STATUS_INVALID_PARAMETER; // Special names: // * If the slash is the first character, then this is a linker member. // * If there is a slash after the slash which is a first character, then this is the longnames // member. // * If there are digits after the slash, then the real name is stored in the longnames member. if (slash == Member->NameBuffer) { if (Member->NameBuffer[1] == '/') { // Longnames member. Set the name to "/". Member->NameBuffer[0] = '/'; Member->NameBuffer[1] = 0; Member->Type = LongnamesArchiveMemberType; } else { // Linker member. Set the name to "". Member->NameBuffer[0] = 0; Member->Type = LinkerArchiveMemberType; } } else { if (isdigit(slash[1])) { PSTR digita; ULONG64 offset64; ULONG offset; // The name is stored in the longnames member. // Note: we make sure we have the longnames member first. if (!MappedArchive->LongnamesMember.Header) return STATUS_INVALID_PARAMETER; // Find the last digit and null terminate the string there. digita = slash + 2; while (isdigit(*digita)) digita++; *digita = 0; // Parse the offset and make sure it lies within the longnames member. if (!PhCopyStringZFromBytes(slash + 1, -1, integerString, 11, NULL)) return STATUS_INVALID_PARAMETER; PhInitializeStringRefLongHint(&string, integerString); if (!PhStringToInteger64(&string, 10, &offset64)) return STATUS_INVALID_PARAMETER; offset = (ULONG)offset64; if (offset >= MappedArchive->LongnamesMember.Size) return STATUS_INVALID_PARAMETER; // TODO: Probe the name. Member->Name = (PSTR)PTR_ADD_OFFSET(MappedArchive->LongnamesMember.Data, offset); } else { // Null terminate the string. slash[0] = 0; } } return STATUS_SUCCESS; }
BOOLEAN NTAPI PhpCommandLineOptionCallback( _In_opt_ PPH_COMMAND_LINE_OPTION Option, _In_opt_ PPH_STRING Value, _In_opt_ PVOID Context ) { ULONG64 integer; if (Option) { switch (Option->Id) { case PH_ARG_SETTINGS: PhSwapReference(&PhStartupParameters.SettingsFileName, Value); break; case PH_ARG_NOSETTINGS: PhStartupParameters.NoSettings = TRUE; break; case PH_ARG_SHOWVISIBLE: PhStartupParameters.ShowVisible = TRUE; break; case PH_ARG_SHOWHIDDEN: PhStartupParameters.ShowHidden = TRUE; break; case PH_ARG_COMMANDMODE: PhStartupParameters.CommandMode = TRUE; break; case PH_ARG_COMMANDTYPE: PhSwapReference(&PhStartupParameters.CommandType, Value); break; case PH_ARG_COMMANDOBJECT: PhSwapReference(&PhStartupParameters.CommandObject, Value); break; case PH_ARG_COMMANDACTION: PhSwapReference(&PhStartupParameters.CommandAction, Value); break; case PH_ARG_COMMANDVALUE: PhSwapReference(&PhStartupParameters.CommandValue, Value); break; case PH_ARG_RUNASSERVICEMODE: PhSwapReference(&PhStartupParameters.RunAsServiceMode, Value); break; case PH_ARG_NOKPH: PhStartupParameters.NoKph = TRUE; break; case PH_ARG_INSTALLKPH: PhStartupParameters.InstallKph = TRUE; break; case PH_ARG_UNINSTALLKPH: PhStartupParameters.UninstallKph = TRUE; break; case PH_ARG_DEBUG: PhStartupParameters.Debug = TRUE; break; case PH_ARG_HWND: if (PhStringToInteger64(&Value->sr, 16, &integer)) PhStartupParameters.WindowHandle = (HWND)(ULONG_PTR)integer; break; case PH_ARG_POINT: { PH_STRINGREF xString; PH_STRINGREF yString; if (PhSplitStringRefAtChar(&Value->sr, ',', &xString, &yString)) { LONG64 x; LONG64 y; if (PhStringToInteger64(&xString, 10, &x) && PhStringToInteger64(&yString, 10, &y)) { PhStartupParameters.Point.x = (LONG)x; PhStartupParameters.Point.y = (LONG)y; } } } break; case PH_ARG_SHOWOPTIONS: PhStartupParameters.ShowOptions = TRUE; break; case PH_ARG_PHSVC: PhStartupParameters.PhSvc = TRUE; break; case PH_ARG_NOPLUGINS: PhStartupParameters.NoPlugins = TRUE; break; case PH_ARG_NEWINSTANCE: PhStartupParameters.NewInstance = TRUE; break; case PH_ARG_ELEVATE: PhStartupParameters.Elevate = TRUE; break; case PH_ARG_SILENT: PhStartupParameters.Silent = TRUE; break; case PH_ARG_HELP: PhStartupParameters.Help = TRUE; break; case PH_ARG_SELECTPID: if (PhStringToInteger64(&Value->sr, 0, &integer)) PhStartupParameters.SelectPid = (ULONG)integer; break; case PH_ARG_PRIORITY: if (PhEqualString2(Value, L"r", TRUE)) PhStartupParameters.PriorityClass = PROCESS_PRIORITY_CLASS_REALTIME; else if (PhEqualString2(Value, L"h", TRUE)) PhStartupParameters.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; else if (PhEqualString2(Value, L"n", TRUE)) PhStartupParameters.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; else if (PhEqualString2(Value, L"l", TRUE)) PhStartupParameters.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE; break; case PH_ARG_PLUGIN: if (!PhStartupParameters.PluginParameters) PhStartupParameters.PluginParameters = PhCreateList(3); PhReferenceObject(Value); PhAddItemList(PhStartupParameters.PluginParameters, Value); break; case PH_ARG_SELECTTAB: PhSwapReference(&PhStartupParameters.SelectTab, Value); break; } } else { PPH_STRING upperValue; upperValue = PhDuplicateString(Value); _wcsupr(upperValue->Buffer); if (PhFindStringInString(upperValue, 0, L"TASKMGR.EXE") != -1) { // User probably has Process Hacker replacing Task Manager. Force // the main window to start visible. PhStartupParameters.ShowVisible = TRUE; } PhDereferenceObject(upperValue); } return TRUE; }
INT_PTR CALLBACK PhpSessionSendMessageDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { HWND iconComboBox; SetProp(hwndDlg, L"SessionId", (HANDLE)(ULONG)lParam); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); iconComboBox = GetDlgItem(hwndDlg, IDC_TYPE); ComboBox_AddString(iconComboBox, L"None"); ComboBox_AddString(iconComboBox, L"Information"); ComboBox_AddString(iconComboBox, L"Warning"); ComboBox_AddString(iconComboBox, L"Error"); ComboBox_AddString(iconComboBox, L"Question"); PhSelectComboBoxString(iconComboBox, L"None", FALSE); if (PhCurrentUserName) { SetDlgItemText( hwndDlg, IDC_TITLE, PhaFormatString(L"Message from %s", PhCurrentUserName->Buffer)->Buffer ); } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_TEXT), TRUE); } break; case WM_DESTROY: { RemoveProp(hwndDlg, L"SessionId"); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { ULONG sessionId = (ULONG)GetProp(hwndDlg, L"SessionId"); PPH_STRING title; PPH_STRING text; ULONG icon = 0; ULONG64 timeout = 0; ULONG response; title = PhaGetDlgItemText(hwndDlg, IDC_TITLE); text = PhaGetDlgItemText(hwndDlg, IDC_TEXT); PhFindIntegerSiKeyValuePairs( PhpMessageBoxIconPairs, sizeof(PhpMessageBoxIconPairs), PhaGetDlgItemText(hwndDlg, IDC_TYPE)->Buffer, &icon ); PhStringToInteger64( &PhaGetDlgItemText(hwndDlg, IDC_TIMEOUT)->sr, 10, &timeout ); if (WinStationSendMessageW( NULL, sessionId, title->Buffer, (ULONG)title->Length, text->Buffer, (ULONG)text->Length, icon, (ULONG)timeout, &response, TRUE )) { EndDialog(hwndDlg, IDOK); } else { PhShowStatus(hwndDlg, L"Unable to send the message", 0, GetLastError()); } } break; } } break; } return FALSE; }
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; }
static INT_PTR CALLBACK PhpMemoryProtectDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)lParam); SetDlgItemText(hwndDlg, IDC_INTRO, L"Possible values:\r\n" L"\r\n" L"0x01 - PAGE_NOACCESS\r\n" L"0x02 - PAGE_READONLY\r\n" L"0x04 - PAGE_READWRITE\r\n" L"0x08 - PAGE_WRITECOPY\r\n" L"0x10 - PAGE_EXECUTE\r\n" L"0x20 - PAGE_EXECUTE_READ\r\n" L"0x40 - PAGE_EXECUTE_READWRITE\r\n" L"0x80 - PAGE_EXECUTE_WRITECOPY\r\n" L"Modifiers:\r\n" L"0x100 - PAGE_GUARD\r\n" L"0x200 - PAGE_NOCACHE\r\n" L"0x400 - PAGE_WRITECOMBINE\r\n" ); SetFocus(GetDlgItem(hwndDlg, IDC_VALUE)); } break; case WM_DESTROY: { RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { NTSTATUS status; PMEMORY_PROTECT_CONTEXT context = (PMEMORY_PROTECT_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); HANDLE processHandle; ULONG64 protect; PhStringToInteger64(&PHA_GET_DLGITEM_TEXT(hwndDlg, IDC_VALUE)->sr, 0, &protect); if (NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_VM_OPERATION, context->ProcessItem->ProcessId ))) { PVOID baseAddress; SIZE_T regionSize; ULONG oldProtect; baseAddress = context->MemoryItem->BaseAddress; regionSize = context->MemoryItem->Size; status = NtProtectVirtualMemory( processHandle, &baseAddress, ®ionSize, (ULONG)protect, &oldProtect ); if (NT_SUCCESS(status)) context->MemoryItem->Protection = (ULONG)protect; } if (NT_SUCCESS(status)) { EndDialog(hwndDlg, IDOK); } else { PhShowStatus(hwndDlg, L"Unable to change memory protection", status, 0); SetFocus(GetDlgItem(hwndDlg, IDC_VALUE)); Edit_SetSel(GetDlgItem(hwndDlg, IDC_VALUE), 0, -1); } } break; } } break; } return FALSE; }
BOOLEAN PhLoadListViewColumnSettings( _In_ HWND ListViewHandle, _In_ PPH_STRING Settings ) { #define ORDER_LIMIT 50 PH_STRINGREF remainingPart; ULONG columnIndex; ULONG orderArray[ORDER_LIMIT]; // HACK, but reasonable limit ULONG maxOrder; if (Settings->Length == 0) return FALSE; remainingPart = Settings->sr; columnIndex = 0; memset(orderArray, 0, sizeof(orderArray)); maxOrder = 0; while (remainingPart.Length != 0) { PH_STRINGREF columnPart; PH_STRINGREF orderPart; PH_STRINGREF widthPart; ULONG64 integer; ULONG order; LVCOLUMN lvColumn; PhSplitStringRefAtChar(&remainingPart, '|', &columnPart, &remainingPart); if (columnPart.Length == 0) return FALSE; PhSplitStringRefAtChar(&columnPart, ',', &orderPart, &widthPart); if (orderPart.Length == 0 || widthPart.Length == 0) return FALSE; // Order if (!PhStringToInteger64(&orderPart, 10, &integer)) return FALSE; order = (ULONG)integer; if (order < ORDER_LIMIT) { orderArray[order] = columnIndex; if (maxOrder < order + 1) maxOrder = order + 1; } // Width if (!PhStringToInteger64(&widthPart, 10, &integer)) return FALSE; lvColumn.mask = LVCF_WIDTH; lvColumn.cx = (ULONG)integer; ListView_SetColumn(ListViewHandle, columnIndex, &lvColumn); columnIndex++; } ListView_SetColumnOrderArray(ListViewHandle, maxOrder, orderArray); return TRUE; }
NTSTATUS LoadDb( VOID ) { NTSTATUS status; HANDLE fileHandle; LARGE_INTEGER fileSize; mxml_node_t *topNode; mxml_node_t *currentNode; status = PhCreateFileWin32( &fileHandle, ObjectDbPath->Buffer, FILE_GENERIC_READ, 0, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ); if (!NT_SUCCESS(status)) return status; if (NT_SUCCESS(PhGetFileSize(fileHandle, &fileSize)) && fileSize.QuadPart == 0) { // A blank file is OK. There are no objects to load. NtClose(fileHandle); return status; } topNode = mxmlLoadFd(NULL, fileHandle, MXML_OPAQUE_CALLBACK); NtClose(fileHandle); if (!topNode) return STATUS_FILE_CORRUPT_ERROR; if (topNode->type != MXML_ELEMENT) { mxmlDelete(topNode); return STATUS_FILE_CORRUPT_ERROR; } LockDb(); for (currentNode = topNode->child; currentNode; currentNode = currentNode->next) { PDB_OBJECT object = NULL; PPH_STRING tag = NULL; PPH_STRING name = NULL; PPH_STRING priorityClass = NULL; PPH_STRING ioPriorityPlusOne = NULL; PPH_STRING comment = NULL; PPH_STRING backColor = NULL; PPH_STRING collapse = NULL; PPH_STRING affinityMask = NULL; if (currentNode->type == MXML_ELEMENT && currentNode->value.element.num_attrs >= 2) { for (INT i = 0; i < currentNode->value.element.num_attrs; i++) { if (_stricmp(currentNode->value.element.attrs[i].name, "tag") == 0) PhMoveReference(&tag, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "name") == 0) PhMoveReference(&name, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "priorityclass") == 0) PhMoveReference(&priorityClass, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "iopriorityplusone") == 0) PhMoveReference(&ioPriorityPlusOne, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "backcolor") == 0) PhMoveReference(&backColor, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "collapse") == 0) PhMoveReference(&collapse, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); else if (_stricmp(currentNode->value.element.attrs[i].name, "affinity") == 0) PhMoveReference(&affinityMask, PhConvertUtf8ToUtf16(currentNode->value.element.attrs[i].value)); } } comment = GetOpaqueXmlNodeText(currentNode); if (tag && name && comment) { ULONG64 tagInteger; ULONG64 priorityClassInteger = 0; ULONG64 ioPriorityPlusOneInteger = 0; PhStringToInteger64(&tag->sr, 10, &tagInteger); if (priorityClass) PhStringToInteger64(&priorityClass->sr, 10, &priorityClassInteger); if (ioPriorityPlusOne) PhStringToInteger64(&ioPriorityPlusOne->sr, 10, &ioPriorityPlusOneInteger); object = CreateDbObject((ULONG)tagInteger, &name->sr, comment); object->PriorityClass = (ULONG)priorityClassInteger; object->IoPriorityPlusOne = (ULONG)ioPriorityPlusOneInteger; } // NOTE: These items are handled separately to maintain compatibility with previous versions of the database. if (object && backColor) { ULONG64 backColorInteger = ULONG_MAX; PhStringToInteger64(&backColor->sr, 10, &backColorInteger); object->BackColor = (COLORREF)backColorInteger; } if (object && collapse) { ULONG64 collapseInteger = 0; PhStringToInteger64(&collapse->sr, 10, &collapseInteger); object->Collapse = !!collapseInteger; } if (object && affinityMask) { ULONG64 affinityInteger = 0; PhStringToInteger64(&affinityMask->sr, 10, &affinityInteger); object->AffinityMask = (ULONG)affinityInteger; } PhClearReference(&tag); PhClearReference(&name); PhClearReference(&priorityClass); PhClearReference(&ioPriorityPlusOne); PhClearReference(&comment); PhClearReference(&backColor); PhClearReference(&collapse); PhClearReference(&affinityMask); } UnlockDb(); mxmlDelete(topNode); return STATUS_SUCCESS; }
VOID ToolbarLoadButtonSettings( VOID ) { INT buttonCount; ULONG64 countInteger; PPH_STRING settingsString; PTBBUTTON buttonArray; PH_STRINGREF remaining; PH_STRINGREF part; settingsString = PhaGetStringSetting(SETTING_NAME_TOOLBAR_CONFIG); remaining = settingsString->sr; if (remaining.Length == 0) { // Load default settings SendMessage(ToolBarHandle, TB_ADDBUTTONS, MAX_DEFAULT_TOOLBAR_ITEMS, (LPARAM)ToolbarButtons); return; } // Query the number of buttons to insert if (!PhSplitStringRefAtChar(&remaining, '|', &part, &remaining)) { // Load default settings SendMessage(ToolBarHandle, TB_ADDBUTTONS, MAX_DEFAULT_TOOLBAR_ITEMS, (LPARAM)ToolbarButtons); return; } if (!PhStringToInteger64(&part, 10, &countInteger)) { // Load default settings SendMessage(ToolBarHandle, TB_ADDBUTTONS, MAX_DEFAULT_TOOLBAR_ITEMS, (LPARAM)ToolbarButtons); return; } buttonCount = (INT)countInteger; // Allocate the button array buttonArray = PhAllocate(buttonCount * sizeof(TBBUTTON)); memset(buttonArray, 0, buttonCount * sizeof(TBBUTTON)); for (INT index = 0; index < buttonCount; index++) { ULONG64 commandInteger; PH_STRINGREF commandIdPart; if (remaining.Length == 0) break; PhSplitStringRefAtChar(&remaining, '|', &commandIdPart, &remaining); PhStringToInteger64(&commandIdPart, 10, &commandInteger); buttonArray[index].idCommand = (INT)commandInteger; buttonArray[index].iBitmap = I_IMAGECALLBACK; buttonArray[index].fsState = TBSTATE_ENABLED; if (commandInteger) { buttonArray[index].fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE; } else { buttonArray[index].fsStyle = BTNS_SEP; } } SendMessage(ToolBarHandle, TB_ADDBUTTONS, buttonCount, (LPARAM)buttonArray); PhFree(buttonArray); }
INT_PTR CALLBACK PhpProcessMemoryDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PPH_MEMORY_CONTEXT memoryContext; HWND tnHandle; if (PhpPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { memoryContext = (PPH_MEMORY_CONTEXT)propPageContext->Context; if (memoryContext) tnHandle = memoryContext->ListContext.TreeNewHandle; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { memoryContext = propPageContext->Context = PhAllocate(PhEmGetObjectSize(EmMemoryContextType, sizeof(PH_MEMORY_CONTEXT))); memset(memoryContext, 0, sizeof(PH_MEMORY_CONTEXT)); memoryContext->ProcessId = processItem->ProcessId; // Initialize the list. tnHandle = GetDlgItem(hwndDlg, IDC_LIST); BringWindowToTop(tnHandle); PhInitializeMemoryList(hwndDlg, tnHandle, &memoryContext->ListContext); TreeNew_SetEmptyText(tnHandle, &PhpLoadingText, 0); memoryContext->LastRunStatus = -1; memoryContext->ErrorMessage = NULL; PhEmCallObjectOperation(EmMemoryContextType, memoryContext, EmObjectCreate); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &memoryContext->ListContext.Cm; treeNewInfo.SystemContext = memoryContext; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackMemoryTreeNewInitializing), &treeNewInfo); } PhLoadSettingsMemoryList(&memoryContext->ListContext); PhSetOptionsMemoryList(&memoryContext->ListContext, TRUE); Button_SetCheck(GetDlgItem(hwndDlg, IDC_HIDEFREEREGIONS), memoryContext->ListContext.HideFreeRegions ? BST_CHECKED : BST_UNCHECKED); PhpRefreshProcessMemoryList(hwndDlg, propPageContext); } break; case WM_DESTROY: { PhEmCallObjectOperation(EmMemoryContextType, memoryContext, EmObjectDelete); if (PhPluginsEnabled) { PH_PLUGIN_TREENEW_INFORMATION treeNewInfo; treeNewInfo.TreeNewHandle = tnHandle; treeNewInfo.CmData = &memoryContext->ListContext.Cm; PhInvokeCallback(PhGetGeneralCallback(GeneralCallbackMemoryTreeNewUninitializing), &treeNewInfo); } PhSaveSettingsMemoryList(&memoryContext->ListContext); PhDeleteMemoryList(&memoryContext->ListContext); if (memoryContext->MemoryItemListValid) PhDeleteMemoryItemList(&memoryContext->MemoryItemList); PhClearReference(&memoryContext->ErrorMessage); PhFree(memoryContext); PhpPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { if (!propPageContext->LayoutInitialized) { PPH_LAYOUT_ITEM dialogItem; dialogItem = PhAddPropPageLayoutItem(hwndDlg, hwndDlg, PH_PROP_PAGE_TAB_CONTROL_PARENT, PH_ANCHOR_ALL); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_STRINGS), dialogItem, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddPropPageLayoutItem(hwndDlg, GetDlgItem(hwndDlg, IDC_REFRESH), dialogItem, PH_ANCHOR_TOP | PH_ANCHOR_RIGHT); PhAddPropPageLayoutItem(hwndDlg, memoryContext->ListContext.TreeNewHandle, dialogItem, PH_ANCHOR_ALL); PhDoPropPageLayout(hwndDlg); propPageContext->LayoutInitialized = TRUE; } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case ID_SHOWCONTEXTMENU: { PhShowMemoryContextMenu(hwndDlg, processItem, memoryContext, (PPH_TREENEW_CONTEXT_MENU)lParam); } break; case ID_MEMORY_READWRITEMEMORY: { PPH_MEMORY_NODE memoryNode = PhGetSelectedMemoryNode(&memoryContext->ListContext); if (memoryNode && !memoryNode->IsAllocationBase) { if (memoryNode->MemoryItem->State & MEM_COMMIT) { PPH_SHOWMEMORYEDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOWMEMORYEDITOR)); memset(showMemoryEditor, 0, sizeof(PH_SHOWMEMORYEDITOR)); showMemoryEditor->ProcessId = processItem->ProcessId; showMemoryEditor->BaseAddress = memoryNode->MemoryItem->BaseAddress; showMemoryEditor->RegionSize = memoryNode->MemoryItem->RegionSize; showMemoryEditor->SelectOffset = -1; showMemoryEditor->SelectLength = 0; ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor); } else { PhShowError(hwndDlg, L"Unable to edit the memory region because it is not committed."); } } } break; case ID_MEMORY_SAVE: { NTSTATUS status; HANDLE processHandle; PPH_MEMORY_NODE *memoryNodes; ULONG numberOfMemoryNodes; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_VM_READ, processItem->ProcessId ))) { PhShowStatus(hwndDlg, L"Unable to open the process", status, 0); break; } PhGetSelectedMemoryNodes(&memoryContext->ListContext, &memoryNodes, &numberOfMemoryNodes); if (numberOfMemoryNodes != 0) { static PH_FILETYPE_FILTER filters[] = { { L"Binary files (*.bin)", L"*.bin" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, PhaConcatStrings2(processItem->ProcessName->Buffer, L".bin")->Buffer); if (PhShowFileDialog(hwndDlg, fileDialog)) { PPH_STRING fileName; PPH_FILE_STREAM fileStream; PVOID buffer; ULONG i; ULONG_PTR offset; fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog)); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { buffer = PhAllocatePage(PAGE_SIZE, NULL); // Go through each selected memory item and append the region contents // to the file. for (i = 0; i < numberOfMemoryNodes; i++) { PPH_MEMORY_NODE memoryNode = memoryNodes[i]; PPH_MEMORY_ITEM memoryItem = memoryNode->MemoryItem; if (!memoryNode->IsAllocationBase && !(memoryItem->State & MEM_COMMIT)) continue; for (offset = 0; offset < memoryItem->RegionSize; offset += PAGE_SIZE) { if (NT_SUCCESS(NtReadVirtualMemory( processHandle, PTR_ADD_OFFSET(memoryItem->BaseAddress, offset), buffer, PAGE_SIZE, NULL ))) { PhWriteFileStream(fileStream, buffer, PAGE_SIZE); } } } PhFreePage(buffer); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } PhFree(memoryNodes); NtClose(processHandle); } break; case ID_MEMORY_CHANGEPROTECTION: { PPH_MEMORY_NODE memoryNode = PhGetSelectedMemoryNode(&memoryContext->ListContext); if (memoryNode) { PhReferenceObject(memoryNode->MemoryItem); PhShowMemoryProtectDialog(hwndDlg, processItem, memoryNode->MemoryItem); PhUpdateMemoryNode(&memoryContext->ListContext, memoryNode); PhDereferenceObject(memoryNode->MemoryItem); } } break; case ID_MEMORY_FREE: { PPH_MEMORY_NODE memoryNode = PhGetSelectedMemoryNode(&memoryContext->ListContext); if (memoryNode) { PhReferenceObject(memoryNode->MemoryItem); PhUiFreeMemory(hwndDlg, processItem->ProcessId, memoryNode->MemoryItem, TRUE); PhDereferenceObject(memoryNode->MemoryItem); // TODO: somehow update the list } } break; case ID_MEMORY_DECOMMIT: { PPH_MEMORY_NODE memoryNode = PhGetSelectedMemoryNode(&memoryContext->ListContext); if (memoryNode) { PhReferenceObject(memoryNode->MemoryItem); PhUiFreeMemory(hwndDlg, processItem->ProcessId, memoryNode->MemoryItem, FALSE); PhDereferenceObject(memoryNode->MemoryItem); } } break; case ID_MEMORY_READWRITEADDRESS: { PPH_STRING selectedChoice = NULL; if (!memoryContext->MemoryItemListValid) break; while (PhaChoiceDialog( hwndDlg, L"Read/Write Address", L"Enter an address:", NULL, 0, NULL, PH_CHOICE_DIALOG_USER_CHOICE, &selectedChoice, NULL, L"MemoryReadWriteAddressChoices" )) { ULONG64 address64; PVOID address; if (selectedChoice->Length == 0) continue; if (PhStringToInteger64(&selectedChoice->sr, 0, &address64)) { PPH_MEMORY_ITEM memoryItem; address = (PVOID)address64; memoryItem = PhLookupMemoryItemList(&memoryContext->MemoryItemList, address); if (memoryItem) { PPH_SHOWMEMORYEDITOR showMemoryEditor = PhAllocate(sizeof(PH_SHOWMEMORYEDITOR)); memset(showMemoryEditor, 0, sizeof(PH_SHOWMEMORYEDITOR)); showMemoryEditor->ProcessId = processItem->ProcessId; showMemoryEditor->BaseAddress = memoryItem->BaseAddress; showMemoryEditor->RegionSize = memoryItem->RegionSize; showMemoryEditor->SelectOffset = (ULONG)((ULONG_PTR)address - (ULONG_PTR)memoryItem->BaseAddress); showMemoryEditor->SelectLength = 0; ProcessHacker_ShowMemoryEditor(PhMainWndHandle, showMemoryEditor); break; } else { PhShowError(hwndDlg, L"Unable to find the memory region for the selected address."); } } } } break; case ID_MEMORY_COPY: { PPH_STRING text; text = PhGetTreeNewText(tnHandle, 0); PhSetClipboardString(tnHandle, &text->sr); PhDereferenceObject(text); } break; case IDC_HIDEFREEREGIONS: { BOOLEAN hide; hide = Button_GetCheck(GetDlgItem(hwndDlg, IDC_HIDEFREEREGIONS)) == BST_CHECKED; PhSetOptionsMemoryList(&memoryContext->ListContext, hide); } break; case IDC_STRINGS: PhShowMemoryStringDialog(hwndDlg, processItem); break; case IDC_REFRESH: PhpRefreshProcessMemoryList(hwndDlg, propPageContext); break; } } break; } return FALSE; }
VOID ReBarLoadLayoutSettings( VOID ) { UINT bandIndex = 0; UINT bandCount = 0; PPH_STRING settingsString; PH_STRINGREF remaining; settingsString = PhGetStringSetting(SETTING_NAME_REBAR_CONFIG); remaining = settingsString->sr; if (remaining.Length == 0) return; bandCount = (UINT)SendMessage(RebarHandle, RB_GETBANDCOUNT, 0, 0); for (bandIndex = 0; bandIndex < bandCount; bandIndex++) { PH_STRINGREF idPart; PH_STRINGREF cxPart; PH_STRINGREF stylePart; ULONG64 idInteger; ULONG64 cxInteger; ULONG64 styleInteger; UINT oldBandIndex; REBARBANDINFO rebarBandInfo = { REBARBANDINFO_V6_SIZE, RBBIM_STYLE | RBBIM_SIZE }; if (remaining.Length == 0) break; PhSplitStringRefAtChar(&remaining, '|', &idPart, &remaining); PhSplitStringRefAtChar(&remaining, '|', &cxPart, &remaining); PhSplitStringRefAtChar(&remaining, '|', &stylePart, &remaining); PhStringToInteger64(&idPart, 10, &idInteger); PhStringToInteger64(&cxPart, 10, &cxInteger); PhStringToInteger64(&stylePart, 10, &styleInteger); if ((oldBandIndex = (UINT)SendMessage(RebarHandle, RB_IDTOINDEX, (UINT)idInteger, 0)) == -1) break; if (oldBandIndex != bandIndex) { SendMessage(RebarHandle, RB_MOVEBAND, oldBandIndex, bandIndex); } if (SendMessage(RebarHandle, RB_GETBANDINFO, bandIndex, (LPARAM)&rebarBandInfo)) { if (idInteger == REBAR_BAND_ID_SEARCHBOX) { rebarBandInfo.fStyle |= RBBS_FIXEDSIZE; } rebarBandInfo.cx = (UINT)cxInteger; rebarBandInfo.fStyle |= (UINT)styleInteger; SendMessage(RebarHandle, RB_SETBANDINFO, bandIndex, (LPARAM)&rebarBandInfo); } } }
static NTSTATUS PhpFindObjectsThreadStart( __in PVOID Parameter ) { 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); PhUpperString(SearchString); if (NT_SUCCESS(PhEnumHandlesEx(&handles))) { processHandleHashtable = PhCreateSimpleHashtable(8); for (i = 0; i < handles->NumberOfHandles; i++) { PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo = &handles->Handles[i]; PPVOID processHandlePtr; HANDLE processHandle; PPH_STRING typeName; PPH_STRING bestObjectName; 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; } } // Get handle information. if (NT_SUCCESS(PhGetHandleInformation( processHandle, (HANDLE)handleInfo->HandleValue, handleInfo->ObjectTypeIndex, NULL, &typeName, NULL, &bestObjectName ))) { PPH_STRING upperBestObjectName; upperBestObjectName = PhDuplicateString(bestObjectName); PhUpperString(upperBestObjectName); if ( PhFindStringInString(upperBestObjectName, 0, SearchString->Buffer) != -1 || (UseSearchPointer && handleInfo->Object == (PVOID)SearchPointer) ) { PPHP_OBJECT_SEARCH_RESULT searchResult; searchResult = PhAllocate(sizeof(PHP_OBJECT_SEARCH_RESULT)); searchResult->ProcessId = (HANDLE)handleInfo->UniqueProcessId; searchResult->ResultType = HandleSearchResult; searchResult->Handle = (HANDLE)handleInfo->HandleValue; searchResult->TypeName = typeName; searchResult->Name = bestObjectName; PhPrintPointer(searchResult->HandleString, (PVOID)searchResult->Handle); searchResult->Info = *handleInfo; PhAcquireQueuedLockExclusive(&SearchResultsLock); PhAddItemList(SearchResults, searchResult); // Update the search results in batches of 40. if (SearchResults->Count % 40 == 0) PostMessage(PhFindObjectsWindowHandle, WM_PH_SEARCH_UPDATE, 0, 0); PhReleaseQueuedLockExclusive(&SearchResultsLock); } else { PhDereferenceObject(typeName); PhDereferenceObject(bestObjectName); } PhDereferenceObject(upperBestObjectName); } } { 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, 0, 0); return STATUS_SUCCESS; }
BOOLEAN PhCmLoadSettingsEx( _In_ HWND TreeNewHandle, _In_opt_ PPH_CM_MANAGER Manager, _In_ ULONG Flags, _In_ PPH_STRINGREF Settings, _In_opt_ PPH_STRINGREF SortSettings ) { BOOLEAN result = FALSE; PH_STRINGREF columnPart; PH_STRINGREF remainingColumnPart; PH_STRINGREF valuePart; PH_STRINGREF subPart; ULONG64 integer; ULONG total; BOOLEAN hasFixedColumn; ULONG count; ULONG i; PPH_HASHTABLE columnHashtable; PH_HASHTABLE_ENUM_CONTEXT enumContext; PPH_KEY_VALUE_PAIR pair; LONG orderArray[PH_CM_ORDER_LIMIT]; LONG maxOrder; if (Settings->Length != 0) { columnHashtable = PhCreateSimpleHashtable(20); remainingColumnPart = *Settings; while (remainingColumnPart.Length != 0) { PPH_TREENEW_COLUMN column; ULONG id; ULONG displayIndex; ULONG width; PhSplitStringRefAtChar(&remainingColumnPart, '|', &columnPart, &remainingColumnPart); if (columnPart.Length != 0) { // Id PhSplitStringRefAtChar(&columnPart, ',', &valuePart, &columnPart); if (valuePart.Length == 0) goto CleanupExit; if (valuePart.Buffer[0] == '+') { PH_STRINGREF pluginName; ULONG subId; PPH_CM_COLUMN cmColumn; // This is a plugin-owned column. if (!Manager) continue; if (!PhEmParseCompoundId(&valuePart, &pluginName, &subId)) continue; cmColumn = PhCmFindColumn(Manager, &pluginName, subId); if (!cmColumn) continue; // can't find the column, skip this part id = cmColumn->Id; } else { if (!PhStringToInteger64(&valuePart, 10, &integer)) goto CleanupExit; id = (ULONG)integer; } // Display Index PhSplitStringRefAtChar(&columnPart, ',', &valuePart, &columnPart); if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY)) { if (valuePart.Length == 0 || !PhStringToInteger64(&valuePart, 10, &integer)) goto CleanupExit; displayIndex = (ULONG)integer; } else { if (valuePart.Length != 0) goto CleanupExit; displayIndex = -1; } // Width if (columnPart.Length == 0 || !PhStringToInteger64(&columnPart, 10, &integer)) goto CleanupExit; width = (ULONG)integer; column = PhAllocate(sizeof(PH_TREENEW_COLUMN)); column->Id = id; column->DisplayIndex = displayIndex; column->Width = width; PhAddItemSimpleHashtable(columnHashtable, (PVOID)column->Id, column); } } TreeNew_SetRedraw(TreeNewHandle, FALSE); // Set visibility and width. i = 0; count = 0; total = TreeNew_GetColumnCount(TreeNewHandle); hasFixedColumn = !!TreeNew_GetFixedColumn(TreeNewHandle); memset(orderArray, 0, sizeof(orderArray)); maxOrder = 0; while (count < total) { PH_TREENEW_COLUMN setColumn; PPH_TREENEW_COLUMN *columnPtr; if (TreeNew_GetColumn(TreeNewHandle, i, &setColumn)) { columnPtr = (PPH_TREENEW_COLUMN *)PhFindItemSimpleHashtable(columnHashtable, (PVOID)i); if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY)) { if (columnPtr) { setColumn.Visible = TRUE; setColumn.Width = (*columnPtr)->Width; TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_FLAG_VISIBLE | TN_COLUMN_WIDTH, &setColumn); if (!setColumn.Fixed) { // For compatibility reasons, normal columns have their display indicies stored // one higher than usual (so they start from 1, not 0). Fix that here. if (hasFixedColumn && (*columnPtr)->DisplayIndex != 0) (*columnPtr)->DisplayIndex--; if ((*columnPtr)->DisplayIndex < PH_CM_ORDER_LIMIT) { orderArray[(*columnPtr)->DisplayIndex] = i; if ((ULONG)maxOrder < (*columnPtr)->DisplayIndex + 1) maxOrder = (*columnPtr)->DisplayIndex + 1; } } } else if (!setColumn.Fixed) // never hide the fixed column { setColumn.Visible = FALSE; TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_FLAG_VISIBLE, &setColumn); } } else { if (columnPtr) { setColumn.Width = (*columnPtr)->Width; TreeNew_SetColumn(TreeNewHandle, TN_COLUMN_WIDTH, &setColumn); } } count++; } i++; } if (!(Flags & PH_CM_COLUMN_WIDTHS_ONLY)) { // Set the order array. TreeNew_SetColumnOrderArray(TreeNewHandle, maxOrder, orderArray); } TreeNew_SetRedraw(TreeNewHandle, TRUE); result = TRUE; CleanupExit: PhBeginEnumHashtable(columnHashtable, &enumContext); while (pair = PhNextEnumHashtable(&enumContext)) PhFree(pair->Value); PhDereferenceObject(columnHashtable); } // Load sort settings. if (SortSettings && SortSettings->Length != 0) { PhSplitStringRefAtChar(SortSettings, ',', &valuePart, &subPart); if (valuePart.Length != 0 && subPart.Length != 0) { ULONG sortColumn; PH_SORT_ORDER sortOrder; sortColumn = -1; if (valuePart.Buffer[0] == '+') { PH_STRINGREF pluginName; ULONG subId; PPH_CM_COLUMN cmColumn; if ( Manager && PhEmParseCompoundId(&valuePart, &pluginName, &subId) && (cmColumn = PhCmFindColumn(Manager, &pluginName, subId)) ) { sortColumn = cmColumn->Id; } } else { PhStringToInteger64(&valuePart, 10, &integer); sortColumn = (ULONG)integer; } PhStringToInteger64(&subPart, 10, &integer); sortOrder = (PH_SORT_ORDER)integer; if (sortColumn != -1 && sortOrder <= DescendingSortOrder) { TreeNew_SetSort(TreeNewHandle, sortColumn, sortOrder); } } } return result; }
static BOOLEAN PhpSettingFromString( _In_ PH_SETTING_TYPE Type, _In_ PPH_STRINGREF StringRef, _In_opt_ PPH_STRING String, _Inout_ PPH_SETTING Setting ) { switch (Type) { case StringSettingType: { if (String) { PhSetReference(&Setting->u.Pointer, String); } else { Setting->u.Pointer = PhCreateString2(StringRef); } return TRUE; } case IntegerSettingType: { ULONG64 integer; if (PhStringToInteger64(StringRef, 16, &integer)) { Setting->u.Integer = (ULONG)integer; return TRUE; } else { return FALSE; } } case IntegerPairSettingType: { LONG64 x; LONG64 y; PH_STRINGREF xString; PH_STRINGREF yString; if (!PhSplitStringRefAtChar(StringRef, ',', &xString, &yString)) return FALSE; if (PhStringToInteger64(&xString, 10, &x) && PhStringToInteger64(&yString, 10, &y)) { Setting->u.IntegerPair.X = (LONG)x; Setting->u.IntegerPair.Y = (LONG)y; return TRUE; } else { return FALSE; } } case ScalableIntegerPairSettingType: { ULONG64 scale; LONG64 x; LONG64 y; PH_STRINGREF stringRef; PH_STRINGREF firstPart; PH_STRINGREF secondPart; PPH_SCALABLE_INTEGER_PAIR scalableIntegerPair; stringRef = *StringRef; if (stringRef.Length != 0 && stringRef.Buffer[0] == '@') { PhSkipStringRef(&stringRef, sizeof(WCHAR)); if (!PhSplitStringRefAtChar(&stringRef, '|', &firstPart, &stringRef)) return FALSE; if (!PhStringToInteger64(&firstPart, 10, &scale)) return FALSE; } else { scale = PhpGetCurrentScale(); } if (!PhSplitStringRefAtChar(&stringRef, ',', &firstPart, &secondPart)) return FALSE; if (PhStringToInteger64(&firstPart, 10, &x) && PhStringToInteger64(&secondPart, 10, &y)) { scalableIntegerPair = PhAllocate(sizeof(PH_SCALABLE_INTEGER_PAIR)); scalableIntegerPair->X = (LONG)x; scalableIntegerPair->Y = (LONG)y; scalableIntegerPair->Scale = (ULONG)scale; Setting->u.Pointer = scalableIntegerPair; return TRUE; } else { return FALSE; } } } return FALSE; }
static BOOL QueryXmlData( VOID ) { PCHAR data = NULL; BOOL isSuccess = FALSE; HINTERNET netInitialize = NULL, netConnection = NULL, netRequest = NULL; mxml_node_t *xmlDoc = NULL, *xmlNodeVer = NULL, *xmlNodeRelDate = NULL, *xmlNodeSize = NULL, *xmlNodeHash = NULL; // Create a user agent string. PPH_STRING phVersion = PhGetPhVersion(); PPH_STRING userAgent = PhConcatStrings2(L"PH Updater v", phVersion->Buffer); __try { // Initialize the wininet library. if (!(netInitialize = InternetOpen( userAgent->Buffer, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 ))) { LogEvent(NULL, PhFormatString(L"Updater: (InitializeConnection) InternetOpen failed (%d)", GetLastError())); __leave; } // Connect to the server. if (!(netConnection = InternetConnect( netInitialize, UPDATE_URL, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 ))) { LogEvent(NULL, PhFormatString(L"Updater: (InitializeConnection) InternetConnect failed (%d)", GetLastError())); __leave; } // Open the HTTP request. if (!(netRequest = HttpOpenRequest( netConnection, L"GET", UPDATE_FILE, NULL, NULL, NULL, // wj32: do NOT cache --------------------------- Old - "Always cache the update xml, it can be cleared by deleting IE history, we configured the file to cache locally for two days." INTERNET_FLAG_RELOAD, 0 ))) { LogEvent(NULL, PhFormatString(L"Updater: (InitializeConnection) HttpOpenRequest failed (%d)", GetLastError())); __leave; } // Send the HTTP request. if (!HttpSendRequest(netRequest, NULL, 0, NULL, 0)) { LogEvent(NULL, PhFormatString(L"HttpSendRequest failed (%d)", GetLastError())); __leave; } // Read the resulting xml into our buffer. if (!ReadRequestString(netRequest, &data, NULL)) { // We don't need to log this. __leave; } // Load our XML. xmlDoc = mxmlLoadString(NULL, data, QueryXmlDataCallback); // Check our XML. if (xmlDoc == NULL || xmlDoc->type != MXML_ELEMENT) { LogEvent(NULL, PhCreateString(L"Updater: (WorkerThreadStart) mxmlLoadString failed.")); __leave; } // Find the ver node. xmlNodeVer = mxmlFindElement(xmlDoc, xmlDoc, "ver", NULL, NULL, MXML_DESCEND); // Find the reldate node. xmlNodeRelDate = mxmlFindElement(xmlDoc, xmlDoc, "reldate", NULL, NULL, MXML_DESCEND); // Find the size node. xmlNodeSize = mxmlFindElement(xmlDoc, xmlDoc, "size", NULL, NULL, MXML_DESCEND); // Find the hash node. xmlNodeHash = mxmlFindElement(xmlDoc, xmlDoc, "sha1", NULL, NULL, MXML_DESCEND); // Format strings into unicode PPH_STRING's UpdateData.Version = PhGetOpaqueXmlNodeText(xmlNodeVer); UpdateData.RelDate = PhGetOpaqueXmlNodeText(xmlNodeRelDate); UpdateData.Size = PhGetOpaqueXmlNodeText(xmlNodeSize); UpdateData.Hash = PhGetOpaqueXmlNodeText(xmlNodeHash); // parse and check string //if (!ParseVersionString(XmlData->Version->Buffer, &XmlData->MajorVersion, &XmlData->MinorVersion)) // __leave; if (!PhIsNullOrEmptyString(UpdateData.Version)) { PH_STRINGREF sr, majorPart, minorPart; ULONG64 majorInteger = 0, minorInteger = 0; PhInitializeStringRef(&sr, UpdateData.Version->Buffer); if (PhSplitStringRefAtChar(&sr, '.', &majorPart, &minorPart)) { PhStringToInteger64(&majorPart, 10, &majorInteger); PhStringToInteger64(&minorPart, 10, &minorInteger); UpdateData.MajorVersion = (ULONG)majorInteger; UpdateData.MinorVersion = (ULONG)minorInteger; isSuccess = TRUE; } } } __finally { if (xmlDoc) { mxmlDelete(xmlDoc); xmlDoc = NULL; } if (netInitialize) { InternetCloseHandle(netInitialize); netInitialize = NULL; } if (netConnection) { InternetCloseHandle(netConnection); netConnection = NULL; } if (netRequest) { InternetCloseHandle(netRequest); netRequest = NULL; } if (userAgent) { PhDereferenceObject(userAgent); userAgent = NULL; } if (phVersion) { PhDereferenceObject(phVersion); phVersion = NULL; } } return isSuccess; }
NTSTATUS PhCommandModeStart( VOID ) { static PH_COMMAND_LINE_OPTION options[] = { { PH_COMMAND_OPTION_HWND, L"hwnd", MandatoryArgumentType } }; NTSTATUS status; PPH_STRING commandLine; if (!NT_SUCCESS(status = PhGetProcessCommandLine(NtCurrentProcess(), &commandLine))) return status; PhParseCommandLine( &commandLine->sr, options, sizeof(options) / sizeof(PH_COMMAND_LINE_OPTION), PH_COMMAND_LINE_IGNORE_UNKNOWN_OPTIONS, PhpCommandModeOptionCallback, NULL ); PhDereferenceObject(commandLine); if (PhEqualString2(PhStartupParameters.CommandType, L"process", TRUE)) { SIZE_T i; SIZE_T processIdLength; HANDLE processId; HANDLE processHandle; if (!PhStartupParameters.CommandObject) return STATUS_INVALID_PARAMETER; processIdLength = PhStartupParameters.CommandObject->Length / 2; for (i = 0; i < processIdLength; i++) { if (!PhIsDigitCharacter(PhStartupParameters.CommandObject->Buffer[i])) break; } if (i == processIdLength) { ULONG64 processId64; if (!PhStringToInteger64(&PhStartupParameters.CommandObject->sr, 10, &processId64)) return STATUS_INVALID_PARAMETER; processId = (HANDLE)processId64; } else { PVOID processes; PSYSTEM_PROCESS_INFORMATION process; if (!NT_SUCCESS(status = PhEnumProcesses(&processes))) return status; if (!(process = PhFindProcessInformationByImageName(processes, &PhStartupParameters.CommandObject->sr))) { PhFree(processes); return STATUS_NOT_FOUND; } processId = process->UniqueProcessId; PhFree(processes); } if (PhEqualString2(PhStartupParameters.CommandAction, L"terminate", TRUE)) { if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_TERMINATE, processId))) { status = NtTerminateProcess(processHandle, STATUS_SUCCESS); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"suspend", TRUE)) { if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SUSPEND_RESUME, processId))) { status = NtSuspendProcess(processHandle); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"resume", TRUE)) { if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SUSPEND_RESUME, processId))) { status = NtResumeProcess(processHandle); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"priority", TRUE)) { UCHAR priority; if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; if (PhEqualString2(PhStartupParameters.CommandValue, L"idle", TRUE)) priority = PROCESS_PRIORITY_CLASS_IDLE; else if (PhEqualString2(PhStartupParameters.CommandValue, L"normal", TRUE)) priority = PROCESS_PRIORITY_CLASS_NORMAL; else if (PhEqualString2(PhStartupParameters.CommandValue, L"high", TRUE)) priority = PROCESS_PRIORITY_CLASS_HIGH; else if (PhEqualString2(PhStartupParameters.CommandValue, L"realtime", TRUE)) priority = PROCESS_PRIORITY_CLASS_REALTIME; else if (PhEqualString2(PhStartupParameters.CommandValue, L"abovenormal", TRUE)) priority = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; else if (PhEqualString2(PhStartupParameters.CommandValue, L"belownormal", TRUE)) priority = PROCESS_PRIORITY_CLASS_BELOW_NORMAL; else return STATUS_INVALID_PARAMETER; if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId))) { PROCESS_PRIORITY_CLASS priorityClass; priorityClass.Foreground = FALSE; priorityClass.PriorityClass = priority; status = NtSetInformationProcess(processHandle, ProcessPriorityClass, &priorityClass, sizeof(PROCESS_PRIORITY_CLASS)); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"iopriority", TRUE)) { ULONG ioPriority; if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; if (PhEqualString2(PhStartupParameters.CommandValue, L"verylow", TRUE)) ioPriority = 0; else if (PhEqualString2(PhStartupParameters.CommandValue, L"low", TRUE)) ioPriority = 1; else if (PhEqualString2(PhStartupParameters.CommandValue, L"normal", TRUE)) ioPriority = 2; else if (PhEqualString2(PhStartupParameters.CommandValue, L"high", TRUE)) ioPriority = 3; else return STATUS_INVALID_PARAMETER; if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId))) { status = PhSetProcessIoPriority(processHandle, ioPriority); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"pagepriority", TRUE)) { ULONG64 pagePriority64; ULONG pagePriority; if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; PhStringToInteger64(&PhStartupParameters.CommandValue->sr, 10, &pagePriority64); pagePriority = (ULONG)pagePriority64; if (NT_SUCCESS(status = PhOpenProcessPublic(&processHandle, PROCESS_SET_INFORMATION, processId))) { status = NtSetInformationProcess( processHandle, ProcessPagePriority, &pagePriority, sizeof(ULONG) ); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"injectdll", TRUE)) { if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; if (NT_SUCCESS(status = PhOpenProcessPublic( &processHandle, ProcessQueryAccess | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, processId ))) { LARGE_INTEGER timeout; timeout.QuadPart = -5 * PH_TIMEOUT_SEC; status = PhInjectDllProcess( processHandle, PhStartupParameters.CommandValue->Buffer, &timeout ); NtClose(processHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"unloaddll", TRUE)) { if (!PhStartupParameters.CommandValue) return STATUS_INVALID_PARAMETER; if (NT_SUCCESS(status = PhOpenProcessPublic( &processHandle, ProcessQueryAccess | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, processId ))) { PVOID baseAddress; if (NT_SUCCESS(status = PhpGetDllBaseRemote( processHandle, &PhStartupParameters.CommandValue->sr, &baseAddress ))) { LARGE_INTEGER timeout; timeout.QuadPart = -5 * PH_TIMEOUT_SEC; status = PhUnloadDllProcess( processHandle, baseAddress, &timeout ); } NtClose(processHandle); } } } else if (PhEqualString2(PhStartupParameters.CommandType, L"service", TRUE)) { SC_HANDLE serviceHandle; SERVICE_STATUS serviceStatus; if (!PhStartupParameters.CommandObject) return STATUS_INVALID_PARAMETER; if (PhEqualString2(PhStartupParameters.CommandAction, L"start", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, SERVICE_START ))) return PhGetLastWin32ErrorAsNtStatus(); if (!StartService(serviceHandle, 0, NULL)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } else if (PhEqualString2(PhStartupParameters.CommandAction, L"continue", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, SERVICE_PAUSE_CONTINUE ))) return PhGetLastWin32ErrorAsNtStatus(); if (!ControlService(serviceHandle, SERVICE_CONTROL_CONTINUE, &serviceStatus)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } else if (PhEqualString2(PhStartupParameters.CommandAction, L"pause", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, SERVICE_PAUSE_CONTINUE ))) return PhGetLastWin32ErrorAsNtStatus(); if (!ControlService(serviceHandle, SERVICE_CONTROL_PAUSE, &serviceStatus)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } else if (PhEqualString2(PhStartupParameters.CommandAction, L"stop", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, SERVICE_STOP ))) return PhGetLastWin32ErrorAsNtStatus(); if (!ControlService(serviceHandle, SERVICE_CONTROL_STOP, &serviceStatus)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } else if (PhEqualString2(PhStartupParameters.CommandAction, L"delete", TRUE)) { if (!(serviceHandle = PhOpenService( PhStartupParameters.CommandObject->Buffer, DELETE ))) return PhGetLastWin32ErrorAsNtStatus(); if (!DeleteService(serviceHandle)) status = PhGetLastWin32ErrorAsNtStatus(); CloseServiceHandle(serviceHandle); } } else if (PhEqualString2(PhStartupParameters.CommandType, L"thread", TRUE)) { ULONG64 threadId64; HANDLE threadId; HANDLE threadHandle; if (!PhStartupParameters.CommandObject) return STATUS_INVALID_PARAMETER; if (!PhStringToInteger64(&PhStartupParameters.CommandObject->sr, 10, &threadId64)) return STATUS_INVALID_PARAMETER; threadId = (HANDLE)threadId64; if (PhEqualString2(PhStartupParameters.CommandAction, L"terminate", TRUE)) { if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_TERMINATE, threadId))) { status = NtTerminateThread(threadHandle, STATUS_SUCCESS); NtClose(threadHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"suspend", TRUE)) { if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_SUSPEND_RESUME, threadId))) { status = NtSuspendThread(threadHandle, NULL); NtClose(threadHandle); } } else if (PhEqualString2(PhStartupParameters.CommandAction, L"resume", TRUE)) { if (NT_SUCCESS(status = PhOpenThreadPublic(&threadHandle, THREAD_SUSPEND_RESUME, threadId))) { status = NtResumeThread(threadHandle, NULL); NtClose(threadHandle); } } } return status; }
INT_PTR CALLBACK PhpMemoryEditorDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PMEMORY_EDITOR_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PMEMORY_EDITOR_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { NTSTATUS status; if (context->Title) { SetWindowText(hwndDlg, context->Title->Buffer); } else { PPH_PROCESS_ITEM processItem; if (processItem = PhReferenceProcessItem(context->ProcessId)) { SetWindowText(hwndDlg, PhaFormatString(L"%s (%u) (0x%Ix - 0x%Ix)", processItem->ProcessName->Buffer, HandleToUlong(context->ProcessId), context->BaseAddress, (ULONG_PTR)context->BaseAddress + context->RegionSize)->Buffer); PhDereferenceObject(processItem); } } PhInitializeLayoutManager(&context->LayoutManager, hwndDlg); if (context->RegionSize > 1024 * 1024 * 1024) // 1 GB { PhShowError(NULL, L"Unable to edit the memory region because it is too large."); return TRUE; } if (!NT_SUCCESS(status = PhOpenProcess( &context->ProcessHandle, PROCESS_VM_READ, context->ProcessId ))) { PhShowStatus(NULL, L"Unable to open the process", status, 0); return TRUE; } context->Buffer = PhAllocatePage(context->RegionSize, NULL); if (!context->Buffer) { PhShowError(NULL, L"Unable to allocate memory for the buffer."); return TRUE; } if (!NT_SUCCESS(status = PhReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(PhMainWndHandle, L"Unable to read memory", status, 0); return TRUE; } PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_BYTESPERROW), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_GOTO), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_WRITE), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); PhAddLayoutItem(&context->LayoutManager, GetDlgItem(hwndDlg, IDC_REREAD), NULL, PH_ANCHOR_BOTTOM | PH_ANCHOR_LEFT); if (MinimumSize.left == -1) { RECT rect; rect.left = 0; rect.top = 0; rect.right = 290; rect.bottom = 140; MapDialogRect(hwndDlg, &rect); MinimumSize = rect; MinimumSize.left = 0; } context->HexEditHandle = GetDlgItem(hwndDlg, IDC_MEMORY); PhAddLayoutItem(&context->LayoutManager, context->HexEditHandle, NULL, PH_ANCHOR_ALL); HexEdit_SetBuffer(context->HexEditHandle, context->Buffer, (ULONG)context->RegionSize); { PH_RECTANGLE windowRectangle; windowRectangle.Position = PhGetIntegerPairSetting(L"MemEditPosition"); windowRectangle.Size = PhGetScalableIntegerPairSetting(L"MemEditSize", TRUE).Pair; PhAdjustRectangleToWorkingArea(NULL, &windowRectangle); MoveWindow(hwndDlg, windowRectangle.Left, windowRectangle.Top, windowRectangle.Width, windowRectangle.Height, FALSE); // Implement cascading by saving an offsetted rectangle. windowRectangle.Left += 20; windowRectangle.Top += 20; PhSetIntegerPairSetting(L"MemEditPosition", windowRectangle.Position); PhSetScalableIntegerPairSetting2(L"MemEditSize", windowRectangle.Size); } { PWSTR bytesPerRowStrings[7]; ULONG i; ULONG bytesPerRow; for (i = 0; i < sizeof(bytesPerRowStrings) / sizeof(PWSTR); i++) bytesPerRowStrings[i] = PhaFormatString(L"%u bytes per row", 1 << (2 + i))->Buffer; PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_BYTESPERROW), bytesPerRowStrings, sizeof(bytesPerRowStrings) / sizeof(PWSTR)); bytesPerRow = PhGetIntegerSetting(L"MemEditBytesPerRow"); if (bytesPerRow >= 4) { HexEdit_SetBytesPerRow(context->HexEditHandle, bytesPerRow); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_BYTESPERROW), PhaFormatString(L"%u bytes per row", bytesPerRow)->Buffer, FALSE); } } context->LoadCompleted = TRUE; } break; case WM_DESTROY: { if (context->LoadCompleted) { PhSaveWindowPlacementToSetting(L"MemEditPosition", L"MemEditSize", hwndDlg); PhRemoveElementAvlTree(&PhMemoryEditorSet, &context->Links); PhUnregisterDialog(hwndDlg); } RemoveProp(hwndDlg, PhMakeContextAtom()); PhDeleteLayoutManager(&context->LayoutManager); if (context->Buffer) PhFreePage(context->Buffer); if (context->ProcessHandle) NtClose(context->ProcessHandle); PhClearReference(&context->Title); if ((context->Flags & PH_MEMORY_EDITOR_UNMAP_VIEW_OF_SECTION) && context->ProcessId == NtCurrentProcessId()) NtUnmapViewOfSection(NtCurrentProcess(), context->BaseAddress); PhFree(context); } break; case WM_SHOWWINDOW: { SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Binary files (*.bin)", L"*.bin" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_PROCESS_ITEM processItem; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); if (!context->Title && (processItem = PhReferenceProcessItem(context->ProcessId))) { PhSetFileDialogFileName(fileDialog, PhaFormatString(L"%s_0x%Ix-0x%Ix.bin", processItem->ProcessName->Buffer, context->BaseAddress, context->RegionSize)->Buffer); PhDereferenceObject(processItem); } else { PhSetFileDialogFileName(fileDialog, L"Memory.bin"); } if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; fileName = PH_AUTO(PhGetFileDialogFileName(fileDialog)); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { status = PhWriteFileStream(fileStream, context->Buffer, (ULONG)context->RegionSize); PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; case IDC_GOTO: { PPH_STRING selectedChoice = NULL; while (PhaChoiceDialog( hwndDlg, L"Go to Offset", L"Enter an offset:", NULL, 0, NULL, PH_CHOICE_DIALOG_USER_CHOICE, &selectedChoice, NULL, L"MemEditGotoChoices" )) { ULONG64 offset; if (selectedChoice->Length == 0) continue; if (PhStringToInteger64(&selectedChoice->sr, 0, &offset)) { if (offset >= context->RegionSize) { PhShowError(hwndDlg, L"The offset is too large."); continue; } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); HexEdit_SetSel(context->HexEditHandle, (LONG)offset, (LONG)offset); break; } } } break; case IDC_WRITE: { NTSTATUS status; if (!context->WriteAccess) { HANDLE processHandle; if (!NT_SUCCESS(status = PhOpenProcess( &processHandle, PROCESS_VM_READ | PROCESS_VM_WRITE, context->ProcessId ))) { PhShowStatus(hwndDlg, L"Unable to open the process", status, 0); break; } if (context->ProcessHandle) NtClose(context->ProcessHandle); context->ProcessHandle = processHandle; context->WriteAccess = TRUE; } if (!NT_SUCCESS(status = PhWriteVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to write memory", status, 0); } } break; case IDC_REREAD: { NTSTATUS status; if (!NT_SUCCESS(status = PhReadVirtualMemory( context->ProcessHandle, context->BaseAddress, context->Buffer, context->RegionSize, NULL ))) { PhShowStatus(hwndDlg, L"Unable to read memory", status, 0); } InvalidateRect(context->HexEditHandle, NULL, TRUE); } break; case IDC_BYTESPERROW: if (HIWORD(wParam) == CBN_SELCHANGE) { PPH_STRING bytesPerRowString = PhaGetDlgItemText(hwndDlg, IDC_BYTESPERROW); PH_STRINGREF firstPart; PH_STRINGREF secondPart; ULONG64 bytesPerRow64; if (PhSplitStringRefAtChar(&bytesPerRowString->sr, ' ', &firstPart, &secondPart)) { if (PhStringToInteger64(&firstPart, 10, &bytesPerRow64)) { PhSetIntegerSetting(L"MemEditBytesPerRow", (ULONG)bytesPerRow64); HexEdit_SetBytesPerRow(context->HexEditHandle, (ULONG)bytesPerRow64); SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)context->HexEditHandle, TRUE); } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&context->LayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_PH_SELECT_OFFSET: { HexEdit_SetEditMode(context->HexEditHandle, EDIT_ASCII); HexEdit_SetSel(context->HexEditHandle, (ULONG)wParam, (ULONG)wParam + (ULONG)lParam); } break; } return FALSE; }
VOID ToolbarLoadButtonSettings( VOID ) { INT count; ULONG64 countInteger; PPH_STRING settingsString; PTBBUTTON buttonArray; PH_STRINGREF remaining; PH_STRINGREF part; settingsString = PhaGetStringSetting(SETTING_NAME_TOOLBAR_CONFIG); remaining = settingsString->sr; if (remaining.Length == 0) { // Load default settings SendMessage(ToolBarHandle, TB_ADDBUTTONS, MAX_DEFAULT_TOOLBAR_ITEMS, (LPARAM)ToolbarButtons); return; } // Query the number of buttons to insert if (!PhSplitStringRefAtChar(&remaining, '|', &part, &remaining)) { // Load default settings SendMessage(ToolBarHandle, TB_ADDBUTTONS, MAX_DEFAULT_TOOLBAR_ITEMS, (LPARAM)ToolbarButtons); return; } if (!PhStringToInteger64(&part, 10, &countInteger)) { // Load default settings SendMessage(ToolBarHandle, TB_ADDBUTTONS, MAX_DEFAULT_TOOLBAR_ITEMS, (LPARAM)ToolbarButtons); return; } count = (INT)countInteger; // Allocate the button array buttonArray = PhAllocate(count * sizeof(TBBUTTON)); memset(buttonArray, 0, count * sizeof(TBBUTTON)); for (INT index = 0; index < count; index++) { ULONG64 commandInteger; PH_STRINGREF commandIdPart; if (remaining.Length == 0) break; PhSplitStringRefAtChar(&remaining, '|', &commandIdPart, &remaining); PhStringToInteger64(&commandIdPart, 10, &commandInteger); buttonArray[index].idCommand = (INT)commandInteger; //buttonArray[index].iBitmap = I_IMAGECALLBACK; buttonArray[index].fsState = TBSTATE_ENABLED; if (commandInteger) { buttonArray[index].fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE; } else { buttonArray[index].fsStyle = BTNS_SEP; } // Pre-cache the image in the Toolbar array on startup. for (INT i = 0; i < ARRAYSIZE(ToolbarButtons); i++) { if (ToolbarButtons[i].idCommand == buttonArray[index].idCommand) { HBITMAP bitmap; bitmap = ToolbarGetImage(ToolbarButtons[i].idCommand); // Add the image, cache the value in the ToolbarButtons array, set the bitmap index. buttonArray[index].iBitmap = ToolbarButtons[i].iBitmap = ImageList_Add( ToolBarImageList, bitmap, NULL ); DeleteObject(bitmap); break; } } } SendMessage(ToolBarHandle, TB_ADDBUTTONS, count, (LPARAM)buttonArray); PhFree(buttonArray); }