1 /* 2 * ReactOS Task Manager 3 * 4 * procpage.c 5 * 6 * Copyright (C) 1999 - 2001 Brian Palmer <brianp@reactos.org> 7 * Copyright (C) 2009 Maxime Vernier <maxime.vernier@gmail.com> 8 * 9 * This library is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU Lesser General Public 11 * License as published by the Free Software Foundation; either 12 * version 2.1 of the License, or (at your option) any later version. 13 * 14 * This library 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 GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this library; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22 */ 23 24 #include "precomp.h" 25 26 #include "proclist.h" 27 28 #define CMP(x1, x2)\ 29 (x1 < x2 ? -1 : (x1 > x2 ? 1 : 0)) 30 31 typedef struct 32 { 33 ULONG ProcessId; 34 } PROCESS_PAGE_LIST_ITEM, *LPPROCESS_PAGE_LIST_ITEM; 35 36 HWND hProcessPage; /* Process List Property Page */ 37 38 HWND hProcessPageListCtrl; /* Process ListCtrl Window */ 39 HWND hProcessPageHeaderCtrl; /* Process Header Control */ 40 HWND hProcessPageEndProcessButton; /* Process End Process button */ 41 HWND hProcessPageShowAllProcessesButton;/* Process Show All Processes checkbox */ 42 BOOL bProcessPageSelectionMade = FALSE; /* Is item in ListCtrl selected */ 43 44 static int nProcessPageWidth; 45 static int nProcessPageHeight; 46 #ifdef RUN_PROC_PAGE 47 static HANDLE hProcessThread = NULL; 48 static DWORD dwProcessThread; 49 #endif 50 51 int CALLBACK ProcessPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); 52 void AddProcess(ULONG Index); 53 void UpdateProcesses(); 54 void gethmsfromlargeint(LARGE_INTEGER largeint, DWORD *dwHours, DWORD *dwMinutes, DWORD *dwSeconds); 55 void ProcessPageOnNotify(WPARAM wParam, LPARAM lParam); 56 void CommaSeparateNumberString(LPWSTR strNumber, ULONG nMaxCount); 57 void ProcessPageShowContextMenu(DWORD dwProcessId); 58 BOOL PerfDataGetText(ULONG Index, ULONG ColumnIndex, LPTSTR lpText, ULONG nMaxCount); 59 DWORD WINAPI ProcessPageRefreshThread(void *lpParameter); 60 int ProcessRunning(ULONG ProcessId); 61 62 void Cleanup(void) 63 { 64 int i; 65 LV_ITEM item; 66 LPPROCESS_PAGE_LIST_ITEM pData; 67 for (i = 0; i < ListView_GetItemCount(hProcessPageListCtrl); i++) 68 { 69 memset(&item, 0, sizeof(LV_ITEM)); 70 item.mask = LVIF_PARAM; 71 item.iItem = i; 72 (void)ListView_GetItem(hProcessPageListCtrl, &item); 73 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 74 HeapFree(GetProcessHeap(), 0, pData); 75 } 76 } 77 78 int ProcGetIndexByProcessId(DWORD dwProcessId) 79 { 80 int i; 81 LVITEM item; 82 LPPROCESS_PAGE_LIST_ITEM pData; 83 84 for (i=0; i<ListView_GetItemCount(hProcessPageListCtrl); i++) 85 { 86 memset(&item, 0, sizeof(LV_ITEM)); 87 item.mask = LVIF_PARAM; 88 item.iItem = i; 89 (void)ListView_GetItem(hProcessPageListCtrl, &item); 90 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 91 if (pData->ProcessId == dwProcessId) 92 { 93 return i; 94 } 95 } 96 return 0; 97 } 98 99 DWORD GetSelectedProcessId(void) 100 { 101 int Index; 102 LVITEM lvitem; 103 104 if(ListView_GetSelectedCount(hProcessPageListCtrl) == 1) 105 { 106 Index = ListView_GetSelectionMark(hProcessPageListCtrl); 107 108 memset(&lvitem, 0, sizeof(LVITEM)); 109 110 lvitem.mask = LVIF_PARAM; 111 lvitem.iItem = Index; 112 113 (void)ListView_GetItem(hProcessPageListCtrl, &lvitem); 114 115 if (lvitem.lParam) 116 return ((LPPROCESS_PAGE_LIST_ITEM)lvitem.lParam)->ProcessId; 117 } 118 119 return 0; 120 } 121 122 void ProcessPageUpdate(void) 123 { 124 /* Enable or disable the "End Process" button */ 125 if (ListView_GetSelectedCount(hProcessPageListCtrl)) 126 EnableWindow(hProcessPageEndProcessButton, TRUE); 127 else 128 EnableWindow(hProcessPageEndProcessButton, FALSE); 129 } 130 131 INT_PTR CALLBACK 132 ProcessPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 133 { 134 RECT rc; 135 int nXDifference; 136 int nYDifference; 137 int cx, cy; 138 139 switch (message) { 140 case WM_INITDIALOG: 141 /* 142 * Save the width and height 143 */ 144 GetClientRect(hDlg, &rc); 145 nProcessPageWidth = rc.right; 146 nProcessPageHeight = rc.bottom; 147 148 /* Update window position */ 149 SetWindowPos(hDlg, NULL, 15, 30, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 150 151 /* 152 * Get handles to the controls 153 */ 154 hProcessPageListCtrl = GetDlgItem(hDlg, IDC_PROCESSLIST); 155 hProcessPageHeaderCtrl = ListView_GetHeader(hProcessPageListCtrl); 156 hProcessPageEndProcessButton = GetDlgItem(hDlg, IDC_ENDPROCESS); 157 hProcessPageShowAllProcessesButton = GetDlgItem(hDlg, IDC_SHOWALLPROCESSES); 158 159 /* 160 * Set the title, and extended window styles for the list control 161 */ 162 SetWindowTextW(hProcessPageListCtrl, L"Processes"); 163 (void)ListView_SetExtendedListViewStyle(hProcessPageListCtrl, ListView_GetExtendedListViewStyle(hProcessPageListCtrl) | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP); 164 165 AddColumns(); 166 167 /* 168 * Subclass the process list control so we can intercept WM_ERASEBKGND 169 */ 170 OldProcessListWndProc = (WNDPROC)SetWindowLongPtrW(hProcessPageListCtrl, GWLP_WNDPROC, (LONG_PTR)ProcessListWndProc); 171 172 #ifdef RUN_PROC_PAGE 173 /* Start our refresh thread */ 174 hProcessThread = CreateThread(NULL, 0, ProcessPageRefreshThread, NULL, 0, &dwProcessThread); 175 #endif 176 177 /* Refresh page */ 178 ProcessPageUpdate(); 179 180 return TRUE; 181 182 case WM_DESTROY: 183 /* Close the event handle, this will make the */ 184 /* refresh thread exit when the wait fails */ 185 #ifdef RUN_PROC_PAGE 186 EndLocalThread(&hProcessThread, dwProcessThread); 187 #endif 188 SaveColumnSettings(); 189 Cleanup(); 190 break; 191 192 case WM_COMMAND: 193 /* Handle the button clicks */ 194 switch (LOWORD(wParam)) 195 { 196 case IDC_ENDPROCESS: 197 ProcessPage_OnEndProcess(); 198 } 199 break; 200 201 case WM_SIZE: 202 if (wParam == SIZE_MINIMIZED) 203 return 0; 204 205 cx = LOWORD(lParam); 206 cy = HIWORD(lParam); 207 nXDifference = cx - nProcessPageWidth; 208 nYDifference = cy - nProcessPageHeight; 209 nProcessPageWidth = cx; 210 nProcessPageHeight = cy; 211 212 /* Reposition the application page's controls */ 213 GetWindowRect(hProcessPageListCtrl, &rc); 214 cx = (rc.right - rc.left) + nXDifference; 215 cy = (rc.bottom - rc.top) + nYDifference; 216 SetWindowPos(hProcessPageListCtrl, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER); 217 InvalidateRect(hProcessPageListCtrl, NULL, TRUE); 218 219 GetClientRect(hProcessPageEndProcessButton, &rc); 220 MapWindowPoints(hProcessPageEndProcessButton, hDlg, (LPPOINT)(PRECT)(&rc), sizeof(RECT)/sizeof(POINT)); 221 cx = rc.left + nXDifference; 222 cy = rc.top + nYDifference; 223 SetWindowPos(hProcessPageEndProcessButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 224 InvalidateRect(hProcessPageEndProcessButton, NULL, TRUE); 225 226 GetClientRect(hProcessPageShowAllProcessesButton, &rc); 227 MapWindowPoints(hProcessPageShowAllProcessesButton, hDlg, (LPPOINT)(PRECT)(&rc), sizeof(RECT)/sizeof(POINT)); 228 cx = rc.left; 229 cy = rc.top + nYDifference; 230 SetWindowPos(hProcessPageShowAllProcessesButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 231 InvalidateRect(hProcessPageShowAllProcessesButton, NULL, TRUE); 232 break; 233 234 case WM_NOTIFY: 235 ProcessPageOnNotify(wParam, lParam); 236 break; 237 238 case WM_KEYDOWN: 239 if (wParam == VK_DELETE) 240 ProcessPage_OnEndProcess(); 241 break; 242 } 243 244 return 0; 245 } 246 247 void ProcessPageOnNotify(WPARAM wParam, LPARAM lParam) 248 { 249 LPNMHDR pnmh; 250 NMLVDISPINFO* pnmdi; 251 LPNMHEADER pnmhdr; 252 ULONG Index; 253 ULONG ColumnIndex; 254 LPPROCESS_PAGE_LIST_ITEM pData; 255 256 pnmh = (LPNMHDR) lParam; 257 pnmdi = (NMLVDISPINFO*) lParam; 258 pnmhdr = (LPNMHEADER) lParam; 259 260 if (pnmh->hwndFrom == hProcessPageListCtrl) 261 { 262 switch (pnmh->code) 263 { 264 case LVN_ITEMCHANGED: 265 ProcessPageUpdate(); 266 break; 267 268 case LVN_GETDISPINFO: 269 270 if (!(pnmdi->item.mask & LVIF_TEXT)) 271 break; 272 273 pData = (LPPROCESS_PAGE_LIST_ITEM)pnmdi->item.lParam; 274 Index = PerfDataGetProcessIndex(pData->ProcessId); 275 ColumnIndex = pnmdi->item.iSubItem; 276 277 PerfDataGetText(Index, ColumnIndex, pnmdi->item.pszText, (ULONG)pnmdi->item.cchTextMax); 278 279 break; 280 281 case NM_RCLICK: 282 283 ProcessPageShowContextMenu(GetSelectedProcessId()); 284 break; 285 286 case LVN_KEYDOWN: 287 288 if (((LPNMLVKEYDOWN)lParam)->wVKey == VK_DELETE) 289 ProcessPage_OnEndProcess(); 290 break; 291 292 } 293 } 294 else if (pnmh->hwndFrom == hProcessPageHeaderCtrl) 295 { 296 switch (pnmh->code) 297 { 298 case HDN_ITEMCLICK: 299 300 TaskManagerSettings.SortColumn = ColumnDataHints[pnmhdr->iItem]; 301 TaskManagerSettings.SortAscending = !TaskManagerSettings.SortAscending; 302 (void)ListView_SortItems(hProcessPageListCtrl, ProcessPageCompareFunc, NULL); 303 304 break; 305 306 case HDN_ITEMCHANGED: 307 308 UpdateColumnDataHints(); 309 310 break; 311 312 case HDN_ENDDRAG: 313 314 UpdateColumnDataHints(); 315 316 break; 317 318 } 319 } 320 } 321 322 void CommaSeparateNumberString(LPWSTR strNumber, ULONG nMaxCount) 323 { 324 WCHAR temp[260]; 325 UINT i, j, k; 326 327 for (i=0,j=0; i<(wcslen(strNumber) % 3); i++, j++) 328 temp[j] = strNumber[i]; 329 for (k=0; i<wcslen(strNumber); i++,j++,k++) { 330 if ((k % 3 == 0) && (j > 0)) 331 temp[j++] = L','; 332 temp[j] = strNumber[i]; 333 } 334 temp[j] = L'\0'; 335 wcsncpy(strNumber, temp, nMaxCount); 336 } 337 338 void ProcessPageShowContextMenu(DWORD dwProcessId) 339 { 340 HMENU hMenu; 341 HMENU hSubMenu; 342 HMENU hPriorityMenu; 343 POINT pt; 344 SYSTEM_INFO si; 345 HANDLE hProcess; 346 DWORD dwProcessPriorityClass; 347 WCHAR strDebugger[260]; 348 DWORD dwDebuggerSize; 349 HKEY hKey; 350 351 memset(&si, 0, sizeof(SYSTEM_INFO)); 352 353 GetCursorPos(&pt); 354 GetSystemInfo(&si); 355 356 hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_PROCESS_PAGE_CONTEXT)); 357 hSubMenu = GetSubMenu(hMenu, 0); 358 hPriorityMenu = GetSubMenu(hSubMenu, 4); 359 360 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId); 361 dwProcessPriorityClass = GetPriorityClass(hProcess); 362 CloseHandle(hProcess); 363 364 if (si.dwNumberOfProcessors < 2) 365 RemoveMenu(hSubMenu, ID_PROCESS_PAGE_SETAFFINITY, MF_BYCOMMAND); 366 367 switch (dwProcessPriorityClass) { 368 case REALTIME_PRIORITY_CLASS: 369 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, MF_BYCOMMAND); 370 break; 371 case HIGH_PRIORITY_CLASS: 372 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_HIGH, MF_BYCOMMAND); 373 break; 374 case ABOVE_NORMAL_PRIORITY_CLASS: 375 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL, MF_BYCOMMAND); 376 break; 377 case NORMAL_PRIORITY_CLASS: 378 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_NORMAL, MF_BYCOMMAND); 379 break; 380 case BELOW_NORMAL_PRIORITY_CLASS: 381 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL, MF_BYCOMMAND); 382 break; 383 case IDLE_PRIORITY_CLASS: 384 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_LOW, MF_BYCOMMAND); 385 break; 386 } 387 388 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", 0, KEY_READ, &hKey) == ERROR_SUCCESS) 389 { 390 dwDebuggerSize = sizeof(strDebugger); 391 if (RegQueryValueExW(hKey, L"Debugger", NULL, NULL, (LPBYTE)strDebugger, &dwDebuggerSize) == ERROR_SUCCESS) 392 { 393 CharUpper(strDebugger); 394 if (wcsstr(strDebugger, L"DRWTSN32")) 395 EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 396 } 397 else 398 EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 399 400 RegCloseKey(hKey); 401 } else { 402 EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 403 } 404 TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL); 405 DestroyMenu(hMenu); 406 } 407 408 void RefreshProcessPage(void) 409 { 410 #ifdef RUN_PROC_PAGE 411 /* Signal the event so that our refresh thread */ 412 /* will wake up and refresh the process page */ 413 PostThreadMessage(dwProcessThread, WM_TIMER, 0, 0); 414 #endif 415 } 416 417 DWORD WINAPI ProcessPageRefreshThread(void *lpParameter) 418 { 419 MSG msg; 420 421 while (1) { 422 /* Wait for an the event or application close */ 423 if (GetMessage(&msg, NULL, 0, 0) <= 0) 424 return 0; 425 426 if (msg.message == WM_TIMER) { 427 428 UpdateProcesses(); 429 430 if (IsWindowVisible(hProcessPage)) 431 InvalidateRect(hProcessPageListCtrl, NULL, FALSE); 432 433 ProcessPageUpdate(); 434 } 435 } 436 return 0; 437 } 438 439 void UpdateProcesses() 440 { 441 int i; 442 ULONG l; 443 LV_ITEM item; 444 LPPROCESS_PAGE_LIST_ITEM pData; 445 446 SendMessage(hProcessPageListCtrl, WM_SETREDRAW, FALSE, 0); 447 448 /* Remove old processes */ 449 for (i = 0; i < ListView_GetItemCount(hProcessPageListCtrl); i++) 450 { 451 memset(&item, 0, sizeof (LV_ITEM)); 452 item.mask = LVIF_PARAM; 453 item.iItem = i; 454 (void)ListView_GetItem(hProcessPageListCtrl, &item); 455 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 456 if (!ProcessRunning(pData->ProcessId)) 457 { 458 (void)ListView_DeleteItem(hProcessPageListCtrl, i); 459 HeapFree(GetProcessHeap(), 0, pData); 460 } 461 } 462 463 /* Check for difference in listview process and performance process counts */ 464 if (ListView_GetItemCount(hProcessPageListCtrl) != PerfDataGetProcessCount()) 465 { 466 /* Add new processes by checking against the current items */ 467 for (l = 0; l < PerfDataGetProcessCount(); l++) 468 { 469 AddProcess(l); 470 } 471 } 472 473 if (TaskManagerSettings.SortColumn != -1) 474 { 475 (void)ListView_SortItems(hProcessPageListCtrl, ProcessPageCompareFunc, NULL); 476 } 477 478 SendMessage(hProcessPageListCtrl, WM_SETREDRAW, TRUE, 0); 479 480 /* Select first item if any */ 481 if ((ListView_GetNextItem(hProcessPageListCtrl, -1, LVNI_FOCUSED | LVNI_SELECTED) == -1) && 482 (ListView_GetItemCount(hProcessPageListCtrl) > 0) && !bProcessPageSelectionMade) 483 { 484 ListView_SetItemState(hProcessPageListCtrl, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); 485 bProcessPageSelectionMade = TRUE; 486 } 487 /* 488 else 489 { 490 bProcessPageSelectionMade = FALSE; 491 } 492 */ 493 } 494 495 BOOL ProcessRunning(ULONG ProcessId) 496 { 497 HANDLE hProcess; 498 DWORD exitCode; 499 500 if (ProcessId == 0) { 501 return TRUE; 502 } 503 504 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId); 505 if (hProcess == NULL) { 506 return FALSE; 507 } 508 509 if (GetExitCodeProcess(hProcess, &exitCode)) { 510 CloseHandle(hProcess); 511 return (exitCode == STILL_ACTIVE); 512 } 513 514 CloseHandle(hProcess); 515 return FALSE; 516 } 517 518 void AddProcess(ULONG Index) 519 { 520 LPPROCESS_PAGE_LIST_ITEM pData; 521 int i; 522 LV_ITEM item; 523 BOOL bAlreadyInList = FALSE; 524 ULONG pid; 525 526 pid = PerfDataGetProcessId(Index); 527 528 /* Check to see if it's already in our list */ 529 for (i=0; i<ListView_GetItemCount(hProcessPageListCtrl); i++) 530 { 531 memset(&item, 0, sizeof(LV_ITEM)); 532 item.mask = LVIF_PARAM; 533 item.iItem = i; 534 (void)ListView_GetItem(hProcessPageListCtrl, &item); 535 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 536 if (pData->ProcessId == pid) 537 { 538 bAlreadyInList = TRUE; 539 break; 540 } 541 } 542 if (!bAlreadyInList) /* Add */ 543 { 544 pData = (LPPROCESS_PAGE_LIST_ITEM)HeapAlloc(GetProcessHeap(), 0, sizeof(PROCESS_PAGE_LIST_ITEM)); 545 pData->ProcessId = pid; 546 547 /* Add the item to the list */ 548 memset(&item, 0, sizeof(LV_ITEM)); 549 item.mask = LVIF_TEXT|LVIF_PARAM; 550 item.pszText = LPSTR_TEXTCALLBACK; 551 item.iItem = ListView_GetItemCount(hProcessPageListCtrl); 552 item.lParam = (LPARAM)pData; 553 (void)ListView_InsertItem(hProcessPageListCtrl, &item); 554 } 555 } 556 557 BOOL PerfDataGetText(ULONG Index, ULONG ColumnIndex, LPTSTR lpText, ULONG nMaxCount) 558 { 559 IO_COUNTERS iocounters; 560 LARGE_INTEGER time; 561 562 if (ColumnDataHints[ColumnIndex] == COLUMN_IMAGENAME) 563 PerfDataGetImageName(Index, lpText, nMaxCount); 564 if (ColumnDataHints[ColumnIndex] == COLUMN_PID) 565 wsprintfW(lpText, L"%lu", PerfDataGetProcessId(Index)); 566 if (ColumnDataHints[ColumnIndex] == COLUMN_USERNAME) 567 PerfDataGetUserName(Index, lpText, nMaxCount); 568 if (ColumnDataHints[ColumnIndex] == COLUMN_COMMANDLINE) 569 PerfDataGetCommandLine(Index, lpText, nMaxCount); 570 if (ColumnDataHints[ColumnIndex] == COLUMN_SESSIONID) 571 wsprintfW(lpText, L"%lu", PerfDataGetSessionId(Index)); 572 if (ColumnDataHints[ColumnIndex] == COLUMN_CPUUSAGE) 573 wsprintfW(lpText, L"%02lu", PerfDataGetCPUUsage(Index)); 574 if (ColumnDataHints[ColumnIndex] == COLUMN_CPUTIME) 575 { 576 DWORD dwHours; 577 DWORD dwMinutes; 578 DWORD dwSeconds; 579 580 time = PerfDataGetCPUTime(Index); 581 gethmsfromlargeint(time, &dwHours, &dwMinutes, &dwSeconds); 582 wsprintfW(lpText, L"%lu:%02lu:%02lu", dwHours, dwMinutes, dwSeconds); 583 } 584 if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGE) 585 { 586 wsprintfW(lpText, L"%lu", PerfDataGetWorkingSetSizeBytes(Index) / 1024); 587 CommaSeparateNumberString(lpText, nMaxCount); 588 wcscat(lpText, L" K"); 589 } 590 if (ColumnDataHints[ColumnIndex] == COLUMN_PEAKMEMORYUSAGE) 591 { 592 wsprintfW(lpText, L"%lu", PerfDataGetPeakWorkingSetSizeBytes(Index) / 1024); 593 CommaSeparateNumberString(lpText, nMaxCount); 594 wcscat(lpText, L" K"); 595 } 596 if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGEDELTA) 597 { 598 wsprintfW(lpText, L"%lu", PerfDataGetWorkingSetSizeDelta(Index) / 1024); 599 CommaSeparateNumberString(lpText, nMaxCount); 600 wcscat(lpText, L" K"); 601 } 602 if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTS) 603 { 604 wsprintfW(lpText, L"%lu", PerfDataGetPageFaultCount(Index)); 605 CommaSeparateNumberString(lpText, nMaxCount); 606 } 607 if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTSDELTA) 608 { 609 wsprintfW(lpText, L"%lu", PerfDataGetPageFaultCountDelta(Index)); 610 CommaSeparateNumberString(lpText, nMaxCount); 611 } 612 if (ColumnDataHints[ColumnIndex] == COLUMN_VIRTUALMEMORYSIZE) 613 { 614 wsprintfW(lpText, L"%lu", PerfDataGetVirtualMemorySizeBytes(Index) / 1024); 615 CommaSeparateNumberString(lpText, nMaxCount); 616 wcscat(lpText, L" K"); 617 } 618 if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEDPOOL) 619 { 620 wsprintfW(lpText, L"%lu", PerfDataGetPagedPoolUsagePages(Index) / 1024); 621 CommaSeparateNumberString(lpText, nMaxCount); 622 wcscat(lpText, L" K"); 623 } 624 if (ColumnDataHints[ColumnIndex] == COLUMN_NONPAGEDPOOL) 625 { 626 wsprintfW(lpText, L"%lu", PerfDataGetNonPagedPoolUsagePages(Index) / 1024); 627 CommaSeparateNumberString(lpText, nMaxCount); 628 wcscat(lpText, L" K"); 629 } 630 if (ColumnDataHints[ColumnIndex] == COLUMN_BASEPRIORITY) 631 wsprintfW(lpText, L"%lu", PerfDataGetBasePriority(Index)); 632 if (ColumnDataHints[ColumnIndex] == COLUMN_HANDLECOUNT) 633 { 634 wsprintfW(lpText, L"%lu", PerfDataGetHandleCount(Index)); 635 CommaSeparateNumberString(lpText, nMaxCount); 636 } 637 if (ColumnDataHints[ColumnIndex] == COLUMN_THREADCOUNT) 638 { 639 wsprintfW(lpText, L"%lu", PerfDataGetThreadCount(Index)); 640 CommaSeparateNumberString(lpText, nMaxCount); 641 } 642 if (ColumnDataHints[ColumnIndex] == COLUMN_USEROBJECTS) 643 { 644 wsprintfW(lpText, L"%lu", PerfDataGetUSERObjectCount(Index)); 645 CommaSeparateNumberString(lpText, nMaxCount); 646 } 647 if (ColumnDataHints[ColumnIndex] == COLUMN_GDIOBJECTS) 648 { 649 wsprintfW(lpText, L"%lu", PerfDataGetGDIObjectCount(Index)); 650 CommaSeparateNumberString(lpText, nMaxCount); 651 } 652 if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADS) 653 { 654 PerfDataGetIOCounters(Index, &iocounters); 655 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.ReadOperationCount); */ 656 _ui64tow(iocounters.ReadOperationCount, lpText, 10); 657 CommaSeparateNumberString(lpText, nMaxCount); 658 } 659 if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITES) 660 { 661 PerfDataGetIOCounters(Index, &iocounters); 662 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.WriteOperationCount); */ 663 _ui64tow(iocounters.WriteOperationCount, lpText, 10); 664 CommaSeparateNumberString(lpText, nMaxCount); 665 } 666 if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHER) 667 { 668 PerfDataGetIOCounters(Index, &iocounters); 669 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.OtherOperationCount); */ 670 _ui64tow(iocounters.OtherOperationCount, lpText, 10); 671 CommaSeparateNumberString(lpText, nMaxCount); 672 } 673 if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADBYTES) 674 { 675 PerfDataGetIOCounters(Index, &iocounters); 676 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.ReadTransferCount); */ 677 _ui64tow(iocounters.ReadTransferCount, lpText, 10); 678 CommaSeparateNumberString(lpText, nMaxCount); 679 } 680 if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITEBYTES) 681 { 682 PerfDataGetIOCounters(Index, &iocounters); 683 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.WriteTransferCount); */ 684 _ui64tow(iocounters.WriteTransferCount, lpText, 10); 685 CommaSeparateNumberString(lpText, nMaxCount); 686 } 687 if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHERBYTES) 688 { 689 PerfDataGetIOCounters(Index, &iocounters); 690 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.OtherTransferCount); */ 691 _ui64tow(iocounters.OtherTransferCount, lpText, 10); 692 CommaSeparateNumberString(lpText, nMaxCount); 693 } 694 695 return FALSE; 696 } 697 698 699 void gethmsfromlargeint(LARGE_INTEGER largeint, DWORD *dwHours, DWORD *dwMinutes, DWORD *dwSeconds) 700 { 701 #ifdef _MSC_VER 702 *dwHours = (DWORD)(largeint.QuadPart / 36000000000L); 703 *dwMinutes = (DWORD)((largeint.QuadPart % 36000000000L) / 600000000L); 704 *dwSeconds = (DWORD)(((largeint.QuadPart % 36000000000L) % 600000000L) / 10000000L); 705 #else 706 *dwHours = (DWORD)(largeint.QuadPart / 36000000000LL); 707 *dwMinutes = (DWORD)((largeint.QuadPart % 36000000000LL) / 600000000LL); 708 *dwSeconds = (DWORD)(((largeint.QuadPart % 36000000000LL) % 600000000LL) / 10000000LL); 709 #endif 710 } 711 712 int largeintcmp(LARGE_INTEGER l1, LARGE_INTEGER l2) 713 { 714 int ret = 0; 715 DWORD dwHours1; 716 DWORD dwMinutes1; 717 DWORD dwSeconds1; 718 DWORD dwHours2; 719 DWORD dwMinutes2; 720 DWORD dwSeconds2; 721 722 gethmsfromlargeint(l1, &dwHours1, &dwMinutes1, &dwSeconds1); 723 gethmsfromlargeint(l2, &dwHours2, &dwMinutes2, &dwSeconds2); 724 ret = CMP(dwHours1, dwHours2); 725 if (ret == 0) 726 { 727 ret = CMP(dwMinutes1, dwMinutes2); 728 if (ret == 0) 729 { 730 ret = CMP(dwSeconds1, dwSeconds2); 731 } 732 } 733 return ret; 734 } 735 736 int CALLBACK ProcessPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 737 { 738 int ret = 0; 739 LPPROCESS_PAGE_LIST_ITEM Param1; 740 LPPROCESS_PAGE_LIST_ITEM Param2; 741 ULONG IndexParam1; 742 ULONG IndexParam2; 743 WCHAR text1[260]; 744 WCHAR text2[260]; 745 ULONG l1; 746 ULONG l2; 747 LARGE_INTEGER time1; 748 LARGE_INTEGER time2; 749 IO_COUNTERS iocounters1; 750 IO_COUNTERS iocounters2; 751 ULONGLONG ull1; 752 ULONGLONG ull2; 753 754 if (TaskManagerSettings.SortAscending) { 755 Param1 = (LPPROCESS_PAGE_LIST_ITEM)lParam1; 756 Param2 = (LPPROCESS_PAGE_LIST_ITEM)lParam2; 757 } else { 758 Param1 = (LPPROCESS_PAGE_LIST_ITEM)lParam2; 759 Param2 = (LPPROCESS_PAGE_LIST_ITEM)lParam1; 760 } 761 IndexParam1 = PerfDataGetProcessIndex(Param1->ProcessId); 762 IndexParam2 = PerfDataGetProcessIndex(Param2->ProcessId); 763 764 if (TaskManagerSettings.SortColumn == COLUMN_IMAGENAME) 765 { 766 PerfDataGetImageName(IndexParam1, text1, sizeof (text1) / sizeof (*text1)); 767 PerfDataGetImageName(IndexParam2, text2, sizeof (text2) / sizeof (*text2)); 768 ret = _wcsicmp(text1, text2); 769 } 770 else if (TaskManagerSettings.SortColumn == COLUMN_PID) 771 { 772 l1 = Param1->ProcessId; 773 l2 = Param2->ProcessId; 774 ret = CMP(l1, l2); 775 } 776 else if (TaskManagerSettings.SortColumn == COLUMN_USERNAME) 777 { 778 PerfDataGetUserName(IndexParam1, text1, sizeof (text1) / sizeof (*text1)); 779 PerfDataGetUserName(IndexParam2, text2, sizeof (text2) / sizeof (*text2)); 780 ret = _wcsicmp(text1, text2); 781 } 782 else if (TaskManagerSettings.SortColumn == COLUMN_COMMANDLINE) 783 { 784 PerfDataGetCommandLine(IndexParam1, text1, sizeof (text1) / sizeof (*text1)); 785 PerfDataGetCommandLine(IndexParam2, text2, sizeof (text2) / sizeof (*text2)); 786 ret = _wcsicmp(text1, text2); 787 } 788 else if (TaskManagerSettings.SortColumn == COLUMN_SESSIONID) 789 { 790 l1 = PerfDataGetSessionId(IndexParam1); 791 l2 = PerfDataGetSessionId(IndexParam2); 792 ret = CMP(l1, l2); 793 } 794 else if (TaskManagerSettings.SortColumn == COLUMN_CPUUSAGE) 795 { 796 l1 = PerfDataGetCPUUsage(IndexParam1); 797 l2 = PerfDataGetCPUUsage(IndexParam2); 798 ret = CMP(l1, l2); 799 } 800 else if (TaskManagerSettings.SortColumn == COLUMN_CPUTIME) 801 { 802 time1 = PerfDataGetCPUTime(IndexParam1); 803 time2 = PerfDataGetCPUTime(IndexParam2); 804 ret = largeintcmp(time1, time2); 805 } 806 else if (TaskManagerSettings.SortColumn == COLUMN_MEMORYUSAGE) 807 { 808 l1 = PerfDataGetWorkingSetSizeBytes(IndexParam1); 809 l2 = PerfDataGetWorkingSetSizeBytes(IndexParam2); 810 ret = CMP(l1, l2); 811 } 812 else if (TaskManagerSettings.SortColumn == COLUMN_PEAKMEMORYUSAGE) 813 { 814 l1 = PerfDataGetPeakWorkingSetSizeBytes(IndexParam1); 815 l2 = PerfDataGetPeakWorkingSetSizeBytes(IndexParam2); 816 ret = CMP(l1, l2); 817 } 818 else if (TaskManagerSettings.SortColumn == COLUMN_MEMORYUSAGEDELTA) 819 { 820 l1 = PerfDataGetWorkingSetSizeDelta(IndexParam1); 821 l2 = PerfDataGetWorkingSetSizeDelta(IndexParam2); 822 ret = CMP(l1, l2); 823 } 824 else if (TaskManagerSettings.SortColumn == COLUMN_PAGEFAULTS) 825 { 826 l1 = PerfDataGetPageFaultCount(IndexParam1); 827 l2 = PerfDataGetPageFaultCount(IndexParam2); 828 ret = CMP(l1, l2); 829 } 830 else if (TaskManagerSettings.SortColumn == COLUMN_PAGEFAULTSDELTA) 831 { 832 l1 = PerfDataGetPageFaultCountDelta(IndexParam1); 833 l2 = PerfDataGetPageFaultCountDelta(IndexParam2); 834 ret = CMP(l1, l2); 835 } 836 else if (TaskManagerSettings.SortColumn == COLUMN_VIRTUALMEMORYSIZE) 837 { 838 l1 = PerfDataGetVirtualMemorySizeBytes(IndexParam1); 839 l2 = PerfDataGetVirtualMemorySizeBytes(IndexParam2); 840 ret = CMP(l1, l2); 841 } 842 else if (TaskManagerSettings.SortColumn == COLUMN_PAGEDPOOL) 843 { 844 l1 = PerfDataGetPagedPoolUsagePages(IndexParam1); 845 l2 = PerfDataGetPagedPoolUsagePages(IndexParam2); 846 ret = CMP(l1, l2); 847 } 848 else if (TaskManagerSettings.SortColumn == COLUMN_NONPAGEDPOOL) 849 { 850 l1 = PerfDataGetNonPagedPoolUsagePages(IndexParam1); 851 l2 = PerfDataGetNonPagedPoolUsagePages(IndexParam2); 852 ret = CMP(l1, l2); 853 } 854 else if (TaskManagerSettings.SortColumn == COLUMN_BASEPRIORITY) 855 { 856 l1 = PerfDataGetBasePriority(IndexParam1); 857 l2 = PerfDataGetBasePriority(IndexParam2); 858 ret = CMP(l1, l2); 859 } 860 else if (TaskManagerSettings.SortColumn == COLUMN_HANDLECOUNT) 861 { 862 l1 = PerfDataGetHandleCount(IndexParam1); 863 l2 = PerfDataGetHandleCount(IndexParam2); 864 ret = CMP(l1, l2); 865 } 866 else if (TaskManagerSettings.SortColumn == COLUMN_THREADCOUNT) 867 { 868 l1 = PerfDataGetThreadCount(IndexParam1); 869 l2 = PerfDataGetThreadCount(IndexParam2); 870 ret = CMP(l1, l2); 871 } 872 else if (TaskManagerSettings.SortColumn == COLUMN_USEROBJECTS) 873 { 874 l1 = PerfDataGetUSERObjectCount(IndexParam1); 875 l2 = PerfDataGetUSERObjectCount(IndexParam2); 876 ret = CMP(l1, l2); 877 } 878 else if (TaskManagerSettings.SortColumn == COLUMN_GDIOBJECTS) 879 { 880 l1 = PerfDataGetGDIObjectCount(IndexParam1); 881 l2 = PerfDataGetGDIObjectCount(IndexParam2); 882 ret = CMP(l1, l2); 883 } 884 else if (TaskManagerSettings.SortColumn == COLUMN_IOREADS) 885 { 886 PerfDataGetIOCounters(IndexParam1, &iocounters1); 887 PerfDataGetIOCounters(IndexParam2, &iocounters2); 888 ull1 = iocounters1.ReadOperationCount; 889 ull2 = iocounters2.ReadOperationCount; 890 ret = CMP(ull1, ull2); 891 } 892 else if (TaskManagerSettings.SortColumn == COLUMN_IOWRITES) 893 { 894 PerfDataGetIOCounters(IndexParam1, &iocounters1); 895 PerfDataGetIOCounters(IndexParam2, &iocounters2); 896 ull1 = iocounters1.WriteOperationCount; 897 ull2 = iocounters2.WriteOperationCount; 898 ret = CMP(ull1, ull2); 899 } 900 else if (TaskManagerSettings.SortColumn == COLUMN_IOOTHER) 901 { 902 PerfDataGetIOCounters(IndexParam1, &iocounters1); 903 PerfDataGetIOCounters(IndexParam2, &iocounters2); 904 ull1 = iocounters1.OtherOperationCount; 905 ull2 = iocounters2.OtherOperationCount; 906 ret = CMP(ull1, ull2); 907 } 908 else if (TaskManagerSettings.SortColumn == COLUMN_IOREADBYTES) 909 { 910 PerfDataGetIOCounters(IndexParam1, &iocounters1); 911 PerfDataGetIOCounters(IndexParam2, &iocounters2); 912 ull1 = iocounters1.ReadTransferCount; 913 ull2 = iocounters2.ReadTransferCount; 914 ret = CMP(ull1, ull2); 915 } 916 else if (TaskManagerSettings.SortColumn == COLUMN_IOWRITEBYTES) 917 { 918 PerfDataGetIOCounters(IndexParam1, &iocounters1); 919 PerfDataGetIOCounters(IndexParam2, &iocounters2); 920 ull1 = iocounters1.WriteTransferCount; 921 ull2 = iocounters2.WriteTransferCount; 922 ret = CMP(ull1, ull2); 923 } 924 else if (TaskManagerSettings.SortColumn == COLUMN_IOOTHERBYTES) 925 { 926 PerfDataGetIOCounters(IndexParam1, &iocounters1); 927 PerfDataGetIOCounters(IndexParam2, &iocounters2); 928 ull1 = iocounters1.OtherTransferCount; 929 ull2 = iocounters2.OtherTransferCount; 930 ret = CMP(ull1, ull2); 931 } 932 return ret; 933 } 934