Process Hacker
ntobjprp.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * properties for NT objects
4  *
5  * Copyright (C) 2010 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 
25 typedef struct _COMMON_PAGE_CONTEXT
26 {
27  PPH_OPEN_OBJECT OpenObject;
28  PVOID Context;
30 
31 HPROPSHEETPAGE PhpCommonCreatePage(
32  _In_ PPH_OPEN_OBJECT OpenObject,
33  _In_opt_ PVOID Context,
34  _In_ PWSTR Template,
35  _In_ DLGPROC DlgProc
36  );
37 
38 INT CALLBACK PhpCommonPropPageProc(
39  _In_ HWND hwnd,
40  _In_ UINT uMsg,
41  _In_ LPPROPSHEETPAGE ppsp
42  );
43 
44 INT_PTR CALLBACK PhpEventPageProc(
45  _In_ HWND hwndDlg,
46  _In_ UINT uMsg,
47  _In_ WPARAM wParam,
48  _In_ LPARAM lParam
49  );
50 
51 INT_PTR CALLBACK PhpEventPairPageProc(
52  _In_ HWND hwndDlg,
53  _In_ UINT uMsg,
54  _In_ WPARAM wParam,
55  _In_ LPARAM lParam
56  );
57 
58 INT_PTR CALLBACK PhpMutantPageProc(
59  _In_ HWND hwndDlg,
60  _In_ UINT uMsg,
61  _In_ WPARAM wParam,
62  _In_ LPARAM lParam
63  );
64 
65 INT_PTR CALLBACK PhpSectionPageProc(
66  _In_ HWND hwndDlg,
67  _In_ UINT uMsg,
68  _In_ WPARAM wParam,
69  _In_ LPARAM lParam
70  );
71 
72 INT_PTR CALLBACK PhpSemaphorePageProc(
73  _In_ HWND hwndDlg,
74  _In_ UINT uMsg,
75  _In_ WPARAM wParam,
76  _In_ LPARAM lParam
77  );
78 
79 INT_PTR CALLBACK PhpTimerPageProc(
80  _In_ HWND hwndDlg,
81  _In_ UINT uMsg,
82  _In_ WPARAM wParam,
83  _In_ LPARAM lParam
84  );
85 
86 static HPROPSHEETPAGE PhpCommonCreatePage(
87  _In_ PPH_OPEN_OBJECT OpenObject,
88  _In_opt_ PVOID Context,
89  _In_ PWSTR Template,
90  _In_ DLGPROC DlgProc
91  )
92 {
93  HPROPSHEETPAGE propSheetPageHandle;
94  PROPSHEETPAGE propSheetPage;
95  PCOMMON_PAGE_CONTEXT pageContext;
96 
97  pageContext = PhCreateAlloc(sizeof(COMMON_PAGE_CONTEXT));
98  memset(pageContext, 0, sizeof(COMMON_PAGE_CONTEXT));
99  pageContext->OpenObject = OpenObject;
100  pageContext->Context = Context;
101 
102  memset(&propSheetPage, 0, sizeof(PROPSHEETPAGE));
103  propSheetPage.dwSize = sizeof(PROPSHEETPAGE);
104  propSheetPage.dwFlags = PSP_USECALLBACK;
105  propSheetPage.pszTemplate = Template;
106  propSheetPage.pfnDlgProc = DlgProc;
107  propSheetPage.lParam = (LPARAM)pageContext;
108  propSheetPage.pfnCallback = PhpCommonPropPageProc;
109 
110  propSheetPageHandle = CreatePropertySheetPage(&propSheetPage);
111  // CreatePropertySheetPage would have sent PSPCB_ADDREF (below),
112  // which would have added a reference.
113  PhDereferenceObject(pageContext);
114 
115  return propSheetPageHandle;
116 }
117 
119  _In_ HWND hwnd,
120  _In_ UINT uMsg,
121  _In_ LPPROPSHEETPAGE ppsp
122  )
123 {
124  PCOMMON_PAGE_CONTEXT pageContext;
125 
126  pageContext = (PCOMMON_PAGE_CONTEXT)ppsp->lParam;
127 
128  if (uMsg == PSPCB_ADDREF)
129  {
130  PhReferenceObject(pageContext);
131  }
132  else if (uMsg == PSPCB_RELEASE)
133  {
134  PhDereferenceObject(pageContext);
135  }
136 
137  return 1;
138 }
139 
141  _In_ HWND hwndDlg,
142  _In_ UINT uMsg,
143  _In_ WPARAM wParam,
144  _In_ LPARAM lParam
145  )
146 {
148  hwndDlg, uMsg, wParam, lParam, L"PageContext");
149 }
150 
151 HPROPSHEETPAGE PhCreateEventPage(
152  _In_ PPH_OPEN_OBJECT OpenObject,
153  _In_opt_ PVOID Context
154  )
155 {
156  return PhpCommonCreatePage(
157  OpenObject,
158  Context,
159  MAKEINTRESOURCE(IDD_OBJEVENT),
161  );
162 }
163 
164 static VOID PhpRefreshEventPageInfo(
165  _In_ HWND hwndDlg,
166  _In_ PCOMMON_PAGE_CONTEXT PageContext
167  )
168 {
169  HANDLE eventHandle;
170 
171  if (NT_SUCCESS(PageContext->OpenObject(
172  &eventHandle,
173  EVENT_QUERY_STATE,
174  PageContext->Context
175  )))
176  {
177  EVENT_BASIC_INFORMATION basicInfo;
178  PWSTR eventType = L"Unknown";
179  PWSTR eventState = L"Unknown";
180 
181  if (NT_SUCCESS(PhGetEventBasicInformation(eventHandle, &basicInfo)))
182  {
183  switch (basicInfo.EventType)
184  {
185  case NotificationEvent:
186  eventType = L"Notification";
187  break;
189  eventType = L"Synchronization";
190  break;
191  }
192 
193  eventState = basicInfo.EventState > 0 ? L"True" : L"False";
194  }
195 
196  SetDlgItemText(hwndDlg, IDC_TYPE, eventType);
197  SetDlgItemText(hwndDlg, IDC_SIGNALED, eventState);
198 
199  NtClose(eventHandle);
200  }
201 }
202 
203 INT_PTR CALLBACK PhpEventPageProc(
204  _In_ HWND hwndDlg,
205  _In_ UINT uMsg,
206  _In_ WPARAM wParam,
207  _In_ LPARAM lParam
208  )
209 {
210  PCOMMON_PAGE_CONTEXT pageContext;
211 
212  pageContext = PhpCommonPageHeader(hwndDlg, uMsg, wParam, lParam);
213 
214  if (!pageContext)
215  return FALSE;
216 
217  switch (uMsg)
218  {
219  case WM_INITDIALOG:
220  {
221  PhpRefreshEventPageInfo(hwndDlg, pageContext);
222  }
223  break;
224  case WM_COMMAND:
225  {
226  switch (LOWORD(wParam))
227  {
228  case IDC_SET:
229  case IDC_RESET:
230  case IDC_PULSE:
231  {
232  NTSTATUS status;
233  HANDLE eventHandle;
234 
235  if (NT_SUCCESS(status = pageContext->OpenObject(
236  &eventHandle,
237  EVENT_MODIFY_STATE,
238  pageContext->Context
239  )))
240  {
241  switch (LOWORD(wParam))
242  {
243  case IDC_SET:
244  NtSetEvent(eventHandle, NULL);
245  break;
246  case IDC_RESET:
247  NtResetEvent(eventHandle, NULL);
248  break;
249  case IDC_PULSE:
250  NtPulseEvent(eventHandle, NULL);
251  break;
252  }
253 
254  NtClose(eventHandle);
255  }
256 
257  PhpRefreshEventPageInfo(hwndDlg, pageContext);
258 
259  if (!NT_SUCCESS(status))
260  PhShowStatus(hwndDlg, L"Unable to open the event", status, 0);
261  }
262  break;
263  }
264  }
265  break;
266  }
267 
268  return FALSE;
269 }
270 
271 HPROPSHEETPAGE PhCreateEventPairPage(
272  _In_ PPH_OPEN_OBJECT OpenObject,
273  _In_opt_ PVOID Context
274  )
275 {
276  return PhpCommonCreatePage(
277  OpenObject,
278  Context,
279  MAKEINTRESOURCE(IDD_OBJEVENTPAIR),
281  );
282 }
283 
284 INT_PTR CALLBACK PhpEventPairPageProc(
285  _In_ HWND hwndDlg,
286  _In_ UINT uMsg,
287  _In_ WPARAM wParam,
288  _In_ LPARAM lParam
289  )
290 {
291  PCOMMON_PAGE_CONTEXT pageContext;
292 
293  pageContext = PhpCommonPageHeader(hwndDlg, uMsg, wParam, lParam);
294 
295  if (!pageContext)
296  return FALSE;
297 
298  switch (uMsg)
299  {
300  case WM_INITDIALOG:
301  {
302  // Nothing
303  }
304  break;
305  case WM_COMMAND:
306  {
307  switch (LOWORD(wParam))
308  {
309  case IDC_SETLOW:
310  case IDC_SETHIGH:
311  {
312  NTSTATUS status;
313  HANDLE eventPairHandle;
314 
315  if (NT_SUCCESS(status = pageContext->OpenObject(
316  &eventPairHandle,
317  EVENT_PAIR_ALL_ACCESS,
318  pageContext->Context
319  )))
320  {
321  switch (LOWORD(wParam))
322  {
323  case IDC_SETLOW:
324  NtSetLowEventPair(eventPairHandle);
325  break;
326  case IDC_SETHIGH:
327  NtSetHighEventPair(eventPairHandle);
328  break;
329  }
330 
331  NtClose(eventPairHandle);
332  }
333 
334  if (!NT_SUCCESS(status))
335  PhShowStatus(hwndDlg, L"Unable to open the event pair", status, 0);
336  }
337  break;
338  }
339  }
340  break;
341  }
342 
343  return FALSE;
344 }
345 
346 HPROPSHEETPAGE PhCreateMutantPage(
347  _In_ PPH_OPEN_OBJECT OpenObject,
348  _In_opt_ PVOID Context
349  )
350 {
351  return PhpCommonCreatePage(
352  OpenObject,
353  Context,
354  MAKEINTRESOURCE(IDD_OBJMUTANT),
356  );
357 }
358 
359 static VOID PhpRefreshMutantPageInfo(
360  _In_ HWND hwndDlg,
361  _In_ PCOMMON_PAGE_CONTEXT PageContext
362  )
363 {
364  HANDLE mutantHandle;
365 
366  if (NT_SUCCESS(PageContext->OpenObject(
367  &mutantHandle,
368  SEMAPHORE_QUERY_STATE,
369  PageContext->Context
370  )))
371  {
372  MUTANT_BASIC_INFORMATION basicInfo;
373  MUTANT_OWNER_INFORMATION ownerInfo;
374 
375  if (NT_SUCCESS(PhGetMutantBasicInformation(mutantHandle, &basicInfo)))
376  {
377  SetDlgItemInt(hwndDlg, IDC_COUNT, basicInfo.CurrentCount, TRUE);
378  SetDlgItemText(hwndDlg, IDC_ABANDONED, basicInfo.AbandonedState ? L"True" : L"False");
379  }
380  else
381  {
382  SetDlgItemText(hwndDlg, IDC_COUNT, L"Unknown");
383  SetDlgItemText(hwndDlg, IDC_ABANDONED, L"Unknown");
384  }
385 
386  if (
388  NT_SUCCESS(PhGetMutantOwnerInformation(mutantHandle, &ownerInfo))
389  )
390  {
391  PPH_STRING name;
392 
393  if (ownerInfo.ClientId.UniqueProcess != NULL)
394  {
395  name = PhGetClientIdName(&ownerInfo.ClientId);
396  SetDlgItemText(hwndDlg, IDC_OWNER, name->Buffer);
397  PhDereferenceObject(name);
398  }
399  else
400  {
401  SetDlgItemText(hwndDlg, IDC_OWNER, L"N/A");
402  }
403  }
404  else
405  {
406  SetDlgItemText(hwndDlg, IDC_OWNER, L"Unknown");
407  }
408 
409  NtClose(mutantHandle);
410  }
411 }
412 
413 INT_PTR CALLBACK PhpMutantPageProc(
414  _In_ HWND hwndDlg,
415  _In_ UINT uMsg,
416  _In_ WPARAM wParam,
417  _In_ LPARAM lParam
418  )
419 {
420  PCOMMON_PAGE_CONTEXT pageContext;
421 
422  pageContext = PhpCommonPageHeader(hwndDlg, uMsg, wParam, lParam);
423 
424  if (!pageContext)
425  return FALSE;
426 
427  switch (uMsg)
428  {
429  case WM_INITDIALOG:
430  {
432  {
433  EnableWindow(GetDlgItem(hwndDlg, IDC_OWNERLABEL), FALSE);
434  EnableWindow(GetDlgItem(hwndDlg, IDC_OWNER), FALSE);
435  }
436 
437  PhpRefreshMutantPageInfo(hwndDlg, pageContext);
438  }
439  break;
440  }
441 
442  return FALSE;
443 }
444 
445 HPROPSHEETPAGE PhCreateSectionPage(
446  _In_ PPH_OPEN_OBJECT OpenObject,
447  _In_opt_ PVOID Context
448  )
449 {
450  return PhpCommonCreatePage(
451  OpenObject,
452  Context,
453  MAKEINTRESOURCE(IDD_OBJSECTION),
455  );
456 }
457 
458 static VOID PhpRefreshSectionPageInfo(
459  _In_ HWND hwndDlg,
460  _In_ PCOMMON_PAGE_CONTEXT PageContext
461  )
462 {
463  HANDLE sectionHandle;
464  SECTION_BASIC_INFORMATION basicInfo;
465  PWSTR sectionType = L"Unknown";
466  PPH_STRING sectionSize = NULL;
467  PPH_STRING fileName = NULL;
468 
469  if (!NT_SUCCESS(PageContext->OpenObject(
470  &sectionHandle,
471  SECTION_QUERY | SECTION_MAP_READ,
472  PageContext->Context
473  )))
474  {
475  if (!NT_SUCCESS(PageContext->OpenObject(
476  &sectionHandle,
477  SECTION_QUERY | SECTION_MAP_READ,
478  PageContext->Context
479  )))
480  {
481  return;
482  }
483  }
484 
485  if (NT_SUCCESS(PhGetSectionBasicInformation(sectionHandle, &basicInfo)))
486  {
487  if (basicInfo.AllocationAttributes & SEC_COMMIT)
488  sectionType = L"Commit";
489  else if (basicInfo.AllocationAttributes & SEC_FILE)
490  sectionType = L"File";
491  else if (basicInfo.AllocationAttributes & SEC_IMAGE)
492  sectionType = L"Image";
493  else if (basicInfo.AllocationAttributes & SEC_RESERVE)
494  sectionType = L"Reserve";
495 
496  sectionSize = PhaFormatSize(basicInfo.MaximumSize.QuadPart, -1);
497  }
498 
499  if (NT_SUCCESS(PhGetSectionFileName(sectionHandle, &fileName)))
500  {
501  PPH_STRING newFileName;
502 
503  PhAutoDereferenceObject(fileName);
504 
505  if (newFileName = PhResolveDevicePrefix(fileName))
506  fileName = PhAutoDereferenceObject(newFileName);
507  }
508 
509  SetDlgItemText(hwndDlg, IDC_TYPE, sectionType);
510  SetDlgItemText(hwndDlg, IDC_SIZE_, PhGetStringOrDefault(sectionSize, L"Unknown"));
511  SetDlgItemText(hwndDlg, IDC_FILE, PhGetStringOrDefault(fileName, L"N/A"));
512 
513  NtClose(sectionHandle);
514 }
515 
516 INT_PTR CALLBACK PhpSectionPageProc(
517  _In_ HWND hwndDlg,
518  _In_ UINT uMsg,
519  _In_ WPARAM wParam,
520  _In_ LPARAM lParam
521  )
522 {
523  PCOMMON_PAGE_CONTEXT pageContext;
524 
525  pageContext = PhpCommonPageHeader(hwndDlg, uMsg, wParam, lParam);
526 
527  if (!pageContext)
528  return FALSE;
529 
530  switch (uMsg)
531  {
532  case WM_INITDIALOG:
533  {
534  PhpRefreshSectionPageInfo(hwndDlg, pageContext);
535  }
536  break;
537  }
538 
539  return FALSE;
540 }
541 
542 HPROPSHEETPAGE PhCreateSemaphorePage(
543  _In_ PPH_OPEN_OBJECT OpenObject,
544  _In_opt_ PVOID Context
545  )
546 {
547  return PhpCommonCreatePage(
548  OpenObject,
549  Context,
550  MAKEINTRESOURCE(IDD_OBJSEMAPHORE),
552  );
553 }
554 
555 static VOID PhpRefreshSemaphorePageInfo(
556  _In_ HWND hwndDlg,
557  _In_ PCOMMON_PAGE_CONTEXT PageContext
558  )
559 {
560  HANDLE semaphoreHandle;
561 
562  if (NT_SUCCESS(PageContext->OpenObject(
563  &semaphoreHandle,
564  SEMAPHORE_QUERY_STATE,
565  PageContext->Context
566  )))
567  {
568  SEMAPHORE_BASIC_INFORMATION basicInfo;
569 
570  if (NT_SUCCESS(PhGetSemaphoreBasicInformation(semaphoreHandle, &basicInfo)))
571  {
572  SetDlgItemInt(hwndDlg, IDC_CURRENTCOUNT, basicInfo.CurrentCount, TRUE);
573  SetDlgItemInt(hwndDlg, IDC_MAXIMUMCOUNT, basicInfo.MaximumCount, TRUE);
574  }
575  else
576  {
577  SetDlgItemText(hwndDlg, IDC_CURRENTCOUNT, L"Unknown");
578  SetDlgItemText(hwndDlg, IDC_MAXIMUMCOUNT, L"Unknown");
579  }
580 
581  NtClose(semaphoreHandle);
582  }
583 }
584 
585 INT_PTR CALLBACK PhpSemaphorePageProc(
586  _In_ HWND hwndDlg,
587  _In_ UINT uMsg,
588  _In_ WPARAM wParam,
589  _In_ LPARAM lParam
590  )
591 {
592  PCOMMON_PAGE_CONTEXT pageContext;
593 
594  pageContext = PhpCommonPageHeader(hwndDlg, uMsg, wParam, lParam);
595 
596  if (!pageContext)
597  return FALSE;
598 
599  switch (uMsg)
600  {
601  case WM_INITDIALOG:
602  {
603  PhpRefreshSemaphorePageInfo(hwndDlg, pageContext);
604  }
605  break;
606  case WM_COMMAND:
607  {
608  switch (LOWORD(wParam))
609  {
610  case IDC_ACQUIRE:
611  case IDC_RELEASE:
612  {
613  NTSTATUS status;
614  HANDLE semaphoreHandle;
615 
616  if (NT_SUCCESS(status = pageContext->OpenObject(
617  &semaphoreHandle,
618  LOWORD(wParam) == IDC_ACQUIRE ? SYNCHRONIZE : SEMAPHORE_MODIFY_STATE,
619  pageContext->Context
620  )))
621  {
622  switch (LOWORD(wParam))
623  {
624  case IDC_ACQUIRE:
625  {
626  LARGE_INTEGER timeout;
627 
628  timeout.QuadPart = 0;
629  NtWaitForSingleObject(semaphoreHandle, FALSE, &timeout);
630  }
631  break;
632  case IDC_RELEASE:
633  NtReleaseSemaphore(semaphoreHandle, 1, NULL);
634  break;
635  }
636 
637  NtClose(semaphoreHandle);
638  }
639 
640  PhpRefreshSemaphorePageInfo(hwndDlg, pageContext);
641 
642  if (!NT_SUCCESS(status))
643  PhShowStatus(hwndDlg, L"Unable to open the semaphore", status, 0);
644  }
645  break;
646  }
647  }
648  break;
649  }
650 
651  return FALSE;
652 }
653 
654 HPROPSHEETPAGE PhCreateTimerPage(
655  _In_ PPH_OPEN_OBJECT OpenObject,
656  _In_opt_ PVOID Context
657  )
658 {
659  return PhpCommonCreatePage(
660  OpenObject,
661  Context,
662  MAKEINTRESOURCE(IDD_OBJTIMER),
664  );
665 }
666 
667 static VOID PhpRefreshTimerPageInfo(
668  _In_ HWND hwndDlg,
669  _In_ PCOMMON_PAGE_CONTEXT PageContext
670  )
671 {
672  HANDLE timerHandle;
673 
674  if (NT_SUCCESS(PageContext->OpenObject(
675  &timerHandle,
676  TIMER_QUERY_STATE,
677  PageContext->Context
678  )))
679  {
680  TIMER_BASIC_INFORMATION basicInfo;
681 
682  if (NT_SUCCESS(PhGetTimerBasicInformation(timerHandle, &basicInfo)))
683  {
684  SetDlgItemText(hwndDlg, IDC_SIGNALED, basicInfo.TimerState ? L"True" : L"False");
685  }
686  else
687  {
688  SetDlgItemText(hwndDlg, IDC_SIGNALED, L"Unknown");
689  }
690 
691  NtClose(timerHandle);
692  }
693 }
694 
695 INT_PTR CALLBACK PhpTimerPageProc(
696  _In_ HWND hwndDlg,
697  _In_ UINT uMsg,
698  _In_ WPARAM wParam,
699  _In_ LPARAM lParam
700  )
701 {
702  PCOMMON_PAGE_CONTEXT pageContext;
703 
704  pageContext = PhpCommonPageHeader(hwndDlg, uMsg, wParam, lParam);
705 
706  if (!pageContext)
707  return FALSE;
708 
709  switch (uMsg)
710  {
711  case WM_INITDIALOG:
712  {
713  PhpRefreshTimerPageInfo(hwndDlg, pageContext);
714  }
715  break;
716  case WM_COMMAND:
717  {
718  switch (LOWORD(wParam))
719  {
720  case IDC_CANCEL:
721  {
722  NTSTATUS status;
723  HANDLE timerHandle;
724 
725  if (NT_SUCCESS(status = pageContext->OpenObject(
726  &timerHandle,
727  TIMER_MODIFY_STATE,
728  pageContext->Context
729  )))
730  {
731  switch (LOWORD(wParam))
732  {
733  case IDC_CANCEL:
734  NtCancelTimer(timerHandle, NULL);
735  break;
736  }
737 
738  NtClose(timerHandle);
739  }
740 
741  PhpRefreshTimerPageInfo(hwndDlg, pageContext);
742 
743  if (!NT_SUCCESS(status))
744  PhShowStatus(hwndDlg, L"Unable to open the timer", status, 0);
745  }
746  break;
747  }
748  }
749  break;
750  }
751 
752  return FALSE;
753 }