Process Hacker
hndllist.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * handle list
4  *
5  * Copyright (C) 2011-2013 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 <secedit.h>
25 #include <settings.h>
26 #include <extmgri.h>
27 #include <phplug.h>
28 #include <emenu.h>
29 
31  _In_ PVOID Entry1,
32  _In_ PVOID Entry2
33  );
34 
36  _In_ PVOID Entry
37  );
38 
40  _In_ PPH_HANDLE_NODE HandleNode
41  );
42 
44  _In_ PPH_HANDLE_NODE HandleNode,
45  _In_ PPH_HANDLE_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 PhpHandleTreeNewCallback(
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_HANDLE_LIST_CONTEXT Context
67  )
68 {
69  HWND hwnd;
70 
71  memset(Context, 0, sizeof(PH_HANDLE_LIST_CONTEXT));
72  Context->EnableStateHighlighting = TRUE;
73 
74  Context->NodeHashtable = PhCreateHashtable(
75  sizeof(PPH_HANDLE_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, PHHNTLC_TYPE, TRUE, L"Type", 100, PH_ALIGN_LEFT, 0, 0);
93  PhAddTreeNewColumn(hwnd, PHHNTLC_NAME, TRUE, L"Name", 200, PH_ALIGN_LEFT, 1, 0);
94  PhAddTreeNewColumn(hwnd, PHHNTLC_HANDLE, TRUE, L"Handle", 80, PH_ALIGN_LEFT, 2, 0);
95 
96  PhAddTreeNewColumn(hwnd, PHHNTLC_OBJECTADDRESS, FALSE, L"Object Address", 80, PH_ALIGN_LEFT, -1, 0);
97  PhAddTreeNewColumnEx(hwnd, PHHNTLC_ATTRIBUTES, FALSE, L"Attributes", 120, PH_ALIGN_LEFT, -1, 0, TRUE);
98  PhAddTreeNewColumn(hwnd, PHHNTLC_GRANTEDACCESS, FALSE, L"Granted Access", 80, PH_ALIGN_LEFT, -1, 0);
99  PhAddTreeNewColumn(hwnd, PHHNTLC_GRANTEDACCESSSYMBOLIC, FALSE, L"Granted Access (Symbolic)", 140, PH_ALIGN_LEFT, -1, 0);
100  PhAddTreeNewColumn(hwnd, PHHNTLC_ORIGINALNAME, FALSE, L"Original Name", 200, PH_ALIGN_LEFT, -1, 0);
101  PhAddTreeNewColumnEx(hwnd, PHHNTLC_FILESHAREACCESS, FALSE, L"File Share Access", 50, PH_ALIGN_LEFT, -1, 0, TRUE);
102 
103  TreeNew_SetRedraw(hwnd, TRUE);
104 
106 
108 }
109 
111  _In_ PPH_HANDLE_LIST_CONTEXT Context
112  )
113 {
114  ULONG i;
115 
116  PhCmDeleteManager(&Context->Cm);
117 
118  for (i = 0; i < Context->NodeList->Count; i++)
119  PhpDestroyHandleNode(Context->NodeList->Items[i]);
120 
121  PhDereferenceObject(Context->NodeHashtable);
122  PhDereferenceObject(Context->NodeList);
123 }
124 
126  _In_ PVOID Entry1,
127  _In_ PVOID Entry2
128  )
129 {
130  PPH_HANDLE_NODE handleNode1 = *(PPH_HANDLE_NODE *)Entry1;
131  PPH_HANDLE_NODE handleNode2 = *(PPH_HANDLE_NODE *)Entry2;
132 
133  return handleNode1->Handle == handleNode2->Handle;
134 }
135 
137  _In_ PVOID Entry
138  )
139 {
140  return (ULONG)(*(PPH_HANDLE_NODE *)Entry)->Handle / 4;
141 }
142 
144  _Inout_ PPH_HANDLE_LIST_CONTEXT Context
145  )
146 {
147  PPH_STRING settings;
148  PPH_STRING sortSettings;
149 
150  settings = PhGetStringSetting(L"HandleTreeListColumns");
151  sortSettings = PhGetStringSetting(L"HandleTreeListSort");
152  PhCmLoadSettingsEx(Context->TreeNewHandle, &Context->Cm, 0, &settings->sr, &sortSettings->sr);
153  PhDereferenceObject(settings);
154  PhDereferenceObject(sortSettings);
155 }
156 
158  _Inout_ PPH_HANDLE_LIST_CONTEXT Context
159  )
160 {
161  PPH_STRING settings;
162  PPH_STRING sortSettings;
163 
164  settings = PhCmSaveSettingsEx(Context->TreeNewHandle, &Context->Cm, 0, &sortSettings);
165  PhSetStringSetting2(L"HandleTreeListColumns", &settings->sr);
166  PhSetStringSetting2(L"HandleTreeListSort", &sortSettings->sr);
167  PhDereferenceObject(settings);
168  PhDereferenceObject(sortSettings);
169 }
170 
172  _Inout_ PPH_HANDLE_LIST_CONTEXT Context,
173  _In_ BOOLEAN HideUnnamedHandles
174  )
175 {
176  ULONG i;
177  BOOLEAN modified;
178 
179  if (Context->HideUnnamedHandles != HideUnnamedHandles)
180  {
181  Context->HideUnnamedHandles = HideUnnamedHandles;
182 
183  modified = FALSE;
184 
185  for (i = 0; i < Context->NodeList->Count; i++)
186  {
187  PPH_HANDLE_NODE node = Context->NodeList->Items[i];
188  BOOLEAN visible;
189 
190  visible = TRUE;
191 
192  if (HideUnnamedHandles && PhIsNullOrEmptyString(node->HandleItem->BestObjectName))
193  visible = FALSE;
194 
195  if (node->Node.Visible != visible)
196  {
197  node->Node.Visible = visible;
198  modified = TRUE;
199 
200  if (!visible)
201  node->Node.Selected = FALSE;
202  }
203  }
204 
205  if (modified)
206  {
207  TreeNew_NodesStructured(Context->TreeNewHandle);
208  }
209  }
210 }
211 
213  _Inout_ PPH_HANDLE_LIST_CONTEXT Context,
214  _In_ PPH_HANDLE_ITEM HandleItem,
215  _In_ ULONG RunId
216  )
217 {
218  PPH_HANDLE_NODE handleNode;
219 
220  handleNode = PhAllocate(PhEmGetObjectSize(EmHandleNodeType, sizeof(PH_HANDLE_NODE)));
221  memset(handleNode, 0, sizeof(PH_HANDLE_NODE));
222  PhInitializeTreeNewNode(&handleNode->Node);
223 
224  if (Context->EnableStateHighlighting && RunId != 1)
225  {
227  &handleNode->Node,
228  &handleNode->ShState,
229  &Context->NodeStateList,
230  NewItemState,
231  PhCsColorNew,
232  NULL
233  );
234  }
235 
236  handleNode->Handle = HandleItem->Handle;
237  handleNode->HandleItem = HandleItem;
238  PhReferenceObject(HandleItem);
239 
240  memset(handleNode->TextCache, 0, sizeof(PH_STRINGREF) * PHHNTLC_MAXIMUM);
241  handleNode->Node.TextCache = handleNode->TextCache;
242  handleNode->Node.TextCacheSize = PHHNTLC_MAXIMUM;
243 
244  PhAddEntryHashtable(Context->NodeHashtable, &handleNode);
245  PhAddItemList(Context->NodeList, handleNode);
246 
247  if (Context->HideUnnamedHandles && PhIsNullOrEmptyString(HandleItem->BestObjectName))
248  handleNode->Node.Visible = FALSE;
249 
251 
252  TreeNew_NodesStructured(Context->TreeNewHandle);
253 
254  return handleNode;
255 }
256 
258  _In_ PPH_HANDLE_LIST_CONTEXT Context,
259  _In_ HANDLE Handle
260  )
261 {
262  PH_HANDLE_NODE lookupHandleNode;
263  PPH_HANDLE_NODE lookupHandleNodePtr = &lookupHandleNode;
264  PPH_HANDLE_NODE *handleNode;
265 
266  lookupHandleNode.Handle = Handle;
267 
268  handleNode = (PPH_HANDLE_NODE *)PhFindEntryHashtable(
269  Context->NodeHashtable,
270  &lookupHandleNodePtr
271  );
272 
273  if (handleNode)
274  return *handleNode;
275  else
276  return NULL;
277 }
278 
280  _In_ PPH_HANDLE_LIST_CONTEXT Context,
281  _In_ PPH_HANDLE_NODE HandleNode
282  )
283 {
284  // Remove from the hashtable here to avoid problems in case the key is re-used.
285  PhRemoveEntryHashtable(Context->NodeHashtable, &HandleNode);
286 
287  if (Context->EnableStateHighlighting)
288  {
290  &HandleNode->Node,
291  &HandleNode->ShState,
292  &Context->NodeStateList,
295  Context->TreeNewHandle
296  );
297  }
298  else
299  {
300  PhpRemoveHandleNode(HandleNode, Context);
301  }
302 }
303 
305  _In_ PPH_HANDLE_NODE HandleNode
306  )
307 {
309 
310  if (HandleNode->GrantedAccessSymbolicText) PhDereferenceObject(HandleNode->GrantedAccessSymbolicText);
311 
312  PhDereferenceObject(HandleNode->HandleItem);
313 
314  PhFree(HandleNode);
315 }
316 
318  _In_ PPH_HANDLE_NODE HandleNode,
319  _In_ PPH_HANDLE_LIST_CONTEXT Context // PH_TICK_SH_STATE requires this parameter to be after HandleNode
320  )
321 {
322  ULONG index;
323 
324  // Remove from list and cleanup.
325 
326  if ((index = PhFindItemList(Context->NodeList, HandleNode)) != -1)
327  PhRemoveItemList(Context->NodeList, index);
328 
329  PhpDestroyHandleNode(HandleNode);
330 
331  TreeNew_NodesStructured(Context->TreeNewHandle);
332 }
333 
335  _In_ PPH_HANDLE_LIST_CONTEXT Context,
336  _In_ PPH_HANDLE_NODE HandleNode
337  )
338 {
339  memset(HandleNode->TextCache, 0, sizeof(PH_STRINGREF) * PHHNTLC_MAXIMUM);
340 
341  PhInvalidateTreeNewNode(&HandleNode->Node, TN_CACHE_COLOR);
342  TreeNew_NodesStructured(Context->TreeNewHandle);
343 }
344 
346  _In_ PPH_HANDLE_LIST_CONTEXT Context
347  )
348 {
349  PH_TICK_SH_STATE_TN(PH_HANDLE_NODE, ShState, Context->NodeStateList, PhpRemoveHandleNode, PhCsHighlightingDuration, Context->TreeNewHandle, TRUE, NULL, Context);
350 }
351 
352 #define SORT_FUNCTION(Column) PhpHandleTreeNewCompare##Column
353 
354 #define BEGIN_SORT_FUNCTION(Column) static int __cdecl PhpHandleTreeNewCompare##Column( \
355  _In_ void *_context, \
356  _In_ const void *_elem1, \
357  _In_ const void *_elem2 \
358  ) \
359 { \
360  PPH_HANDLE_NODE node1 = *(PPH_HANDLE_NODE *)_elem1; \
361  PPH_HANDLE_NODE node2 = *(PPH_HANDLE_NODE *)_elem2; \
362  PPH_HANDLE_ITEM handleItem1 = node1->HandleItem; \
363  PPH_HANDLE_ITEM handleItem2 = node2->HandleItem; \
364  PPH_HANDLE_LIST_CONTEXT context = (PPH_HANDLE_LIST_CONTEXT)_context; \
365  int sortResult = 0;
366 
367 #define END_SORT_FUNCTION \
368  if (sortResult == 0) \
369  sortResult = uintptrcmp((ULONG_PTR)node1->Handle, (ULONG_PTR)node2->Handle); \
370  \
371  return PhModifySort(sortResult, context->TreeNewSortOrder); \
372 }
373 
375  _In_ LONG Result,
376  _In_ PVOID Node1,
377  _In_ PVOID Node2,
378  _In_ PH_SORT_ORDER SortOrder
379  )
380 {
381  if (Result == 0)
382  Result = uintptrcmp((ULONG_PTR)((PPH_HANDLE_NODE)Node1)->Handle, (ULONG_PTR)((PPH_HANDLE_NODE)Node2)->Handle);
383 
384  return PhModifySort(Result, SortOrder);
385 }
386 
388 {
389  sortResult = PhCompareString(handleItem1->TypeName, handleItem2->TypeName, TRUE);
390 }
392 
394 {
395  sortResult = PhCompareStringWithNull(handleItem1->BestObjectName, handleItem2->BestObjectName, TRUE);
396 }
398 
400 {
401  sortResult = uintptrcmp((ULONG_PTR)node1->Handle, (ULONG_PTR)node2->Handle);
402 }
404 
405 BEGIN_SORT_FUNCTION(ObjectAddress)
406 {
407  sortResult = uintptrcmp((ULONG_PTR)handleItem1->Object, (ULONG_PTR)handleItem2->Object);
408 }
410 
412 {
413  sortResult = uintcmp(handleItem1->Attributes, handleItem2->Attributes);
414 }
416 
417 BEGIN_SORT_FUNCTION(GrantedAccess)
418 {
419  sortResult = uintcmp(handleItem1->GrantedAccess, handleItem2->GrantedAccess);
420 }
422 
423 BEGIN_SORT_FUNCTION(OriginalName)
424 {
425  sortResult = PhCompareStringWithNull(handleItem1->ObjectName, handleItem2->ObjectName, TRUE);
426 }
428 
429 BEGIN_SORT_FUNCTION(FileShareAccess)
430 {
431  sortResult = uintcmp(handleItem1->FileFlags & (PH_HANDLE_FILE_SHARED_MASK), handleItem2->FileFlags & (PH_HANDLE_FILE_SHARED_MASK));
432 
433  // Make sure all file handles get grouped together regardless of share access.
434  if (sortResult == 0)
435  sortResult = intcmp(PhEqualString2(handleItem1->TypeName, L"File", TRUE), PhEqualString2(handleItem2->TypeName, L"File", TRUE));
436 }
438 
440  _In_ HWND hwnd,
441  _In_ PH_TREENEW_MESSAGE Message,
442  _In_opt_ PVOID Parameter1,
443  _In_opt_ PVOID Parameter2,
444  _In_opt_ PVOID Context
445  )
446 {
447  PPH_HANDLE_LIST_CONTEXT context;
448  PPH_HANDLE_NODE node;
449 
450  context = Context;
451 
452  if (PhCmForwardMessage(hwnd, Message, Parameter1, Parameter2, &context->Cm))
453  return TRUE;
454 
455  switch (Message)
456  {
457  case TreeNewGetChildren:
458  {
459  PPH_TREENEW_GET_CHILDREN getChildren = Parameter1;
460 
461  if (!getChildren->Node)
462  {
463  static PVOID sortFunctions[] =
464  {
465  SORT_FUNCTION(Type),
466  SORT_FUNCTION(Name),
467  SORT_FUNCTION(Handle),
468  SORT_FUNCTION(ObjectAddress),
469  SORT_FUNCTION(Attributes),
470  SORT_FUNCTION(GrantedAccess),
471  SORT_FUNCTION(GrantedAccess), // Granted Access (Symbolic)
472  SORT_FUNCTION(OriginalName),
473  SORT_FUNCTION(FileShareAccess)
474  };
475  int (__cdecl *sortFunction)(void *, const void *, const void *);
476 
477  if (!PhCmForwardSort(
478  (PPH_TREENEW_NODE *)context->NodeList->Items,
479  context->NodeList->Count,
480  context->TreeNewSortColumn,
481  context->TreeNewSortOrder,
482  &context->Cm
483  ))
484  {
485  if (context->TreeNewSortColumn < PHHNTLC_MAXIMUM)
486  sortFunction = sortFunctions[context->TreeNewSortColumn];
487  else
488  sortFunction = NULL;
489  }
490  else
491  {
492  sortFunction = NULL;
493  }
494 
495  if (sortFunction)
496  {
497  qsort_s(context->NodeList->Items, context->NodeList->Count, sizeof(PVOID), sortFunction, context);
498  }
499 
500  getChildren->Children = (PPH_TREENEW_NODE *)context->NodeList->Items;
501  getChildren->NumberOfChildren = context->NodeList->Count;
502  }
503  }
504  return TRUE;
505  case TreeNewIsLeaf:
506  {
507  PPH_TREENEW_IS_LEAF isLeaf = Parameter1;
508 
509  isLeaf->IsLeaf = TRUE;
510  }
511  return TRUE;
512  case TreeNewGetCellText:
513  {
514  PPH_TREENEW_GET_CELL_TEXT getCellText = Parameter1;
515  PPH_HANDLE_ITEM handleItem;
516 
517  node = (PPH_HANDLE_NODE)getCellText->Node;
518  handleItem = node->HandleItem;
519 
520  switch (getCellText->Id)
521  {
522  case PHHNTLC_TYPE:
523  getCellText->Text = handleItem->TypeName->sr;
524  break;
525  case PHHNTLC_NAME:
526  getCellText->Text = PhGetStringRef(handleItem->BestObjectName);
527  break;
528  case PHHNTLC_HANDLE:
529  PhInitializeStringRefLongHint(&getCellText->Text, handleItem->HandleString);
530  break;
532  PhInitializeStringRefLongHint(&getCellText->Text, handleItem->ObjectString);
533  break;
534  case PHHNTLC_ATTRIBUTES:
535  switch (handleItem->Attributes & (OBJ_PROTECT_CLOSE | OBJ_INHERIT))
536  {
537  case OBJ_PROTECT_CLOSE:
538  PhInitializeStringRef(&getCellText->Text, L"Protected");
539  break;
540  case OBJ_INHERIT:
541  PhInitializeStringRef(&getCellText->Text, L"Inherit");
542  break;
544  PhInitializeStringRef(&getCellText->Text, L"Protected, Inherit");
545  break;
546  }
547  break;
549  PhInitializeStringRefLongHint(&getCellText->Text, handleItem->GrantedAccessString);
550  break;
552  if (handleItem->GrantedAccess != 0)
553  {
554  if (!node->GrantedAccessSymbolicText)
555  {
556  PPH_ACCESS_ENTRY accessEntries;
557  ULONG numberOfAccessEntries;
558 
559  if (PhGetAccessEntries(handleItem->TypeName->Buffer, &accessEntries, &numberOfAccessEntries))
560  {
561  node->GrantedAccessSymbolicText = PhGetAccessString(handleItem->GrantedAccess, accessEntries, numberOfAccessEntries);
562  PhFree(accessEntries);
563  }
564  else
565  {
567  }
568  }
569 
570  if (node->GrantedAccessSymbolicText->Length != 0)
571  getCellText->Text = node->GrantedAccessSymbolicText->sr;
572  else
573  PhInitializeStringRefLongHint(&getCellText->Text, handleItem->GrantedAccessString);
574  }
575  break;
577  getCellText->Text = PhGetStringRef(handleItem->ObjectName);
578  break;
580  if (handleItem->FileFlags & PH_HANDLE_FILE_SHARED_MASK)
581  {
582  node->FileShareAccessText[0] = '-';
583  node->FileShareAccessText[1] = '-';
584  node->FileShareAccessText[2] = '-';
585  node->FileShareAccessText[3] = 0;
586 
587  if (handleItem->FileFlags & PH_HANDLE_FILE_SHARED_READ)
588  node->FileShareAccessText[0] = 'R';
589  if (handleItem->FileFlags & PH_HANDLE_FILE_SHARED_WRITE)
590  node->FileShareAccessText[1] = 'W';
591  if (handleItem->FileFlags & PH_HANDLE_FILE_SHARED_DELETE)
592  node->FileShareAccessText[2] = 'D';
593 
594  PhInitializeStringRef(&getCellText->Text, node->FileShareAccessText);
595  }
596  break;
597  default:
598  return FALSE;
599  }
600 
601  getCellText->Flags = TN_CACHE;
602  }
603  return TRUE;
604  case TreeNewGetNodeColor:
605  {
606  PPH_TREENEW_GET_NODE_COLOR getNodeColor = Parameter1;
607  PPH_HANDLE_ITEM handleItem;
608 
609  node = (PPH_HANDLE_NODE)getNodeColor->Node;
610  handleItem = node->HandleItem;
611 
612  if (!handleItem)
613  ; // Dummy
614  else if (PhCsUseColorProtectedHandles && (handleItem->Attributes & OBJ_PROTECT_CLOSE))
615  getNodeColor->BackColor = PhCsColorProtectedHandles;
616  else if (PhCsUseColorInheritHandles && (handleItem->Attributes & OBJ_INHERIT))
617  getNodeColor->BackColor = PhCsColorInheritHandles;
618 
619  getNodeColor->Flags = TN_CACHE | TN_AUTO_FORECOLOR;
620  }
621  return TRUE;
622  case TreeNewSortChanged:
623  {
624  TreeNew_GetSort(hwnd, &context->TreeNewSortColumn, &context->TreeNewSortOrder);
625  // Force a rebuild to sort the items.
627  }
628  return TRUE;
629  case TreeNewKeyDown:
630  {
631  PPH_TREENEW_KEY_EVENT keyEvent = Parameter1;
632 
633  switch (keyEvent->VirtualKey)
634  {
635  case 'C':
636  if (GetKeyState(VK_CONTROL) < 0)
637  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_HANDLE_COPY, 0);
638  break;
639  case 'A':
640  if (GetKeyState(VK_CONTROL) < 0)
641  TreeNew_SelectRange(context->TreeNewHandle, 0, -1);
642  break;
643  case VK_DELETE:
644  // Pass a 1 in lParam to indicate that warnings should be enabled.
645  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_HANDLE_CLOSE, 1);
646  break;
647  case VK_RETURN:
648  if (GetKeyState(VK_CONTROL) >= 0)
649  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_HANDLE_PROPERTIES, 0);
650  else
651  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_HANDLE_OBJECTPROPERTIES1, 0);
652  break;
653  }
654  }
655  return TRUE;
657  {
659 
660  data.TreeNewHandle = hwnd;
661  data.MouseEvent = Parameter1;
662  data.DefaultSortColumn = 0;
665 
670  }
671  return TRUE;
673  {
674  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_HANDLE_PROPERTIES, 0);
675  }
676  return TRUE;
677  case TreeNewContextMenu:
678  {
679  PPH_TREENEW_CONTEXT_MENU contextMenu = Parameter1;
680 
681  SendMessage(context->ParentWindowHandle, WM_COMMAND, ID_SHOWCONTEXTMENU, (LPARAM)contextMenu);
682  }
683  return TRUE;
685  {
686  PULONG code = Parameter2;
687 
688  if (PtrToUlong(Parameter1) == VK_RETURN)
689  {
690  *code = DLGC_WANTMESSAGE;
691  return TRUE;
692  }
693  }
694  return FALSE;
695  }
696 
697  return FALSE;
698 }
699 
701  _In_ PPH_HANDLE_LIST_CONTEXT Context
702  )
703 {
704  PPH_HANDLE_ITEM handleItem = NULL;
705  ULONG i;
706 
707  for (i = 0; i < Context->NodeList->Count; i++)
708  {
709  PPH_HANDLE_NODE node = Context->NodeList->Items[i];
710 
711  if (node->Node.Selected)
712  {
713  handleItem = node->HandleItem;
714  break;
715  }
716  }
717 
718  return handleItem;
719 }
720 
722  _In_ PPH_HANDLE_LIST_CONTEXT Context,
723  _Out_ PPH_HANDLE_ITEM **Handles,
724  _Out_ PULONG NumberOfHandles
725  )
726 {
727  PPH_LIST list;
728  ULONG i;
729 
730  list = PhCreateList(2);
731 
732  for (i = 0; i < Context->NodeList->Count; i++)
733  {
734  PPH_HANDLE_NODE node = Context->NodeList->Items[i];
735 
736  if (node->Node.Selected)
737  {
738  PhAddItemList(list, node->HandleItem);
739  }
740  }
741 
742  *Handles = PhAllocateCopy(list->Items, sizeof(PVOID) * list->Count);
743  *NumberOfHandles = list->Count;
744 
745  PhDereferenceObject(list);
746 }
747 
749  _In_ PPH_HANDLE_LIST_CONTEXT Context
750  )
751 {
752  TreeNew_DeselectRange(Context->TreeNewHandle, 0, -1);
753 }