Process Hacker
modlist.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * module list
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 <extmgri.h>
26 #include <phplug.h>
27 #include <emenu.h>
28 #include <verify.h>
29 
31  _In_ PVOID Entry1,
32  _In_ PVOID Entry2
33  );
34 
36  _In_ PVOID Entry
37  );
38 
40  _In_ PPH_MODULE_NODE ModuleNode
41  );
42 
44  _In_ PPH_MODULE_NODE ModuleNode,
45  _In_ PPH_MODULE_LIST_CONTEXT Context
46  );
47 
49  _In_ LONG Result,
50  _In_ PVOID Node1,
51  _In_ PVOID Node2,
52  _In_ PH_SORT_ORDER SortOrder
53  );
54 
55 BOOLEAN NTAPI PhpModuleTreeNewCallback(
56  _In_ HWND hwnd,
57  _In_ PH_TREENEW_MESSAGE Message,
58  _In_opt_ PVOID Parameter1,
59  _In_opt_ PVOID Parameter2,
60  _In_opt_ PVOID Context
61  );
62 
64  _In_ HWND ParentWindowHandle,
65  _In_ HWND TreeNewHandle,
66  _Out_ PPH_MODULE_LIST_CONTEXT Context
67  )
68 {
69  HWND hwnd;
70 
71  memset(Context, 0, sizeof(PH_MODULE_LIST_CONTEXT));
72  Context->EnableStateHighlighting = TRUE;
73 
74  Context->NodeHashtable = PhCreateHashtable(
75  sizeof(PPH_MODULE_NODE),
78  100
79  );
80  Context->NodeList = PhCreateList(100);
81 
82  Context->ParentWindowHandle = ParentWindowHandle;
83  Context->TreeNewHandle = TreeNewHandle;
84  hwnd = TreeNewHandle;
85  PhSetControlTheme(hwnd, L"explorer");
86 
88 
89  TreeNew_SetRedraw(hwnd, FALSE);
90 
91  // Default columns
92  PhAddTreeNewColumn(hwnd, PHMOTLC_NAME, TRUE, L"Name", 100, PH_ALIGN_LEFT, -2, 0);
93  PhAddTreeNewColumn(hwnd, PHMOTLC_BASEADDRESS, TRUE, L"Base Address", 80, PH_ALIGN_RIGHT, 0, DT_RIGHT);
94  PhAddTreeNewColumnEx(hwnd, PHMOTLC_SIZE, TRUE, L"Size", 60, PH_ALIGN_RIGHT, 1, DT_RIGHT, TRUE);
95  PhAddTreeNewColumn(hwnd, PHMOTLC_DESCRIPTION, TRUE, L"Description", 160, PH_ALIGN_LEFT, 2, 0);
96 
97  PhAddTreeNewColumn(hwnd, PHMOTLC_COMPANYNAME, FALSE, L"Company Name", 180, PH_ALIGN_LEFT, -1, 0);
98  PhAddTreeNewColumn(hwnd, PHMOTLC_VERSION, FALSE, L"Version", 100, PH_ALIGN_LEFT, -1, 0);
99  PhAddTreeNewColumn(hwnd, PHMOTLC_FILENAME, FALSE, L"File Name", 180, PH_ALIGN_LEFT, -1, DT_PATH_ELLIPSIS);
100 
101  PhAddTreeNewColumn(hwnd, PHMOTLC_TYPE, FALSE, L"Type", 80, PH_ALIGN_LEFT, -1, 0);
102  PhAddTreeNewColumnEx(hwnd, PHMOTLC_LOADCOUNT, FALSE, L"Load Count", 40, PH_ALIGN_RIGHT, -1, DT_RIGHT, TRUE);
103  PhAddTreeNewColumn(hwnd, PHMOTLC_VERIFICATIONSTATUS, FALSE, L"Verification Status", 70, PH_ALIGN_LEFT, -1, 0);
104  PhAddTreeNewColumn(hwnd, PHMOTLC_VERIFIEDSIGNER, FALSE, L"Verified Signer", 100, PH_ALIGN_LEFT, -1, 0);
105  PhAddTreeNewColumnEx(hwnd, PHMOTLC_ASLR, FALSE, L"ASLR", 50, PH_ALIGN_LEFT, -1, 0, TRUE);
106  PhAddTreeNewColumnEx(hwnd, PHMOTLC_TIMESTAMP, FALSE, L"Time Stamp", 100, PH_ALIGN_LEFT, -1, 0, TRUE);
107  PhAddTreeNewColumnEx(hwnd, PHMOTLC_CFGUARD, FALSE, L"CF Guard", 70, PH_ALIGN_LEFT, -1, 0, TRUE);
108  PhAddTreeNewColumnEx(hwnd, PHMOTLC_LOADTIME, FALSE, L"Load Time", 100, PH_ALIGN_LEFT, -1, 0, TRUE);
109  PhAddTreeNewColumn(hwnd, PHMOTLC_LOADREASON, FALSE, L"Load Reason", 80, PH_ALIGN_LEFT, -1, 0);
110 
111  TreeNew_SetRedraw(hwnd, TRUE);
112 
113  TreeNew_SetTriState(hwnd, TRUE);
114  TreeNew_SetSort(hwnd, 0, NoSortOrder);
115 
117 }
118 
120  _In_ PPH_MODULE_LIST_CONTEXT Context
121  )
122 {
123  ULONG i;
124 
125  if (Context->BoldFont)
126  DeleteObject(Context->BoldFont);
127 
128  PhCmDeleteManager(&Context->Cm);
129 
130  for (i = 0; i < Context->NodeList->Count; i++)
131  PhpDestroyModuleNode(Context->NodeList->Items[i]);
132 
133  PhDereferenceObject(Context->NodeHashtable);
134  PhDereferenceObject(Context->NodeList);
135 }
136 
138  _In_ PVOID Entry1,
139  _In_ PVOID Entry2
140  )
141 {
142  PPH_MODULE_NODE moduleNode1 = *(PPH_MODULE_NODE *)Entry1;
143  PPH_MODULE_NODE moduleNode2 = *(PPH_MODULE_NODE *)Entry2;
144 
145  return moduleNode1->ModuleItem == moduleNode2->ModuleItem;
146 }
147 
149  _In_ PVOID Entry
150  )
151 {
152  return PhHashIntPtr((ULONG_PTR)(*(PPH_MODULE_NODE *)Entry)->ModuleItem);
153 }
154 
156  _Inout_ PPH_MODULE_LIST_CONTEXT Context
157  )
158 {
159  PPH_STRING settings;
160  PPH_STRING sortSettings;
161 
162  settings = PhGetStringSetting(L"ModuleTreeListColumns");
163  sortSettings = PhGetStringSetting(L"ModuleTreeListSort");
164  PhCmLoadSettingsEx(Context->TreeNewHandle, &Context->Cm, 0, &settings->sr, &sortSettings->sr);
165  PhDereferenceObject(settings);
166  PhDereferenceObject(sortSettings);
167 }
168 
170  _Inout_ PPH_MODULE_LIST_CONTEXT Context
171  )
172 {
173  PPH_STRING settings;
174  PPH_STRING sortSettings;
175 
176  settings = PhCmSaveSettingsEx(Context->TreeNewHandle, &Context->Cm, 0, &sortSettings);
177  PhSetStringSetting2(L"ModuleTreeListColumns", &settings->sr);
178  PhSetStringSetting2(L"ModuleTreeListSort", &sortSettings->sr);
179  PhDereferenceObject(settings);
180  PhDereferenceObject(sortSettings);
181 }
182 
184  _Inout_ PPH_MODULE_LIST_CONTEXT Context,
185  _In_ PPH_MODULE_ITEM ModuleItem,
186  _In_ ULONG RunId
187  )
188 {
189  PPH_MODULE_NODE moduleNode;
190 
191  moduleNode = PhAllocate(PhEmGetObjectSize(EmModuleNodeType, sizeof(PH_MODULE_NODE)));
192  memset(moduleNode, 0, sizeof(PH_MODULE_NODE));
193  PhInitializeTreeNewNode(&moduleNode->Node);
194 
195  if (Context->EnableStateHighlighting && RunId != 1)
196  {
198  &moduleNode->Node,
199  &moduleNode->ShState,
200  &Context->NodeStateList,
201  NewItemState,
202  PhCsColorNew,
203  NULL
204  );
205  }
206 
207  moduleNode->ModuleItem = ModuleItem;
208  PhReferenceObject(ModuleItem);
209 
210  memset(moduleNode->TextCache, 0, sizeof(PH_STRINGREF) * PHMOTLC_MAXIMUM);
211  moduleNode->Node.TextCache = moduleNode->TextCache;
212  moduleNode->Node.TextCacheSize = PHMOTLC_MAXIMUM;
213 
214  PhAddEntryHashtable(Context->NodeHashtable, &moduleNode);
215  PhAddItemList(Context->NodeList, moduleNode);
216 
218 
219  TreeNew_NodesStructured(Context->TreeNewHandle);
220 
221  return moduleNode;
222 }
223 
225  _In_ PPH_MODULE_LIST_CONTEXT Context,
226  _In_ PPH_MODULE_ITEM ModuleItem
227  )
228 {
229  PH_MODULE_NODE lookupModuleNode;
230  PPH_MODULE_NODE lookupModuleNodePtr = &lookupModuleNode;
231  PPH_MODULE_NODE *moduleNode;
232 
233  lookupModuleNode.ModuleItem = ModuleItem;
234 
235  moduleNode = (PPH_MODULE_NODE *)PhFindEntryHashtable(
236  Context->NodeHashtable,
237  &lookupModuleNodePtr
238  );
239 
240  if (moduleNode)
241  return *moduleNode;
242  else
243  return NULL;
244 }
245 
247  _In_ PPH_MODULE_LIST_CONTEXT Context,
248  _In_ PPH_MODULE_NODE ModuleNode
249  )
250 {
251  // Remove from the hashtable here to avoid problems in case the key is re-used.
252  PhRemoveEntryHashtable(Context->NodeHashtable, &ModuleNode);
253 
254  if (Context->EnableStateHighlighting)
255  {
257  &ModuleNode->Node,
258  &ModuleNode->ShState,
259  &Context->NodeStateList,
262  Context->TreeNewHandle
263  );
264  }
265  else
266  {
267  PhpRemoveModuleNode(ModuleNode, Context);
268  }
269 }
270 
272  _In_ PPH_MODULE_NODE ModuleNode
273  )
274 {
276 
277  if (ModuleNode->TooltipText) PhDereferenceObject(ModuleNode->TooltipText);
278 
279  if (ModuleNode->SizeText) PhDereferenceObject(ModuleNode->SizeText);
280  if (ModuleNode->TimeStampText) PhDereferenceObject(ModuleNode->TimeStampText);
281  if (ModuleNode->LoadTimeText) PhDereferenceObject(ModuleNode->LoadTimeText);
282 
283  PhDereferenceObject(ModuleNode->ModuleItem);
284 
285  PhFree(ModuleNode);
286 }
287 
289  _In_ PPH_MODULE_NODE ModuleNode,
290  _In_ PPH_MODULE_LIST_CONTEXT Context // PH_TICK_SH_STATE requires this parameter to be after ModuleNode
291  )
292 {
293  ULONG index;
294 
295  // Remove from list and cleanup.
296 
297  if ((index = PhFindItemList(Context->NodeList, ModuleNode)) != -1)
298  PhRemoveItemList(Context->NodeList, index);
299 
300  PhpDestroyModuleNode(ModuleNode);
301 
302  TreeNew_NodesStructured(Context->TreeNewHandle);
303 }
304 
306  _In_ PPH_MODULE_LIST_CONTEXT Context,
307  _In_ PPH_MODULE_NODE ModuleNode
308  )
309 {
310  memset(ModuleNode->TextCache, 0, sizeof(PH_STRINGREF) * PHMOTLC_MAXIMUM);
311  PhClearReference(&ModuleNode->TooltipText);
312 
313  ModuleNode->ValidMask = 0;
314  PhInvalidateTreeNewNode(&ModuleNode->Node, TN_CACHE_COLOR);
315  TreeNew_NodesStructured(Context->TreeNewHandle);
316 }
317 
319  _In_ PPH_MODULE_LIST_CONTEXT Context
320  )
321 {
322  PH_TICK_SH_STATE_TN(PH_MODULE_NODE, ShState, Context->NodeStateList, PhpRemoveModuleNode, PhCsHighlightingDuration, Context->TreeNewHandle, TRUE, NULL, Context);
323 }
324 
325 #define SORT_FUNCTION(Column) PhpModuleTreeNewCompare##Column
326 
327 #define BEGIN_SORT_FUNCTION(Column) static int __cdecl PhpModuleTreeNewCompare##Column( \
328  _In_ void *_context, \
329  _In_ const void *_elem1, \
330  _In_ const void *_elem2 \
331  ) \
332 { \
333  PPH_MODULE_NODE node1 = *(PPH_MODULE_NODE *)_elem1; \
334  PPH_MODULE_NODE node2 = *(PPH_MODULE_NODE *)_elem2; \
335  PPH_MODULE_ITEM moduleItem1 = node1->ModuleItem; \
336  PPH_MODULE_ITEM moduleItem2 = node2->ModuleItem; \
337  int sortResult = 0;
338 
339 #define END_SORT_FUNCTION \
340  if (sortResult == 0) \
341  sortResult = uintptrcmp((ULONG_PTR)moduleItem1->BaseAddress, (ULONG_PTR)moduleItem2->BaseAddress); \
342  \
343  return PhModifySort(sortResult, ((PPH_MODULE_LIST_CONTEXT)_context)->TreeNewSortOrder); \
344 }
345 
347  _In_ LONG Result,
348  _In_ PVOID Node1,
349  _In_ PVOID Node2,
350  _In_ PH_SORT_ORDER SortOrder
351  )
352 {
353  if (Result == 0)
354  Result = uintptrcmp((ULONG_PTR)((PPH_MODULE_NODE)Node1)->ModuleItem->BaseAddress, (ULONG_PTR)((PPH_MODULE_NODE)Node2)->ModuleItem->BaseAddress);
355 
356  return PhModifySort(Result, SortOrder);
357 }
358 
360 {
361  if (moduleItem1->IsFirst)
362  {
363  sortResult = -1;
364  }
365  else if (moduleItem2->IsFirst)
366  {
367  sortResult = 1;
368  }
369  else
370  {
371  sortResult = PhCompareString(moduleItem1->Name, moduleItem2->Name, TRUE); // fall back to sorting by name
372  }
373 }
375 
377 {
378  sortResult = PhCompareString(moduleItem1->Name, moduleItem2->Name, TRUE);
379 }
381 
383 {
384  sortResult = uintptrcmp((ULONG_PTR)moduleItem1->BaseAddress, (ULONG_PTR)moduleItem2->BaseAddress);
385 }
387 
389 {
390  sortResult = uintcmp(moduleItem1->Size, moduleItem2->Size);
391 }
393 
395 {
396  sortResult = PhCompareStringWithNull(moduleItem1->VersionInfo.FileDescription, moduleItem2->VersionInfo.FileDescription, TRUE);
397 }
399 
401 {
402  sortResult = PhCompareStringWithNull(moduleItem1->VersionInfo.CompanyName, moduleItem2->VersionInfo.CompanyName, TRUE);
403 }
405 
407 {
408  sortResult = PhCompareStringWithNull(moduleItem1->VersionInfo.FileVersion, moduleItem2->VersionInfo.FileVersion, TRUE);
409 }
411 
413 {
414  sortResult = PhCompareStringWithNull(moduleItem1->FileName, moduleItem2->FileName, TRUE);
415 }
417 
419 {
420  sortResult = uintcmp(moduleItem1->Type, moduleItem2->Type);
421 }
423 
425 {
426  sortResult = uintcmp(moduleItem1->LoadCount, moduleItem2->LoadCount);
427 }
429 
430 BEGIN_SORT_FUNCTION(VerificationStatus)
431 {
432  sortResult = intcmp(moduleItem1->VerifyResult, moduleItem2->VerifyResult);
433 }
435 
436 BEGIN_SORT_FUNCTION(VerifiedSigner)
437 {
438  sortResult = PhCompareStringWithNull(
439  moduleItem1->VerifySignerName,
440  moduleItem2->VerifySignerName,
441  TRUE
442  );
443 }
445 
447 {
448  sortResult = intcmp(
449  moduleItem1->ImageDllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE,
450  moduleItem2->ImageDllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
451  );
452 }
454 
456 {
457  sortResult = uintcmp(moduleItem1->ImageTimeDateStamp, moduleItem2->ImageTimeDateStamp);
458 }
460 
462 {
463  sortResult = intcmp(
464  moduleItem1->ImageDllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF,
465  moduleItem2->ImageDllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF
466  );
467 }
469 
471 {
472  sortResult = uint64cmp(moduleItem1->LoadTime.QuadPart, moduleItem2->LoadTime.QuadPart);
473 }
475 
477 {
478  sortResult = uintcmp(moduleItem1->LoadReason, moduleItem2->LoadReason);
479 }
481 
483  _In_ HWND hwnd,
484  _In_ PH_TREENEW_MESSAGE Message,
485  _In_opt_ PVOID Parameter1,
486  _In_opt_ PVOID Parameter2,
487  _In_opt_ PVOID Context
488  )
489 {
490  PPH_MODULE_LIST_CONTEXT context;
491  PPH_MODULE_NODE node;
492 
493  context = Context;
494 
495  if (PhCmForwardMessage(hwnd, Message, Parameter1, Parameter2, &context->Cm))
496  return TRUE;
497 
498  switch (Message)
499  {
500  case TreeNewGetChildren:
501  {
502  PPH_TREENEW_GET_CHILDREN getChildren = Parameter1;
503 
504  if (!getChildren->Node)
505  {
506  static PVOID sortFunctions[] =
507  {
508  SORT_FUNCTION(Name),
509  SORT_FUNCTION(BaseAddress),
511  SORT_FUNCTION(Description),
512  SORT_FUNCTION(CompanyName),
513  SORT_FUNCTION(Version),
514  SORT_FUNCTION(FileName),
515  SORT_FUNCTION(Type),
516  SORT_FUNCTION(LoadCount),
517  SORT_FUNCTION(VerificationStatus),
518  SORT_FUNCTION(VerifiedSigner),
519  SORT_FUNCTION(Aslr),
520  SORT_FUNCTION(TimeStamp),
521  SORT_FUNCTION(CfGuard),
522  SORT_FUNCTION(LoadTime),
523  SORT_FUNCTION(LoadReason)
524  };
525  int (__cdecl *sortFunction)(void *, const void *, const void *);
526 
527  if (context->TreeNewSortOrder == NoSortOrder)
528  {
529  sortFunction = SORT_FUNCTION(TriState);
530  }
531  else
532  {
533  if (!PhCmForwardSort(
534  (PPH_TREENEW_NODE *)context->NodeList->Items,
535  context->NodeList->Count,
536  context->TreeNewSortColumn,
537  context->TreeNewSortOrder,
538  &context->Cm
539  ))
540  {
541  if (context->TreeNewSortColumn < PHMOTLC_MAXIMUM)
542  sortFunction = sortFunctions[context->TreeNewSortColumn];
543  else
544  sortFunction = NULL;
545  }
546  else
547  {
548  sortFunction = NULL;
549  }
550  }
551 
552  if (sortFunction)
553  {
554  qsort_s(context->NodeList->Items, context->NodeList->Count, sizeof(PVOID), sortFunction, context);
555  }
556 
557  getChildren->Children = (PPH_TREENEW_NODE *)context->NodeList->Items;
558  getChildren->NumberOfChildren = context->NodeList->Count;
559  }
560  }
561  return TRUE;
562  case TreeNewIsLeaf:
563  {
564  PPH_TREENEW_IS_LEAF isLeaf = Parameter1;
565 
566  isLeaf->IsLeaf = TRUE;
567  }
568  return TRUE;
569  case TreeNewGetCellText:
570  {
571  PPH_TREENEW_GET_CELL_TEXT getCellText = Parameter1;
572  PPH_MODULE_ITEM moduleItem;
573 
574  node = (PPH_MODULE_NODE)getCellText->Node;
575  moduleItem = node->ModuleItem;
576 
577  switch (getCellText->Id)
578  {
579  case PHMOTLC_NAME:
580  getCellText->Text = moduleItem->Name->sr;
581  break;
582  case PHMOTLC_BASEADDRESS:
583  PhInitializeStringRefLongHint(&getCellText->Text, moduleItem->BaseAddressString);
584  break;
585  case PHMOTLC_SIZE:
586  if (!node->SizeText)
587  node->SizeText = PhFormatSize(moduleItem->Size, -1);
588  getCellText->Text = PhGetStringRef(node->SizeText);
589  break;
590  case PHMOTLC_DESCRIPTION:
591  getCellText->Text = PhGetStringRef(moduleItem->VersionInfo.FileDescription);
592  break;
593  case PHMOTLC_COMPANYNAME:
594  getCellText->Text = PhGetStringRef(moduleItem->VersionInfo.CompanyName);
595  break;
596  case PHMOTLC_VERSION:
597  getCellText->Text = PhGetStringRef(moduleItem->VersionInfo.FileVersion);
598  break;
599  case PHMOTLC_FILENAME:
600  getCellText->Text = PhGetStringRef(moduleItem->FileName);
601  break;
602  case PHMOTLC_TYPE:
603  {
604  PWSTR typeString;
605 
606  switch (moduleItem->Type)
607  {
609  typeString = L"DLL";
610  break;
612  typeString = L"Mapped File";
613  break;
615  typeString = L"Mapped Image";
616  break;
618  typeString = L"WOW64 DLL";
619  break;
621  typeString = L"Kernel Module";
622  break;
623  default:
624  typeString = L"Unknown";
625  break;
626  }
627 
628  PhInitializeStringRefLongHint(&getCellText->Text, typeString);
629  }
630  break;
631  case PHMOTLC_LOADCOUNT:
632  if (moduleItem->Type == PH_MODULE_TYPE_MODULE || moduleItem->Type == PH_MODULE_TYPE_KERNEL_MODULE ||
633  moduleItem->Type == PH_MODULE_TYPE_WOW64_MODULE)
634  {
635  if (moduleItem->LoadCount != (USHORT)-1)
636  {
637  PhPrintInt32(node->LoadCountText, moduleItem->LoadCount);
638  PhInitializeStringRefLongHint(&getCellText->Text, node->LoadCountText);
639  }
640  else
641  {
642  PhInitializeStringRef(&getCellText->Text, L"Static");
643  }
644  }
645  else
646  {
647  PhInitializeEmptyStringRef(&getCellText->Text);
648  }
649  break;
651  if (moduleItem->Type == PH_MODULE_TYPE_MODULE || moduleItem->Type == PH_MODULE_TYPE_KERNEL_MODULE ||
652  moduleItem->Type == PH_MODULE_TYPE_WOW64_MODULE || moduleItem->Type == PH_MODULE_TYPE_MAPPED_IMAGE)
653  {
654  PhInitializeStringRef(&getCellText->Text,
655  moduleItem->VerifyResult == VrTrusted ? L"Trusted" : L"Not Trusted");
656  }
657  else
658  {
659  PhInitializeEmptyStringRef(&getCellText->Text);
660  }
661  break;
663  getCellText->Text = PhGetStringRef(moduleItem->VerifySignerName);
664  break;
665  case PHMOTLC_ASLR:
667  {
668  if (moduleItem->ImageDllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE)
669  PhInitializeStringRef(&getCellText->Text, L"ASLR");
670  }
671  else
672  {
673  PhInitializeStringRef(&getCellText->Text, L"N/A");
674  }
675  break;
676  case PHMOTLC_TIMESTAMP:
677  {
678  LARGE_INTEGER time;
679  SYSTEMTIME systemTime;
680 
681  if (moduleItem->ImageTimeDateStamp != 0)
682  {
683  RtlSecondsSince1970ToTime(moduleItem->ImageTimeDateStamp, &time);
684  PhLargeIntegerToLocalSystemTime(&systemTime, &time);
685  PhMoveReference(&node->TimeStampText, PhFormatDateTime(&systemTime));
686  getCellText->Text = node->TimeStampText->sr;
687  }
688  else
689  {
690  PhInitializeEmptyStringRef(&getCellText->Text);
691  }
692  }
693  break;
694  case PHMOTLC_CFGUARD:
696  {
697  if (moduleItem->ImageDllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF)
698  PhInitializeStringRef(&getCellText->Text, L"CF Guard");
699  }
700  else
701  {
702  PhInitializeStringRef(&getCellText->Text, L"N/A");
703  }
704  break;
705  case PHMOTLC_LOADTIME:
706  {
707  SYSTEMTIME systemTime;
708 
709  if (moduleItem->LoadTime.QuadPart != 0)
710  {
711  PhLargeIntegerToLocalSystemTime(&systemTime, &moduleItem->LoadTime);
712  PhMoveReference(&node->LoadTimeText, PhFormatDateTime(&systemTime));
713  getCellText->Text = node->LoadTimeText->sr;
714  }
715  else
716  {
717  PhInitializeEmptyStringRef(&getCellText->Text);
718  }
719  }
720  break;
721  case PHMOTLC_LOADREASON:
722  {
723  PWSTR string = L"";
724 
725  if (moduleItem->Type == PH_MODULE_TYPE_MODULE || moduleItem->Type == PH_MODULE_TYPE_WOW64_MODULE)
726  {
727  switch (moduleItem->LoadReason)
728  {
729  case LoadReasonStaticDependency:
730  string = L"Static Dependency";
731  break;
732  case LoadReasonStaticForwarderDependency:
733  string = L"Static Forwarder Dependency";
734  break;
735  case LoadReasonDynamicForwarderDependency:
736  string = L"Dynamic Forwarder Dependency";
737  break;
738  case LoadReasonDelayloadDependency:
739  string = L"Delay Load Dependency";
740  break;
741  case LoadReasonDynamicLoad:
742  string = L"Dynamic";
743  break;
744  case LoadReasonAsImageLoad:
745  string = L"As Image";
746  break;
747  case LoadReasonAsDataLoad:
748  string = L"As Data";
749  break;
750  default:
751  if (WindowsVersion >= WINDOWS_8)
752  string = L"Unknown";
753  else
754  string = L"N/A";
755  break;
756  }
757  }
758 
759  PhInitializeStringRefLongHint(&getCellText->Text, string);
760  }
761  break;
762  default:
763  return FALSE;
764  }
765 
766  getCellText->Flags = TN_CACHE;
767  }
768  return TRUE;
769  case TreeNewGetNodeColor:
770  {
771  PPH_TREENEW_GET_NODE_COLOR getNodeColor = Parameter1;
772  PPH_MODULE_ITEM moduleItem;
773 
774  node = (PPH_MODULE_NODE)getNodeColor->Node;
775  moduleItem = node->ModuleItem;
776 
777  if (!moduleItem)
778  ; // Dummy
779  else if (PhCsUseColorDotNet && (moduleItem->Flags & LDRP_COR_IMAGE))
780  getNodeColor->BackColor = PhCsColorDotNet;
781  else if (PhCsUseColorImmersiveProcesses && (moduleItem->ImageDllCharacteristics & IMAGE_DLLCHARACTERISTICS_APPCONTAINER))
782  getNodeColor->BackColor = PhCsColorImmersiveProcesses;
783  else if (PhCsUseColorRelocatedModules && (moduleItem->Flags & LDRP_IMAGE_NOT_AT_BASE))
784  getNodeColor->BackColor = PhCsColorRelocatedModules;
785 
786  getNodeColor->Flags = TN_CACHE | TN_AUTO_FORECOLOR;
787  }
788  return TRUE;
789  case TreeNewGetNodeFont:
790  {
791  PPH_TREENEW_GET_NODE_FONT getNodeFont = Parameter1;
792 
793  node = (PPH_MODULE_NODE)getNodeFont->Node;
794 
795  // Make the executable file module item bold.
796  if (node->ModuleItem->IsFirst)
797  {
798  if (!context->BoldFont)
799  context->BoldFont = PhDuplicateFontWithNewWeight((HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0), FW_BOLD);
800 
801  getNodeFont->Font = context->BoldFont ? context->BoldFont : NULL;
802  getNodeFont->Flags = TN_CACHE;
803  return TRUE;
804  }
805  }
806  break;
808  {
809  PPH_TREENEW_GET_CELL_TOOLTIP getCellTooltip = Parameter1;
810 
811  node = (PPH_MODULE_NODE)getCellTooltip->Node;
812 
813  if (getCellTooltip->Column->Id != 0)
814  return FALSE;
815 
816  if (!node->TooltipText)
817  {
819  node->ModuleItem->FileName,
820  &node->ModuleItem->VersionInfo,
821  NULL,
822  0
823  );
824 
825  // Make sure we don't try to create the tooltip text again.
826  if (!node->TooltipText)
828  }
829 
831  {
832  getCellTooltip->Text = node->TooltipText->sr;
833  getCellTooltip->Unfolding = FALSE;
834  getCellTooltip->Font = NULL; // use default font
835  getCellTooltip->MaximumWidth = 550;
836  }
837  else
838  {
839  return FALSE;
840  }
841  }
842  return TRUE;
843  case TreeNewSortChanged:
844  {
845  TreeNew_GetSort(hwnd, &context->TreeNewSortColumn, &context->TreeNewSortOrder);
846  // Force a rebuild to sort the items.
848  }
849  return TRUE;
850  case TreeNewKeyDown:
851  {
852  PPH_TREENEW_KEY_EVENT keyEvent = Parameter1;
853 
854  switch (keyEvent->VirtualKey)
855  {
856  case 'C':
857  if (GetKeyState(VK_CONTROL) < 0)
858  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_MODULE_COPY, 0);
859  break;
860  case 'A':
861  if (GetKeyState(VK_CONTROL) < 0)
862  TreeNew_SelectRange(context->TreeNewHandle, 0, -1);
863  break;
864  case 'M':
865  if (GetKeyState(VK_CONTROL) < 0)
866  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_MODULE_SEARCHONLINE, 0);
867  break;
868  case VK_DELETE:
869  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_MODULE_UNLOAD, 0);
870  break;
871  case VK_RETURN:
872  if (GetKeyState(VK_CONTROL) >= 0)
873  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_MODULE_INSPECT, 0);
874  else
875  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_MODULE_OPENFILELOCATION, 0);
876  break;
877  }
878  }
879  return TRUE;
881  {
883 
884  data.TreeNewHandle = hwnd;
885  data.MouseEvent = Parameter1;
886  data.DefaultSortColumn = 0;
889 
894  }
895  return TRUE;
897  {
898  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_MODULE_INSPECT, 0);
899  }
900  return TRUE;
901  case TreeNewContextMenu:
902  {
903  PPH_TREENEW_CONTEXT_MENU contextMenu = Parameter1;
904 
905  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_SHOWCONTEXTMENU, (LPARAM)contextMenu);
906  }
907  return TRUE;
909  {
910  PULONG code = Parameter2;
911 
912  if (PtrToUlong(Parameter1) == VK_RETURN)
913  {
914  *code = DLGC_WANTMESSAGE;
915  return TRUE;
916  }
917  }
918  return FALSE;
919  }
920 
921  return FALSE;
922 }
923 
925  _In_ PPH_MODULE_LIST_CONTEXT Context
926  )
927 {
928  PPH_MODULE_ITEM moduleItem = NULL;
929  ULONG i;
930 
931  for (i = 0; i < Context->NodeList->Count; i++)
932  {
933  PPH_MODULE_NODE node = Context->NodeList->Items[i];
934 
935  if (node->Node.Selected)
936  {
937  moduleItem = node->ModuleItem;
938  break;
939  }
940  }
941 
942  return moduleItem;
943 }
944 
946  _In_ PPH_MODULE_LIST_CONTEXT Context,
947  _Out_ PPH_MODULE_ITEM **Modules,
948  _Out_ PULONG NumberOfModules
949  )
950 {
951  PPH_LIST list;
952  ULONG i;
953 
954  list = PhCreateList(2);
955 
956  for (i = 0; i < Context->NodeList->Count; i++)
957  {
958  PPH_MODULE_NODE node = Context->NodeList->Items[i];
959 
960  if (node->Node.Selected)
961  {
962  PhAddItemList(list, node->ModuleItem);
963  }
964  }
965 
966  *Modules = PhAllocateCopy(list->Items, sizeof(PVOID) * list->Count);
967  *NumberOfModules = list->Count;
968 
969  PhDereferenceObject(list);
970 }
971 
973  _In_ PPH_MODULE_LIST_CONTEXT Context
974  )
975 {
976  TreeNew_DeselectRange(Context->TreeNewHandle, 0, -1);
977 }