static VOID ServiceActionToComboBox( _In_ HWND ComboBoxHandle, _In_ SC_ACTION_TYPE ActionType ) { PWSTR string; if (string = EspServiceActionToString(ActionType)) PhSelectComboBoxString(ComboBoxHandle, string, FALSE); else PhSelectComboBoxString(ComboBoxHandle, (PWSTR)ServiceActionPairs[0].Key, FALSE); }
VOID EspAddServiceActionStrings( _In_ HWND ComboBoxHandle ) { ULONG i; for (i = 0; i < sizeof(ServiceActionPairs) / sizeof(PH_KEY_VALUE_PAIR); i++) ComboBox_AddString(ComboBoxHandle, (PWSTR)ServiceActionPairs[i].Key); PhSelectComboBoxString(ComboBoxHandle, (PWSTR)ServiceActionPairs[0].Key, FALSE); }
INT_PTR CALLBACK PhpServiceGeneralDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PSERVICE_PROPERTIES_CONTEXT context = (PSERVICE_PROPERTIES_CONTEXT)propSheetPage->lParam; PPH_SERVICE_ITEM serviceItem = context->ServiceItem; SC_HANDLE serviceHandle; ULONG startType; ULONG errorControl; // HACK PhCenterWindow(GetParent(hwndDlg), GetParent(GetParent(hwndDlg))); SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_TYPE), PhServiceTypeStrings, sizeof(PhServiceTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_STARTTYPE), PhServiceStartTypeStrings, sizeof(PhServiceStartTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), PhServiceErrorControlStrings, sizeof(PhServiceErrorControlStrings) / sizeof(WCHAR *)); SetDlgItemText(hwndDlg, IDC_DESCRIPTION, serviceItem->DisplayName->Buffer); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), PhGetServiceTypeString(serviceItem->Type), FALSE); startType = serviceItem->StartType; errorControl = serviceItem->ErrorControl; serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_QUERY_CONFIG); if (serviceHandle) { LPQUERY_SERVICE_CONFIG config; PPH_STRING description; BOOLEAN delayedStart; if (config = PhGetServiceConfig(serviceHandle)) { SetDlgItemText(hwndDlg, IDC_GROUP, config->lpLoadOrderGroup); SetDlgItemText(hwndDlg, IDC_BINARYPATH, config->lpBinaryPathName); SetDlgItemText(hwndDlg, IDC_USERACCOUNT, config->lpServiceStartName); if (startType != config->dwStartType || errorControl != config->dwErrorControl) { startType = config->dwStartType; errorControl = config->dwErrorControl; PhMarkNeedsConfigUpdateServiceItem(serviceItem); } PhFree(config); } if (description = PhGetServiceDescription(serviceHandle)) { SetDlgItemText(hwndDlg, IDC_DESCRIPTION, description->Buffer); PhDereferenceObject(description); } if ( WindowsVersion >= WINDOWS_VISTA && PhGetServiceDelayedAutoStart(serviceHandle, &delayedStart) ) { context->OldDelayedStart = delayedStart; if (delayedStart) Button_SetCheck(GetDlgItem(hwndDlg, IDC_DELAYEDSTART), BST_CHECKED); } CloseServiceHandle(serviceHandle); } PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_STARTTYPE), PhGetServiceStartTypeString(startType), FALSE); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), PhGetServiceErrorControlString(errorControl), FALSE); SetDlgItemText(hwndDlg, IDC_PASSWORD, L"password"); Button_SetCheck(GetDlgItem(hwndDlg, IDC_PASSWORDCHECK), BST_UNCHECKED); SetDlgItemText(hwndDlg, IDC_SERVICEDLL, L"N/A"); { HANDLE keyHandle; PPH_STRING keyName; keyName = PhConcatStrings( 3, L"System\\CurrentControlSet\\Services\\", serviceItem->Name->Buffer, L"\\Parameters" ); if (NT_SUCCESS(PhOpenKey( &keyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &keyName->sr, 0 ))) { PPH_STRING serviceDllString; if (serviceDllString = PhQueryRegistryString(keyHandle, L"ServiceDll")) { PPH_STRING expandedString; if (expandedString = PhExpandEnvironmentStrings(&serviceDllString->sr)) { SetDlgItemText(hwndDlg, IDC_SERVICEDLL, expandedString->Buffer); PhDereferenceObject(expandedString); } PhDereferenceObject(serviceDllString); } NtClose(keyHandle); } PhDereferenceObject(keyName); } PhpRefreshControls(hwndDlg); context->Ready = TRUE; } break; case WM_DESTROY: { RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { PSERVICE_PROPERTIES_CONTEXT context = (PSERVICE_PROPERTIES_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); switch (LOWORD(wParam)) { case IDCANCEL: { // Workaround for property sheet + multiline edit: http://support.microsoft.com/kb/130765 SendMessage(GetParent(hwndDlg), uMsg, wParam, lParam); } break; case IDC_PASSWORD: { if (HIWORD(wParam) == EN_CHANGE) { Button_SetCheck(GetDlgItem(hwndDlg, IDC_PASSWORDCHECK), BST_CHECKED); } } break; case IDC_DELAYEDSTART: { context->Dirty = TRUE; } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Executable files (*.exe;*.sys)", L"*.exe;*.sys" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_STRING fileName; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); fileName = PhGetFileName(PHA_GET_DLGITEM_TEXT(hwndDlg, IDC_BINARYPATH)); PhSetFileDialogFileName(fileDialog, fileName->Buffer); PhDereferenceObject(fileName); if (PhShowFileDialog(hwndDlg, fileDialog)) { fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_BINARYPATH, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; } switch (HIWORD(wParam)) { case EN_CHANGE: case CBN_SELCHANGE: { PhpRefreshControls(hwndDlg); if (context->Ready) context->Dirty = TRUE; } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_QUERYINITIALFOCUS: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hwndDlg, IDC_STARTTYPE)); } return TRUE; case PSN_KILLACTIVE: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); } return TRUE; case PSN_APPLY: { NTSTATUS status; PSERVICE_PROPERTIES_CONTEXT context = (PSERVICE_PROPERTIES_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); PPH_SERVICE_ITEM serviceItem = context->ServiceItem; SC_HANDLE serviceHandle; PPH_STRING newServiceTypeString; PPH_STRING newServiceStartTypeString; PPH_STRING newServiceErrorControlString; ULONG newServiceType; ULONG newServiceStartType; ULONG newServiceErrorControl; PPH_STRING newServiceGroup; PPH_STRING newServiceBinaryPath; PPH_STRING newServiceUserAccount; PPH_STRING newServicePassword; SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); if (!context->Dirty) { return TRUE; } newServiceTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_TYPE))); newServiceStartTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_STARTTYPE))); newServiceErrorControlString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_ERRORCONTROL))); newServiceType = PhGetServiceTypeInteger(newServiceTypeString->Buffer); newServiceStartType = PhGetServiceStartTypeInteger(newServiceStartTypeString->Buffer); newServiceErrorControl = PhGetServiceErrorControlInteger(newServiceErrorControlString->Buffer); newServiceGroup = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_GROUP))); newServiceBinaryPath = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_BINARYPATH))); newServiceUserAccount = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_USERACCOUNT))); if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_PASSWORDCHECK)) == BST_CHECKED) { newServicePassword = PhGetWindowText(GetDlgItem(hwndDlg, IDC_PASSWORD)); } else { newServicePassword = NULL; } if (newServiceType == SERVICE_KERNEL_DRIVER && newServiceUserAccount->Length == 0) { newServiceUserAccount = NULL; } serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_CHANGE_CONFIG); if (serviceHandle) { if (ChangeServiceConfig( serviceHandle, newServiceType, newServiceStartType, newServiceErrorControl, newServiceBinaryPath->Buffer, newServiceGroup->Buffer, NULL, NULL, PhGetString(newServiceUserAccount), PhGetString(newServicePassword), NULL )) { if (WindowsVersion >= WINDOWS_VISTA) { BOOLEAN newDelayedStart; newDelayedStart = Button_GetCheck(GetDlgItem(hwndDlg, IDC_DELAYEDSTART)) == BST_CHECKED; if (newDelayedStart != context->OldDelayedStart) { PhSetServiceDelayedAutoStart(serviceHandle, newDelayedStart); } } PhMarkNeedsConfigUpdateServiceItem(serviceItem); CloseServiceHandle(serviceHandle); } else { CloseServiceHandle(serviceHandle); goto ErrorCase; } } else { if (GetLastError() == ERROR_ACCESS_DENIED && !PhElevated) { // Elevate using phsvc. if (PhUiConnectToPhSvc(hwndDlg, FALSE)) { if (NT_SUCCESS(status = PhSvcCallChangeServiceConfig( serviceItem->Name->Buffer, newServiceType, newServiceStartType, newServiceErrorControl, newServiceBinaryPath->Buffer, newServiceGroup->Buffer, NULL, NULL, PhGetString(newServiceUserAccount), PhGetString(newServicePassword), NULL ))) { if (WindowsVersion >= WINDOWS_VISTA) { BOOLEAN newDelayedStart; newDelayedStart = Button_GetCheck(GetDlgItem(hwndDlg, IDC_DELAYEDSTART)) == BST_CHECKED; if (newDelayedStart != context->OldDelayedStart) { SERVICE_DELAYED_AUTO_START_INFO info; info.fDelayedAutostart = newDelayedStart; PhSvcCallChangeServiceConfig2( serviceItem->Name->Buffer, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &info ); } } PhMarkNeedsConfigUpdateServiceItem(serviceItem); } PhUiDisconnectFromPhSvc(); if (!NT_SUCCESS(status)) { SetLastError(PhNtStatusToDosError(status)); goto ErrorCase; } } else { // User cancelled elevation. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } } else { goto ErrorCase; } } goto Cleanup; ErrorCase: if (PhShowMessage( hwndDlg, MB_ICONERROR | MB_RETRYCANCEL, L"Unable to change service configuration: %s", ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(GetLastError())))->Buffer ) == IDRETRY) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } Cleanup: if (newServicePassword) { RtlSecureZeroMemory(newServicePassword->Buffer, newServicePassword->Length); PhDereferenceObject(newServicePassword); } } return TRUE; } } break; } return FALSE; }
INT_PTR CALLBACK PhpCreateServiceDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_TYPE), PhServiceTypeStrings, sizeof(PhServiceTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_STARTTYPE), PhServiceStartTypeStrings, sizeof(PhServiceStartTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), PhServiceErrorControlStrings, sizeof(PhServiceErrorControlStrings) / sizeof(WCHAR *)); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"Own Process", FALSE); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_STARTTYPE), L"Demand Start", FALSE); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), L"Ignore", FALSE); if (!PhElevated) { SendMessage(GetDlgItem(hwndDlg, IDOK), BCM_SETSHIELD, 0, TRUE); } SetFocus(GetDlgItem(hwndDlg, IDC_NAME)); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: { EndDialog(hwndDlg, IDCANCEL); } break; case IDOK: { NTSTATUS status = 0; BOOLEAN success = FALSE; SC_HANDLE scManagerHandle; SC_HANDLE serviceHandle; ULONG win32Result = 0; PPH_STRING serviceName; PPH_STRING serviceDisplayName; PPH_STRING serviceTypeString; PPH_STRING serviceStartTypeString; PPH_STRING serviceErrorControlString; ULONG serviceType; ULONG serviceStartType; ULONG serviceErrorControl; PPH_STRING serviceBinaryPath; serviceName = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_NAME))); serviceDisplayName = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_DISPLAYNAME))); serviceTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_TYPE))); serviceStartTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_STARTTYPE))); serviceErrorControlString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_ERRORCONTROL))); serviceType = PhGetServiceTypeInteger(serviceTypeString->Buffer); serviceStartType = PhGetServiceStartTypeInteger(serviceStartTypeString->Buffer); serviceErrorControl = PhGetServiceErrorControlInteger(serviceErrorControlString->Buffer); serviceBinaryPath = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_BINARYPATH))); if (PhElevated) { if (scManagerHandle = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE)) { if (serviceHandle = CreateService( scManagerHandle, serviceName->Buffer, serviceDisplayName->Buffer, SERVICE_CHANGE_CONFIG, serviceType, serviceStartType, serviceErrorControl, serviceBinaryPath->Buffer, NULL, NULL, NULL, NULL, L"" )) { EndDialog(hwndDlg, IDOK); CloseServiceHandle(serviceHandle); success = TRUE; } else { win32Result = GetLastError(); } CloseServiceHandle(scManagerHandle); } else { win32Result = GetLastError(); } } else { if (PhUiConnectToPhSvc(hwndDlg, FALSE)) { status = PhSvcCallCreateService( serviceName->Buffer, serviceDisplayName->Buffer, serviceType, serviceStartType, serviceErrorControl, serviceBinaryPath->Buffer, NULL, NULL, NULL, NULL, L"" ); PhUiDisconnectFromPhSvc(); if (NT_SUCCESS(status)) { EndDialog(hwndDlg, IDOK); success = TRUE; } } else { // User cancelled elevation. success = TRUE; } } if (!success) PhShowStatus(hwndDlg, L"Unable to create the service", status, win32Result); } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Executable files (*.exe;*.sys)", L"*.exe;*.sys" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_STRING fileName; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); fileName = PhGetFileName(PHA_GET_DLGITEM_TEXT(hwndDlg, IDC_BINARYPATH)); PhSetFileDialogFileName(fileDialog, fileName->Buffer); PhDereferenceObject(fileName); if (PhShowFileDialog(hwndDlg, fileDialog)) { fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_BINARYPATH, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; } } break; } return FALSE; }
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; }
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; }
INT_PTR CALLBACK PhpRunAsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { PRUNAS_DIALOG_CONTEXT context; if (uMsg != WM_INITDIALOG) { context = (PRUNAS_DIALOG_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); } else { context = (PRUNAS_DIALOG_CONTEXT)lParam; SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { HWND typeComboBoxHandle = GetDlgItem(hwndDlg, IDC_TYPE); HWND userNameComboBoxHandle = GetDlgItem(hwndDlg, IDC_USERNAME); ULONG sessionId; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); if (SHAutoComplete_I) { SHAutoComplete_I( GetDlgItem(hwndDlg, IDC_PROGRAM), SHACF_AUTOAPPEND_FORCE_ON | SHACF_AUTOSUGGEST_FORCE_ON | SHACF_FILESYS_ONLY ); } ComboBox_AddString(typeComboBoxHandle, L"Batch"); ComboBox_AddString(typeComboBoxHandle, L"Interactive"); ComboBox_AddString(typeComboBoxHandle, L"Network"); ComboBox_AddString(typeComboBoxHandle, L"New credentials"); ComboBox_AddString(typeComboBoxHandle, L"Service"); PhSelectComboBoxString(typeComboBoxHandle, L"Interactive", FALSE); ComboBox_AddString(userNameComboBoxHandle, L"NT AUTHORITY\\SYSTEM"); ComboBox_AddString(userNameComboBoxHandle, L"NT AUTHORITY\\LOCAL SERVICE"); ComboBox_AddString(userNameComboBoxHandle, L"NT AUTHORITY\\NETWORK SERVICE"); PhpAddAccountsToComboBox(userNameComboBoxHandle); if (NT_SUCCESS(PhGetProcessSessionId(NtCurrentProcess(), &sessionId))) SetDlgItemInt(hwndDlg, IDC_SESSIONID, sessionId, FALSE); SetDlgItemText(hwndDlg, IDC_DESKTOP, L"WinSta0\\Default"); SetDlgItemText(hwndDlg, IDC_PROGRAM, PhaGetStringSetting(L"RunAsProgram")->Buffer); if (!context->ProcessId) { SetDlgItemText(hwndDlg, IDC_USERNAME, PH_AUTO_T(PH_STRING, PhGetStringSetting(L"RunAsUserName"))->Buffer); // Fire the user name changed event so we can fix the logon type. SendMessage(hwndDlg, WM_COMMAND, MAKEWPARAM(IDC_USERNAME, CBN_EDITCHANGE), 0); } else { HANDLE processHandle; HANDLE tokenHandle; PTOKEN_USER user; PPH_STRING userName; if (NT_SUCCESS(PhOpenProcess( &processHandle, ProcessQueryAccess, context->ProcessId ))) { if (NT_SUCCESS(PhOpenProcessToken( processHandle, TOKEN_QUERY, &tokenHandle ))) { if (NT_SUCCESS(PhGetTokenUser(tokenHandle, &user))) { if (userName = PhGetSidFullName(user->User.Sid, TRUE, NULL)) { SetDlgItemText(hwndDlg, IDC_USERNAME, userName->Buffer); PhDereferenceObject(userName); } PhFree(user); } NtClose(tokenHandle); } NtClose(processHandle); } EnableWindow(GetDlgItem(hwndDlg, IDC_USERNAME), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_TYPE), FALSE); } SendMessage(hwndDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwndDlg, IDC_PROGRAM), TRUE); Edit_SetSel(GetDlgItem(hwndDlg, IDC_PROGRAM), 0, -1); //if (!PhGetOwnTokenAttributes().Elevated) // SendMessage(GetDlgItem(hwndDlg, IDOK), BCM_SETSHIELD, 0, TRUE); if (!WINDOWS_HAS_UAC) ShowWindow(GetDlgItem(hwndDlg, IDC_TOGGLEELEVATION), SW_HIDE); } break; case WM_DESTROY: { if (context->DesktopList) PhDereferenceObject(context->DesktopList); RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hwndDlg, IDCANCEL); break; case IDOK: { NTSTATUS status; PPH_STRING program; PPH_STRING userName; PPH_STRING password; PPH_STRING logonTypeString; ULONG logonType; ULONG sessionId; PPH_STRING desktopName; BOOLEAN useLinkedToken; program = PhaGetDlgItemText(hwndDlg, IDC_PROGRAM); userName = PhaGetDlgItemText(hwndDlg, IDC_USERNAME); logonTypeString = PhaGetDlgItemText(hwndDlg, IDC_TYPE); // Fix up the user name if it doesn't have a domain. if (PhFindCharInString(userName, 0, '\\') == -1) { PSID sid; PPH_STRING newUserName; if (NT_SUCCESS(PhLookupName(&userName->sr, &sid, NULL, NULL))) { if (newUserName = PH_AUTO(PhGetSidFullName(sid, TRUE, NULL))) userName = newUserName; PhFree(sid); } } if (!IsServiceAccount(userName)) password = PhGetWindowText(GetDlgItem(hwndDlg, IDC_PASSWORD)); else password = NULL; sessionId = GetDlgItemInt(hwndDlg, IDC_SESSIONID, NULL, FALSE); desktopName = PhaGetDlgItemText(hwndDlg, IDC_DESKTOP); if (WINDOWS_HAS_UAC) useLinkedToken = Button_GetCheck(GetDlgItem(hwndDlg, IDC_TOGGLEELEVATION)) == BST_CHECKED; else useLinkedToken = FALSE; if (PhFindIntegerSiKeyValuePairs( PhpLogonTypePairs, sizeof(PhpLogonTypePairs), logonTypeString->Buffer, &logonType )) { if ( logonType == LOGON32_LOGON_INTERACTIVE && !context->ProcessId && sessionId == NtCurrentPeb()->SessionId && !useLinkedToken ) { // We are eligible to load the user profile. // This must be done here, not in the service, because // we need to be in the target session. PH_CREATE_PROCESS_AS_USER_INFO createInfo; PPH_STRING domainPart; PPH_STRING userPart; PhpSplitUserName(userName->Buffer, &domainPart, &userPart); memset(&createInfo, 0, sizeof(PH_CREATE_PROCESS_AS_USER_INFO)); createInfo.CommandLine = program->Buffer; createInfo.UserName = userPart->Buffer; createInfo.DomainName = domainPart->Buffer; createInfo.Password = PhGetStringOrEmpty(password); // Whenever we can, try not to set the desktop name; it breaks a lot of things. // Note that on XP we must set it, otherwise the program doesn't display correctly. if (WindowsVersion < WINDOWS_VISTA || (desktopName->Length != 0 && !PhEqualString2(desktopName, L"WinSta0\\Default", TRUE))) createInfo.DesktopName = desktopName->Buffer; PhSetDesktopWinStaAccess(); status = PhCreateProcessAsUser( &createInfo, PH_CREATE_PROCESS_WITH_PROFILE, NULL, NULL, NULL ); if (domainPart) PhDereferenceObject(domainPart); if (userPart) PhDereferenceObject(userPart); } else { status = PhExecuteRunAsCommand2( hwndDlg, program->Buffer, userName->Buffer, PhGetStringOrEmpty(password), logonType, context->ProcessId, sessionId, desktopName->Buffer, useLinkedToken ); } } else { status = STATUS_INVALID_PARAMETER; } if (password) { RtlSecureZeroMemory(password->Buffer, password->Length); PhDereferenceObject(password); } if (!NT_SUCCESS(status)) { if (status != STATUS_CANCELLED) PhShowStatus(hwndDlg, L"Unable to start the program", status, 0); } else if (status != STATUS_TIMEOUT) { PhSetStringSetting2(L"RunAsProgram", &program->sr); PhSetStringSetting2(L"RunAsUserName", &userName->sr); EndDialog(hwndDlg, IDOK); } } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Programs (*.exe;*.pif;*.com;*.bat)", L"*.exe;*.pif;*.com;*.bat" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, PhaGetDlgItemText(hwndDlg, IDC_PROGRAM)->Buffer); if (PhShowFileDialog(hwndDlg, fileDialog)) { PPH_STRING fileName; fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_PROGRAM, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; case IDC_USERNAME: { PPH_STRING userName = NULL; if (!context->ProcessId && HIWORD(wParam) == CBN_SELCHANGE) { userName = PH_AUTO(PhGetComboBoxString(GetDlgItem(hwndDlg, IDC_USERNAME), -1)); } else if (!context->ProcessId && ( HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_CLOSEUP )) { userName = PhaGetDlgItemText(hwndDlg, IDC_USERNAME); } if (userName) { if (IsServiceAccount(userName)) { EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), FALSE); // Hack for Windows XP if ( PhEqualString2(userName, L"NT AUTHORITY\\SYSTEM", TRUE) && WindowsVersion <= WINDOWS_XP ) { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"New credentials", FALSE); } else { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"Service", FALSE); } } else { EnableWindow(GetDlgItem(hwndDlg, IDC_PASSWORD), TRUE); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_TYPE), L"Interactive", FALSE); } } } break; case IDC_SESSIONS: { PPH_EMENU sessionsMenu; PSESSIONIDW sessions; ULONG numberOfSessions; ULONG i; RECT buttonRect; PPH_EMENU_ITEM selectedItem; sessionsMenu = PhCreateEMenu(); if (WinStationEnumerateW(NULL, &sessions, &numberOfSessions)) { for (i = 0; i < numberOfSessions; i++) { PPH_STRING menuString; WINSTATIONINFORMATION winStationInfo; ULONG returnLength; if (!WinStationQueryInformationW( NULL, sessions[i].SessionId, WinStationInformation, &winStationInfo, sizeof(WINSTATIONINFORMATION), &returnLength )) { winStationInfo.Domain[0] = 0; winStationInfo.UserName[0] = 0; } if ( winStationInfo.UserName[0] != 0 && sessions[i].WinStationName[0] != 0 ) { menuString = PhaFormatString( L"%u: %s (%s\\%s)", sessions[i].SessionId, sessions[i].WinStationName, winStationInfo.Domain, winStationInfo.UserName ); } else if (winStationInfo.UserName[0] != 0) { menuString = PhaFormatString( L"%u: %s\\%s", sessions[i].SessionId, winStationInfo.Domain, winStationInfo.UserName ); } else if (sessions[i].WinStationName[0] != 0) { menuString = PhaFormatString( L"%u: %s", sessions[i].SessionId, sessions[i].WinStationName ); } else { menuString = PhaFormatString(L"%u", sessions[i].SessionId); } PhInsertEMenuItem(sessionsMenu, PhCreateEMenuItem(0, 0, menuString->Buffer, NULL, UlongToPtr(sessions[i].SessionId)), -1); } WinStationFreeMemory(sessions); GetWindowRect(GetDlgItem(hwndDlg, IDC_SESSIONS), &buttonRect); selectedItem = PhShowEMenu( sessionsMenu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, buttonRect.right, buttonRect.top ); if (selectedItem) { SetDlgItemInt( hwndDlg, IDC_SESSIONID, PtrToUlong(selectedItem->Context), FALSE ); } PhDestroyEMenu(sessionsMenu); } } break; case IDC_DESKTOPS: { PPH_EMENU desktopsMenu; ULONG i; RECT buttonRect; PPH_EMENU_ITEM selectedItem; desktopsMenu = PhCreateEMenu(); if (!context->DesktopList) context->DesktopList = PhCreateList(10); context->CurrentWinStaName = GetCurrentWinStaName(); EnumDesktops(GetProcessWindowStation(), EnumDesktopsCallback, (LPARAM)context); for (i = 0; i < context->DesktopList->Count; i++) { PhInsertEMenuItem( desktopsMenu, PhCreateEMenuItem(0, 0, ((PPH_STRING)context->DesktopList->Items[i])->Buffer, NULL, NULL), -1 ); } GetWindowRect(GetDlgItem(hwndDlg, IDC_DESKTOPS), &buttonRect); selectedItem = PhShowEMenu( desktopsMenu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, buttonRect.right, buttonRect.top ); if (selectedItem) { SetDlgItemText( hwndDlg, IDC_DESKTOP, selectedItem->Text ); } for (i = 0; i < context->DesktopList->Count; i++) PhDereferenceObject(context->DesktopList->Items[i]); PhClearList(context->DesktopList); PhDereferenceObject(context->CurrentWinStaName); PhDestroyEMenu(desktopsMenu); } break; } } break; } return FALSE; }
NTSTATUS EspLoadOtherInfo( _In_ HWND hwndDlg, _In_ PSERVICE_OTHER_CONTEXT Context ) { NTSTATUS status = STATUS_SUCCESS; SC_HANDLE serviceHandle; ULONG returnLength; SERVICE_PRESHUTDOWN_INFO preshutdownInfo; LPSERVICE_REQUIRED_PRIVILEGES_INFO requiredPrivilegesInfo; SERVICE_SID_INFO sidInfo; SERVICE_LAUNCH_PROTECTED_INFO launchProtectedInfo; if (!(serviceHandle = PhOpenService(Context->ServiceItem->Name->Buffer, SERVICE_QUERY_CONFIG))) return NTSTATUS_FROM_WIN32(GetLastError()); // Preshutdown timeout if (QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_PRESHUTDOWN_INFO, (PBYTE)&preshutdownInfo, sizeof(SERVICE_PRESHUTDOWN_INFO), &returnLength )) { SetDlgItemInt(hwndDlg, IDC_PRESHUTDOWNTIMEOUT, preshutdownInfo.dwPreshutdownTimeout, FALSE); Context->PreshutdownTimeoutValid = TRUE; } // Required privileges if (requiredPrivilegesInfo = PhQueryServiceVariableSize(serviceHandle, SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO)) { PWSTR privilege; ULONG privilegeLength; INT lvItemIndex; PH_STRINGREF privilegeSr; PPH_STRING privilegeString; PPH_STRING displayName; privilege = requiredPrivilegesInfo->pmszRequiredPrivileges; if (privilege) { while (TRUE) { privilegeLength = (ULONG)PhCountStringZ(privilege); if (privilegeLength == 0) break; privilegeString = PhCreateStringEx(privilege, privilegeLength * sizeof(WCHAR)); PhAddItemList(Context->PrivilegeList, privilegeString); lvItemIndex = PhAddListViewItem(Context->PrivilegesLv, MAXINT, privilege, privilegeString); privilegeSr.Buffer = privilege; privilegeSr.Length = privilegeLength * sizeof(WCHAR); if (PhLookupPrivilegeDisplayName(&privilegeSr, &displayName)) { PhSetListViewSubItem(Context->PrivilegesLv, lvItemIndex, 1, displayName->Buffer); PhDereferenceObject(displayName); } privilege += privilegeLength + 1; } } ExtendedListView_SortItems(Context->PrivilegesLv); PhFree(requiredPrivilegesInfo); Context->RequiredPrivilegesValid = TRUE; } // SID type if (QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_SERVICE_SID_INFO, (PBYTE)&sidInfo, sizeof(SERVICE_SID_INFO), &returnLength )) { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_SIDTYPE), EspGetServiceSidTypeString(sidInfo.dwServiceSidType), FALSE); Context->SidTypeValid = TRUE; } // Launch protected if (QueryServiceConfig2(serviceHandle, SERVICE_CONFIG_LAUNCH_PROTECTED, (PBYTE)&launchProtectedInfo, sizeof(SERVICE_LAUNCH_PROTECTED_INFO), &returnLength )) { PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_PROTECTION), EspGetServiceLaunchProtectedString(launchProtectedInfo.dwLaunchProtected), FALSE); Context->LaunchProtectedValid = TRUE; Context->OriginalLaunchProtected = launchProtectedInfo.dwLaunchProtected; } CloseServiceHandle(serviceHandle); return status; }
INT_PTR CALLBACK PhpSessionShadowDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { HWND virtualKeyComboBox; PH_INTEGER_PAIR hotkey; ULONG i; PWSTR stringToSelect; SetProp(hwndDlg, L"SessionId", (HANDLE)(ULONG)lParam); PhCenterWindow(hwndDlg, GetParent(hwndDlg)); hotkey = PhGetIntegerPairSetting(L"SessionShadowHotkey"); // Set up the hotkeys. virtualKeyComboBox = GetDlgItem(hwndDlg, IDC_VIRTUALKEY); stringToSelect = L"{*}"; for (i = 0; i < sizeof(VirtualKeyPairs) / sizeof(PH_KEY_VALUE_PAIR); i++) { ComboBox_AddString(virtualKeyComboBox, VirtualKeyPairs[i].Key); if ((ULONG)VirtualKeyPairs[i].Value == (ULONG)hotkey.X) { stringToSelect = VirtualKeyPairs[i].Key; } } PhSelectComboBoxString(virtualKeyComboBox, stringToSelect, FALSE); // Set up the modifiers. Button_SetCheck(GetDlgItem(hwndDlg, IDC_SHIFT), hotkey.Y & KBDSHIFT); Button_SetCheck(GetDlgItem(hwndDlg, IDC_CTRL), hotkey.Y & KBDCTRL); Button_SetCheck(GetDlgItem(hwndDlg, IDC_ALT), hotkey.Y & KBDALT); } 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"); ULONG virtualKey; ULONG modifiers; WCHAR computerName[64]; ULONG computerNameLength = 64; virtualKey = VK_MULTIPLY; PhFindIntegerSiKeyValuePairs( VirtualKeyPairs, sizeof(VirtualKeyPairs), PhaGetDlgItemText(hwndDlg, IDC_VIRTUALKEY)->Buffer, &virtualKey ); modifiers = 0; if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_SHIFT)) == BST_CHECKED) modifiers |= KBDSHIFT; if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_CTRL)) == BST_CHECKED) modifiers |= KBDCTRL; if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALT)) == BST_CHECKED) modifiers |= KBDALT; if (GetComputerName(computerName, &computerNameLength)) { if (WinStationShadow(NULL, computerName, sessionId, (UCHAR)virtualKey, (USHORT)modifiers)) { PH_INTEGER_PAIR hotkey; hotkey.X = virtualKey; hotkey.Y = modifiers; PhSetIntegerPairSetting(L"SessionShadowHotkey", hotkey); EndDialog(hwndDlg, IDOK); } else { PhShowStatus(hwndDlg, L"Unable to remote control the session", 0, GetLastError()); } } else { PhShowError(hwndDlg, L"The computer name is too long."); } } break; } } break; } return FALSE; }
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 INT_PTR CALLBACK PhpHiddenProcessesDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { HWND lvHandle; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); PhHiddenProcessesListViewHandle = lvHandle = GetDlgItem(hwndDlg, IDC_PROCESSES); PhInitializeLayoutManager(&WindowLayoutManager, hwndDlg); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_INTRO), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_TOP | PH_ANCHOR_RIGHT | PH_LAYOUT_FORCE_INVALIDATE); PhAddLayoutItem(&WindowLayoutManager, lvHandle, NULL, PH_ANCHOR_ALL); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_DESCRIPTION), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM | PH_LAYOUT_FORCE_INVALIDATE); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_METHOD), NULL, PH_ANCHOR_LEFT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_TERMINATE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_SAVE), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDC_SCAN), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); PhAddLayoutItem(&WindowLayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM); MinimumSize.left = 0; MinimumSize.top = 0; MinimumSize.right = 330; MinimumSize.bottom = 140; MapDialogRect(hwndDlg, &MinimumSize); PhRegisterDialog(hwndDlg); PhLoadWindowPlacementFromSetting(L"HiddenProcessesWindowPosition", L"HiddenProcessesWindowSize", hwndDlg); PhSetListViewStyle(lvHandle, TRUE, TRUE); PhSetControlTheme(lvHandle, L"explorer"); PhAddListViewColumn(lvHandle, 0, 0, 0, LVCFMT_LEFT, 320, L"Process"); PhAddListViewColumn(lvHandle, 1, 1, 1, LVCFMT_LEFT, 60, L"PID"); PhSetExtendedListView(lvHandle); PhLoadListViewColumnsFromSetting(L"HiddenProcessesListViewColumns", lvHandle); ExtendedListView_AddFallbackColumn(lvHandle, 0); ExtendedListView_AddFallbackColumn(lvHandle, 1); ExtendedListView_SetItemColorFunction(lvHandle, PhpHiddenProcessesColorFunction); ComboBox_AddString(GetDlgItem(hwndDlg, IDC_METHOD), L"Brute Force"); ComboBox_AddString(GetDlgItem(hwndDlg, IDC_METHOD), L"CSR Handles"); PhSelectComboBoxString(GetDlgItem(hwndDlg, IDC_METHOD), L"CSR Handles", FALSE); EnableWindow(GetDlgItem(hwndDlg, IDC_TERMINATE), FALSE); } break; case WM_DESTROY: { PhSaveWindowPlacementToSetting(L"HiddenProcessesWindowPosition", L"HiddenProcessesWindowSize", hwndDlg); PhSaveListViewColumnsToSetting(L"HiddenProcessesListViewColumns", PhHiddenProcessesListViewHandle); } break; case WM_CLOSE: { // Hide, don't close. ShowWindow(hwndDlg, SW_HIDE); SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, 0); } return TRUE; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: { SendMessage(hwndDlg, WM_CLOSE, 0, 0); } break; case IDC_SCAN: { NTSTATUS status; PPH_STRING method; method = PhGetWindowText(GetDlgItem(hwndDlg, IDC_METHOD)); PhAutoDereferenceObject(method); if (ProcessesList) { ULONG i; for (i = 0; i < ProcessesList->Count; i++) { PPH_HIDDEN_PROCESS_ENTRY entry = ProcessesList->Items[i]; if (entry->FileName) PhDereferenceObject(entry->FileName); PhFree(entry); } PhDereferenceObject(ProcessesList); } ListView_DeleteAllItems(PhHiddenProcessesListViewHandle); ProcessesList = PhCreateList(40); ProcessesMethod = PhEqualString2(method, L"Brute Force", TRUE) ? BruteForceScanMethod : CsrHandlesScanMethod; NumberOfHiddenProcesses = 0; NumberOfTerminatedProcesses = 0; ExtendedListView_SetRedraw(PhHiddenProcessesListViewHandle, FALSE); status = PhEnumHiddenProcesses( ProcessesMethod, PhpHiddenProcessesCallback, NULL ); ExtendedListView_SortItems(PhHiddenProcessesListViewHandle); ExtendedListView_SetRedraw(PhHiddenProcessesListViewHandle, TRUE); if (NT_SUCCESS(status)) { SetDlgItemText(hwndDlg, IDC_DESCRIPTION, PhaFormatString(L"%u hidden process(es), %u terminated process(es).", NumberOfHiddenProcesses, NumberOfTerminatedProcesses)->Buffer ); InvalidateRect(GetDlgItem(hwndDlg, IDC_DESCRIPTION), NULL, TRUE); } else { PhShowStatus(hwndDlg, L"Unable to perform the scan", status, 0); } } break; case IDC_TERMINATE: { PPH_HIDDEN_PROCESS_ENTRY *entries; ULONG numberOfEntries; ULONG i; PhGetSelectedListViewItemParams(PhHiddenProcessesListViewHandle, &entries, &numberOfEntries); if (numberOfEntries != 0) { if (!PhGetIntegerSetting(L"EnableWarnings") || PhShowConfirmMessage( hwndDlg, L"terminate", L"the selected process(es)", L"Terminating a hidden process may cause the system to become unstable " L"or crash.", TRUE )) { NTSTATUS status; HANDLE processHandle; BOOLEAN refresh; refresh = FALSE; for (i = 0; i < numberOfEntries; i++) { if (ProcessesMethod == BruteForceScanMethod) { status = PhOpenProcess( &processHandle, PROCESS_TERMINATE, entries[i]->ProcessId ); } else { status = PhOpenProcessByCsrHandles( &processHandle, PROCESS_TERMINATE, entries[i]->ProcessId ); } if (NT_SUCCESS(status)) { status = PhTerminateProcess(processHandle, STATUS_SUCCESS); NtClose(processHandle); if (NT_SUCCESS(status)) refresh = TRUE; } else { PhShowStatus(hwndDlg, L"Unable to terminate the process", status, 0); } } if (refresh) { LARGE_INTEGER interval; // Sleep for a bit before continuing. It seems to help avoid // BSODs. interval.QuadPart = -250 * PH_TIMEOUT_MS; NtDelayExecution(FALSE, &interval); SendMessage(hwndDlg, WM_COMMAND, IDC_SCAN, 0); } } } PhFree(entries); } break; case IDC_SAVE: { static PH_FILETYPE_FILTER filters[] = { { L"Text files (*.txt)", L"*.txt" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; fileDialog = PhCreateSaveFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); PhSetFileDialogFileName(fileDialog, L"Hidden Processes.txt"); if (PhShowFileDialog(hwndDlg, fileDialog)) { NTSTATUS status; PPH_STRING fileName; PPH_FILE_STREAM fileStream; fileName = PhGetFileDialogFileName(fileDialog); PhAutoDereferenceObject(fileName); if (NT_SUCCESS(status = PhCreateFileStream( &fileStream, fileName->Buffer, FILE_GENERIC_WRITE, FILE_SHARE_READ, FILE_OVERWRITE_IF, 0 ))) { PhWriteStringAsUtf8FileStream(fileStream, &PhUnicodeByteOrderMark); PhWritePhTextHeader(fileStream); PhWriteStringAsUtf8FileStream2(fileStream, L"Method: "); PhWriteStringAsUtf8FileStream2(fileStream, ProcessesMethod == BruteForceScanMethod ? L"Brute Force\r\n" : L"CSR Handles\r\n"); PhWriteStringFormatAsUtf8FileStream( fileStream, L"Hidden: %u\r\nTerminated: %u\r\n\r\n", NumberOfHiddenProcesses, NumberOfTerminatedProcesses ); if (ProcessesList) { ULONG i; for (i = 0; i < ProcessesList->Count; i++) { PPH_HIDDEN_PROCESS_ENTRY entry = ProcessesList->Items[i]; if (entry->Type == HiddenProcess) PhWriteStringAsUtf8FileStream2(fileStream, L"[HIDDEN] "); else if (entry->Type == TerminatedProcess) PhWriteStringAsUtf8FileStream2(fileStream, L"[Terminated] "); else if (entry->Type != NormalProcess) continue; PhWriteStringFormatAsUtf8FileStream( fileStream, L"%s (%u)\r\n", entry->FileName->Buffer, HandleToUlong(entry->ProcessId) ); } } PhDereferenceObject(fileStream); } if (!NT_SUCCESS(status)) PhShowStatus(hwndDlg, L"Unable to create the file", status, 0); } PhFreeFileDialog(fileDialog); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; PhHandleListViewNotifyBehaviors(lParam, PhHiddenProcessesListViewHandle, PH_LIST_VIEW_DEFAULT_1_BEHAVIORS); switch (header->code) { case LVN_ITEMCHANGED: { if (header->hwndFrom == PhHiddenProcessesListViewHandle) { EnableWindow( GetDlgItem(hwndDlg, IDC_TERMINATE), ListView_GetSelectedCount(PhHiddenProcessesListViewHandle) > 0 ); } } break; case NM_DBLCLK: { if (header->hwndFrom == PhHiddenProcessesListViewHandle) { PPH_HIDDEN_PROCESS_ENTRY entry; entry = PhGetSelectedListViewItemParam(PhHiddenProcessesListViewHandle); if (entry) { PPH_PROCESS_ITEM processItem; if (processItem = PhpCreateProcessItemForHiddenProcess(entry)) { ProcessHacker_ShowProcessProperties(PhMainWndHandle, processItem); PhDereferenceObject(processItem); } else { PhShowError(hwndDlg, L"Unable to create a process structure for the selected process."); } } } } break; } } break; case WM_SIZE: { PhLayoutManagerLayout(&WindowLayoutManager); } break; case WM_SIZING: { PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom); } break; case WM_CTLCOLORSTATIC: { if ((HWND)lParam == GetDlgItem(hwndDlg, IDC_DESCRIPTION)) { if (NumberOfHiddenProcesses != 0) { SetTextColor((HDC)wParam, RGB(0xff, 0x00, 0x00)); } SetBkColor((HDC)wParam, GetSysColor(COLOR_3DFACE)); return (INT_PTR)GetSysColorBrush(COLOR_3DFACE); } } break; } REFLECT_MESSAGE_DLG(hwndDlg, PhHiddenProcessesListViewHandle, uMsg, wParam, lParam); return FALSE; }