/* * Process Hacker - * memory list information * * Copyright (C) 2010-2011 wj32 * * This file is part of Process Hacker. * * Process Hacker is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Process Hacker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Process Hacker. If not, see . */ #include #include #include #define MSG_UPDATE (WM_APP + 1) INT_PTR CALLBACK PhpMemoryListsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ); HWND PhMemoryListsWindowHandle = NULL; static VOID (NTAPI *UnregisterDialogFunction)(HWND); static PH_CALLBACK_REGISTRATION ProcessesUpdatedRegistration; VOID PhShowMemoryListsDialog( _In_ HWND ParentWindowHandle, _In_opt_ VOID (NTAPI *RegisterDialog)(HWND), _In_opt_ VOID (NTAPI *UnregisterDialog)(HWND) ) { if (!PhMemoryListsWindowHandle) { PhMemoryListsWindowHandle = CreateDialog( PhInstanceHandle, MAKEINTRESOURCE(IDD_MEMLISTS), ParentWindowHandle, PhpMemoryListsDlgProc ); RegisterDialog(PhMemoryListsWindowHandle); UnregisterDialogFunction = UnregisterDialog; } if (!IsWindowVisible(PhMemoryListsWindowHandle)) ShowWindow(PhMemoryListsWindowHandle, SW_SHOW); else if (IsIconic(PhMemoryListsWindowHandle)) ShowWindow(PhMemoryListsWindowHandle, SW_RESTORE); else SetForegroundWindow(PhMemoryListsWindowHandle); } static VOID NTAPI ProcessesUpdatedCallback( _In_opt_ PVOID Parameter, _In_opt_ PVOID Context ) { PostMessage(PhMemoryListsWindowHandle, MSG_UPDATE, 0, 0); } static VOID PhpUpdateMemoryListInfo( _In_ HWND hwndDlg ) { SYSTEM_MEMORY_LIST_INFORMATION memoryListInfo; if (NT_SUCCESS(NtQuerySystemInformation( SystemMemoryListInformation, &memoryListInfo, sizeof(SYSTEM_MEMORY_LIST_INFORMATION), NULL ))) { ULONG_PTR standbyPageCount; ULONG_PTR repurposedPageCount; ULONG i; standbyPageCount = 0; repurposedPageCount = 0; for (i = 0; i < 8; i++) { standbyPageCount += memoryListInfo.PageCountByPriority[i]; repurposedPageCount += memoryListInfo.RepurposedPagesByPriority[i]; } SetDlgItemText(hwndDlg, IDC_ZLISTZEROED_V, PhaFormatSize((ULONG64)memoryListInfo.ZeroPageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTFREE_V, PhaFormatSize((ULONG64)memoryListInfo.FreePageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIED_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedPageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDNOWRITE_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedNoWritePageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTBAD_V, PhaFormatSize((ULONG64)memoryListInfo.BadPageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY_V, PhaFormatSize((ULONG64)standbyPageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY0_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[0] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY1_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[1] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY2_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[2] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY3_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[3] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY4_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[4] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY5_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[5] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY6_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[6] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY7_V, PhaFormatSize((ULONG64)memoryListInfo.PageCountByPriority[7] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED_V, PhaFormatSize((ULONG64)repurposedPageCount * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED0_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[0] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED1_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[1] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED2_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[2] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED3_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[3] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED4_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[4] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED5_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[5] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED6_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[6] * PAGE_SIZE, -1)->Buffer); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED7_V, PhaFormatSize((ULONG64)memoryListInfo.RepurposedPagesByPriority[7] * PAGE_SIZE, -1)->Buffer); if (WindowsVersion >= WINDOWS_8) SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDPAGEFILE_V, PhaFormatSize((ULONG64)memoryListInfo.ModifiedPageCountPageFile * PAGE_SIZE, -1)->Buffer); else SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDPAGEFILE_V, L"N/A"); } else { SetDlgItemText(hwndDlg, IDC_ZLISTZEROED_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTFREE_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIED_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDNOWRITE_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTMODIFIEDPAGEFILE_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTBAD_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY0_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY1_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY2_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY3_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY4_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY5_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY6_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTSTANDBY7_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED0_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED1_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED2_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED3_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED4_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED5_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED6_V, L"Unknown"); SetDlgItemText(hwndDlg, IDC_ZLISTREPURPOSED7_V, L"Unknown"); } } INT_PTR CALLBACK PhpMemoryListsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { PhRegisterCallback(&PhProcessesUpdatedEvent, ProcessesUpdatedCallback, NULL, &ProcessesUpdatedRegistration); PhpUpdateMemoryListInfo(hwndDlg); PhLoadWindowPlacementFromSetting(L"MemoryListsWindowPosition", NULL, hwndDlg); PhRegisterDialog(hwndDlg); } break; case WM_DESTROY: { PhUnregisterDialog(hwndDlg); PhSaveWindowPlacementToSetting(L"MemoryListsWindowPosition", NULL, hwndDlg); PhUnregisterCallback(&PhProcessesUpdatedEvent, &ProcessesUpdatedRegistration); UnregisterDialogFunction(hwndDlg); PhMemoryListsWindowHandle = NULL; } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: DestroyWindow(hwndDlg); break; case IDC_EMPTY: { PPH_EMENU menu; RECT buttonRect; POINT point; PPH_EMENU_ITEM selectedItem; SYSTEM_MEMORY_LIST_COMMAND command = -1; menu = PhCreateEMenu(); PhLoadResourceEMenuItem(menu, PhInstanceHandle, MAKEINTRESOURCE(IDR_EMPTYMEMLISTS), 0); GetClientRect(GetDlgItem(hwndDlg, IDC_EMPTY), &buttonRect); point.x = 0; point.y = buttonRect.bottom; ClientToScreen(GetDlgItem(hwndDlg, IDC_EMPTY), &point); selectedItem = PhShowEMenu(menu, hwndDlg, PH_EMENU_SHOW_LEFTRIGHT, PH_ALIGN_LEFT | PH_ALIGN_TOP, point.x, point.y); if (selectedItem) { switch (selectedItem->Id) { case ID_EMPTY_EMPTYWORKINGSETS: command = MemoryEmptyWorkingSets; break; case ID_EMPTY_EMPTYMODIFIEDPAGELIST: command = MemoryFlushModifiedList; break; case ID_EMPTY_EMPTYSTANDBYLIST: command = MemoryPurgeStandbyList; break; case ID_EMPTY_EMPTYPRIORITY0STANDBYLIST: command = MemoryPurgeLowPriorityStandbyList; break; } } if (command != -1) { NTSTATUS status; SetCursor(LoadCursor(NULL, IDC_WAIT)); status = NtSetSystemInformation( SystemMemoryListInformation, &command, sizeof(SYSTEM_MEMORY_LIST_COMMAND) ); SetCursor(LoadCursor(NULL, IDC_ARROW)); if (status == STATUS_PRIVILEGE_NOT_HELD) { if (!PhElevated) { if (PhUiConnectToPhSvc(hwndDlg, FALSE)) { SetCursor(LoadCursor(NULL, IDC_WAIT)); status = PhSvcCallIssueMemoryListCommand(command); SetCursor(LoadCursor(NULL, IDC_ARROW)); PhUiDisconnectFromPhSvc(); } else { // User cancelled eleavtion. status = STATUS_SUCCESS; } } } if (!NT_SUCCESS(status)) { PhShowStatus(hwndDlg, L"Unable to execute the memory list command", status, 0); } } PhDestroyEMenu(menu); } break; } } break; case MSG_UPDATE: { PhpUpdateMemoryListInfo(hwndDlg); } break; } return FALSE; }