Process Hacker
options.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * options window
4  *
5  * Copyright (C) 2010-2015 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <phapp.h>
24 #include <settings.h>
25 #include <colorbox.h>
26 #include <sysinfo.h>
27 #include <windowsx.h>
28 
29 #define WM_PH_CHILD_EXIT (WM_APP + 301)
30 
31 INT CALLBACK PhpOptionsPropSheetProc(
32  _In_ HWND hwndDlg,
33  _In_ UINT uMsg,
34  _In_ LPARAM lParam
35  );
36 
37 LRESULT CALLBACK PhpOptionsWndProc(
38  _In_ HWND hwnd,
39  _In_ UINT uMsg,
40  _In_ WPARAM wParam,
41  _In_ LPARAM lParam
42  );
43 
44 INT_PTR CALLBACK PhpOptionsGeneralDlgProc(
45  _In_ HWND hwndDlg,
46  _In_ UINT uMsg,
47  _In_ WPARAM wParam,
48  _In_ LPARAM lParam
49  );
50 
51 INT_PTR CALLBACK PhpOptionsAdvancedDlgProc(
52  _In_ HWND hwndDlg,
53  _In_ UINT uMsg,
54  _In_ WPARAM wParam,
55  _In_ LPARAM lParam
56  );
57 
58 INT_PTR CALLBACK PhpOptionsSymbolsDlgProc(
59  _In_ HWND hwndDlg,
60  _In_ UINT uMsg,
61  _In_ WPARAM wParam,
62  _In_ LPARAM lParam
63  );
64 
65 INT_PTR CALLBACK PhpOptionsHighlightingDlgProc(
66  _In_ HWND hwndDlg,
67  _In_ UINT uMsg,
68  _In_ WPARAM wParam,
69  _In_ LPARAM lParam
70  );
71 
72 INT_PTR CALLBACK PhpOptionsGraphsDlgProc(
73  _In_ HWND hwndDlg,
74  _In_ UINT uMsg,
75  _In_ WPARAM wParam,
76  _In_ LPARAM lParam
77  );
78 
79 // All
80 static BOOLEAN PageInit;
81 static BOOLEAN PressedOk;
82 static BOOLEAN RestartRequired;
83 static POINT StartLocation;
84 static WNDPROC OldWndProc;
85 
86 // General
87 static HFONT CurrentFontInstance;
88 static PPH_STRING NewFontSelection;
89 
90 // Advanced
91 static PH_STRINGREF TaskMgrImageOptionsKeyName = PH_STRINGREF_INIT(L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\taskmgr.exe");
92 static PPH_STRING OldTaskMgrDebugger;
93 static BOOLEAN OldReplaceTaskMgr;
94 static HWND WindowHandleForElevate;
95 
96 // Highlighting
97 static HWND HighlightingListViewHandle;
98 
100  _In_ HWND ParentWindowHandle
101  )
102 {
103  PROPSHEETHEADER propSheetHeader = { sizeof(propSheetHeader) };
104  PROPSHEETPAGE propSheetPage;
105  HPROPSHEETPAGE pages[5];
106 
107  propSheetHeader.dwFlags =
108  PSH_NOAPPLYNOW |
109  PSH_NOCONTEXTHELP |
110  PSH_PROPTITLE |
111  PSH_USECALLBACK |
112  PSH_USEPSTARTPAGE;
113  propSheetHeader.hwndParent = ParentWindowHandle;
114  propSheetHeader.pszCaption = L"Options";
115  propSheetHeader.nPages = 0;
116  propSheetHeader.pStartPage = !PhStartupParameters.ShowOptions ? L"General" : L"Advanced";
117  propSheetHeader.phpage = pages;
118  propSheetHeader.pfnCallback = PhpOptionsPropSheetProc;
119 
121  {
122  // Disable all pages other than Advanced.
123  // General page
124  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
125  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
126  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_OPTGENERAL);
127  propSheetPage.pfnDlgProc = PhpOptionsGeneralDlgProc;
128  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
129  }
130 
131  // Advanced page
132  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
133  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
134  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_OPTADVANCED);
135  propSheetPage.pfnDlgProc = PhpOptionsAdvancedDlgProc;
136  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
137 
139  {
140  // Symbols page
141  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
142  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
143  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_OPTSYMBOLS);
144  propSheetPage.pfnDlgProc = PhpOptionsSymbolsDlgProc;
145  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
146  }
147 
149  {
150  // Highlighting page
151  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
152  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
153  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_OPTHIGHLIGHTING);
154  propSheetPage.pfnDlgProc = PhpOptionsHighlightingDlgProc;
155  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
156  }
157 
159  {
160  // Graphs page
161  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
162  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
163  propSheetPage.pszTemplate = MAKEINTRESOURCE(IDD_OPTGRAPHS);
164  propSheetPage.pfnDlgProc = PhpOptionsGraphsDlgProc;
165  pages[propSheetHeader.nPages++] = CreatePropertySheetPage(&propSheetPage);
166  }
167 
168  PageInit = FALSE;
169  PressedOk = FALSE;
170  RestartRequired = FALSE;
171 
173  StartLocation = PhStartupParameters.Point;
174  else
175  StartLocation.x = MINLONG;
176 
177  OldTaskMgrDebugger = NULL;
178 
179  PropertySheet(&propSheetHeader);
180 
181  if (PressedOk)
182  {
184  {
190 
191  if (RestartRequired)
192  {
193  if (PhShowMessage(
195  MB_ICONQUESTION | MB_YESNO,
196  L"One or more options you have changed requires a restart of Process Hacker. "
197  L"Do you want to restart Process Hacker now?"
198  ) == IDYES)
199  {
203  L"-v",
204  SW_SHOW,
205  0,
207  0,
208  NULL
209  );
211  }
212  }
213  }
214  else
215  {
216  // Main window not available.
217  if (PhSettingsFileName)
219  }
220  }
221 }
222 
224  _In_ HWND hwndDlg,
225  _In_ UINT uMsg,
226  _In_ LPARAM lParam
227  )
228 {
229  switch (uMsg)
230  {
231  case PSCB_BUTTONPRESSED:
232  {
233  if (lParam == PSBTN_OK)
234  {
235  PressedOk = TRUE;
236  }
237  }
238  break;
239  }
240 
241  return 0;
242 }
243 
244 static VOID PhpPageInit(
245  _In_ HWND hwndDlg
246  )
247 {
248  if (!PageInit)
249  {
250  HWND optionsWindow;
251  HWND resetButton;
252  RECT clientRect;
253  RECT rect;
254 
255  optionsWindow = GetParent(hwndDlg);
256  OldWndProc = (WNDPROC)GetWindowLongPtr(optionsWindow, GWLP_WNDPROC);
257  SetWindowLongPtr(optionsWindow, GWLP_WNDPROC, (LONG_PTR)PhpOptionsWndProc);
258 
259  // Create the Reset button.
260  GetClientRect(optionsWindow, &clientRect);
261  GetWindowRect(GetDlgItem(optionsWindow, IDCANCEL), &rect);
262  MapWindowPoints(NULL, optionsWindow, (POINT *)&rect, 2);
263  resetButton = CreateWindowEx(
264  WS_EX_NOPARENTNOTIFY,
265  L"BUTTON",
266  L"Reset",
267  WS_CHILD | WS_VISIBLE | WS_TABSTOP,
268  clientRect.right - rect.right,
269  rect.top,
270  rect.right - rect.left,
271  rect.bottom - rect.top,
272  optionsWindow,
273  (HMENU)IDC_RESET,
275  NULL
276  );
277  SendMessage(resetButton, WM_SETFONT, SendMessage(GetDlgItem(optionsWindow, IDCANCEL), WM_GETFONT, 0, 0), TRUE);
278 
280  ShowWindow(resetButton, SW_HIDE);
281 
282  // Set the location of the options window.
283  if (StartLocation.x == MINLONG)
284  {
285  PhCenterWindow(optionsWindow, GetParent(optionsWindow));
286  }
287  else
288  {
289  SetWindowPos(optionsWindow, NULL, StartLocation.x, StartLocation.y, 0, 0,
290  SWP_NOACTIVATE | SWP_NOREDRAW | SWP_NOSIZE | SWP_NOZORDER);
291  }
292 
293  SetWindowText(optionsWindow, L"Options"); // so the title isn't "Options Properties"
294 
295  PageInit = TRUE;
296  }
297 }
298 
299 LRESULT CALLBACK PhpOptionsWndProc(
300  _In_ HWND hwnd,
301  _In_ UINT uMsg,
302  _In_ WPARAM wParam,
303  _In_ LPARAM lParam
304  )
305 {
306  switch (uMsg)
307  {
308  case WM_COMMAND:
309  {
310  switch (LOWORD(wParam))
311  {
312  case IDC_RESET:
313  {
314  if (PhShowMessage(
315  hwnd,
316  MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2,
317  L"Do you want to reset all settings and restart Process Hacker?"
318  ) == IDYES)
319  {
321 
322  PhResetSettings();
323 
324  if (PhSettingsFileName)
326 
329  L"-v",
330  SW_SHOW,
331  0,
333  0,
334  NULL
335  );
337  }
338  }
339  break;
340  }
341  }
342  break;
343  }
344 
345  return CallWindowProc(OldWndProc, hwnd, uMsg, wParam, lParam);
346 }
347 
348 #define SetDlgItemCheckForSetting(hwndDlg, Id, Name) \
349  Button_SetCheck(GetDlgItem(hwndDlg, Id), PhGetIntegerSetting(Name) ? BST_CHECKED : BST_UNCHECKED)
350 #define SetSettingForDlgItemCheck(hwndDlg, Id, Name) \
351  PhSetIntegerSetting(Name, Button_GetCheck(GetDlgItem(hwndDlg, Id)) == BST_CHECKED)
352 #define SetSettingForDlgItemCheckRestartRequired(hwndDlg, Id, Name) \
353  do { \
354  BOOLEAN __oldValue = !!PhGetIntegerSetting(Name); \
355  BOOLEAN __newValue = Button_GetCheck(GetDlgItem(hwndDlg, Id)) == BST_CHECKED; \
356  if (__newValue != __oldValue) \
357  RestartRequired = TRUE; \
358  PhSetIntegerSetting(Name, __newValue); \
359  } while (0)
360 #define DialogChanged PropSheet_Changed(GetParent(hwndDlg), hwndDlg)
361 
362 static BOOLEAN GetCurrentFont(
363  _Out_ PLOGFONT Font
364  )
365 {
366  BOOLEAN result;
367  PPH_STRING fontHexString;
368 
369  if (NewFontSelection)
370  PhSetReference(&fontHexString, NewFontSelection);
371  else
372  fontHexString = PhGetStringSetting(L"Font");
373 
374  if (fontHexString->Length / 2 / 2 == sizeof(LOGFONT))
375  result = PhHexStringToBuffer(&fontHexString->sr, (PUCHAR)Font);
376  else
377  result = FALSE;
378 
379  PhDereferenceObject(fontHexString);
380 
381  return result;
382 }
383 
384 INT_PTR CALLBACK PhpOptionsGeneralDlgProc(
385  _In_ HWND hwndDlg,
386  _In_ UINT uMsg,
387  _In_ WPARAM wParam,
388  _In_ LPARAM lParam
389  )
390 {
391  switch (uMsg)
392  {
393  case WM_INITDIALOG:
394  {
395  HWND comboBoxHandle;
396  ULONG i;
397  LOGFONT font;
398 
399  PhpPageInit(hwndDlg);
400 
401  comboBoxHandle = GetDlgItem(hwndDlg, IDC_MAXSIZEUNIT);
402 
403  for (i = 0; i < sizeof(PhSizeUnitNames) / sizeof(PWSTR); i++)
404  ComboBox_AddString(comboBoxHandle, PhSizeUnitNames[i]);
405 
406  SetDlgItemText(hwndDlg, IDC_SEARCHENGINE, PhaGetStringSetting(L"SearchEngine")->Buffer);
407  SetDlgItemText(hwndDlg, IDC_PEVIEWER, PhaGetStringSetting(L"ProgramInspectExecutables")->Buffer);
408 
409  if (PhMaxSizeUnit != -1)
410  ComboBox_SetCurSel(comboBoxHandle, PhMaxSizeUnit);
411  else
412  ComboBox_SetCurSel(comboBoxHandle, sizeof(PhSizeUnitNames) / sizeof(PWSTR) - 1);
413 
414  SetDlgItemInt(hwndDlg, IDC_ICONPROCESSES, PhGetIntegerSetting(L"IconProcesses"), FALSE);
415 
416  SetDlgItemCheckForSetting(hwndDlg, IDC_ALLOWONLYONEINSTANCE, L"AllowOnlyOneInstance");
417  SetDlgItemCheckForSetting(hwndDlg, IDC_HIDEONCLOSE, L"HideOnClose");
418  SetDlgItemCheckForSetting(hwndDlg, IDC_HIDEONMINIMIZE, L"HideOnMinimize");
419  SetDlgItemCheckForSetting(hwndDlg, IDC_STARTHIDDEN, L"StartHidden");
420  SetDlgItemCheckForSetting(hwndDlg, IDC_COLLAPSESERVICES, L"CollapseServicesOnStart");
421  SetDlgItemCheckForSetting(hwndDlg, IDC_ICONSINGLECLICK, L"IconSingleClick");
422  SetDlgItemCheckForSetting(hwndDlg, IDC_ICONTOGGLESVISIBILITY, L"IconTogglesVisibility");
423  SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEPLUGINS, L"EnablePlugins");
424 
425  // Set the font of the button for a nice preview.
426  if (GetCurrentFont(&font))
427  {
428  CurrentFontInstance = CreateFontIndirect(&font);
429 
430  if (CurrentFontInstance)
431  SendMessage(GetDlgItem(hwndDlg, IDC_FONT), WM_SETFONT, (WPARAM)CurrentFontInstance, TRUE);
432  }
433  }
434  break;
435  case WM_DESTROY:
436  {
437  if (CurrentFontInstance)
438  DeleteObject(CurrentFontInstance);
439 
440  PhClearReference(&NewFontSelection);
441  }
442  break;
443  case WM_COMMAND:
444  {
445  switch (LOWORD(wParam))
446  {
447  case IDC_FONT:
448  {
449  LOGFONT font;
450  CHOOSEFONT chooseFont;
451 
452  if (!GetCurrentFont(&font))
453  {
454  // Can't get LOGFONT from the existing setting, probably
455  // because the user hasn't ever chosen a font before.
456  // Set the font to something familiar.
457  GetObject((HFONT)SendMessage(PhMainWndHandle, WM_PH_GET_FONT, 0, 0), sizeof(LOGFONT), &font);
458  }
459 
460  memset(&chooseFont, 0, sizeof(CHOOSEFONT));
461  chooseFont.lStructSize = sizeof(CHOOSEFONT);
462  chooseFont.hwndOwner = hwndDlg;
463  chooseFont.lpLogFont = &font;
464  chooseFont.Flags = CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS;
465 
466  if (ChooseFont(&chooseFont))
467  {
468  PhMoveReference(&NewFontSelection, PhBufferToHexString((PUCHAR)&font, sizeof(LOGFONT)));
469 
470  // Update the button's font.
471 
472  if (CurrentFontInstance)
473  DeleteObject(CurrentFontInstance);
474 
475  CurrentFontInstance = CreateFontIndirect(&font);
476  SendMessage(GetDlgItem(hwndDlg, IDC_FONT), WM_SETFONT, (WPARAM)CurrentFontInstance, TRUE);
477  }
478  }
479  break;
480  }
481  }
482  break;
483  case WM_NOTIFY:
484  {
485  LPNMHDR header = (LPNMHDR)lParam;
486 
487  switch (header->code)
488  {
489  case PSN_APPLY:
490  {
491  PhSetStringSetting2(L"SearchEngine", &(PhaGetDlgItemText(hwndDlg, IDC_SEARCHENGINE)->sr));
492  PhSetStringSetting2(L"ProgramInspectExecutables", &(PhaGetDlgItemText(hwndDlg, IDC_PEVIEWER)->sr));
493  PhSetIntegerSetting(L"MaxSizeUnit", PhMaxSizeUnit = ComboBox_GetCurSel(GetDlgItem(hwndDlg, IDC_MAXSIZEUNIT)));
494  PhSetIntegerSetting(L"IconProcesses", GetDlgItemInt(hwndDlg, IDC_ICONPROCESSES, NULL, FALSE));
495  SetSettingForDlgItemCheck(hwndDlg, IDC_ALLOWONLYONEINSTANCE, L"AllowOnlyOneInstance");
496  SetSettingForDlgItemCheck(hwndDlg, IDC_HIDEONCLOSE, L"HideOnClose");
497  SetSettingForDlgItemCheck(hwndDlg, IDC_HIDEONMINIMIZE, L"HideOnMinimize");
498  SetSettingForDlgItemCheck(hwndDlg, IDC_STARTHIDDEN, L"StartHidden");
499  SetSettingForDlgItemCheck(hwndDlg, IDC_COLLAPSESERVICES, L"CollapseServicesOnStart");
500  SetSettingForDlgItemCheck(hwndDlg, IDC_ICONSINGLECLICK, L"IconSingleClick");
501  SetSettingForDlgItemCheck(hwndDlg, IDC_ICONTOGGLESVISIBILITY, L"IconTogglesVisibility");
503 
504  if (NewFontSelection)
505  {
506  PhSetStringSetting2(L"Font", &NewFontSelection->sr);
507  PostMessage(PhMainWndHandle, WM_PH_UPDATE_FONT, 0, 0);
508  }
509 
510  SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
511  }
512  return TRUE;
513  }
514  }
515  break;
516  }
517 
518  return FALSE;
519 }
520 
521 static BOOLEAN PathMatchesPh(
522  _In_ PPH_STRING Path
523  )
524 {
525  BOOLEAN match = FALSE;
526 
527  if (PhEqualString(OldTaskMgrDebugger, PhApplicationFileName, TRUE))
528  {
529  match = TRUE;
530  }
531  // Allow for a quoted value.
532  else if (
533  OldTaskMgrDebugger->Length == PhApplicationFileName->Length + 4 &&
534  OldTaskMgrDebugger->Buffer[0] == '"' &&
535  OldTaskMgrDebugger->Buffer[OldTaskMgrDebugger->Length / 2 - 1] == '"'
536  )
537  {
538  PH_STRINGREF partInside;
539 
540  partInside.Buffer = &OldTaskMgrDebugger->Buffer[1];
541  partInside.Length = OldTaskMgrDebugger->Length - sizeof(WCHAR) * 2;
542 
543  if (PhEqualStringRef(&partInside, &PhApplicationFileName->sr, TRUE))
544  match = TRUE;
545  }
546 
547  return match;
548 }
549 
551  _In_ HWND hwndDlg
552  )
553 {
554  HWND changeButton;
555 
556  SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEWARNINGS, L"EnableWarnings");
558  SetDlgItemCheckForSetting(hwndDlg, IDC_HIDEUNNAMEDHANDLES, L"HideUnnamedHandles");
559  SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLESTAGE2, L"EnableStage2");
560  SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLENETWORKRESOLVE, L"EnableNetworkResolve");
561  SetDlgItemCheckForSetting(hwndDlg, IDC_PROPAGATECPUUSAGE, L"PropagateCpuUsage");
562  SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLEINSTANTTOOLTIPS, L"EnableInstantTooltips");
563 
564  if (WindowsVersion >= WINDOWS_7)
565  SetDlgItemCheckForSetting(hwndDlg, IDC_ENABLECYCLECPUUSAGE, L"EnableCycleCpuUsage");
566 
567  SetDlgItemInt(hwndDlg, IDC_SAMPLECOUNT, PhGetIntegerSetting(L"SampleCount"), FALSE);
568  SetDlgItemCheckForSetting(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC, L"SampleCountAutomatic");
569 
570  if (PhGetIntegerSetting(L"SampleCountAutomatic"))
571  EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNT), FALSE);
572 
573  // Replace Task Manager
574 
575  changeButton = GetDlgItem(hwndDlg, IDC_CHANGE);
576 
577  if (PhElevated)
578  {
579  ShowWindow(changeButton, SW_HIDE);
580  }
581  else
582  {
583  SendMessage(changeButton, BCM_SETSHIELD, 0, TRUE);
584  }
585 
586  {
587  HANDLE taskmgrKeyHandle = NULL;
588  ULONG disposition;
589  BOOLEAN success = FALSE;
590  BOOLEAN alreadyReplaced = FALSE;
591 
592  // See if we can write to the key.
594  &taskmgrKeyHandle,
595  KEY_READ | KEY_WRITE,
597  &TaskMgrImageOptionsKeyName,
598  0,
599  0,
600  &disposition
601  )))
602  {
603  success = TRUE;
604  }
605 
606  if (taskmgrKeyHandle || NT_SUCCESS(PhOpenKey(
607  &taskmgrKeyHandle,
608  KEY_READ,
610  &TaskMgrImageOptionsKeyName,
611  0
612  )))
613  {
614  if (OldTaskMgrDebugger)
615  PhDereferenceObject(OldTaskMgrDebugger);
616 
617  if (OldTaskMgrDebugger = PhQueryRegistryString(taskmgrKeyHandle, L"Debugger"))
618  {
619  alreadyReplaced = PathMatchesPh(OldTaskMgrDebugger);
620  }
621 
622  NtClose(taskmgrKeyHandle);
623  }
624 
625  if (!success)
626  EnableWindow(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER), FALSE);
627 
628  OldReplaceTaskMgr = alreadyReplaced;
629  Button_SetCheck(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER), alreadyReplaced ? BST_CHECKED : BST_UNCHECKED);
630  }
631 }
632 
634  _In_ HWND hwndDlg
635  )
636 {
637  ULONG sampleCount;
638 
639  SetSettingForDlgItemCheck(hwndDlg, IDC_ENABLEWARNINGS, L"EnableWarnings");
641  SetSettingForDlgItemCheck(hwndDlg, IDC_HIDEUNNAMEDHANDLES, L"HideUnnamedHandles");
643  SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLENETWORKRESOLVE, L"EnableNetworkResolve");
644  SetSettingForDlgItemCheck(hwndDlg, IDC_PROPAGATECPUUSAGE, L"PropagateCpuUsage");
645  SetSettingForDlgItemCheck(hwndDlg, IDC_ENABLEINSTANTTOOLTIPS, L"EnableInstantTooltips");
646 
647  if (WindowsVersion >= WINDOWS_7)
648  SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_ENABLECYCLECPUUSAGE, L"EnableCycleCpuUsage");
649 
650  sampleCount = GetDlgItemInt(hwndDlg, IDC_SAMPLECOUNT, NULL, FALSE);
651  SetSettingForDlgItemCheckRestartRequired(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC, L"SampleCountAutomatic");
652 
653  if (sampleCount == 0)
654  sampleCount = 1;
655 
656  if (sampleCount != PhGetIntegerSetting(L"SampleCount"))
657  RestartRequired = TRUE;
658 
659  PhSetIntegerSetting(L"SampleCount", sampleCount);
660 
661  // Replace Task Manager
662  if (IsWindowEnabled(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER)))
663  {
664  NTSTATUS status;
665  HANDLE taskmgrKeyHandle;
666  BOOLEAN replaceTaskMgr;
667  UNICODE_STRING valueName;
668 
669  replaceTaskMgr = Button_GetCheck(GetDlgItem(hwndDlg, IDC_REPLACETASKMANAGER)) == BST_CHECKED;
670 
671  if (OldReplaceTaskMgr != replaceTaskMgr)
672  {
673  // We should have created the key back in PhpAdvancedPageLoad, which is why
674  // we're opening the key here.
675  if (NT_SUCCESS(PhOpenKey(
676  &taskmgrKeyHandle,
677  KEY_WRITE,
679  &TaskMgrImageOptionsKeyName,
680  0
681  )))
682  {
683  RtlInitUnicodeString(&valueName, L"Debugger");
684 
685  if (replaceTaskMgr)
686  {
687  PPH_STRING quotedFileName;
688 
689  quotedFileName = PhConcatStrings(3, L"\"", PhApplicationFileName->Buffer, L"\"");
690  status = NtSetValueKey(taskmgrKeyHandle, &valueName, 0, REG_SZ, quotedFileName->Buffer, (ULONG)quotedFileName->Length + 2);
691  PhDereferenceObject(quotedFileName);
692  }
693  else
694  {
695  status = NtDeleteValueKey(taskmgrKeyHandle, &valueName);
696  }
697 
698  if (!NT_SUCCESS(status))
699  PhShowStatus(hwndDlg, L"Unable to replace Task Manager", status, 0);
700 
701  NtClose(taskmgrKeyHandle);
702  }
703  }
704  }
705 }
706 
708  _In_ PVOID Parameter
709  )
710 {
711  PPH_STRING arguments;
712 
713  arguments = Parameter;
715  WindowHandleForElevate,
716  arguments->Buffer,
717  SW_SHOW,
720  INFINITE,
721  NULL
722  );
723  PhDereferenceObject(arguments);
724 
725  PostMessage(WindowHandleForElevate, WM_PH_CHILD_EXIT, 0, 0);
726 
727  return STATUS_SUCCESS;
728 }
729 
730 INT_PTR CALLBACK PhpOptionsAdvancedDlgProc(
731  _In_ HWND hwndDlg,
732  _In_ UINT uMsg,
733  _In_ WPARAM wParam,
734  _In_ LPARAM lParam
735  )
736 {
737  switch (uMsg)
738  {
739  case WM_INITDIALOG:
740  {
741  PhpPageInit(hwndDlg);
742  PhpAdvancedPageLoad(hwndDlg);
743 
745  {
746  // Disable all controls except for Replace Task Manager.
747  EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEWARNINGS), FALSE);
748  EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEKERNELMODEDRIVER), FALSE);
749  EnableWindow(GetDlgItem(hwndDlg, IDC_HIDEUNNAMEDHANDLES), FALSE);
750  EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLESTAGE2), FALSE);
751  EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLENETWORKRESOLVE), FALSE);
752  EnableWindow(GetDlgItem(hwndDlg, IDC_PROPAGATECPUUSAGE), FALSE);
753  EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLEINSTANTTOOLTIPS), FALSE);
754  EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLECYCLECPUUSAGE), FALSE);
755  EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNTLABEL), FALSE);
756  EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNT), FALSE);
757  EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC), FALSE);
758  }
759  else
760  {
762  EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLECYCLECPUUSAGE), FALSE); // cycle-based CPU usage not available before Windows 7
763  }
764  }
765  break;
766  case WM_DESTROY:
767  {
768  if (OldTaskMgrDebugger)
769  PhDereferenceObject(OldTaskMgrDebugger);
770  }
771  break;
772  case WM_COMMAND:
773  {
774  switch (LOWORD(wParam))
775  {
776  case IDC_CHANGE:
777  {
778  HANDLE threadHandle;
779  RECT windowRect;
780 
781  // Save the options so they don't get "overwritten" when
782  // WM_PH_CHILD_EXIT gets sent.
783  PhpAdvancedPageSave(hwndDlg);
784 
785  GetWindowRect(GetParent(hwndDlg), &windowRect);
786  WindowHandleForElevate = hwndDlg;
788  L"-showoptions -hwnd %Ix -point %u,%u",
789  (ULONG_PTR)GetParent(hwndDlg),
790  windowRect.left + 20,
791  windowRect.top + 20
792  ));
793 
794  if (threadHandle)
795  NtClose(threadHandle);
796  }
797  break;
799  {
800  EnableWindow(GetDlgItem(hwndDlg, IDC_SAMPLECOUNT), Button_GetCheck(GetDlgItem(hwndDlg, IDC_SAMPLECOUNTAUTOMATIC)) != BST_CHECKED);
801  }
802  break;
803  }
804  }
805  break;
806  case WM_NOTIFY:
807  {
808  LPNMHDR header = (LPNMHDR)lParam;
809 
810  switch (header->code)
811  {
812  case PSN_APPLY:
813  {
814  PhpAdvancedPageSave(hwndDlg);
815  SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
816  }
817  return TRUE;
818  }
819  }
820  break;
821  case WM_PH_CHILD_EXIT:
822  {
823  PhpAdvancedPageLoad(hwndDlg);
824  }
825  break;
826  }
827 
828  return FALSE;
829 }
830 
831 INT_PTR CALLBACK PhpOptionsSymbolsDlgProc(
832  _In_ HWND hwndDlg,
833  _In_ UINT uMsg,
834  _In_ WPARAM wParam,
835  _In_ LPARAM lParam
836  )
837 {
838  switch (uMsg)
839  {
840  case WM_INITDIALOG:
841  {
842  PhpPageInit(hwndDlg);
843 
844  SetDlgItemText(hwndDlg, IDC_DBGHELPPATH, PhaGetStringSetting(L"DbgHelpPath")->Buffer);
845  SetDlgItemText(hwndDlg, IDC_DBGHELPSEARCHPATH, PhaGetStringSetting(L"DbgHelpSearchPath")->Buffer);
846 
847  SetDlgItemCheckForSetting(hwndDlg, IDC_UNDECORATESYMBOLS, L"DbgHelpUndecorate");
848  }
849  break;
850  case WM_COMMAND:
851  {
852  switch (LOWORD(wParam))
853  {
854  case IDC_BROWSE:
855  {
856  static PH_FILETYPE_FILTER filters[] =
857  {
858  { L"dbghelp.dll", L"dbghelp.dll" },
859  { L"All files (*.*)", L"*.*" }
860  };
861  PVOID fileDialog;
862  PPH_STRING fileName;
863 
864  fileDialog = PhCreateOpenFileDialog();
865  PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER));
866 
867  fileName = PhGetFileName(PhaGetDlgItemText(hwndDlg, IDC_DBGHELPPATH));
868  PhSetFileDialogFileName(fileDialog, fileName->Buffer);
869  PhDereferenceObject(fileName);
870 
871  if (PhShowFileDialog(hwndDlg, fileDialog))
872  {
873  fileName = PhGetFileDialogFileName(fileDialog);
874  SetDlgItemText(hwndDlg, IDC_DBGHELPPATH, fileName->Buffer);
875  PhDereferenceObject(fileName);
876  }
877 
878  PhFreeFileDialog(fileDialog);
879  }
880  break;
881  }
882  }
883  break;
884  case WM_NOTIFY:
885  {
886  LPNMHDR header = (LPNMHDR)lParam;
887 
888  switch (header->code)
889  {
890  case PSN_APPLY:
891  {
892  PPH_STRING dbgHelpPath;
893  PPH_STRING existingDbgHelpPath;
894 
895  dbgHelpPath = PhaGetDlgItemText(hwndDlg, IDC_DBGHELPPATH);
896  existingDbgHelpPath = PhAutoDereferenceObject(PhGetStringSetting(L"DbgHelpPath"));
897 
898  if (!PhEqualString(dbgHelpPath, existingDbgHelpPath, TRUE))
899  RestartRequired = TRUE;
900 
901  PhSetStringSetting2(L"DbgHelpPath", &dbgHelpPath->sr);
902  PhSetStringSetting2(L"DbgHelpSearchPath", &(PhaGetDlgItemText(hwndDlg, IDC_DBGHELPSEARCHPATH)->sr));
903  SetSettingForDlgItemCheck(hwndDlg, IDC_UNDECORATESYMBOLS, L"DbgHelpUndecorate");
904 
905  SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
906  }
907  return TRUE;
908  }
909  }
910  break;
911  }
912 
913  return FALSE;
914 }
915 
916 #define CROSS_INDEX 0
917 #define TICK_INDEX 1
918 
919 typedef struct _COLOR_ITEM
920 {
921  PWSTR SettingName;
922  PWSTR UseSettingName;
923  PWSTR Name;
924  PWSTR Description;
925 
926  BOOLEAN CurrentUse;
927  COLORREF CurrentColor;
929 
930 #define COLOR_ITEM(SettingName, Name, Description) { SettingName, L"Use" SettingName, Name, Description }
931 
932 static COLOR_ITEM ColorItems[] =
933 {
934  COLOR_ITEM(L"ColorOwnProcesses", L"Own Processes", L"Processes running under the same user account as Process Hacker."),
935  COLOR_ITEM(L"ColorSystemProcesses", L"System Processes", L"Processes running under the NT AUTHORITY\\SYSTEM user account."),
936  COLOR_ITEM(L"ColorServiceProcesses", L"Service Processes", L"Processes which host one or more services."),
937  COLOR_ITEM(L"ColorJobProcesses", L"Job Processes", L"Processes associated with a job."),
938 #ifdef _WIN64
939  COLOR_ITEM(L"ColorWow64Processes", L"32-bit Processes", L"Processes running under WOW64, i.e. 32-bit."),
940 #endif
941  COLOR_ITEM(L"ColorPosixProcesses", L"POSIX Processes", L"Processes running under the POSIX subsystem."),
942  COLOR_ITEM(L"ColorDebuggedProcesses", L"Debugged Processes", L"Processes that are currently being debugged."),
943  COLOR_ITEM(L"ColorElevatedProcesses", L"Elevated Processes", L"Processes with full privileges on a system with UAC enabled."),
944  COLOR_ITEM(L"ColorImmersiveProcesses", L"Immersive Processes and DLLs", L"Processes and DLLs that belong to a Modern UI app."),
945  COLOR_ITEM(L"ColorSuspended", L"Suspended Processes and Threads", L"Processes and threads that are suspended from execution."),
946  COLOR_ITEM(L"ColorDotNet", L".NET Processes and DLLs", L".NET (i.e. managed) processes and DLLs."),
947  COLOR_ITEM(L"ColorPacked", L"Packed Processes", L"Executables are sometimes \"packed\" to reduce their size."),
948  COLOR_ITEM(L"ColorGuiThreads", L"GUI Threads", L"Threads that have made at least one GUI-related system call."),
949  COLOR_ITEM(L"ColorRelocatedModules", L"Relocated DLLs", L"DLLs that were not loaded at their preferred image bases."),
950  COLOR_ITEM(L"ColorProtectedHandles", L"Protected Handles", L"Handles that are protected from being closed."),
951  COLOR_ITEM(L"ColorInheritHandles", L"Inheritable Handles", L"Handles that can be inherited by child processes.")
952 };
953 
955  _In_ INT Index,
956  _In_ PVOID Param,
957  _In_opt_ PVOID Context
958  )
959 {
960  PCOLOR_ITEM item = Param;
961 
962  return item->CurrentColor;
963 }
964 
966  _In_ HWND hwndDlg,
967  _In_ UINT uMsg,
968  _In_ WPARAM wParam,
969  _In_ LPARAM lParam
970  )
971 {
972  switch (uMsg)
973  {
974  case WM_INITDIALOG:
975  {
976  ULONG i;
977 
978  PhpPageInit(hwndDlg);
979 
980  // Highlighting Duration
981  SetDlgItemInt(hwndDlg, IDC_HIGHLIGHTINGDURATION, PhCsHighlightingDuration, FALSE);
982 
983  // New Objects
984  ColorBox_SetColor(GetDlgItem(hwndDlg, IDC_NEWOBJECTS), PhCsColorNew);
985 
986  // Removed Objects
988 
989  // Highlighting
990  HighlightingListViewHandle = GetDlgItem(hwndDlg, IDC_LIST);
991  PhSetListViewStyle(HighlightingListViewHandle, FALSE, TRUE);
992  ListView_SetExtendedListViewStyleEx(HighlightingListViewHandle, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
993  PhAddListViewColumn(HighlightingListViewHandle, 0, 0, 0, LVCFMT_LEFT, 240, L"Name");
994  PhSetExtendedListView(HighlightingListViewHandle);
996 
997  for (i = 0; i < sizeof(ColorItems) / sizeof(COLOR_ITEM); i++)
998  {
999  INT lvItemIndex;
1000 
1001  lvItemIndex = PhAddListViewItem(HighlightingListViewHandle, MAXINT, ColorItems[i].Name, &ColorItems[i]);
1002  ColorItems[i].CurrentColor = PhGetIntegerSetting(ColorItems[i].SettingName);
1003  ColorItems[i].CurrentUse = !!PhGetIntegerSetting(ColorItems[i].UseSettingName);
1004  ListView_SetCheckState(HighlightingListViewHandle, lvItemIndex, ColorItems[i].CurrentUse);
1005  }
1006 
1007  EnableWindow(GetDlgItem(hwndDlg, IDC_ENABLE), FALSE);
1008  }
1009  break;
1010  case WM_COMMAND:
1011  {
1012  switch (LOWORD(wParam))
1013  {
1014  case IDC_ENABLEALL:
1015  {
1016  ULONG i;
1017 
1018  for (i = 0; i < sizeof(ColorItems) / sizeof(COLOR_ITEM); i++)
1019  ListView_SetCheckState(HighlightingListViewHandle, i, TRUE);
1020  }
1021  break;
1022  case IDC_DISABLEALL:
1023  {
1024  ULONG i;
1025 
1026  for (i = 0; i < sizeof(ColorItems) / sizeof(COLOR_ITEM); i++)
1027  ListView_SetCheckState(HighlightingListViewHandle, i, FALSE);
1028  }
1029  break;
1030  }
1031  }
1032  break;
1033  case WM_NOTIFY:
1034  {
1035  LPNMHDR header = (LPNMHDR)lParam;
1036 
1037  switch (header->code)
1038  {
1039  case PSN_APPLY:
1040  {
1041  ULONG i;
1042 
1043  PH_SET_INTEGER_CACHED_SETTING(HighlightingDuration, GetDlgItemInt(hwndDlg, IDC_HIGHLIGHTINGDURATION, NULL, FALSE));
1044  PH_SET_INTEGER_CACHED_SETTING(ColorNew, ColorBox_GetColor(GetDlgItem(hwndDlg, IDC_NEWOBJECTS)));
1045  PH_SET_INTEGER_CACHED_SETTING(ColorRemoved, ColorBox_GetColor(GetDlgItem(hwndDlg, IDC_REMOVEDOBJECTS)));
1046 
1047  for (i = 0; i < sizeof(ColorItems) / sizeof(COLOR_ITEM); i++)
1048  {
1049  ColorItems[i].CurrentUse = !!ListView_GetCheckState(HighlightingListViewHandle, i);
1050  PhSetIntegerSetting(ColorItems[i].SettingName, ColorItems[i].CurrentColor);
1051  PhSetIntegerSetting(ColorItems[i].UseSettingName, ColorItems[i].CurrentUse);
1052  }
1053 
1054  SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
1055  }
1056  return TRUE;
1057  case NM_DBLCLK:
1058  {
1059  if (header->hwndFrom == HighlightingListViewHandle)
1060  {
1061  PCOLOR_ITEM item;
1062 
1063  if (item = PhGetSelectedListViewItemParam(HighlightingListViewHandle))
1064  {
1065  CHOOSECOLOR chooseColor = { sizeof(chooseColor) };
1066  COLORREF customColors[16] = { 0 };
1067 
1068  chooseColor.hwndOwner = hwndDlg;
1069  chooseColor.rgbResult = item->CurrentColor;
1070  chooseColor.lpCustColors = customColors;
1071  chooseColor.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT;
1072 
1073  if (ChooseColor(&chooseColor))
1074  {
1075  item->CurrentColor = chooseColor.rgbResult;
1076  InvalidateRect(HighlightingListViewHandle, NULL, TRUE);
1077  }
1078  }
1079  }
1080  }
1081  break;
1082  case LVN_GETINFOTIP:
1083  {
1084  if (header->hwndFrom == HighlightingListViewHandle)
1085  {
1086  NMLVGETINFOTIP *getInfoTip = (NMLVGETINFOTIP *)lParam;
1087  PH_STRINGREF tip;
1088 
1089  PhInitializeStringRefLongHint(&tip, ColorItems[getInfoTip->iItem].Description);
1090  PhCopyListViewInfoTip(getInfoTip, &tip);
1091  }
1092  }
1093  break;
1094  }
1095  }
1096  break;
1097  }
1098 
1099  REFLECT_MESSAGE_DLG(hwndDlg, HighlightingListViewHandle, uMsg, wParam, lParam);
1100 
1101  return FALSE;
1102 }
1103 
1104 INT_PTR CALLBACK PhpOptionsGraphsDlgProc(
1105  _In_ HWND hwndDlg,
1106  _In_ UINT uMsg,
1107  _In_ WPARAM wParam,
1108  _In_ LPARAM lParam
1109  )
1110 {
1111  switch (uMsg)
1112  {
1113  case WM_INITDIALOG:
1114  {
1115  PhpPageInit(hwndDlg);
1116 
1117  // Show Text
1118  SetDlgItemCheckForSetting(hwndDlg, IDC_SHOWTEXT, L"GraphShowText");
1119  SetDlgItemCheckForSetting(hwndDlg, IDC_USEOLDCOLORS, L"GraphColorMode");
1120  SetDlgItemCheckForSetting(hwndDlg, IDC_SHOWCOMMITINSUMMARY, L"ShowCommitInSummary");
1121 
1122  ColorBox_SetColor(GetDlgItem(hwndDlg, IDC_CPUUSER), PhCsColorCpuUser);
1123  ColorBox_SetColor(GetDlgItem(hwndDlg, IDC_CPUKERNEL), PhCsColorCpuKernel);
1124  ColorBox_SetColor(GetDlgItem(hwndDlg, IDC_IORO), PhCsColorIoReadOther);
1125  ColorBox_SetColor(GetDlgItem(hwndDlg, IDC_IOW), PhCsColorIoWrite);
1126  ColorBox_SetColor(GetDlgItem(hwndDlg, IDC_PRIVATE), PhCsColorPrivate);
1127  ColorBox_SetColor(GetDlgItem(hwndDlg, IDC_PHYSICAL), PhCsColorPhysical);
1128  }
1129  break;
1130  case WM_NOTIFY:
1131  {
1132  LPNMHDR header = (LPNMHDR)lParam;
1133 
1134  switch (header->code)
1135  {
1136  case PSN_APPLY:
1137  {
1138  SetSettingForDlgItemCheck(hwndDlg, IDC_SHOWTEXT, L"GraphShowText");
1139  SetSettingForDlgItemCheck(hwndDlg, IDC_USEOLDCOLORS, L"GraphColorMode");
1140  SetSettingForDlgItemCheck(hwndDlg, IDC_SHOWCOMMITINSUMMARY, L"ShowCommitInSummary");
1141  PH_SET_INTEGER_CACHED_SETTING(ColorCpuUser, ColorBox_GetColor(GetDlgItem(hwndDlg, IDC_CPUUSER)));
1142  PH_SET_INTEGER_CACHED_SETTING(ColorCpuKernel, ColorBox_GetColor(GetDlgItem(hwndDlg, IDC_CPUKERNEL)));
1143  PH_SET_INTEGER_CACHED_SETTING(ColorIoReadOther, ColorBox_GetColor(GetDlgItem(hwndDlg, IDC_IORO)));
1144  PH_SET_INTEGER_CACHED_SETTING(ColorIoWrite, ColorBox_GetColor(GetDlgItem(hwndDlg, IDC_IOW)));
1145  PH_SET_INTEGER_CACHED_SETTING(ColorPrivate, ColorBox_GetColor(GetDlgItem(hwndDlg, IDC_PRIVATE)));
1146  PH_SET_INTEGER_CACHED_SETTING(ColorPhysical, ColorBox_GetColor(GetDlgItem(hwndDlg, IDC_PHYSICAL)));
1147 
1148  SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR);
1149  }
1150  return TRUE;
1151  }
1152  }
1153  break;
1154  }
1155 
1156  return FALSE;
1157 }