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 * Copyright (C) 2022 Thamatip Chitpong <tangaming123456@outlook.com> 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 */ 24 25 #include "precomp.h" 26 27 #include "proclist.h" 28 29 #include <strsafe.h> 30 31 #include <ndk/psfuncs.h> 32 33 #define CMP(x1, x2)\ 34 (x1 < x2 ? -1 : (x1 > x2 ? 1 : 0)) 35 36 typedef struct 37 { 38 ULONG ProcessId; 39 } PROCESS_PAGE_LIST_ITEM, *LPPROCESS_PAGE_LIST_ITEM; 40 41 HWND hProcessPage; /* Process List Property Page */ 42 43 HWND hProcessPageListCtrl; /* Process ListCtrl Window */ 44 HWND hProcessPageHeaderCtrl; /* Process Header Control */ 45 HWND hProcessPageEndProcessButton; /* Process End Process button */ 46 HWND hProcessPageShowAllProcessesButton;/* Process Show All Processes checkbox */ 47 BOOL bProcessPageSelectionMade = FALSE; /* Is item in ListCtrl selected */ 48 49 static int nProcessPageWidth; 50 static int nProcessPageHeight; 51 #ifdef RUN_PROC_PAGE 52 static HANDLE hProcessThread = NULL; 53 static DWORD dwProcessThread; 54 #endif 55 56 int CALLBACK ProcessPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); 57 void AddProcess(ULONG Index); 58 void UpdateProcesses(); 59 void gethmsfromlargeint(LARGE_INTEGER largeint, DWORD *dwHours, DWORD *dwMinutes, DWORD *dwSeconds); 60 void ProcessPageOnNotify(WPARAM wParam, LPARAM lParam); 61 void CommaSeparateNumberString(LPWSTR strNumber, ULONG nMaxCount); 62 void ProcessPageShowContextMenu(DWORD dwProcessId); 63 BOOL PerfDataGetText(ULONG Index, ULONG ColumnIndex, LPTSTR lpText, ULONG nMaxCount); 64 DWORD WINAPI ProcessPageRefreshThread(void *lpParameter); 65 int ProcessRunning(ULONG ProcessId); 66 67 void Cleanup(void) 68 { 69 int i; 70 LV_ITEM item; 71 LPPROCESS_PAGE_LIST_ITEM pData; 72 for (i = 0; i < ListView_GetItemCount(hProcessPageListCtrl); i++) 73 { 74 memset(&item, 0, sizeof(LV_ITEM)); 75 item.mask = LVIF_PARAM; 76 item.iItem = i; 77 (void)ListView_GetItem(hProcessPageListCtrl, &item); 78 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 79 HeapFree(GetProcessHeap(), 0, pData); 80 } 81 } 82 83 int ProcGetIndexByProcessId(DWORD dwProcessId) 84 { 85 int i; 86 LVITEM item; 87 LPPROCESS_PAGE_LIST_ITEM pData; 88 89 for (i=0; i<ListView_GetItemCount(hProcessPageListCtrl); i++) 90 { 91 memset(&item, 0, sizeof(LV_ITEM)); 92 item.mask = LVIF_PARAM; 93 item.iItem = i; 94 (void)ListView_GetItem(hProcessPageListCtrl, &item); 95 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 96 if (pData->ProcessId == dwProcessId) 97 { 98 return i; 99 } 100 } 101 return 0; 102 } 103 104 DWORD GetSelectedProcessId(void) 105 { 106 int Index; 107 LVITEM lvitem; 108 109 if(ListView_GetSelectedCount(hProcessPageListCtrl) == 1) 110 { 111 Index = ListView_GetSelectionMark(hProcessPageListCtrl); 112 113 memset(&lvitem, 0, sizeof(LVITEM)); 114 115 lvitem.mask = LVIF_PARAM; 116 lvitem.iItem = Index; 117 118 (void)ListView_GetItem(hProcessPageListCtrl, &lvitem); 119 120 if (lvitem.lParam) 121 return ((LPPROCESS_PAGE_LIST_ITEM)lvitem.lParam)->ProcessId; 122 } 123 124 return 0; 125 } 126 127 void ProcessPageUpdate(void) 128 { 129 /* Enable or disable the "End Process" button */ 130 if (ListView_GetSelectedCount(hProcessPageListCtrl)) 131 EnableWindow(hProcessPageEndProcessButton, TRUE); 132 else 133 EnableWindow(hProcessPageEndProcessButton, FALSE); 134 } 135 136 INT_PTR CALLBACK 137 ProcessPageWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 138 { 139 RECT rc; 140 int nXDifference; 141 int nYDifference; 142 int cx, cy; 143 144 switch (message) { 145 case WM_INITDIALOG: 146 /* 147 * Save the width and height 148 */ 149 GetClientRect(hDlg, &rc); 150 nProcessPageWidth = rc.right; 151 nProcessPageHeight = rc.bottom; 152 153 /* Update window position */ 154 SetWindowPos(hDlg, NULL, 15, 30, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 155 156 /* 157 * Get handles to the controls 158 */ 159 hProcessPageListCtrl = GetDlgItem(hDlg, IDC_PROCESSLIST); 160 hProcessPageHeaderCtrl = ListView_GetHeader(hProcessPageListCtrl); 161 hProcessPageEndProcessButton = GetDlgItem(hDlg, IDC_ENDPROCESS); 162 hProcessPageShowAllProcessesButton = GetDlgItem(hDlg, IDC_SHOWALLPROCESSES); 163 164 /* 165 * Set the title, and extended window styles for the list control 166 */ 167 SetWindowTextW(hProcessPageListCtrl, L"Processes"); 168 (void)ListView_SetExtendedListViewStyle(hProcessPageListCtrl, ListView_GetExtendedListViewStyle(hProcessPageListCtrl) | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP); 169 170 AddColumns(); 171 172 /* 173 * Subclass the process list control so we can intercept WM_ERASEBKGND 174 */ 175 OldProcessListWndProc = (WNDPROC)SetWindowLongPtrW(hProcessPageListCtrl, GWLP_WNDPROC, (LONG_PTR)ProcessListWndProc); 176 177 #ifdef RUN_PROC_PAGE 178 /* Start our refresh thread */ 179 hProcessThread = CreateThread(NULL, 0, ProcessPageRefreshThread, NULL, 0, &dwProcessThread); 180 #endif 181 182 /* Refresh page */ 183 ProcessPageUpdate(); 184 185 return TRUE; 186 187 case WM_DESTROY: 188 /* Close the event handle, this will make the */ 189 /* refresh thread exit when the wait fails */ 190 #ifdef RUN_PROC_PAGE 191 EndLocalThread(&hProcessThread, dwProcessThread); 192 #endif 193 SaveColumnSettings(); 194 Cleanup(); 195 break; 196 197 case WM_COMMAND: 198 /* Handle the button clicks */ 199 switch (LOWORD(wParam)) 200 { 201 case IDC_ENDPROCESS: 202 ProcessPage_OnEndProcess(); 203 } 204 break; 205 206 case WM_SIZE: 207 if (wParam == SIZE_MINIMIZED) 208 return 0; 209 210 cx = LOWORD(lParam); 211 cy = HIWORD(lParam); 212 nXDifference = cx - nProcessPageWidth; 213 nYDifference = cy - nProcessPageHeight; 214 nProcessPageWidth = cx; 215 nProcessPageHeight = cy; 216 217 /* Reposition the application page's controls */ 218 GetWindowRect(hProcessPageListCtrl, &rc); 219 cx = (rc.right - rc.left) + nXDifference; 220 cy = (rc.bottom - rc.top) + nYDifference; 221 SetWindowPos(hProcessPageListCtrl, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER); 222 InvalidateRect(hProcessPageListCtrl, NULL, TRUE); 223 224 GetClientRect(hProcessPageEndProcessButton, &rc); 225 MapWindowPoints(hProcessPageEndProcessButton, hDlg, (LPPOINT)(PRECT)(&rc), sizeof(RECT)/sizeof(POINT)); 226 cx = rc.left + nXDifference; 227 cy = rc.top + nYDifference; 228 SetWindowPos(hProcessPageEndProcessButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 229 InvalidateRect(hProcessPageEndProcessButton, NULL, TRUE); 230 231 GetClientRect(hProcessPageShowAllProcessesButton, &rc); 232 MapWindowPoints(hProcessPageShowAllProcessesButton, hDlg, (LPPOINT)(PRECT)(&rc), sizeof(RECT)/sizeof(POINT)); 233 cx = rc.left; 234 cy = rc.top + nYDifference; 235 SetWindowPos(hProcessPageShowAllProcessesButton, NULL, cx, cy, 0, 0, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOSIZE|SWP_NOZORDER); 236 InvalidateRect(hProcessPageShowAllProcessesButton, NULL, TRUE); 237 break; 238 239 case WM_NOTIFY: 240 ProcessPageOnNotify(wParam, lParam); 241 break; 242 243 case WM_KEYDOWN: 244 if (wParam == VK_DELETE) 245 ProcessPage_OnEndProcess(); 246 break; 247 } 248 249 return 0; 250 } 251 252 void ProcessPageOnNotify(WPARAM wParam, LPARAM lParam) 253 { 254 LPNMHDR pnmh; 255 NMLVDISPINFO* pnmdi; 256 LPNMHEADER pnmhdr; 257 ULONG Index; 258 ULONG ColumnIndex; 259 LPPROCESS_PAGE_LIST_ITEM pData; 260 261 pnmh = (LPNMHDR) lParam; 262 pnmdi = (NMLVDISPINFO*) lParam; 263 pnmhdr = (LPNMHEADER) lParam; 264 265 if (pnmh->hwndFrom == hProcessPageListCtrl) 266 { 267 switch (pnmh->code) 268 { 269 case LVN_ITEMCHANGED: 270 ProcessPageUpdate(); 271 break; 272 273 case LVN_GETDISPINFO: 274 275 if (!(pnmdi->item.mask & LVIF_TEXT)) 276 break; 277 278 pData = (LPPROCESS_PAGE_LIST_ITEM)pnmdi->item.lParam; 279 Index = PerfDataGetProcessIndex(pData->ProcessId); 280 ColumnIndex = pnmdi->item.iSubItem; 281 282 PerfDataGetText(Index, ColumnIndex, pnmdi->item.pszText, (ULONG)pnmdi->item.cchTextMax); 283 284 break; 285 286 case NM_RCLICK: 287 288 ProcessPageShowContextMenu(GetSelectedProcessId()); 289 break; 290 291 case LVN_KEYDOWN: 292 293 if (((LPNMLVKEYDOWN)lParam)->wVKey == VK_DELETE) 294 ProcessPage_OnEndProcess(); 295 break; 296 297 } 298 } 299 else if (pnmh->hwndFrom == hProcessPageHeaderCtrl) 300 { 301 switch (pnmh->code) 302 { 303 case HDN_ITEMCLICK: 304 305 TaskManagerSettings.SortColumn = ColumnDataHints[pnmhdr->iItem]; 306 TaskManagerSettings.SortAscending = !TaskManagerSettings.SortAscending; 307 (void)ListView_SortItems(hProcessPageListCtrl, ProcessPageCompareFunc, NULL); 308 309 break; 310 311 case HDN_ITEMCHANGED: 312 313 UpdateColumnDataHints(); 314 315 break; 316 317 case HDN_ENDDRAG: 318 319 UpdateColumnDataHints(); 320 321 break; 322 323 } 324 } 325 } 326 327 void CommaSeparateNumberString(LPWSTR strNumber, ULONG nMaxCount) 328 { 329 WCHAR temp[260]; 330 UINT i, j, k; 331 332 for (i=0,j=0; i<(wcslen(strNumber) % 3); i++, j++) 333 temp[j] = strNumber[i]; 334 for (k=0; i<wcslen(strNumber); i++,j++,k++) { 335 if ((k % 3 == 0) && (j > 0)) 336 temp[j++] = L','; 337 temp[j] = strNumber[i]; 338 } 339 temp[j] = L'\0'; 340 wcsncpy(strNumber, temp, nMaxCount); 341 } 342 343 void ProcessPageShowContextMenu(DWORD dwProcessId) 344 { 345 HMENU hMenu; 346 HMENU hSubMenu; 347 HMENU hPriorityMenu; 348 POINT pt; 349 SYSTEM_INFO si; 350 HANDLE hProcess; 351 DWORD dwProcessPriorityClass; 352 WCHAR strDebugger[260]; 353 DWORD dwDebuggerSize; 354 HKEY hKey; 355 356 memset(&si, 0, sizeof(SYSTEM_INFO)); 357 358 GetCursorPos(&pt); 359 GetSystemInfo(&si); 360 361 hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_PROCESS_PAGE_CONTEXT)); 362 hSubMenu = GetSubMenu(hMenu, 0); 363 hPriorityMenu = GetSubMenu(hSubMenu, 4); 364 365 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId); 366 dwProcessPriorityClass = GetPriorityClass(hProcess); 367 CloseHandle(hProcess); 368 369 if (si.dwNumberOfProcessors < 2) 370 RemoveMenu(hSubMenu, ID_PROCESS_PAGE_SETAFFINITY, MF_BYCOMMAND); 371 372 switch (dwProcessPriorityClass) { 373 case REALTIME_PRIORITY_CLASS: 374 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, MF_BYCOMMAND); 375 break; 376 case HIGH_PRIORITY_CLASS: 377 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_HIGH, MF_BYCOMMAND); 378 break; 379 case ABOVE_NORMAL_PRIORITY_CLASS: 380 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL, MF_BYCOMMAND); 381 break; 382 case NORMAL_PRIORITY_CLASS: 383 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_NORMAL, MF_BYCOMMAND); 384 break; 385 case BELOW_NORMAL_PRIORITY_CLASS: 386 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL, MF_BYCOMMAND); 387 break; 388 case IDLE_PRIORITY_CLASS: 389 CheckMenuRadioItem(hPriorityMenu, ID_PROCESS_PAGE_SETPRIORITY_REALTIME, ID_PROCESS_PAGE_SETPRIORITY_LOW, ID_PROCESS_PAGE_SETPRIORITY_LOW, MF_BYCOMMAND); 390 break; 391 } 392 393 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug", 0, KEY_READ, &hKey) == ERROR_SUCCESS) 394 { 395 dwDebuggerSize = sizeof(strDebugger); 396 if (RegQueryValueExW(hKey, L"Debugger", NULL, NULL, (LPBYTE)strDebugger, &dwDebuggerSize) == ERROR_SUCCESS) 397 { 398 CharUpper(strDebugger); 399 if (wcsstr(strDebugger, L"DRWTSN32")) 400 EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 401 } 402 else 403 EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 404 405 RegCloseKey(hKey); 406 } else { 407 EnableMenuItem(hSubMenu, ID_PROCESS_PAGE_DEBUG, MF_BYCOMMAND|MF_DISABLED|MF_GRAYED); 408 } 409 TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_TOPALIGN|TPM_LEFTBUTTON, pt.x, pt.y, 0, hMainWnd, NULL); 410 DestroyMenu(hMenu); 411 } 412 413 void RefreshProcessPage(void) 414 { 415 #ifdef RUN_PROC_PAGE 416 /* Signal the event so that our refresh thread */ 417 /* will wake up and refresh the process page */ 418 PostThreadMessage(dwProcessThread, WM_TIMER, 0, 0); 419 #endif 420 } 421 422 DWORD WINAPI ProcessPageRefreshThread(void *lpParameter) 423 { 424 MSG msg; 425 426 while (1) { 427 /* Wait for an the event or application close */ 428 if (GetMessage(&msg, NULL, 0, 0) <= 0) 429 return 0; 430 431 if (msg.message == WM_TIMER) { 432 433 UpdateProcesses(); 434 435 if (IsWindowVisible(hProcessPage)) 436 InvalidateRect(hProcessPageListCtrl, NULL, FALSE); 437 438 ProcessPageUpdate(); 439 } 440 } 441 return 0; 442 } 443 444 void UpdateProcesses() 445 { 446 int i; 447 ULONG l; 448 LV_ITEM item; 449 LPPROCESS_PAGE_LIST_ITEM pData; 450 451 SendMessage(hProcessPageListCtrl, WM_SETREDRAW, FALSE, 0); 452 453 /* Remove old processes */ 454 for (i = 0; i < ListView_GetItemCount(hProcessPageListCtrl); i++) 455 { 456 memset(&item, 0, sizeof (LV_ITEM)); 457 item.mask = LVIF_PARAM; 458 item.iItem = i; 459 (void)ListView_GetItem(hProcessPageListCtrl, &item); 460 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 461 if (!ProcessRunning(pData->ProcessId)) 462 { 463 (void)ListView_DeleteItem(hProcessPageListCtrl, i); 464 HeapFree(GetProcessHeap(), 0, pData); 465 } 466 } 467 468 /* Check for difference in listview process and performance process counts */ 469 if (ListView_GetItemCount(hProcessPageListCtrl) != PerfDataGetProcessCount()) 470 { 471 /* Add new processes by checking against the current items */ 472 for (l = 0; l < PerfDataGetProcessCount(); l++) 473 { 474 AddProcess(l); 475 } 476 } 477 478 if (TaskManagerSettings.SortColumn != -1) 479 { 480 (void)ListView_SortItems(hProcessPageListCtrl, ProcessPageCompareFunc, NULL); 481 } 482 483 SendMessage(hProcessPageListCtrl, WM_SETREDRAW, TRUE, 0); 484 485 /* Select first item if any */ 486 if ((ListView_GetNextItem(hProcessPageListCtrl, -1, LVNI_FOCUSED | LVNI_SELECTED) == -1) && 487 (ListView_GetItemCount(hProcessPageListCtrl) > 0) && !bProcessPageSelectionMade) 488 { 489 ListView_SetItemState(hProcessPageListCtrl, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED); 490 bProcessPageSelectionMade = TRUE; 491 } 492 /* 493 else 494 { 495 bProcessPageSelectionMade = FALSE; 496 } 497 */ 498 } 499 500 BOOL ProcessRunning(ULONG ProcessId) 501 { 502 HANDLE hProcess; 503 DWORD exitCode; 504 505 if (ProcessId == 0) { 506 return TRUE; 507 } 508 509 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId); 510 if (hProcess == NULL) { 511 return FALSE; 512 } 513 514 if (GetExitCodeProcess(hProcess, &exitCode)) { 515 CloseHandle(hProcess); 516 return (exitCode == STILL_ACTIVE); 517 } 518 519 CloseHandle(hProcess); 520 return FALSE; 521 } 522 523 void AddProcess(ULONG Index) 524 { 525 LPPROCESS_PAGE_LIST_ITEM pData; 526 int i; 527 LV_ITEM item; 528 BOOL bAlreadyInList = FALSE; 529 ULONG pid; 530 531 pid = PerfDataGetProcessId(Index); 532 533 /* Check to see if it's already in our list */ 534 for (i=0; i<ListView_GetItemCount(hProcessPageListCtrl); i++) 535 { 536 memset(&item, 0, sizeof(LV_ITEM)); 537 item.mask = LVIF_PARAM; 538 item.iItem = i; 539 (void)ListView_GetItem(hProcessPageListCtrl, &item); 540 pData = (LPPROCESS_PAGE_LIST_ITEM)item.lParam; 541 if (pData->ProcessId == pid) 542 { 543 bAlreadyInList = TRUE; 544 break; 545 } 546 } 547 if (!bAlreadyInList) /* Add */ 548 { 549 pData = (LPPROCESS_PAGE_LIST_ITEM)HeapAlloc(GetProcessHeap(), 0, sizeof(PROCESS_PAGE_LIST_ITEM)); 550 pData->ProcessId = pid; 551 552 /* Add the item to the list */ 553 memset(&item, 0, sizeof(LV_ITEM)); 554 item.mask = LVIF_TEXT|LVIF_PARAM; 555 item.pszText = LPSTR_TEXTCALLBACK; 556 item.iItem = ListView_GetItemCount(hProcessPageListCtrl); 557 item.lParam = (LPARAM)pData; 558 (void)ListView_InsertItem(hProcessPageListCtrl, &item); 559 } 560 } 561 562 BOOL PerfDataGetText(ULONG Index, ULONG ColumnIndex, LPTSTR lpText, ULONG nMaxCount) 563 { 564 IO_COUNTERS iocounters; 565 LARGE_INTEGER time; 566 567 if (ColumnDataHints[ColumnIndex] == COLUMN_IMAGENAME) 568 PerfDataGetImageName(Index, lpText, nMaxCount); 569 if (ColumnDataHints[ColumnIndex] == COLUMN_PID) 570 wsprintfW(lpText, L"%lu", PerfDataGetProcessId(Index)); 571 if (ColumnDataHints[ColumnIndex] == COLUMN_USERNAME) 572 PerfDataGetUserName(Index, lpText, nMaxCount); 573 if (ColumnDataHints[ColumnIndex] == COLUMN_COMMANDLINE) 574 PerfDataGetCommandLine(Index, lpText, nMaxCount); 575 if (ColumnDataHints[ColumnIndex] == COLUMN_SESSIONID) 576 wsprintfW(lpText, L"%lu", PerfDataGetSessionId(Index)); 577 if (ColumnDataHints[ColumnIndex] == COLUMN_CPUUSAGE) 578 wsprintfW(lpText, L"%02lu", PerfDataGetCPUUsage(Index)); 579 if (ColumnDataHints[ColumnIndex] == COLUMN_CPUTIME) 580 { 581 DWORD dwHours; 582 DWORD dwMinutes; 583 DWORD dwSeconds; 584 585 time = PerfDataGetCPUTime(Index); 586 gethmsfromlargeint(time, &dwHours, &dwMinutes, &dwSeconds); 587 wsprintfW(lpText, L"%lu:%02lu:%02lu", dwHours, dwMinutes, dwSeconds); 588 } 589 if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGE) 590 { 591 wsprintfW(lpText, L"%lu", PerfDataGetWorkingSetSizeBytes(Index) / 1024); 592 CommaSeparateNumberString(lpText, nMaxCount); 593 wcscat(lpText, L" K"); 594 } 595 if (ColumnDataHints[ColumnIndex] == COLUMN_PEAKMEMORYUSAGE) 596 { 597 wsprintfW(lpText, L"%lu", PerfDataGetPeakWorkingSetSizeBytes(Index) / 1024); 598 CommaSeparateNumberString(lpText, nMaxCount); 599 wcscat(lpText, L" K"); 600 } 601 if (ColumnDataHints[ColumnIndex] == COLUMN_MEMORYUSAGEDELTA) 602 { 603 wsprintfW(lpText, L"%lu", PerfDataGetWorkingSetSizeDelta(Index) / 1024); 604 CommaSeparateNumberString(lpText, nMaxCount); 605 wcscat(lpText, L" K"); 606 } 607 if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTS) 608 { 609 wsprintfW(lpText, L"%lu", PerfDataGetPageFaultCount(Index)); 610 CommaSeparateNumberString(lpText, nMaxCount); 611 } 612 if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEFAULTSDELTA) 613 { 614 wsprintfW(lpText, L"%lu", PerfDataGetPageFaultCountDelta(Index)); 615 CommaSeparateNumberString(lpText, nMaxCount); 616 } 617 if (ColumnDataHints[ColumnIndex] == COLUMN_VIRTUALMEMORYSIZE) 618 { 619 wsprintfW(lpText, L"%lu", PerfDataGetVirtualMemorySizeBytes(Index) / 1024); 620 CommaSeparateNumberString(lpText, nMaxCount); 621 wcscat(lpText, L" K"); 622 } 623 if (ColumnDataHints[ColumnIndex] == COLUMN_PAGEDPOOL) 624 { 625 wsprintfW(lpText, L"%lu", PerfDataGetPagedPoolUsagePages(Index) / 1024); 626 CommaSeparateNumberString(lpText, nMaxCount); 627 wcscat(lpText, L" K"); 628 } 629 if (ColumnDataHints[ColumnIndex] == COLUMN_NONPAGEDPOOL) 630 { 631 wsprintfW(lpText, L"%lu", PerfDataGetNonPagedPoolUsagePages(Index) / 1024); 632 CommaSeparateNumberString(lpText, nMaxCount); 633 wcscat(lpText, L" K"); 634 } 635 if (ColumnDataHints[ColumnIndex] == COLUMN_BASEPRIORITY) 636 wsprintfW(lpText, L"%lu", PerfDataGetBasePriority(Index)); 637 if (ColumnDataHints[ColumnIndex] == COLUMN_HANDLECOUNT) 638 { 639 wsprintfW(lpText, L"%lu", PerfDataGetHandleCount(Index)); 640 CommaSeparateNumberString(lpText, nMaxCount); 641 } 642 if (ColumnDataHints[ColumnIndex] == COLUMN_THREADCOUNT) 643 { 644 wsprintfW(lpText, L"%lu", PerfDataGetThreadCount(Index)); 645 CommaSeparateNumberString(lpText, nMaxCount); 646 } 647 if (ColumnDataHints[ColumnIndex] == COLUMN_USEROBJECTS) 648 { 649 wsprintfW(lpText, L"%lu", PerfDataGetUSERObjectCount(Index)); 650 CommaSeparateNumberString(lpText, nMaxCount); 651 } 652 if (ColumnDataHints[ColumnIndex] == COLUMN_GDIOBJECTS) 653 { 654 wsprintfW(lpText, L"%lu", PerfDataGetGDIObjectCount(Index)); 655 CommaSeparateNumberString(lpText, nMaxCount); 656 } 657 if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADS) 658 { 659 PerfDataGetIOCounters(Index, &iocounters); 660 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.ReadOperationCount); */ 661 _ui64tow(iocounters.ReadOperationCount, lpText, 10); 662 CommaSeparateNumberString(lpText, nMaxCount); 663 } 664 if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITES) 665 { 666 PerfDataGetIOCounters(Index, &iocounters); 667 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.WriteOperationCount); */ 668 _ui64tow(iocounters.WriteOperationCount, lpText, 10); 669 CommaSeparateNumberString(lpText, nMaxCount); 670 } 671 if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHER) 672 { 673 PerfDataGetIOCounters(Index, &iocounters); 674 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.OtherOperationCount); */ 675 _ui64tow(iocounters.OtherOperationCount, lpText, 10); 676 CommaSeparateNumberString(lpText, nMaxCount); 677 } 678 if (ColumnDataHints[ColumnIndex] == COLUMN_IOREADBYTES) 679 { 680 PerfDataGetIOCounters(Index, &iocounters); 681 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.ReadTransferCount); */ 682 _ui64tow(iocounters.ReadTransferCount, lpText, 10); 683 CommaSeparateNumberString(lpText, nMaxCount); 684 } 685 if (ColumnDataHints[ColumnIndex] == COLUMN_IOWRITEBYTES) 686 { 687 PerfDataGetIOCounters(Index, &iocounters); 688 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.WriteTransferCount); */ 689 _ui64tow(iocounters.WriteTransferCount, lpText, 10); 690 CommaSeparateNumberString(lpText, nMaxCount); 691 } 692 if (ColumnDataHints[ColumnIndex] == COLUMN_IOOTHERBYTES) 693 { 694 PerfDataGetIOCounters(Index, &iocounters); 695 /* wsprintfW(pnmdi->item.pszText, L"%d", iocounters.OtherTransferCount); */ 696 _ui64tow(iocounters.OtherTransferCount, lpText, 10); 697 CommaSeparateNumberString(lpText, nMaxCount); 698 } 699 700 return FALSE; 701 } 702 703 704 void gethmsfromlargeint(LARGE_INTEGER largeint, DWORD *dwHours, DWORD *dwMinutes, DWORD *dwSeconds) 705 { 706 #ifdef _MSC_VER 707 *dwHours = (DWORD)(largeint.QuadPart / 36000000000L); 708 *dwMinutes = (DWORD)((largeint.QuadPart % 36000000000L) / 600000000L); 709 *dwSeconds = (DWORD)(((largeint.QuadPart % 36000000000L) % 600000000L) / 10000000L); 710 #else 711 *dwHours = (DWORD)(largeint.QuadPart / 36000000000LL); 712 *dwMinutes = (DWORD)((largeint.QuadPart % 36000000000LL) / 600000000LL); 713 *dwSeconds = (DWORD)(((largeint.QuadPart % 36000000000LL) % 600000000LL) / 10000000LL); 714 #endif 715 } 716 717 int largeintcmp(LARGE_INTEGER l1, LARGE_INTEGER l2) 718 { 719 int ret = 0; 720 DWORD dwHours1; 721 DWORD dwMinutes1; 722 DWORD dwSeconds1; 723 DWORD dwHours2; 724 DWORD dwMinutes2; 725 DWORD dwSeconds2; 726 727 gethmsfromlargeint(l1, &dwHours1, &dwMinutes1, &dwSeconds1); 728 gethmsfromlargeint(l2, &dwHours2, &dwMinutes2, &dwSeconds2); 729 ret = CMP(dwHours1, dwHours2); 730 if (ret == 0) 731 { 732 ret = CMP(dwMinutes1, dwMinutes2); 733 if (ret == 0) 734 { 735 ret = CMP(dwSeconds1, dwSeconds2); 736 } 737 } 738 return ret; 739 } 740 741 int CALLBACK ProcessPageCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 742 { 743 int ret = 0; 744 LPPROCESS_PAGE_LIST_ITEM Param1; 745 LPPROCESS_PAGE_LIST_ITEM Param2; 746 ULONG IndexParam1; 747 ULONG IndexParam2; 748 WCHAR text1[260]; 749 WCHAR text2[260]; 750 ULONG l1; 751 ULONG l2; 752 LARGE_INTEGER time1; 753 LARGE_INTEGER time2; 754 IO_COUNTERS iocounters1; 755 IO_COUNTERS iocounters2; 756 ULONGLONG ull1; 757 ULONGLONG ull2; 758 759 if (TaskManagerSettings.SortAscending) { 760 Param1 = (LPPROCESS_PAGE_LIST_ITEM)lParam1; 761 Param2 = (LPPROCESS_PAGE_LIST_ITEM)lParam2; 762 } else { 763 Param1 = (LPPROCESS_PAGE_LIST_ITEM)lParam2; 764 Param2 = (LPPROCESS_PAGE_LIST_ITEM)lParam1; 765 } 766 IndexParam1 = PerfDataGetProcessIndex(Param1->ProcessId); 767 IndexParam2 = PerfDataGetProcessIndex(Param2->ProcessId); 768 769 if (TaskManagerSettings.SortColumn == COLUMN_IMAGENAME) 770 { 771 PerfDataGetImageName(IndexParam1, text1, sizeof (text1) / sizeof (*text1)); 772 PerfDataGetImageName(IndexParam2, text2, sizeof (text2) / sizeof (*text2)); 773 ret = _wcsicmp(text1, text2); 774 } 775 else if (TaskManagerSettings.SortColumn == COLUMN_PID) 776 { 777 l1 = Param1->ProcessId; 778 l2 = Param2->ProcessId; 779 ret = CMP(l1, l2); 780 } 781 else if (TaskManagerSettings.SortColumn == COLUMN_USERNAME) 782 { 783 PerfDataGetUserName(IndexParam1, text1, sizeof (text1) / sizeof (*text1)); 784 PerfDataGetUserName(IndexParam2, text2, sizeof (text2) / sizeof (*text2)); 785 ret = _wcsicmp(text1, text2); 786 } 787 else if (TaskManagerSettings.SortColumn == COLUMN_COMMANDLINE) 788 { 789 PerfDataGetCommandLine(IndexParam1, text1, sizeof (text1) / sizeof (*text1)); 790 PerfDataGetCommandLine(IndexParam2, text2, sizeof (text2) / sizeof (*text2)); 791 ret = _wcsicmp(text1, text2); 792 } 793 else if (TaskManagerSettings.SortColumn == COLUMN_SESSIONID) 794 { 795 l1 = PerfDataGetSessionId(IndexParam1); 796 l2 = PerfDataGetSessionId(IndexParam2); 797 ret = CMP(l1, l2); 798 } 799 else if (TaskManagerSettings.SortColumn == COLUMN_CPUUSAGE) 800 { 801 l1 = PerfDataGetCPUUsage(IndexParam1); 802 l2 = PerfDataGetCPUUsage(IndexParam2); 803 ret = CMP(l1, l2); 804 } 805 else if (TaskManagerSettings.SortColumn == COLUMN_CPUTIME) 806 { 807 time1 = PerfDataGetCPUTime(IndexParam1); 808 time2 = PerfDataGetCPUTime(IndexParam2); 809 ret = largeintcmp(time1, time2); 810 } 811 else if (TaskManagerSettings.SortColumn == COLUMN_MEMORYUSAGE) 812 { 813 l1 = PerfDataGetWorkingSetSizeBytes(IndexParam1); 814 l2 = PerfDataGetWorkingSetSizeBytes(IndexParam2); 815 ret = CMP(l1, l2); 816 } 817 else if (TaskManagerSettings.SortColumn == COLUMN_PEAKMEMORYUSAGE) 818 { 819 l1 = PerfDataGetPeakWorkingSetSizeBytes(IndexParam1); 820 l2 = PerfDataGetPeakWorkingSetSizeBytes(IndexParam2); 821 ret = CMP(l1, l2); 822 } 823 else if (TaskManagerSettings.SortColumn == COLUMN_MEMORYUSAGEDELTA) 824 { 825 l1 = PerfDataGetWorkingSetSizeDelta(IndexParam1); 826 l2 = PerfDataGetWorkingSetSizeDelta(IndexParam2); 827 ret = CMP(l1, l2); 828 } 829 else if (TaskManagerSettings.SortColumn == COLUMN_PAGEFAULTS) 830 { 831 l1 = PerfDataGetPageFaultCount(IndexParam1); 832 l2 = PerfDataGetPageFaultCount(IndexParam2); 833 ret = CMP(l1, l2); 834 } 835 else if (TaskManagerSettings.SortColumn == COLUMN_PAGEFAULTSDELTA) 836 { 837 l1 = PerfDataGetPageFaultCountDelta(IndexParam1); 838 l2 = PerfDataGetPageFaultCountDelta(IndexParam2); 839 ret = CMP(l1, l2); 840 } 841 else if (TaskManagerSettings.SortColumn == COLUMN_VIRTUALMEMORYSIZE) 842 { 843 l1 = PerfDataGetVirtualMemorySizeBytes(IndexParam1); 844 l2 = PerfDataGetVirtualMemorySizeBytes(IndexParam2); 845 ret = CMP(l1, l2); 846 } 847 else if (TaskManagerSettings.SortColumn == COLUMN_PAGEDPOOL) 848 { 849 l1 = PerfDataGetPagedPoolUsagePages(IndexParam1); 850 l2 = PerfDataGetPagedPoolUsagePages(IndexParam2); 851 ret = CMP(l1, l2); 852 } 853 else if (TaskManagerSettings.SortColumn == COLUMN_NONPAGEDPOOL) 854 { 855 l1 = PerfDataGetNonPagedPoolUsagePages(IndexParam1); 856 l2 = PerfDataGetNonPagedPoolUsagePages(IndexParam2); 857 ret = CMP(l1, l2); 858 } 859 else if (TaskManagerSettings.SortColumn == COLUMN_BASEPRIORITY) 860 { 861 l1 = PerfDataGetBasePriority(IndexParam1); 862 l2 = PerfDataGetBasePriority(IndexParam2); 863 ret = CMP(l1, l2); 864 } 865 else if (TaskManagerSettings.SortColumn == COLUMN_HANDLECOUNT) 866 { 867 l1 = PerfDataGetHandleCount(IndexParam1); 868 l2 = PerfDataGetHandleCount(IndexParam2); 869 ret = CMP(l1, l2); 870 } 871 else if (TaskManagerSettings.SortColumn == COLUMN_THREADCOUNT) 872 { 873 l1 = PerfDataGetThreadCount(IndexParam1); 874 l2 = PerfDataGetThreadCount(IndexParam2); 875 ret = CMP(l1, l2); 876 } 877 else if (TaskManagerSettings.SortColumn == COLUMN_USEROBJECTS) 878 { 879 l1 = PerfDataGetUSERObjectCount(IndexParam1); 880 l2 = PerfDataGetUSERObjectCount(IndexParam2); 881 ret = CMP(l1, l2); 882 } 883 else if (TaskManagerSettings.SortColumn == COLUMN_GDIOBJECTS) 884 { 885 l1 = PerfDataGetGDIObjectCount(IndexParam1); 886 l2 = PerfDataGetGDIObjectCount(IndexParam2); 887 ret = CMP(l1, l2); 888 } 889 else if (TaskManagerSettings.SortColumn == COLUMN_IOREADS) 890 { 891 PerfDataGetIOCounters(IndexParam1, &iocounters1); 892 PerfDataGetIOCounters(IndexParam2, &iocounters2); 893 ull1 = iocounters1.ReadOperationCount; 894 ull2 = iocounters2.ReadOperationCount; 895 ret = CMP(ull1, ull2); 896 } 897 else if (TaskManagerSettings.SortColumn == COLUMN_IOWRITES) 898 { 899 PerfDataGetIOCounters(IndexParam1, &iocounters1); 900 PerfDataGetIOCounters(IndexParam2, &iocounters2); 901 ull1 = iocounters1.WriteOperationCount; 902 ull2 = iocounters2.WriteOperationCount; 903 ret = CMP(ull1, ull2); 904 } 905 else if (TaskManagerSettings.SortColumn == COLUMN_IOOTHER) 906 { 907 PerfDataGetIOCounters(IndexParam1, &iocounters1); 908 PerfDataGetIOCounters(IndexParam2, &iocounters2); 909 ull1 = iocounters1.OtherOperationCount; 910 ull2 = iocounters2.OtherOperationCount; 911 ret = CMP(ull1, ull2); 912 } 913 else if (TaskManagerSettings.SortColumn == COLUMN_IOREADBYTES) 914 { 915 PerfDataGetIOCounters(IndexParam1, &iocounters1); 916 PerfDataGetIOCounters(IndexParam2, &iocounters2); 917 ull1 = iocounters1.ReadTransferCount; 918 ull2 = iocounters2.ReadTransferCount; 919 ret = CMP(ull1, ull2); 920 } 921 else if (TaskManagerSettings.SortColumn == COLUMN_IOWRITEBYTES) 922 { 923 PerfDataGetIOCounters(IndexParam1, &iocounters1); 924 PerfDataGetIOCounters(IndexParam2, &iocounters2); 925 ull1 = iocounters1.WriteTransferCount; 926 ull2 = iocounters2.WriteTransferCount; 927 ret = CMP(ull1, ull2); 928 } 929 else if (TaskManagerSettings.SortColumn == COLUMN_IOOTHERBYTES) 930 { 931 PerfDataGetIOCounters(IndexParam1, &iocounters1); 932 PerfDataGetIOCounters(IndexParam2, &iocounters2); 933 ull1 = iocounters1.OtherTransferCount; 934 ull2 = iocounters2.OtherTransferCount; 935 ret = CMP(ull1, ull2); 936 } 937 return ret; 938 } 939 940 static BOOL DevicePathToDosPath(LPWSTR lpPath, DWORD dwSize) 941 { 942 WCHAR cDrive; 943 944 /* Check if lpPath is a device path */ 945 if (_wcsnicmp(lpPath, L"\\Device\\", 8) != 0) 946 { 947 return FALSE; 948 } 949 950 for (cDrive = L'A'; cDrive <= L'Z'; cDrive++) 951 { 952 WCHAR szDrive[3]; 953 WCHAR szDevPath[MAX_PATH]; 954 955 szDrive[0] = cDrive; 956 szDrive[1] = L':'; 957 szDrive[2] = UNICODE_NULL; 958 959 if (QueryDosDeviceW(szDrive, szDevPath, _countof(szDevPath)) != 0) 960 { 961 size_t len = wcslen(szDevPath); 962 963 if (_wcsnicmp(lpPath, szDevPath, len) == 0) 964 { 965 StringCbPrintfW(lpPath, dwSize, L"%s%s", szDrive, lpPath + len); 966 967 return TRUE; 968 } 969 } 970 } 971 972 return FALSE; 973 } 974 975 static DWORD GetProcessExecutablePath(HANDLE hProcess, LPWSTR lpExePath, DWORD dwLength) 976 { 977 BYTE StaticBuffer[sizeof(UNICODE_STRING) + (MAX_PATH * sizeof(WCHAR))]; 978 PVOID DynamicBuffer = NULL; 979 PUNICODE_STRING ImagePath = NULL; 980 LPWSTR pszExePath = NULL; 981 ULONG SizeNeeded; 982 NTSTATUS Status; 983 DWORD dwRet = 0; 984 985 Status = NtQueryInformationProcess(hProcess, 986 ProcessImageFileName, 987 StaticBuffer, 988 sizeof(StaticBuffer) - sizeof(WCHAR), 989 &SizeNeeded); 990 991 if (Status == STATUS_INFO_LENGTH_MISMATCH) 992 { 993 DynamicBuffer = HeapAlloc(GetProcessHeap(), 0, SizeNeeded + sizeof(WCHAR)); 994 995 if (!DynamicBuffer) 996 { 997 return 0; 998 } 999 1000 Status = NtQueryInformationProcess(hProcess, 1001 ProcessImageFileName, 1002 DynamicBuffer, 1003 SizeNeeded, 1004 &SizeNeeded); 1005 1006 ImagePath = (PUNICODE_STRING)DynamicBuffer; 1007 } 1008 else 1009 { 1010 ImagePath = (PUNICODE_STRING)StaticBuffer; 1011 } 1012 1013 if (!NT_SUCCESS(Status)) 1014 { 1015 goto Cleanup; 1016 } 1017 1018 pszExePath = HeapAlloc(GetProcessHeap(), 0, ImagePath->Length + sizeof(WCHAR)); 1019 1020 if (!pszExePath) 1021 { 1022 goto Cleanup; 1023 } 1024 1025 StringCbCopyNW(pszExePath, ImagePath->Length + sizeof(WCHAR), ImagePath->Buffer, ImagePath->Length); 1026 1027 if (!DevicePathToDosPath(pszExePath, ImagePath->Length + sizeof(WCHAR))) 1028 { 1029 goto Cleanup; 1030 } 1031 1032 dwRet = wcslen(pszExePath) + 1; 1033 1034 if (dwLength >= dwRet) 1035 { 1036 StringCchCopyW(lpExePath, dwLength, pszExePath); 1037 1038 dwRet -= 1; 1039 } 1040 1041 Cleanup: 1042 1043 if (pszExePath) 1044 { 1045 HeapFree(GetProcessHeap(), 0, pszExePath); 1046 } 1047 1048 if (DynamicBuffer) 1049 { 1050 HeapFree(GetProcessHeap(), 0, DynamicBuffer); 1051 } 1052 1053 return dwRet; 1054 } 1055 1056 static DWORD GetProcessExecutablePathById(DWORD dwProcessId, LPWSTR lpExePath, DWORD dwLength) 1057 { 1058 DWORD dwRet = 0; 1059 1060 if (dwProcessId == 0) 1061 { 1062 return 0; 1063 } 1064 1065 /* PID = 4 or "System" */ 1066 if (dwProcessId == 4) 1067 { 1068 static const WCHAR szKernelExe[] = L"\\ntoskrnl.exe"; 1069 WCHAR szSystemDir[MAX_PATH]; 1070 UINT uLength; 1071 1072 uLength = GetSystemDirectoryW(szSystemDir, _countof(szSystemDir)); 1073 1074 if (uLength != 0) 1075 { 1076 dwRet = uLength + _countof(szKernelExe); 1077 1078 if (dwLength >= dwRet) 1079 { 1080 StringCchPrintfW(lpExePath, dwLength, L"%s%s", szSystemDir, szKernelExe); 1081 1082 dwRet -= 1; 1083 } 1084 } 1085 } 1086 else 1087 { 1088 HANDLE hProcess; 1089 1090 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId); 1091 1092 if (hProcess) 1093 { 1094 dwRet = GetProcessExecutablePath(hProcess, lpExePath, dwLength); 1095 1096 CloseHandle(hProcess); 1097 } 1098 } 1099 1100 return dwRet; 1101 } 1102 1103 void ProcessPage_OnProperties(void) 1104 { 1105 DWORD dwProcessId; 1106 WCHAR szPath[MAX_PATH]; 1107 LPWSTR pszPath = NULL; 1108 LPWSTR pszExePath = NULL; 1109 DWORD dwLength; 1110 SHELLEXECUTEINFOW info = { 0 }; 1111 1112 dwProcessId = GetSelectedProcessId(); 1113 dwLength = GetProcessExecutablePathById(dwProcessId, szPath, _countof(szPath)); 1114 1115 if (dwLength == 0) 1116 { 1117 return; 1118 } 1119 else if (dwLength > _countof(szPath)) 1120 { 1121 pszPath = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR)); 1122 1123 if (!pszPath) 1124 { 1125 return; 1126 } 1127 1128 if (GetProcessExecutablePathById(dwProcessId, pszPath, dwLength) == 0) 1129 { 1130 goto Cleanup; 1131 } 1132 1133 pszExePath = pszPath; 1134 } 1135 else 1136 { 1137 pszExePath = szPath; 1138 } 1139 1140 info.cbSize = sizeof(SHELLEXECUTEINFOW); 1141 info.fMask = SEE_MASK_INVOKEIDLIST; 1142 info.hwnd = NULL; 1143 info.lpVerb = L"properties"; 1144 info.lpFile = pszExePath; 1145 info.lpParameters = L""; 1146 info.lpDirectory = NULL; 1147 info.nShow = SW_SHOW; 1148 info.hInstApp = NULL; 1149 1150 ShellExecuteExW(&info); 1151 1152 Cleanup: 1153 1154 if (pszPath) 1155 { 1156 HeapFree(GetProcessHeap(), 0, pszPath); 1157 } 1158 } 1159 1160 void ProcessPage_OnOpenFileLocation(void) 1161 { 1162 DWORD dwProcessId; 1163 WCHAR szPath[MAX_PATH]; 1164 LPWSTR pszPath = NULL; 1165 LPWSTR pszExePath = NULL; 1166 LPWSTR pszCmdLine = NULL; 1167 DWORD dwLength; 1168 1169 dwProcessId = GetSelectedProcessId(); 1170 dwLength = GetProcessExecutablePathById(dwProcessId, szPath, _countof(szPath)); 1171 1172 if (dwLength == 0) 1173 { 1174 return; 1175 } 1176 else if (dwLength > _countof(szPath)) 1177 { 1178 pszPath = HeapAlloc(GetProcessHeap(), 0, dwLength * sizeof(WCHAR)); 1179 1180 if (!pszPath) 1181 { 1182 return; 1183 } 1184 1185 if (GetProcessExecutablePathById(dwProcessId, pszPath, dwLength) == 0) 1186 { 1187 goto Cleanup; 1188 } 1189 1190 pszExePath = pszPath; 1191 } 1192 else 1193 { 1194 pszExePath = szPath; 1195 dwLength += 1; 1196 } 1197 1198 pszCmdLine = HeapAlloc(GetProcessHeap(), 0, (dwLength + 10) * sizeof(WCHAR)); 1199 1200 if (!pszCmdLine) 1201 { 1202 goto Cleanup; 1203 } 1204 1205 StringCchPrintfW(pszCmdLine, dwLength + 10, L"/select,\"%s\"", pszExePath); 1206 1207 /* Open file explorer and select the exe file */ 1208 ShellExecuteW(NULL, L"open", L"explorer.exe", pszCmdLine, NULL, SW_SHOWNORMAL); 1209 1210 HeapFree(GetProcessHeap(), 0, pszCmdLine); 1211 1212 Cleanup: 1213 1214 if (pszPath) 1215 { 1216 HeapFree(GetProcessHeap(), 0, pszPath); 1217 } 1218 } 1219