Process Hacker
main.c
Go to the documentation of this file.
1 /*
2  * Process Hacker Extended Tools -
3  * main program
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 "exttools.h"
24 #include "resource.h"
25 
26 VOID NTAPI LoadCallback(
27  _In_opt_ PVOID Parameter,
28  _In_opt_ PVOID Context
29  );
30 
31 VOID NTAPI UnloadCallback(
32  _In_opt_ PVOID Parameter,
33  _In_opt_ PVOID Context
34  );
35 
37  _In_opt_ PVOID Parameter,
38  _In_opt_ PVOID Context
39  );
40 
42  _In_opt_ PVOID Parameter,
43  _In_opt_ PVOID Context
44  );
45 
47  _In_opt_ PVOID Parameter,
48  _In_opt_ PVOID Context
49  );
50 
52  _In_opt_ PVOID Parameter,
53  _In_opt_ PVOID Context
54  );
55 
57  _In_opt_ PVOID Parameter,
58  _In_opt_ PVOID Context
59  );
60 
62  _In_opt_ PVOID Parameter,
63  _In_opt_ PVOID Context
64  );
65 
67  _In_opt_ PVOID Parameter,
68  _In_opt_ PVOID Context
69  );
70 
72  _In_opt_ PVOID Parameter,
73  _In_opt_ PVOID Context
74  );
75 
77  _In_opt_ PVOID Parameter,
78  _In_opt_ PVOID Context
79  );
80 
82  _In_opt_ PVOID Parameter,
83  _In_opt_ PVOID Context
84  );
85 
87  _In_opt_ PVOID Parameter,
88  _In_opt_ PVOID Context
89  );
90 
92  _In_opt_ PVOID Parameter,
93  _In_opt_ PVOID Context
94  );
95 
97  _In_opt_ PVOID Parameter,
98  _In_opt_ PVOID Context
99  );
100 
102  _In_opt_ PVOID Parameter,
103  _In_opt_ PVOID Context
104  );
105 
107  _In_opt_ PVOID Parameter,
108  _In_opt_ PVOID Context
109  );
110 
112  _In_ PVOID Object,
113  _In_ PH_EM_OBJECT_TYPE ObjectType,
114  _In_ PVOID Extension
115  );
116 
118  _In_ PVOID Object,
119  _In_ PH_EM_OBJECT_TYPE ObjectType,
120  _In_ PVOID Extension
121  );
122 
124  _In_ PVOID Object,
125  _In_ PH_EM_OBJECT_TYPE ObjectType,
126  _In_ PVOID Extension
127  );
128 
130  _In_ PVOID Object,
131  _In_ PH_EM_OBJECT_TYPE ObjectType,
132  _In_ PVOID Extension
133  );
134 
157 
158 static HANDLE ModuleProcessId;
159 
161  _In_ HINSTANCE Instance,
162  _In_ ULONG Reason,
163  _Reserved_ PVOID Reserved
164  )
165 {
166  switch (Reason)
167  {
168  case DLL_PROCESS_ATTACH:
169  {
171 
172  PluginInstance = PhRegisterPlugin(PLUGIN_NAME, Instance, &info);
173 
174  if (!PluginInstance)
175  return FALSE;
176 
177  info->DisplayName = L"Extended Tools";
178  info->Author = L"wj32";
179  info->Description = L"Extended functionality for Windows Vista and above, including ETW monitoring, GPU monitoring and a Disk tab.";
180  info->Url = L"http://processhacker.sf.net/forums/viewtopic.php?t=1114";
181  info->HasOptions = TRUE;
182 
184  PhGetPluginCallback(PluginInstance, PluginCallbackLoad),
185  LoadCallback,
186  NULL,
187  &PluginLoadCallbackRegistration
188  );
190  PhGetPluginCallback(PluginInstance, PluginCallbackUnload),
192  NULL,
193  &PluginUnloadCallbackRegistration
194  );
198  NULL,
199  &PluginShowOptionsCallbackRegistration
200  );
204  NULL,
205  &PluginMenuItemCallbackRegistration
206  );
210  NULL,
211  &PluginTreeNewMessageCallbackRegistration
212  );
213 
217  NULL,
218  &MainWindowShowingCallbackRegistration
219  );
223  NULL,
224  &ProcessPropertiesInitializingCallbackRegistration
225  );
229  NULL,
230  &HandlePropertiesInitializingCallbackRegistration
231  );
235  NULL,
236  &ProcessMenuInitializingCallbackRegistration
237  );
241  NULL,
242  &ThreadMenuInitializingCallbackRegistration
243  );
247  NULL,
248  &ModuleMenuInitializingCallbackRegistration
249  );
253  NULL,
254  &ProcessTreeNewInitializingCallbackRegistration
255  );
259  NULL,
260  &NetworkTreeNewInitializingCallbackRegistration
261  );
265  NULL,
266  &SystemInformationInitializingCallbackRegistration
267  );
271  NULL,
272  &MiniInformationInitializingCallbackRegistration
273  );
274 
278  NULL,
279  &ProcessesUpdatedCallbackRegistration
280  );
284  NULL,
285  &NetworkItemsUpdatedCallbackRegistration
286  );
287 
290 
292  PluginInstance,
294  sizeof(ET_PROCESS_BLOCK),
297  );
299  PluginInstance,
301  sizeof(ET_NETWORK_BLOCK),
304  );
305 
306  {
307  static PH_SETTING_CREATE settings[] =
308  {
310  { IntegerPairSettingType, SETTING_NAME_DISK_TREE_LIST_SORT, L"4,2" }, // 4, DescendingSortOrder
315  };
316 
317  PhAddSettings(settings, sizeof(settings) / sizeof(PH_SETTING_CREATE));
318  }
319  }
320  break;
321  }
322 
323  return TRUE;
324 }
325 
326 VOID NTAPI LoadCallback(
327  _In_opt_ PVOID Parameter,
328  _In_opt_ PVOID Context
329  )
330 {
333 
335 }
336 
337 VOID NTAPI UnloadCallback(
338  _In_opt_ PVOID Parameter,
339  _In_opt_ PVOID Context
340  )
341 {
344 }
345 
347  _In_opt_ PVOID Parameter,
348  _In_opt_ PVOID Context
349  )
350 {
351  EtShowOptionsDialog((HWND)Parameter);
352 }
353 
354 VOID NTAPI MenuItemCallback(
355  _In_opt_ PVOID Parameter,
356  _In_opt_ PVOID Context
357  )
358 {
359  PPH_PLUGIN_MENU_ITEM menuItem = Parameter;
360 
361  switch (menuItem->Id)
362  {
364  {
366  }
367  break;
368  case ID_PROCESS_WSWATCH:
369  {
371  }
372  break;
373  case ID_THREAD_CANCELIO:
374  {
375  EtUiCancelIoThread(menuItem->OwnerWindow, menuItem->Context);
376  }
377  break;
378  case ID_MODULE_SERVICES:
379  {
381  menuItem->OwnerWindow,
382  ModuleProcessId,
383  ((PPH_MODULE_ITEM)menuItem->Context)->Name->Buffer
384  );
385  }
386  break;
387  }
388 }
389 
391  _In_opt_ PVOID Parameter,
392  _In_opt_ PVOID Context
393  )
394 {
395  PPH_PLUGIN_TREENEW_MESSAGE message = Parameter;
396 
397  if (message->TreeNewHandle == ProcessTreeNewHandle)
398  EtProcessTreeNewMessage(Parameter);
399  else if (message->TreeNewHandle == NetworkTreeNewHandle)
400  EtNetworkTreeNewMessage(Parameter);
401 }
402 
404  _In_opt_ PVOID Parameter,
405  _In_opt_ PVOID Context
406  )
407 {
409 }
410 
412  _In_opt_ PVOID Parameter,
413  _In_opt_ PVOID Context
414  )
415 {
418 }
419 
421  _In_opt_ PVOID Parameter,
422  _In_opt_ PVOID Context
423  )
424 {
426 }
427 
429  _In_opt_ PVOID Parameter,
430  _In_opt_ PVOID Context
431  )
432 {
433  PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
434  PPH_PROCESS_ITEM processItem;
435  ULONG flags;
436  PPH_EMENU_ITEM miscMenu;
437 
438  if (menuInfo->u.Process.NumberOfProcesses == 1)
439  processItem = menuInfo->u.Process.Processes[0];
440  else
441  processItem = NULL;
442 
443  flags = 0;
444 
445  if (!processItem)
446  flags = PH_EMENU_DISABLED;
447 
448  miscMenu = PhFindEMenuItem(menuInfo->Menu, 0, L"Miscellaneous", 0);
449 
450  if (miscMenu)
451  {
452  PhInsertEMenuItem(miscMenu, PhPluginCreateEMenuItem(PluginInstance, flags, ID_PROCESS_UNLOADEDMODULES, L"Unloaded Modules", processItem), -1);
453  PhInsertEMenuItem(miscMenu, PhPluginCreateEMenuItem(PluginInstance, flags, ID_PROCESS_WSWATCH, L"WS Watch", processItem), -1);
454  }
455 }
456 
458  _In_opt_ PVOID Parameter,
459  _In_opt_ PVOID Context
460  )
461 {
462  PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
463  PPH_THREAD_ITEM threadItem;
464  ULONG insertIndex;
465  PPH_EMENU_ITEM menuItem;
466 
467  if (menuInfo->u.Thread.NumberOfThreads == 1)
468  threadItem = menuInfo->u.Thread.Threads[0];
469  else
470  threadItem = NULL;
471 
472  if (menuItem = PhFindEMenuItem(menuInfo->Menu, 0, L"Resume", 0))
473  insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1;
474  else
475  insertIndex = 0;
476 
477  PhInsertEMenuItem(menuInfo->Menu, menuItem = PhPluginCreateEMenuItem(PluginInstance, 0, ID_THREAD_CANCELIO,
478  L"Cancel I/O", threadItem), insertIndex);
479 
480  if (!threadItem) menuItem->Flags |= PH_EMENU_DISABLED;
481 }
482 
484  _In_opt_ PVOID Parameter,
485  _In_opt_ PVOID Context
486  )
487 {
488  PPH_PLUGIN_MENU_INFORMATION menuInfo = Parameter;
489  PPH_PROCESS_ITEM processItem;
490  BOOLEAN addMenuItem;
491  PPH_MODULE_ITEM moduleItem;
492  ULONG insertIndex;
493  PPH_EMENU_ITEM menuItem;
494 
495  addMenuItem = FALSE;
496 
497  if (processItem = PhReferenceProcessItem(menuInfo->u.Module.ProcessId))
498  {
499  if (processItem->ServiceList && processItem->ServiceList->Count != 0)
500  addMenuItem = TRUE;
501 
502  PhDereferenceObject(processItem);
503  }
504 
505  if (!addMenuItem)
506  return;
507 
508  if (menuInfo->u.Module.NumberOfModules == 1)
509  moduleItem = menuInfo->u.Module.Modules[0];
510  else
511  moduleItem = NULL;
512 
513  if (menuItem = PhFindEMenuItem(menuInfo->Menu, PH_EMENU_FIND_STARTSWITH, L"Inspect", 0))
514  insertIndex = PhIndexOfEMenuItem(menuInfo->Menu, menuItem) + 1;
515  else
516  insertIndex = 0;
517 
518  ModuleProcessId = menuInfo->u.Module.ProcessId;
519 
520  PhInsertEMenuItem(menuInfo->Menu, menuItem = PhPluginCreateEMenuItem(PluginInstance, 0, ID_MODULE_SERVICES,
521  L"Services", moduleItem), insertIndex);
522 
523  if (!moduleItem) menuItem->Flags |= PH_EMENU_DISABLED;
524 }
525 
527  _In_opt_ PVOID Parameter,
528  _In_opt_ PVOID Context
529  )
530 {
531  PPH_PLUGIN_TREENEW_INFORMATION treeNewInfo = Parameter;
532 
533  ProcessTreeNewHandle = treeNewInfo->TreeNewHandle;
534  EtProcessTreeNewInitializing(Parameter);
535 }
536 
538  _In_opt_ PVOID Parameter,
539  _In_opt_ PVOID Context
540  )
541 {
542  PPH_PLUGIN_TREENEW_INFORMATION treeNewInfo = Parameter;
543 
544  NetworkTreeNewHandle = treeNewInfo->TreeNewHandle;
545  EtNetworkTreeNewInitializing(Parameter);
546 }
547 
549  _In_opt_ PVOID Parameter,
550  _In_opt_ PVOID Context
551  )
552 {
553  if (EtGpuEnabled)
555  if (EtEtwEnabled)
557 }
558 
560  _In_opt_ PVOID Parameter,
561  _In_opt_ PVOID Context
562  )
563 {
564  if (EtGpuEnabled)
566  if (EtEtwEnabled)
568 }
569 
570 static VOID NTAPI ProcessesUpdatedCallback(
571  _In_opt_ PVOID Parameter,
572  _In_opt_ PVOID Context
573  )
574 {
575  PLIST_ENTRY listEntry;
576 
577  // Note: no lock is needed because we only ever modify the list on this same thread.
578 
579  listEntry = EtProcessBlockListHead.Flink;
580 
581  while (listEntry != &EtProcessBlockListHead)
582  {
583  PET_PROCESS_BLOCK block;
584 
585  block = CONTAINING_RECORD(listEntry, ET_PROCESS_BLOCK, ListEntry);
586 
588 
589  // Invalidate all text.
590 
592  memset(block->TextCacheValid, 0, sizeof(block->TextCacheValid));
594 
595  listEntry = listEntry->Flink;
596  }
597 }
598 
599 static VOID NTAPI NetworkItemsUpdatedCallback(
600  _In_opt_ PVOID Parameter,
601  _In_opt_ PVOID Context
602  )
603 {
604  PLIST_ENTRY listEntry;
605 
606  // Note: no lock is needed because we only ever modify the list on this same thread.
607 
608  listEntry = EtNetworkBlockListHead.Flink;
609 
610  while (listEntry != &EtNetworkBlockListHead)
611  {
612  PET_NETWORK_BLOCK block;
613 
614  block = CONTAINING_RECORD(listEntry, ET_NETWORK_BLOCK, ListEntry);
615 
616  // Invalidate all text.
617 
619  memset(block->TextCacheValid, 0, sizeof(block->TextCacheValid));
621 
622  listEntry = listEntry->Flink;
623  }
624 }
625 
627  _In_ PPH_PROCESS_ITEM ProcessItem
628  )
629 {
630  return PhPluginGetObjectExtension(PluginInstance, ProcessItem, EmProcessItemType);
631 }
632 
634  _In_ PPH_NETWORK_ITEM NetworkItem
635  )
636 {
637  return PhPluginGetObjectExtension(PluginInstance, NetworkItem, EmNetworkItemType);
638 }
639 
641  _Out_ PET_PROCESS_BLOCK Block,
642  _In_ PPH_PROCESS_ITEM ProcessItem
643  )
644 {
645  memset(Block, 0, sizeof(ET_PROCESS_BLOCK));
646  Block->ProcessItem = ProcessItem;
647  PhInitializeQueuedLock(&Block->TextCacheLock);
648  InsertTailList(&EtProcessBlockListHead, &Block->ListEntry);
649 }
650 
652  _In_ PET_PROCESS_BLOCK Block
653  )
654 {
655  ULONG i;
656 
658 
659  for (i = 1; i <= ETPRTNC_MAXIMUM; i++)
660  {
661  PhClearReference(&Block->TextCache[i]);
662  }
663 
664  RemoveEntryList(&Block->ListEntry);
665 }
666 
668  _Out_ PET_NETWORK_BLOCK Block,
669  _In_ PPH_NETWORK_ITEM NetworkItem
670  )
671 {
672  memset(Block, 0, sizeof(ET_NETWORK_BLOCK));
673  Block->NetworkItem = NetworkItem;
674  PhInitializeQueuedLock(&Block->TextCacheLock);
675  InsertTailList(&EtNetworkBlockListHead, &Block->ListEntry);
676 }
677 
679  _In_ PET_NETWORK_BLOCK Block
680  )
681 {
682  ULONG i;
683 
684  for (i = 1; i <= ETNETNC_MAXIMUM; i++)
685  {
686  PhClearReference(&Block->TextCache[i]);
687  }
688 
689  RemoveEntryList(&Block->ListEntry);
690 }
691 
693  _In_ PVOID Object,
694  _In_ PH_EM_OBJECT_TYPE ObjectType,
695  _In_ PVOID Extension
696  )
697 {
698  EtInitializeProcessBlock(Extension, Object);
699 }
700 
702  _In_ PVOID Object,
703  _In_ PH_EM_OBJECT_TYPE ObjectType,
704  _In_ PVOID Extension
705  )
706 {
707  EtDeleteProcessBlock(Extension);
708 }
709 
711  _In_ PVOID Object,
712  _In_ PH_EM_OBJECT_TYPE ObjectType,
713  _In_ PVOID Extension
714  )
715 {
716  EtInitializeNetworkBlock(Extension, Object);
717 }
718 
720  _In_ PVOID Object,
721  _In_ PH_EM_OBJECT_TYPE ObjectType,
722  _In_ PVOID Extension
723  )
724 {
725  EtDeleteNetworkBlock(Extension);
726 }