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 if (!DebugChannelsAreSupported()) 368 RemoveMenu(hSubMenu, ID_PROCESS_PAGE_DEBUGCHANNELS, MF_BYCOMMAND); 369 370 switch (dwProcessPriorityClass) { 371 case REALTIME_PRIORITY_CLASS: 372 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, MF_BYCOMMAND); 373 break; 374 case HIGH_PRIORITY_CLASS: 375 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_HIGH, MF_BYCOMMAND); 376 break; 377 case ABOVE_NORMAL_PRIORITY_CLASS: 378 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL, MF_BYCOMMAND); 379 break; 380 case NORMAL_PRIORITY_CLASS: 381 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_NORMAL, MF_BYCOMMAND); 382 break; 383 case BELOW_NORMAL_PRIORITY_CLASS: 384 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL, MF_BYCOMMAND); 385 break; 386 case IDLE_PRIORITY_CLASS: 387 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_LOW, MF_BYCOMMAND); 388 break; 389 } 390 391 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", 0, KEY_READ, &hKey) == ERROR_SUCCESS) 392 { 393 dwDebuggerSize = sizeof(strDebugger); 394 if (RegQueryValueExW(hKey, L"Debugger", NULL, NULL, (LPBYTE)strDebugger, &dwDebuggerSize) == ERROR_SUCCESS) 395 { 396 CharUpper(strDebugger); 397 if (wcsstr(strDebugger, L"DRWTSN32")) 398 EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 399 } 400 else 401 EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 402 403 RegCloseKey(hKey); 404 } else { 405 EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 406 } 407 TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL); 408 DestroyMenu(hMenu); 409 } 410 411 void RefreshProcessPage(void) 412 { 413 #ifdef RUN_PROC_PAGE 414 /* Signal the event so that our refresh thread */ 415 /* will wake up and refresh the process page */ 416 PostThreadMessage(dwProcessThread, WM_TIMER, 0, 0); 417 #endif 418 } 419 420 DWORD WINAPI ProcessPageRefreshThread(void *lpParameter) 421 { 422 MSG msg; 423 424 while (1) { 425 /* Wait for an the event or application close */ 426 if (GetMessage(&msg, NULL, 0, 0) <= 0) 427 return 0; 428 429 if (msg.message == WM_TIMER) { 430 431 UpdateProcesses(); 432 433 if (IsWindowVisible(hProcessPage)) 434 InvalidateRect(hProcessPageListCtrl, NULL, FALSE); 435 436 ProcessPageUpdate(); 437 } 438 } 439 return 0; 440 } 441 442 void UpdateProcesses() 443 { 444 int i; 445 ULONG l; 446 LV_ITEM item; 447 LPPROCESS_PAGE_LIST_ITEM pData; 448 449 SendMessage(hProcessPageListCtrl, WM_SETREDRAW, FALSE, 0); 450 451 /* Remove old processes */ 452 for (i = 0; i < ListView_GetItemCount(hProcessPageListCtrl); i++) 453 { 454 memset(&item, 0, sizeof (LV_ITEM)); 455 item.mask = LVIF_PARAM; 456 item.iItem = i; 457 (void)ListView_GetItem(hProcessPageListCtrl, &item); 458 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 459 if (!ProcessRunning(pData->ProcessId)) 460 { 461 (void)ListView_DeleteItem(hProcessPageListCtrl, i); 462 HeapFree(GetProcessHeap(), 0, pData); 463 } 464 } 465 466 /* Check for difference in listview process and performance process counts */ 467 if (ListView_GetItemCount(hProcessPageListCtrl) != PerfDataGetProcessCount()) 468 { 469 /* Add new processes by checking against the current items */ 470 for (l = 0; l < PerfDataGetProcessCount(); l++) 471 { 472 AddProcess(l); 473 } 474 } 475 476 if (TaskManagerSettings.SortColumn != -1) 477 { 478 (void)ListView_SortItems(hProcessPageListCtrl, ProcessPageCompareFunc, NULL); 479 } 480 481 SendMessage(hProcessPageListCtrl, WM_SETREDRAW, TRUE, 0); 482 483 /* Select first item if any */ 484 if ((ListView_GetNextItem(hProcessPageListCtrl, -1, LVNI_FOCUSED | LVNI_SELECTED) == -1) && 485 (ListView_GetItemCount(hProcessPageListCtrl) > 0) && !bProcessPageSelectionMade) 486 { 487 ListView_SetItemState(hProcessPageListCtrl, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); 488 bProcessPageSelectionMade = TRUE; 489 } 490 /* 491 else 492 { 493 bProcessPageSelectionMade = FALSE; 494 } 495 */ 496 } 497 498 BOOL ProcessRunning(ULONG ProcessId) 499 { 500 HANDLE hProcess; 501 DWORD exitCode; 502 503 if (ProcessId == 0) { 504 return TRUE; 505 } 506 507 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId); 508 if (hProcess == NULL) { 509 return FALSE; 510 } 511 512 if (GetExitCodeProcess(hProcess, &exitCode)) { 513 CloseHandle(hProcess); 514 return (exitCode == STILL_ACTIVE); 515 } 516 517 CloseHandle(hProcess); 518 return FALSE; 519 } 520 521 void AddProcess(ULONG Index) 522 { 523 LPPROCESS_PAGE_LIST_ITEM pData; 524 int i; 525 LV_ITEM item; 526 BOOL bAlreadyInList = FALSE; 527 ULONG pid; 528 529 pid = PerfDataGetProcessId(Index); 530 531 /* Check to see if it's already in our list */ 532 for (i=0; i<ListView_GetItemCount(hProcessPageListCtrl); i++) 533 { 534 memset(&item, 0, sizeof(LV_ITEM)); 535 item.mask = LVIF_PARAM; 536 item.iItem = i; 537 (void)ListView_GetItem(hProcessPageListCtrl, &item); 538 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 539 if (pData->ProcessId == pid) 540 { 541 bAlreadyInList = TRUE; 542 break; 543 } 544 } 545 if (!bAlreadyInList) /* Add */ 546 { 547 pData = (LPPROCESS_PAGE_LIST_ITEM)HeapAlloc(GetProcessHeap(), 0, sizeof(PROCESS_PAGE_LIST_ITEM)); 548 pData->ProcessId = pid; 549 550 /* Add the item to the list */ 551 memset(&item, 0, sizeof(LV_ITEM)); 552 item.mask = LVIF_TEXT|LVIF_PARAM; 553 item.pszText = LPSTR_TEXTCALLBACK; 554 item.iItem = ListView_GetItemCount(hProcessPageListCtrl); 555 item.lParam = (LPARAM)pData; 556 (void)ListView_InsertItem(hProcessPageListCtrl, &item); 557 } 558 } 559 560 BOOL PerfDataGetText(ULONG Index, ULONG ColumnIndex, LPTSTR lpText, ULONG nMaxCount) 561 { 562 IO_COUNTERS iocounters; 563 LARGE_INTEGER time; 564 565 if (ColumnDataHints[ColumnIndex] == COLUMN_IMAGENAME) 566 PerfDataGetImageName(Index, lpText, nMaxCount); 567 if (ColumnDataHints[ColumnIndex] == COLUMN_PID) 568 wsprintfW(lpText, L"%lu", PerfDataGetProcessId(Index)); 569 if (ColumnDataHints[ColumnIndex] == COLUMN_USERNAME) 570 PerfDataGetUserName(Index, lpText, nMaxCount); 571 if (ColumnDataHints[ColumnIndex] == COLUMN_COMMANDLINE) 572 PerfDataGetCommandLine(Index, lpText, nMaxCount); 573 if (ColumnDataHints[ColumnIndex] == COLUMN_SESSIONID) 574 wsprintfW(lpText, L"%lu", PerfDataGetSessionId(Index)); 575 if (ColumnDataHints[ColumnIndex] == COLUMN_CPUUSAGE) 576 wsprintfW(lpText, L"%02lu", PerfDataGetCPUUsage(Index)); 577 if (ColumnDataHints[ColumnIndex] == COLUMN_CPUTIME) 578 { 579 DWORD dwHours; 580 DWORD dwMinutes; 581 DWORD dwSeconds; 582 583 time = PerfDataGetCPUTime(Index); 584 gethmsfromlargeint(time, &dwHours, &dwMinutes, &dwSeconds); 585 wsprintfW(lpText, L"%lu:%02lu:%02lu", dwHours, dwMinutes, dwSeconds); 586 } 587 if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGE) 588 { 589 wsprintfW(lpText, L"%lu", PerfDataGetWorkingSetSizeBytes(Index) / 1024); 590 CommaSeparateNumberString(lpText, nMaxCount); 591 wcscat(lpText, L" K"); 592 } 593 if (ColumnDataHints[ColumnIndex] == COLUMN_PEAKMEMORYUSAGE) 594 { 595 wsprintfW(lpText, L"%lu", PerfDataGetPeakWorkingSetSizeBytes(Index) / 1024); 596 CommaSeparateNumberString(lpText, nMaxCount); 597 wcscat(lpText, L" K"); 598 } 599 if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGEDELTA) 600 { 601 wsprintfW(lpText, L"%lu", PerfDataGetWorkingSetSizeDelta(Index) / 1024); 602 CommaSeparateNumberString(lpText, nMaxCount); 603 wcscat(lpText, L" K"); 604 } 605 if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTS) 606 { 607 wsprintfW(lpText, L"%lu", PerfDataGetPageFaultCount(Index)); 608 CommaSeparateNumberString(lpText, nMaxCount); 609 } 610 if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTSDELTA) 611 { 612 wsprintfW(lpText, L"%lu", PerfDataGetPageFaultCountDelta(Index)); 613 CommaSeparateNumberString(lpText, nMaxCount); 614 } 615 if (ColumnDataHints[ColumnIndex] == COLUMN_VIRTUALMEMORYSIZE) 616 { 617 wsprintfW(lpText, L"%lu", PerfDataGetVirtualMemorySizeBytes(Index) / 1024); 618 CommaSeparateNumberString(lpText, nMaxCount); 619 wcscat(lpText, L" K"); 620 } 621 if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEDPOOL) 622 { 623 wsprintfW(lpText, L"%lu", PerfDataGetPagedPoolUsagePages(Index) / 1024); 624 CommaSeparateNumberString(lpText, nMaxCount); 625 wcscat(lpText, L" K"); 626 } 627 if (ColumnDataHints[ColumnIndex] == COLUMN_NONPAGEDPOOL) 628 { 629 wsprintfW(lpText, L"%lu", PerfDataGetNonPagedPoolUsagePages(Index) / 1024); 630 CommaSeparateNumberString(lpText, nMaxCount); 631 wcscat(lpText, L" K"); 632 } 633 if (ColumnDataHints[ColumnIndex] == COLUMN_BASEPRIORITY) 634 wsprintfW(lpText, L"%lu", PerfDataGetBasePriority(Index)); 635 if (ColumnDataHints[ColumnIndex] == COLUMN_HANDLECOUNT) 636 { 637 wsprintfW(lpText, L"%lu", PerfDataGetHandleCount(Index)); 638 CommaSeparateNumberString(lpText, nMaxCount); 639 } 640 if (ColumnDataHints[ColumnIndex] == COLUMN_THREADCOUNT) 641 { 642 wsprintfW(lpText, L"%lu", PerfDataGetThreadCount(Index)); 643 CommaSeparateNumberString(lpText, nMaxCount); 644 } 645 if (ColumnDataHints[ColumnIndex] == COLUMN_USEROBJECTS) 646 { 647 wsprintfW(lpText, L"%lu", PerfDataGetUSERObjectCount(Index)); 648 CommaSeparateNumberString(lpText, nMaxCount); 649 } 650 if (ColumnDataHints[ColumnIndex] == COLUMN_GDIOBJECTS) 651 { 652 wsprintfW(lpText, L"%lu", PerfDataGetGDIObjectCount(Index)); 653 CommaSeparateNumberString(lpText, nMaxCount); 654 } 655 if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADS) 656 { 657 PerfDataGetIOCounters(Index, &iocounters); 658 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.ReadOperationCount); */ 659 _ui64tow(iocounters.ReadOperationCount, lpText, 10); 660 CommaSeparateNumberString(lpText, nMaxCount); 661 } 662 if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITES) 663 { 664 PerfDataGetIOCounters(Index, &iocounters); 665 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.WriteOperationCount); */ 666 _ui64tow(iocounters.WriteOperationCount, lpText, 10); 667 CommaSeparateNumberString(lpText, nMaxCount); 668 } 669 if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHER) 670 { 671 PerfDataGetIOCounters(Index, &iocounters); 672 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.OtherOperationCount); */ 673 _ui64tow(iocounters.OtherOperationCount, lpText, 10); 674 CommaSeparateNumberString(lpText, nMaxCount); 675 } 676 if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADBYTES) 677 { 678 PerfDataGetIOCounters(Index, &iocounters); 679 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.ReadTransferCount); */ 680 _ui64tow(iocounters.ReadTransferCount, lpText, 10); 681 CommaSeparateNumberString(lpText, nMaxCount); 682 } 683 if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITEBYTES) 684 { 685 PerfDataGetIOCounters(Index, &iocounters); 686 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.WriteTransferCount); */ 687 _ui64tow(iocounters.WriteTransferCount, lpText, 10); 688 CommaSeparateNumberString(lpText, nMaxCount); 689 } 690 if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHERBYTES) 691 { 692 PerfDataGetIOCounters(Index, &iocounters); 693 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.OtherTransferCount); */ 694 _ui64tow(iocounters.OtherTransferCount, lpText, 10); 695 CommaSeparateNumberString(lpText, nMaxCount); 696 } 697 698 return FALSE; 699 } 700 701 702 void gethmsfromlargeint(LARGE_INTEGER largeint, DWORD *dwHours, DWORD *dwMinutes, DWORD *dwSeconds) 703 { 704 #ifdef _MSC_VER 705 *dwHours = (DWORD)(largeint.QuadPart / 36000000000L); 706 *dwMinutes = (DWORD)((largeint.QuadPart % 36000000000L) / 600000000L); 707 *dwSeconds = (DWORD)(((largeint.QuadPart % 36000000000L) % 600000000L) / 10000000L); 708 #else 709 *dwHours = (DWORD)(largeint.QuadPart / 36000000000LL); 710 *dwMinutes = (DWORD)((largeint.QuadPart % 36000000000LL) / 600000000LL); 711 *dwSeconds = (DWORD)(((largeint.QuadPart % 36000000000LL) % 600000000LL) / 10000000LL); 712 #endif 713 } 714 715 int largeintcmp(LARGE_INTEGER l1, LARGE_INTEGER l2) 716 { 717 int ret = 0; 718 DWORD dwHours1; 719 DWORD dwMinutes1; 720 DWORD dwSeconds1; 721 DWORD dwHours2; 722 DWORD dwMinutes2; 723 DWORD dwSeconds2; 724 725 gethmsfromlargeint(l1, &dwHours1, &dwMinutes1, &dwSeconds1); 726 gethmsfromlargeint(l2, &dwHours2, &dwMinutes2, &dwSeconds2); 727 ret = CMP(dwHours1, dwHours2); 728 if (ret == 0) 729 { 730 ret = CMP(dwMinutes1, dwMinutes2); 731 if (ret == 0) 732 { 733 ret = CMP(dwSeconds1, dwSeconds2); 734 } 735 } 736 return ret; 737 } 738 739 int CALLBACK ProcessPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 740 { 741 int ret = 0; 742 LPPROCESS_PAGE_LIST_ITEM Param1; 743 LPPROCESS_PAGE_LIST_ITEM Param2; 744 ULONG IndexParam1; 745 ULONG IndexParam2; 746 WCHAR text1[260]; 747 WCHAR text2[260]; 748 ULONG l1; 749 ULONG l2; 750 LARGE_INTEGER time1; 751 LARGE_INTEGER time2; 752 IO_COUNTERS iocounters1; 753 IO_COUNTERS iocounters2; 754 ULONGLONG ull1; 755 ULONGLONG ull2; 756 757 if (TaskManagerSettings.SortAscending) { 758 Param1 = (LPPROCESS_PAGE_LIST_ITEM)lParam1; 759 Param2 = (LPPROCESS_PAGE_LIST_ITEM)lParam2; 760 } else { 761 Param1 = (LPPROCESS_PAGE_LIST_ITEM)lParam2; 762 Param2 = (LPPROCESS_PAGE_LIST_ITEM)lParam1; 763 } 764 IndexParam1 = PerfDataGetProcessIndex(Param1->ProcessId); 765 IndexParam2 = PerfDataGetProcessIndex(Param2->ProcessId); 766 767 if (TaskManagerSettings.SortColumn == COLUMN_IMAGENAME) 768 { 769 PerfDataGetImageName(IndexParam1, text1, sizeof (text1) / sizeof (*text1)); 770 PerfDataGetImageName(IndexParam2, text2, sizeof (text2) / sizeof (*text2)); 771 ret = _wcsicmp(text1, text2); 772 } 773 else if (TaskManagerSettings.SortColumn == COLUMN_PID) 774 { 775 l1 = Param1->ProcessId; 776 l2 = Param2->ProcessId; 777 ret = CMP(l1, l2); 778 } 779 else if (TaskManagerSettings.SortColumn == COLUMN_USERNAME) 780 { 781 PerfDataGetUserName(IndexParam1, text1, sizeof (text1) / sizeof (*text1)); 782 PerfDataGetUserName(IndexParam2, text2, sizeof (text2) / sizeof (*text2)); 783 ret = _wcsicmp(text1, text2); 784 } 785 else if (TaskManagerSettings.SortColumn == COLUMN_COMMANDLINE) 786 { 787 PerfDataGetCommandLine(IndexParam1, text1, sizeof (text1) / sizeof (*text1)); 788 PerfDataGetCommandLine(IndexParam2, text2, sizeof (text2) / sizeof (*text2)); 789 ret = _wcsicmp(text1, text2); 790 } 791 else if (TaskManagerSettings.SortColumn == COLUMN_SESSIONID) 792 { 793 l1 = PerfDataGetSessionId(IndexParam1); 794 l2 = PerfDataGetSessionId(IndexParam2); 795 ret = CMP(l1, l2); 796 } 797 else if (TaskManagerSettings.SortColumn == COLUMN_CPUUSAGE) 798 { 799 l1 = PerfDataGetCPUUsage(IndexParam1); 800 l2 = PerfDataGetCPUUsage(IndexParam2); 801 ret = CMP(l1, l2); 802 } 803 else if (TaskManagerSettings.SortColumn == COLUMN_CPUTIME) 804 { 805 time1 = PerfDataGetCPUTime(IndexParam1); 806 time2 = PerfDataGetCPUTime(IndexParam2); 807 ret = largeintcmp(time1, time2); 808 } 809 else if (TaskManagerSettings.SortColumn == COLUMN_MEMORYUSAGE) 810 { 811 l1 = PerfDataGetWorkingSetSizeBytes(IndexParam1); 812 l2 = PerfDataGetWorkingSetSizeBytes(IndexParam2); 813 ret = CMP(l1, l2); 814 } 815 else if (TaskManagerSettings.SortColumn == COLUMN_PEAKMEMORYUSAGE) 816 { 817 l1 = PerfDataGetPeakWorkingSetSizeBytes(IndexParam1); 818 l2 = PerfDataGetPeakWorkingSetSizeBytes(IndexParam2); 819 ret = CMP(l1, l2); 820 } 821 else if (TaskManagerSettings.SortColumn == COLUMN_MEMORYUSAGEDELTA) 822 { 823 l1 = PerfDataGetWorkingSetSizeDelta(IndexParam1); 824 l2 = PerfDataGetWorkingSetSizeDelta(IndexParam2); 825 ret = CMP(l1, l2); 826 } 827 else if (TaskManagerSettings.SortColumn == COLUMN_PAGEFAULTS) 828 { 829 l1 = PerfDataGetPageFaultCount(IndexParam1); 830 l2 = PerfDataGetPageFaultCount(IndexParam2); 831 ret = CMP(l1, l2); 832 } 833 else if (TaskManagerSettings.SortColumn == COLUMN_PAGEFAULTSDELTA) 834 { 835 l1 = PerfDataGetPageFaultCountDelta(IndexParam1); 836 l2 = PerfDataGetPageFaultCountDelta(IndexParam2); 837 ret = CMP(l1, l2); 838 } 839 else if (TaskManagerSettings.SortColumn == COLUMN_VIRTUALMEMORYSIZE) 840 { 841 l1 = PerfDataGetVirtualMemorySizeBytes(IndexParam1); 842 l2 = PerfDataGetVirtualMemorySizeBytes(IndexParam2); 843 ret = CMP(l1, l2); 844 } 845 else if (TaskManagerSettings.SortColumn == COLUMN_PAGEDPOOL) 846 { 847 l1 = PerfDataGetPagedPoolUsagePages(IndexParam1); 848 l2 = PerfDataGetPagedPoolUsagePages(IndexParam2); 849 ret = CMP(l1, l2); 850 } 851 else if (TaskManagerSettings.SortColumn == COLUMN_NONPAGEDPOOL) 852 { 853 l1 = PerfDataGetNonPagedPoolUsagePages(IndexParam1); 854 l2 = PerfDataGetNonPagedPoolUsagePages(IndexParam2); 855 ret = CMP(l1, l2); 856 } 857 else if (TaskManagerSettings.SortColumn == COLUMN_BASEPRIORITY) 858 { 859 l1 = PerfDataGetBasePriority(IndexParam1); 860 l2 = PerfDataGetBasePriority(IndexParam2); 861 ret = CMP(l1, l2); 862 } 863 else if (TaskManagerSettings.SortColumn == COLUMN_HANDLECOUNT) 864 { 865 l1 = PerfDataGetHandleCount(IndexParam1); 866 l2 = PerfDataGetHandleCount(IndexParam2); 867 ret = CMP(l1, l2); 868 } 869 else if (TaskManagerSettings.SortColumn == COLUMN_THREADCOUNT) 870 { 871 l1 = PerfDataGetThreadCount(IndexParam1); 872 l2 = PerfDataGetThreadCount(IndexParam2); 873 ret = CMP(l1, l2); 874 } 875 else if (TaskManagerSettings.SortColumn == COLUMN_USEROBJECTS) 876 { 877 l1 = PerfDataGetUSERObjectCount(IndexParam1); 878 l2 = PerfDataGetUSERObjectCount(IndexParam2); 879 ret = CMP(l1, l2); 880 } 881 else if (TaskManagerSettings.SortColumn == COLUMN_GDIOBJECTS) 882 { 883 l1 = PerfDataGetGDIObjectCount(IndexParam1); 884 l2 = PerfDataGetGDIObjectCount(IndexParam2); 885 ret = CMP(l1, l2); 886 } 887 else if (TaskManagerSettings.SortColumn == COLUMN_IOREADS) 888 { 889 PerfDataGetIOCounters(IndexParam1, &iocounters1); 890 PerfDataGetIOCounters(IndexParam2, &iocounters2); 891 ull1 = iocounters1.ReadOperationCount; 892 ull2 = iocounters2.ReadOperationCount; 893 ret = CMP(ull1, ull2); 894 } 895 else if (TaskManagerSettings.SortColumn == COLUMN_IOWRITES) 896 { 897 PerfDataGetIOCounters(IndexParam1, &iocounters1); 898 PerfDataGetIOCounters(IndexParam2, &iocounters2); 899 ull1 = iocounters1.WriteOperationCount; 900 ull2 = iocounters2.WriteOperationCount; 901 ret = CMP(ull1, ull2); 902 } 903 else if (TaskManagerSettings.SortColumn == COLUMN_IOOTHER) 904 { 905 PerfDataGetIOCounters(IndexParam1, &iocounters1); 906 PerfDataGetIOCounters(IndexParam2, &iocounters2); 907 ull1 = iocounters1.OtherOperationCount; 908 ull2 = iocounters2.OtherOperationCount; 909 ret = CMP(ull1, ull2); 910 } 911 else if (TaskManagerSettings.SortColumn == COLUMN_IOREADBYTES) 912 { 913 PerfDataGetIOCounters(IndexParam1, &iocounters1); 914 PerfDataGetIOCounters(IndexParam2, &iocounters2); 915 ull1 = iocounters1.ReadTransferCount; 916 ull2 = iocounters2.ReadTransferCount; 917 ret = CMP(ull1, ull2); 918 } 919 else if (TaskManagerSettings.SortColumn == COLUMN_IOWRITEBYTES) 920 { 921 PerfDataGetIOCounters(IndexParam1, &iocounters1); 922 PerfDataGetIOCounters(IndexParam2, &iocounters2); 923 ull1 = iocounters1.WriteTransferCount; 924 ull2 = iocounters2.WriteTransferCount; 925 ret = CMP(ull1, ull2); 926 } 927 else if (TaskManagerSettings.SortColumn == COLUMN_IOOTHERBYTES) 928 { 929 PerfDataGetIOCounters(IndexParam1, &iocounters1); 930 PerfDataGetIOCounters(IndexParam2, &iocounters2); 931 ull1 = iocounters1.OtherTransferCount; 932 ull2 = iocounters2.OtherTransferCount; 933 ret = CMP(ull1, ull2); 934 } 935 return ret; 936 } 937