Process Hacker
memlists.c
Go to the documentation of this file.
1 /*
2  * Process Hacker -
3  * memory list information
4  *
5  * Copyright (C) 2010-2011 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 <phsvccl.h>
25 #include <emenu.h>
26 
27 #define MSG_UPDATE (WM_APP + 1)
28 
29 INT_PTR CALLBACK PhpMemoryListsDlgProc(
30  _In_ HWND hwndDlg,
31  _In_ UINT uMsg,
32  _In_ WPARAM wParam,
33  _In_ LPARAM lParam
34  );
35 
37 static VOID (NTAPI *UnregisterDialogFunction)(HWND);
38 static PH_CALLBACK_REGISTRATION ProcessesUpdatedRegistration;
39 
41  _In_ HWND ParentWindowHandle,
42  _In_opt_ VOID (NTAPI *RegisterDialog)(HWND),
43  _In_opt_ VOID (NTAPI *UnregisterDialog)(HWND)
44  )
45 {
47  {
48  PhMemoryListsWindowHandle = CreateDialog(
50  MAKEINTRESOURCE(IDD_MEMLISTS),
51  ParentWindowHandle,
53  );
54  RegisterDialog(PhMemoryListsWindowHandle);
55  UnregisterDialogFunction = UnregisterDialog;
56  }
57 
58  if (!IsWindowVisible(PhMemoryListsWindowHandle))
59  ShowWindow(PhMemoryListsWindowHandle, SW_SHOW);
60  else if (IsIconic(PhMemoryListsWindowHandle))
61  ShowWindow(PhMemoryListsWindowHandle, SW_RESTORE);
62  else
63  SetForegroundWindow(PhMemoryListsWindowHandle);
64 }
65 
66 static VOID NTAPI ProcessesUpdatedCallback(
67  _In_opt_ PVOID Parameter,
68  _In_opt_ PVOID Context
69  )
70 {
71  PostMessage(PhMemoryListsWindowHandle, MSG_UPDATE, 0, 0);
72 }
73 
74 static VOID PhpUpdateMemoryListInfo(
75  _In_ HWND hwndDlg
76  )
77 {
78  SYSTEM_MEMORY_LIST_INFORMATION memoryListInfo;
79 
80  if (NT_SUCCESS(NtQuerySystemInformation(
82  &memoryListInfo,
84  NULL
85  )))
86  {
87  ULONG_PTR standbyPageCount;
88  ULONG_PTR repurposedPageCount;
89  ULONG i;
90 
91  standbyPageCount = 0;
92  repurposedPageCount = 0;
93 
94  for (i = 0; i < 8; i++)
95  {
96  standbyPageCount += memoryListInfo.PageCountByPriority[i];
97  repurposedPageCount += memoryListInfo.RepurposedPagesByPriority[i];
98  }
99 
100  SetDlgItemText(hwndDlg, IDC_ZLISTZEROED_V, PhaFormatSize((ULONG64)memoryListInfo.ZeroPageCount * PAGE_SIZE, -1)->Buffer);
101  SetDlgItemText(hwndDlg, IDC_ZLISTFREE_V, PhaFormatSize((ULONG64)memoryListInfo.FreePageCount * PAGE_SIZE, -1)->Buffer);
102  SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIED_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedPageCount * PAGE_SIZE, -1)->Buffer);
103  SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDNOWRITE_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedNoWritePageCount * PAGE_SIZE, -1)->Buffer);
104  SetDlgItemText(hwndDlg, IDC_ZLISTBAD_V, PhaFormatSize((ULONG64)memoryListInfo.BadPageCount * PAGE_SIZE, -1)->Buffer);
105  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY_V, PhaFormatSize((ULONG64)standbyPageCount * PAGE_SIZE, -1)->Buffer);
106  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY0_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[0] * PAGE_SIZE, -1)->Buffer);
107  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY1_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[1] * PAGE_SIZE, -1)->Buffer);
108  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY2_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[2] * PAGE_SIZE, -1)->Buffer);
109  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY3_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[3] * PAGE_SIZE, -1)->Buffer);
110  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY4_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[4] * PAGE_SIZE, -1)->Buffer);
111  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY5_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[5] * PAGE_SIZE, -1)->Buffer);
112  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY6_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[6] * PAGE_SIZE, -1)->Buffer);
113  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY7_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[7] * PAGE_SIZE, -1)->Buffer);
114  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED_V, PhaFormatSize((ULONG64)repurposedPageCount * PAGE_SIZE, -1)->Buffer);
115  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED0_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[0] * PAGE_SIZE, -1)->Buffer);
116  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED1_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[1] * PAGE_SIZE, -1)->Buffer);
117  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED2_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[2] * PAGE_SIZE, -1)->Buffer);
118  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED3_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[3] * PAGE_SIZE, -1)->Buffer);
119  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED4_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[4] * PAGE_SIZE, -1)->Buffer);
120  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED5_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[5] * PAGE_SIZE, -1)->Buffer);
121  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED6_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[6] * PAGE_SIZE, -1)->Buffer);
122  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED7_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[7] * PAGE_SIZE, -1)->Buffer);
123 
124  if (WindowsVersion >= WINDOWS_8)
125  SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDPAGEFILE_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedPageCountPageFile * PAGE_SIZE, -1)->Buffer);
126  else
127  SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDPAGEFILE_V, L"N/A");
128  }
129  else
130  {
131  SetDlgItemText(hwndDlg, IDC_ZLISTZEROED_V, L"Unknown");
132  SetDlgItemText(hwndDlg, IDC_ZLISTFREE_V, L"Unknown");
133  SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIED_V, L"Unknown");
134  SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDNOWRITE_V, L"Unknown");
135  SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDPAGEFILE_V, L"Unknown");
136  SetDlgItemText(hwndDlg, IDC_ZLISTBAD_V, L"Unknown");
137  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY_V, L"Unknown");
138  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY0_V, L"Unknown");
139  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY1_V, L"Unknown");
140  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY2_V, L"Unknown");
141  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY3_V, L"Unknown");
142  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY4_V, L"Unknown");
143  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY5_V, L"Unknown");
144  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY6_V, L"Unknown");
145  SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY7_V, L"Unknown");
146  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED_V, L"Unknown");
147  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED0_V, L"Unknown");
148  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED1_V, L"Unknown");
149  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED2_V, L"Unknown");
150  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED3_V, L"Unknown");
151  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED4_V, L"Unknown");
152  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED5_V, L"Unknown");
153  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED6_V, L"Unknown");
154  SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED7_V, L"Unknown");
155  }
156 }
157 
158 INT_PTR CALLBACK PhpMemoryListsDlgProc(
159  _In_ HWND hwndDlg,
160  _In_ UINT uMsg,
161  _In_ WPARAM wParam,
162  _In_ LPARAM lParam
163  )
164 {
165  switch (uMsg)
166  {
167  case WM_INITDIALOG:
168  {
169  PhRegisterCallback(&PhProcessesUpdatedEvent, ProcessesUpdatedCallback, NULL, &ProcessesUpdatedRegistration);
170  PhpUpdateMemoryListInfo(hwndDlg);
171 
172  PhLoadWindowPlacementFromSetting(L"MemoryListsWindowPosition", NULL, hwndDlg);
173  PhRegisterDialog(hwndDlg);
174  }
175  break;
176  case WM_DESTROY:
177  {
178  PhUnregisterDialog(hwndDlg);
179  PhSaveWindowPlacementToSetting(L"MemoryListsWindowPosition", NULL, hwndDlg);
180 
181  PhUnregisterCallback(&PhProcessesUpdatedEvent, &ProcessesUpdatedRegistration);
182 
183  UnregisterDialogFunction(hwndDlg);
185  }
186  break;
187  case WM_COMMAND:
188  {
189  switch (LOWORD(wParam))
190  {
191  case IDCANCEL:
192  case IDOK:
193  DestroyWindow(hwndDlg);
194  break;
195  case IDC_EMPTY:
196  {
197  PPH_EMENU menu;
198  RECT buttonRect;
199  POINT point;
200  PPH_EMENU_ITEM selectedItem;
201  SYSTEM_MEMORY_LIST_COMMAND command = -1;
202 
203  menu = PhCreateEMenu();
204  PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_EMPTYMEMLISTS), 0);
205 
206  GetClientRect(GetDlgItem(hwndDlg, IDC_EMPTY), &buttonRect);
207  point.x = 0;
208  point.y = buttonRect.bottom;
209 
210  ClientToScreen(GetDlgItem(hwndDlg, IDC_EMPTY), &point);
211  selectedItem = PhShowEMenu(menu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT,
212  PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y);
213 
214  if (selectedItem)
215  {
216  switch (selectedItem->Id)
217  {
219  command = MemoryEmptyWorkingSets;
220  break;
222  command = MemoryFlushModifiedList;
223  break;
225  command = MemoryPurgeStandbyList;
226  break;
229  break;
230  }
231  }
232 
233  if (command != -1)
234  {
235  NTSTATUS status;
236 
237  SetCursor(LoadCursor(NULL, IDC_WAIT));
238  status = NtSetSystemInformation(
240  &command,
242  );
243  SetCursor(LoadCursor(NULL, IDC_ARROW));
244 
245  if (status == STATUS_PRIVILEGE_NOT_HELD)
246  {
247  if (!PhElevated)
248  {
249  if (PhUiConnectToPhSvc(hwndDlg, FALSE))
250  {
251  SetCursor(LoadCursor(NULL, IDC_WAIT));
252  status = PhSvcCallIssueMemoryListCommand(command);
253  SetCursor(LoadCursor(NULL, IDC_ARROW));
255  }
256  else
257  {
258  // User cancelled eleavtion.
259  status = STATUS_SUCCESS;
260  }
261  }
262  }
263 
264  if (!NT_SUCCESS(status))
265  {
266  PhShowStatus(hwndDlg, L"Unable to execute the memory list command", status, 0);
267  }
268  }
269 
270  PhDestroyEMenu(menu);
271  }
272  break;
273  }
274  }
275  break;
276  case MSG_UPDATE:
277  {
278  PhpUpdateMemoryListInfo(hwndDlg);
279  }
280  break;
281  }
282 
283  return FALSE;
284 }