xref: /reactos/base/applications/taskmgr/taskmgr.c (revision 5d1be078)
1 /*
2  * PROJECT:     ReactOS Task Manager
3  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4  * PURPOSE:     Application Entry-point
5  * COPYRIGHT:   Copyright 1999-2001 Brian Palmer <brianp@reactos.org>
6  *              Copyright 2005 Klemens Friedl <frik85@reactos.at>
7  */
8 
9 #include "precomp.h"
10 
11 #include "perfpage.h"
12 #include "about.h"
13 #include "affinity.h"
14 #include "debug.h"
15 #include "priority.h"
16 
17 #define STATUS_WINDOW   2001
18 
19 /* Global Variables: */
20 HINSTANCE hInst;                 /* current instance */
21 
22 HWND hMainWnd;                   /* Main Window */
23 HWND hStatusWnd;                 /* Status Bar Window */
24 HWND hTabWnd;                    /* Tab Control Window */
25 
26 HMENU hWindowMenu = NULL;
27 
28 int  nMinimumWidth;              /* Minimum width of the dialog (OnSize()'s cx) */
29 int  nMinimumHeight;             /* Minimum height of the dialog (OnSize()'s cy) */
30 
31 int  nOldWidth;                  /* Holds the previous client area width */
32 int  nOldHeight;                 /* Holds the previous client area height */
33 
34 BOOL bTrackMenu = FALSE;         /* Signals when we display menu hints */
35 BOOL bWasKeyboardInput = FALSE;  /* TabChange by Keyboard or Mouse ? */
36 
37 TASKMANAGER_SETTINGS TaskManagerSettings;
38 
39 ////////////////////////////////////////////////////////////////////////////////
40 // Taken from WinSpy++ 1.7
41 // http://www.catch22.net/software/winspy
42 // Copyright (c) 2002 by J Brown
43 //
44 
45 //
46 //	Copied from uxtheme.h
47 //  If you have this new header, then delete these and
48 //  #include <uxtheme.h> instead!
49 //
50 #define ETDT_DISABLE        0x00000001
51 #define ETDT_ENABLE         0x00000002
52 #define ETDT_USETABTEXTURE  0x00000004
53 #define ETDT_ENABLETAB      (ETDT_ENABLE  | ETDT_USETABTEXTURE)
54 
55 //
56 typedef HRESULT (WINAPI * ETDTProc) (HWND, DWORD);
57 
58 //
59 //	Try to call EnableThemeDialogTexture, if uxtheme.dll is present
60 //
EnableDialogTheme(HWND hwnd)61 BOOL EnableDialogTheme(HWND hwnd)
62 {
63     HMODULE hUXTheme;
64     ETDTProc fnEnableThemeDialogTexture;
65 
66     hUXTheme = LoadLibraryA("uxtheme.dll");
67 
68     if(hUXTheme)
69     {
70         fnEnableThemeDialogTexture =
71             (ETDTProc)GetProcAddress(hUXTheme, "EnableThemeDialogTexture");
72 
73         if(fnEnableThemeDialogTexture)
74         {
75             fnEnableThemeDialogTexture(hwnd, ETDT_ENABLETAB);
76 
77             FreeLibrary(hUXTheme);
78             return TRUE;
79         }
80         else
81         {
82             // Failed to locate API!
83             FreeLibrary(hUXTheme);
84             return FALSE;
85         }
86     }
87     else
88     {
89         // Not running under XP? Just fail gracefully
90         return FALSE;
91     }
92 }
93 
wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR lpCmdLine,int nCmdShow)94 int APIENTRY wWinMain(HINSTANCE hInstance,
95                       HINSTANCE hPrevInstance,
96                       LPWSTR    lpCmdLine,
97                       int       nCmdShow)
98 {
99     HANDLE hProcess;
100     HANDLE hToken;
101     TOKEN_PRIVILEGES tkp;
102     HANDLE hMutex;
103 
104     /* check wether we're already running or not */
105     hMutex = CreateMutexW(NULL, TRUE, L"taskmgrros");
106     if (hMutex && GetLastError() == ERROR_ALREADY_EXISTS)
107     {
108         /* Restore existing taskmanager and bring window to front */
109         /* Relies on the fact that the application title string and window title are the same */
110         HWND hTaskMgr;
111         TCHAR szTaskmgr[128];
112 
113         LoadString(hInst, IDS_APP_TITLE, szTaskmgr, _countof(szTaskmgr));
114         hTaskMgr = FindWindow(NULL, szTaskmgr);
115 
116         if (hTaskMgr != NULL)
117         {
118             SendMessage(hTaskMgr, WM_SYSCOMMAND, SC_RESTORE, 0);
119             SetForegroundWindow(hTaskMgr);
120         }
121 
122         CloseHandle(hMutex);
123         return 0;
124     }
125     else if (!hMutex)
126     {
127         return 1;
128     }
129 
130     /* Initialize global variables */
131     hInst = hInstance;
132 
133     /* Change our priority class to HIGH */
134     hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
135     SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);
136     CloseHandle(hProcess);
137 
138     /* Now lets get the SE_DEBUG_NAME privilege
139      * so that we can debug processes
140      */
141 
142     /* Get a token for this process. */
143     if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
144     {
145         /* Get the LUID for the debug privilege. */
146         if (LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid))
147         {
148             tkp.PrivilegeCount = 1;  /* one privilege to set */
149             tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
150 
151             /* Get the debug privilege for this process. */
152             AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
153         }
154         CloseHandle(hToken);
155     }
156 
157     /* Load our settings from the registry */
158     LoadSettings();
159 
160     /* Initialize perf data */
161     if (!PerfDataInitialize())
162         return -1;
163 
164     /*
165      * Set our shutdown parameters: we want to shutdown the very last,
166      * without displaying any end task dialog if needed.
167      */
168     SetProcessShutdownParameters(1, SHUTDOWN_NORETRY);
169 
170     DialogBoxW(hInst, (LPCWSTR)IDD_TASKMGR_DIALOG, NULL, TaskManagerWndProc);
171 
172     /* Save our settings to the registry */
173     SaveSettings();
174     PerfDataUninitialize();
175     CloseHandle(hMutex);
176     if (hWindowMenu)
177         DestroyMenu(hWindowMenu);
178     return 0;
179 }
180 
181 /* Message handler for dialog box. */
182 INT_PTR CALLBACK
TaskManagerWndProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)183 TaskManagerWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
184 {
185 #if 0
186     HDC              hdc;
187     PAINTSTRUCT      ps;
188     RECT             rc;
189 #endif
190     LPRECT           pRC;
191     LPNMHDR          pnmh;
192     WINDOWPLACEMENT  wp;
193 
194     switch (message) {
195     case WM_INITDIALOG:
196         // For now, the Help dialog menu item is disabled because of lacking of HTML Help support
197         EnableMenuItem(GetMenu(hDlg), ID_HELP_TOPICS, MF_BYCOMMAND | MF_GRAYED);
198         hMainWnd = hDlg;
199         return OnCreate(hDlg);
200 
201     case WM_COMMAND:
202         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
203             EndDialog(hDlg, LOWORD(wParam));
204             return TRUE;
205         }
206         /* Process menu commands */
207         switch (LOWORD(wParam))
208         {
209         case ID_FILE_NEW:
210             TaskManager_OnFileNew();
211             break;
212         case ID_OPTIONS_ALWAYSONTOP:
213             TaskManager_OnOptionsAlwaysOnTop();
214             break;
215         case ID_OPTIONS_MINIMIZEONUSE:
216             TaskManager_OnOptionsMinimizeOnUse();
217             break;
218         case ID_OPTIONS_HIDEWHENMINIMIZED:
219             TaskManager_OnOptionsHideWhenMinimized();
220             break;
221         case ID_OPTIONS_SHOW16BITTASKS:
222             TaskManager_OnOptionsShow16BitTasks();
223             break;
224         case ID_RESTORE:
225             TaskManager_OnRestoreMainWindow();
226             break;
227         case ID_VIEW_LARGE:
228         case ID_VIEW_SMALL:
229         case ID_VIEW_DETAILS:
230             ApplicationPage_OnView(LOWORD(wParam));
231             break;
232         case ID_VIEW_SHOWKERNELTIMES:
233             PerformancePage_OnViewShowKernelTimes();
234             break;
235         case ID_VIEW_CPUHISTORY_ONEGRAPHALL:
236             PerformancePage_OnViewCPUHistoryOneGraphAll();
237             break;
238         case ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU:
239             PerformancePage_OnViewCPUHistoryOneGraphPerCPU();
240             break;
241         case ID_VIEW_UPDATESPEED_HIGH:
242         case ID_VIEW_UPDATESPEED_NORMAL:
243         case ID_VIEW_UPDATESPEED_LOW:
244         case ID_VIEW_UPDATESPEED_PAUSED:
245             TaskManager_OnViewUpdateSpeed(LOWORD(wParam));
246             break;
247         case ID_VIEW_SELECTCOLUMNS:
248             ProcessPage_OnViewSelectColumns();
249             break;
250         case ID_VIEW_REFRESH:
251             PostMessageW(hDlg, WM_TIMER, 0, 0);
252             break;
253         case ID_WINDOWS_TILEHORIZONTALLY:
254             ApplicationPage_OnWindowsTile(MDITILE_HORIZONTAL);
255             break;
256         case ID_WINDOWS_TILEVERTICALLY:
257             ApplicationPage_OnWindowsTile(MDITILE_VERTICAL);
258             break;
259         case ID_WINDOWS_MINIMIZE:
260             ApplicationPage_OnWindowsMinimize();
261             break;
262         case ID_WINDOWS_MAXIMIZE:
263             ApplicationPage_OnWindowsMaximize();
264             break;
265         case ID_WINDOWS_CASCADE:
266             ApplicationPage_OnWindowsCascade();
267             break;
268         case ID_WINDOWS_BRINGTOFRONT:
269             ApplicationPage_OnWindowsBringToFront();
270             break;
271         case ID_APPLICATION_PAGE_SWITCHTO:
272             ApplicationPage_OnSwitchTo();
273             break;
274         case ID_APPLICATION_PAGE_ENDTASK:
275             ApplicationPage_OnEndTask();
276             break;
277         case ID_APPLICATION_PAGE_GOTOPROCESS:
278             ApplicationPage_OnGotoProcess();
279             break;
280         case ID_PROCESS_PAGE_ENDPROCESS:
281             ProcessPage_OnEndProcess();
282             break;
283         case ID_PROCESS_PAGE_ENDPROCESSTREE:
284             ProcessPage_OnEndProcessTree();
285             break;
286         case ID_PROCESS_PAGE_DEBUG:
287             ProcessPage_OnDebug();
288             break;
289         case ID_PROCESS_PAGE_SETAFFINITY:
290             ProcessPage_OnSetAffinity();
291             break;
292         case ID_PROCESS_PAGE_SETPRIORITY_REALTIME:
293             DoSetPriority(REALTIME_PRIORITY_CLASS);
294             break;
295         case ID_PROCESS_PAGE_SETPRIORITY_HIGH:
296             DoSetPriority(HIGH_PRIORITY_CLASS);
297             break;
298         case ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL:
299             DoSetPriority(ABOVE_NORMAL_PRIORITY_CLASS);
300             break;
301         case ID_PROCESS_PAGE_SETPRIORITY_NORMAL:
302             DoSetPriority(NORMAL_PRIORITY_CLASS);
303             break;
304         case ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL:
305             DoSetPriority(BELOW_NORMAL_PRIORITY_CLASS);
306             break;
307         case ID_PROCESS_PAGE_SETPRIORITY_LOW:
308             DoSetPriority(IDLE_PRIORITY_CLASS);
309             break;
310         case ID_PROCESS_PAGE_PROPERTIES:
311             ProcessPage_OnProperties();
312             break;
313         case ID_PROCESS_PAGE_OPENFILELOCATION:
314             ProcessPage_OnOpenFileLocation();
315             break;
316 
317 /* ShutDown items */
318         case ID_SHUTDOWN_STANDBY:
319             ShutDown_StandBy();
320             break;
321         case ID_SHUTDOWN_HIBERNATE:
322             ShutDown_Hibernate();
323             break;
324         case ID_SHUTDOWN_POWEROFF:
325             ShutDown_PowerOff();
326             break;
327         case ID_SHUTDOWN_REBOOT:
328             ShutDown_Reboot();
329             break;
330         case ID_SHUTDOWN_LOGOFF:
331             ShutDown_LogOffUser();
332             break;
333         case ID_SHUTDOWN_SWITCHUSER:
334             ShutDown_SwitchUser();
335             break;
336         case ID_SHUTDOWN_LOCKCOMPUTER:
337             ShutDown_LockComputer();
338             break;
339         case ID_SHUTDOWN_DISCONNECT:
340             ShutDown_Disconnect();
341             break;
342         case ID_SHUTDOWN_EJECT_COMPUTER:
343             ShutDown_EjectComputer();
344             break;
345 
346         case ID_HELP_ABOUT:
347             OnAbout();
348             break;
349         case ID_FILE_EXIT:
350             EndDialog(hDlg, IDOK);
351             break;
352         }
353         break;
354 
355     case WM_ONTRAYICON:
356         switch(lParam)
357         {
358         case WM_RBUTTONDOWN:
359             {
360             POINT pt;
361             BOOL OnTop;
362             HMENU hMenu, hPopupMenu;
363 
364             GetCursorPos(&pt);
365 
366             OnTop = ((GetWindowLongPtrW(hMainWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0);
367 
368             hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_TRAY_POPUP));
369             hPopupMenu = GetSubMenu(hMenu, 0);
370 
371             if(IsWindowVisible(hMainWnd))
372                 DeleteMenu(hPopupMenu, ID_RESTORE, MF_BYCOMMAND);
373             else
374                 SetMenuDefaultItem(hPopupMenu, ID_RESTORE, FALSE);
375 
376             if(OnTop)
377                 CheckMenuItem(hPopupMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND | MF_CHECKED);
378             else
379                 CheckMenuItem(hPopupMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND | MF_UNCHECKED);
380 
381             SetForegroundWindow(hMainWnd);
382             TrackPopupMenuEx(hPopupMenu, 0, pt.x, pt.y, hMainWnd, NULL);
383 
384             DestroyMenu(hMenu);
385             break;
386             }
387         case WM_LBUTTONDBLCLK:
388             TaskManager_OnRestoreMainWindow();
389             break;
390         }
391         break;
392 
393     case WM_NOTIFY:
394         pnmh = (LPNMHDR)lParam;
395         if ((pnmh->hwndFrom == hTabWnd) &&
396             (pnmh->idFrom == IDC_TAB))
397         {
398             switch (pnmh->code)
399             {
400                 case TCN_SELCHANGE:
401                     TaskManager_OnTabWndSelChange();
402                     break;
403                 case TCN_KEYDOWN:
404                     bWasKeyboardInput = TRUE;
405                     break;
406                 case NM_CLICK:
407                     bWasKeyboardInput = FALSE;
408                 break;
409             }
410         }
411         break;
412 
413     case WM_SIZING:
414         /* Make sure the user is sizing the dialog */
415         /* in an acceptable range */
416         pRC = (LPRECT)lParam;
417         if ((wParam == WMSZ_LEFT) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_BOTTOMLEFT)) {
418             /* If the width is too small enlarge it to the minimum */
419             if (nMinimumWidth > (pRC->right - pRC->left))
420                 pRC->left = pRC->right - nMinimumWidth;
421         } else {
422             /* If the width is too small enlarge it to the minimum */
423             if (nMinimumWidth > (pRC->right - pRC->left))
424                 pRC->right = pRC->left + nMinimumWidth;
425         }
426         if ((wParam == WMSZ_TOP) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_TOPRIGHT)) {
427             /* If the height is too small enlarge it to the minimum */
428             if (nMinimumHeight > (pRC->bottom - pRC->top))
429                 pRC->top = pRC->bottom - nMinimumHeight;
430         } else {
431             /* If the height is too small enlarge it to the minimum */
432             if (nMinimumHeight > (pRC->bottom - pRC->top))
433                 pRC->bottom = pRC->top + nMinimumHeight;
434         }
435         return TRUE;
436         break;
437 
438     case WM_SIZE:
439         /* Handle the window sizing in it's own function */
440         OnSize(wParam, LOWORD(lParam), HIWORD(lParam));
441         break;
442 
443     case WM_MOVE:
444         /* Handle the window moving in it's own function */
445         OnMove(wParam, LOWORD(lParam), HIWORD(lParam));
446         break;
447 
448     case WM_DESTROY:
449         ShowWindow(hDlg, SW_HIDE);
450         TrayIcon_RemoveIcon();
451         wp.length = sizeof(WINDOWPLACEMENT);
452         GetWindowPlacement(hDlg, &wp);
453         TaskManagerSettings.Left = wp.rcNormalPosition.left;
454         TaskManagerSettings.Top = wp.rcNormalPosition.top;
455         TaskManagerSettings.Right = wp.rcNormalPosition.right;
456         TaskManagerSettings.Bottom = wp.rcNormalPosition.bottom;
457         if (IsZoomed(hDlg) || (wp.flags & WPF_RESTORETOMAXIMIZED))
458             TaskManagerSettings.Maximized = TRUE;
459         else
460             TaskManagerSettings.Maximized = FALSE;
461         /* Get rid of the allocated command line cache, if any */
462         PerfDataDeallocCommandLineCache();
463         if (hWindowMenu)
464             DestroyMenu(hWindowMenu);
465         return DefWindowProcW(hDlg, message, wParam, lParam);
466 
467     case WM_TIMER:
468         /* Refresh the performance data */
469         PerfDataRefresh();
470         RefreshApplicationPage();
471         RefreshProcessPage();
472         RefreshPerformancePage();
473         TrayIcon_UpdateIcon();
474         break;
475 
476     case WM_MENUSELECT:
477         TaskManager_OnMenuSelect(hDlg, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
478         break;
479 
480     case WM_SYSCOLORCHANGE:
481         /* Forward WM_SYSCOLORCHANGE to common controls */
482         SendMessage(hApplicationPageListCtrl, WM_SYSCOLORCHANGE, 0, 0);
483         SendMessage(hProcessPageListCtrl, WM_SYSCOLORCHANGE, 0, 0);
484         SendMessage(hProcessPageHeaderCtrl, WM_SYSCOLORCHANGE, 0, 0);
485         break;
486     }
487 
488     return 0;
489 }
490 
FillSolidRect(HDC hDC,LPCRECT lpRect,COLORREF clr)491 void FillSolidRect(HDC hDC, LPCRECT lpRect, COLORREF clr)
492 {
493     SetBkColor(hDC, clr);
494     ExtTextOutW(hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
495 }
496 
SetUpdateSpeed(HWND hWnd)497 static void SetUpdateSpeed(HWND hWnd)
498 {
499     /* Setup update speed (pause=fall down) */
500     switch (TaskManagerSettings.UpdateSpeed) {
501     case ID_VIEW_UPDATESPEED_HIGH:
502         SetTimer(hWnd, 1, 500, NULL);
503         break;
504     case ID_VIEW_UPDATESPEED_NORMAL:
505         SetTimer(hWnd, 1, 2000, NULL);
506         break;
507     case ID_VIEW_UPDATESPEED_LOW:
508         SetTimer(hWnd, 1, 4000, NULL);
509         break;
510     }
511 }
512 
OnCreate(HWND hWnd)513 BOOL OnCreate(HWND hWnd)
514 {
515     HMENU   hMenu;
516     HMENU   hEditMenu;
517     HMENU   hViewMenu;
518     HMENU   hShutMenu;
519     HMENU   hUpdateSpeedMenu;
520     HMENU   hCPUHistoryMenu;
521     int     nActivePage;
522     int     nParts[3];
523     RECT    rc;
524     WCHAR   szTemp[256];
525     WCHAR   szLogOffItem[MAX_PATH];
526     LPWSTR  lpUserName;
527     TCITEM  item;
528     DWORD   len = 0;
529 
530     SendMessageW(hMainWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIconW(hInst, MAKEINTRESOURCEW(IDI_TASKMANAGER)));
531 
532     /* Initialize the Windows Common Controls DLL */
533     InitCommonControls();
534 
535     /* Get the minimum window sizes */
536     GetWindowRect(hWnd, &rc);
537     nMinimumWidth = (rc.right - rc.left);
538     nMinimumHeight = (rc.bottom - rc.top);
539 
540     /* Create the status bar */
541     hStatusWnd = CreateStatusWindow(WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|SBT_NOBORDERS, L"", hWnd, STATUS_WINDOW);
542     if(!hStatusWnd)
543         return FALSE;
544 
545     /* Create the status bar panes */
546     nParts[0] = STATUS_SIZE1;
547     nParts[1] = STATUS_SIZE2;
548     nParts[2] = STATUS_SIZE3;
549     SendMessageW(hStatusWnd, SB_SETPARTS, _countof(nParts), (LPARAM)(LPINT)nParts);
550 
551     /* Create tab pages */
552     hTabWnd = GetDlgItem(hWnd, IDC_TAB);
553 #if 1
554     hApplicationPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_APPLICATION_PAGE), hWnd, ApplicationPageWndProc); EnableDialogTheme(hApplicationPage);
555     hProcessPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PROCESS_PAGE), hWnd, ProcessPageWndProc); EnableDialogTheme(hProcessPage);
556     hPerformancePage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PERFORMANCE_PAGE), hWnd, PerformancePageWndProc); EnableDialogTheme(hPerformancePage);
557 #else
558     hApplicationPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_APPLICATION_PAGE), hTabWnd, ApplicationPageWndProc); EnableDialogTheme(hApplicationPage);
559     hProcessPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PROCESS_PAGE), hTabWnd, ProcessPageWndProc); EnableDialogTheme(hProcessPage);
560     hPerformancePage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PERFORMANCE_PAGE), hTabWnd, PerformancePageWndProc); EnableDialogTheme(hPerformancePage);
561 #endif
562 
563     /* Insert tabs */
564     LoadStringW(hInst, IDS_TAB_APPS, szTemp, 256);
565     memset(&item, 0, sizeof(TCITEM));
566     item.mask = TCIF_TEXT;
567     item.pszText = szTemp;
568     (void)TabCtrl_InsertItem(hTabWnd, 0, &item);
569     LoadStringW(hInst, IDS_TAB_PROCESSES, szTemp, 256);
570     memset(&item, 0, sizeof(TCITEM));
571     item.mask = TCIF_TEXT;
572     item.pszText = szTemp;
573     (void)TabCtrl_InsertItem(hTabWnd, 1, &item);
574     LoadStringW(hInst, IDS_TAB_PERFORMANCE, szTemp, 256);
575     memset(&item, 0, sizeof(TCITEM));
576     item.mask = TCIF_TEXT;
577     item.pszText = szTemp;
578     (void)TabCtrl_InsertItem(hTabWnd, 2, &item);
579 
580     /* Size everything correctly */
581     GetClientRect(hWnd, &rc);
582     nOldWidth = rc.right;
583     nOldHeight = rc.bottom;
584     /* nOldStartX = rc.left; */
585     /*nOldStartY = rc.top;  */
586 
587 #define PAGE_OFFSET_LEFT    17
588 #define PAGE_OFFSET_TOP     72
589 #define PAGE_OFFSET_WIDTH   (PAGE_OFFSET_LEFT*2)
590 #define PAGE_OFFSET_HEIGHT  (PAGE_OFFSET_TOP+32)
591 
592     if ((TaskManagerSettings.Left != 0) ||
593         (TaskManagerSettings.Top != 0) ||
594         (TaskManagerSettings.Right != 0) ||
595         (TaskManagerSettings.Bottom != 0))
596     {
597         MoveWindow(hWnd, TaskManagerSettings.Left, TaskManagerSettings.Top, TaskManagerSettings.Right - TaskManagerSettings.Left, TaskManagerSettings.Bottom - TaskManagerSettings.Top, TRUE);
598 #ifdef __GNUC__TEST__
599         MoveWindow(hApplicationPage, TaskManagerSettings.Left + PAGE_OFFSET_LEFT, TaskManagerSettings.Top + PAGE_OFFSET_TOP, TaskManagerSettings.Right - TaskManagerSettings.Left - PAGE_OFFSET_WIDTH, TaskManagerSettings.Bottom - TaskManagerSettings.Top - PAGE_OFFSET_HEIGHT, FALSE);
600         MoveWindow(hProcessPage, TaskManagerSettings.Left + PAGE_OFFSET_LEFT, TaskManagerSettings.Top + PAGE_OFFSET_TOP, TaskManagerSettings.Right - TaskManagerSettings.Left - PAGE_OFFSET_WIDTH, TaskManagerSettings.Bottom - TaskManagerSettings.Top - PAGE_OFFSET_HEIGHT, FALSE);
601         MoveWindow(hPerformancePage, TaskManagerSettings.Left + PAGE_OFFSET_LEFT, TaskManagerSettings.Top + PAGE_OFFSET_TOP, TaskManagerSettings.Right - TaskManagerSettings.Left - PAGE_OFFSET_WIDTH, TaskManagerSettings.Bottom - TaskManagerSettings.Top - PAGE_OFFSET_HEIGHT, FALSE);
602 #endif
603     }
604     if (TaskManagerSettings.Maximized)
605         ShowWindow(hWnd, SW_MAXIMIZE);
606 
607     /* Set the always on top style */
608     hMenu = GetMenu(hWnd);
609     hEditMenu = GetSubMenu(hMenu, 1);
610     hViewMenu = GetSubMenu(hMenu, 2);
611     hShutMenu = GetSubMenu(hMenu, 4);
612     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
613     hCPUHistoryMenu  = GetSubMenu(hViewMenu, 7);
614 
615     /* Check or uncheck the always on top menu item */
616     if (TaskManagerSettings.AlwaysOnTop) {
617         CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_CHECKED);
618         SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
619     } else {
620         CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_UNCHECKED);
621         SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
622     }
623 
624     /* Check or uncheck the minimize on use menu item */
625     if (TaskManagerSettings.MinimizeOnUse)
626         CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_CHECKED);
627     else
628         CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_UNCHECKED);
629 
630     /* Check or uncheck the hide when minimized menu item */
631     if (TaskManagerSettings.HideWhenMinimized)
632         CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_CHECKED);
633     else
634         CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_UNCHECKED);
635 
636     /* Check or uncheck the show 16-bit tasks menu item */
637     if (TaskManagerSettings.Show16BitTasks)
638         CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED);
639     else
640         CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_UNCHECKED);
641 
642     /* Set the view mode */
643     CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, TaskManagerSettings.ViewMode, MF_BYCOMMAND);
644 
645     if (TaskManagerSettings.ShowKernelTimes)
646         CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
647     else
648         CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
649 
650     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, TaskManagerSettings.UpdateSpeed, MF_BYCOMMAND);
651 
652     if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
653         CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
654     else
655         CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
656 
657     nActivePage = TaskManagerSettings.ActiveTabPage;
658     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 0);
659     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 1);
660     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 2);
661     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, nActivePage);
662 
663     /* Set the username in the "Log Off %s" item of the Shutdown menu */
664 
665     /* 1- Get the menu item text and store it temporarily */
666     GetMenuStringW(hShutMenu, ID_SHUTDOWN_LOGOFF, szTemp, 256, MF_BYCOMMAND);
667 
668     /* 2- Retrieve the username length first, then allocate a buffer for it and call it again */
669     if (!GetUserNameW(NULL, &len) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
670     {
671         lpUserName = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR));
672         if (lpUserName && GetUserNameW(lpUserName, &len))
673         {
674             _snwprintf(szLogOffItem, _countof(szLogOffItem), szTemp, lpUserName);
675             szLogOffItem[_countof(szLogOffItem) - 1] = UNICODE_NULL;
676         }
677         else
678         {
679             _snwprintf(szLogOffItem, _countof(szLogOffItem), szTemp, L"n/a");
680         }
681 
682         if (lpUserName) HeapFree(GetProcessHeap(), 0, lpUserName);
683     }
684     else
685     {
686         _snwprintf(szLogOffItem, _countof(szLogOffItem), szTemp, L"n/a");
687     }
688 
689     /* 3- Set the menu item text to its formatted counterpart */
690     ModifyMenuW(hShutMenu, ID_SHUTDOWN_LOGOFF, MF_BYCOMMAND | MF_STRING, ID_SHUTDOWN_LOGOFF, szLogOffItem);
691 
692     /* Setup update speed */
693     SetUpdateSpeed(hWnd);
694 
695     /*
696      * Refresh the performance data
697      * Sample it twice so we can establish
698      * the delta values & cpu usage
699      */
700     PerfDataRefresh();
701     PerfDataRefresh();
702 
703     RefreshApplicationPage();
704     RefreshProcessPage();
705     RefreshPerformancePage();
706 
707     TrayIcon_AddIcon();
708 
709     return TRUE;
710 }
711 
712 /* OnMove()
713  * This function handles all the moving events for the application
714  * It moves every child window that needs moving
715  */
OnMove(WPARAM nType,int cx,int cy)716 void OnMove( WPARAM nType, int cx, int cy )
717 {
718 #ifdef __GNUC__TEST__
719     MoveWindow(hApplicationPage, TaskManagerSettings.Left + PAGE_OFFSET_LEFT, TaskManagerSettings.Top + PAGE_OFFSET_TOP, TaskManagerSettings.Right - TaskManagerSettings.Left - PAGE_OFFSET_WIDTH, TaskManagerSettings.Bottom - TaskManagerSettings.Top - PAGE_OFFSET_HEIGHT, FALSE);
720     MoveWindow(hProcessPage, TaskManagerSettings.Left + PAGE_OFFSET_LEFT, TaskManagerSettings.Top + PAGE_OFFSET_TOP, TaskManagerSettings.Right - TaskManagerSettings.Left - PAGE_OFFSET_WIDTH, TaskManagerSettings.Bottom - TaskManagerSettings.Top - PAGE_OFFSET_HEIGHT, FALSE);
721     MoveWindow(hPerformancePage, TaskManagerSettings.Left + PAGE_OFFSET_LEFT, TaskManagerSettings.Top + PAGE_OFFSET_TOP, TaskManagerSettings.Right - TaskManagerSettings.Left - PAGE_OFFSET_WIDTH, TaskManagerSettings.Bottom - TaskManagerSettings.Top - PAGE_OFFSET_HEIGHT, FALSE);
722 #endif
723 }
724 
725 /* OnSize()
726  * This function handles all the sizing events for the application
727  * It re-sizes every window, and child window that needs re-sizing
728  */
OnSize(WPARAM nType,int cx,int cy)729 void OnSize( WPARAM nType, int cx, int cy )
730 {
731     int   nParts[3];
732     int   nXDifference;
733     int   nYDifference;
734     RECT  rc;
735 
736     if (nType == SIZE_MINIMIZED)
737     {
738         if (TaskManagerSettings.HideWhenMinimized)
739             ShowWindow(hMainWnd, SW_HIDE);
740         return;
741     }
742 
743     nXDifference = cx - nOldWidth;
744     nYDifference = cy - nOldHeight;
745     nOldWidth = cx;
746     nOldHeight = cy;
747 
748     /* Update the status bar size */
749     GetWindowRect(hStatusWnd, &rc);
750     SendMessageW(hStatusWnd, WM_SIZE, nType, MAKELPARAM(cx,rc.bottom - rc.top));
751 
752     /* Update the status bar pane sizes */
753     nParts[0] = STATUS_SIZE1;
754     nParts[1] = STATUS_SIZE2;
755     nParts[2] = cx;
756     SendMessageW(hStatusWnd, SB_SETPARTS, _countof(nParts), (LPARAM)(LPINT)nParts);
757 
758     /* Resize the tab control */
759     GetWindowRect(hTabWnd, &rc);
760     cx = (rc.right - rc.left) + nXDifference;
761     cy = (rc.bottom - rc.top) + nYDifference;
762     SetWindowPos(hTabWnd, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
763 
764     /* Resize the application page */
765     GetWindowRect(hApplicationPage, &rc);
766     cx = (rc.right - rc.left) + nXDifference;
767     cy = (rc.bottom - rc.top) + nYDifference;
768     SetWindowPos(hApplicationPage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
769 
770     /* Resize the process page */
771     GetWindowRect(hProcessPage, &rc);
772     cx = (rc.right - rc.left) + nXDifference;
773     cy = (rc.bottom - rc.top) + nYDifference;
774     SetWindowPos(hProcessPage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
775 
776     /* Resize the performance page */
777     GetWindowRect(hPerformancePage, &rc);
778     cx = (rc.right - rc.left) + nXDifference;
779     cy = (rc.bottom - rc.top) + nYDifference;
780     SetWindowPos(hPerformancePage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
781 }
782 
LoadSettings(void)783 void LoadSettings(void)
784 {
785     HKEY   hKey;
786     WCHAR  szSubKey[] = L"Software\\ReactOS\\TaskManager";
787     int    i;
788     DWORD  dwSize;
789 
790     /* Window size & position settings */
791     TaskManagerSettings.Maximized = FALSE;
792     TaskManagerSettings.Left = 0;
793     TaskManagerSettings.Top = 0;
794     TaskManagerSettings.Right = 0;
795     TaskManagerSettings.Bottom = 0;
796 
797     /* Tab settings */
798     TaskManagerSettings.ActiveTabPage = 0;
799 
800     /* Options menu settings */
801     TaskManagerSettings.AlwaysOnTop = TRUE;
802     TaskManagerSettings.MinimizeOnUse = TRUE;
803     TaskManagerSettings.HideWhenMinimized = FALSE;
804     TaskManagerSettings.Show16BitTasks = TRUE;
805 
806     /* Update speed settings */
807     TaskManagerSettings.UpdateSpeed = ID_VIEW_UPDATESPEED_NORMAL;
808 
809     /* Applications page settings */
810     TaskManagerSettings.ViewMode = ID_VIEW_DETAILS;
811 
812     /* Processes page settings */
813     TaskManagerSettings.ShowProcessesFromAllUsers = FALSE; /* It's the default */
814 
815     for (i = 0; i < COLUMN_NMAX; i++) {
816         TaskManagerSettings.Columns[i] = ColumnPresets[i].bDefaults;
817         TaskManagerSettings.ColumnOrderArray[i] = i;
818         TaskManagerSettings.ColumnSizeArray[i] = ColumnPresets[i].size;
819     }
820 
821     TaskManagerSettings.SortColumn = COLUMN_IMAGENAME;
822     TaskManagerSettings.SortAscending = TRUE;
823 
824     /* Performance page settings */
825     TaskManagerSettings.CPUHistory_OneGraphPerCPU = TRUE;
826     TaskManagerSettings.ShowKernelTimes = FALSE;
827 
828     /* Open the key */
829     if (RegOpenKeyExW(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
830         return;
831     /* Read the settings */
832     dwSize = sizeof(TASKMANAGER_SETTINGS);
833     RegQueryValueExW(hKey, L"Preferences", NULL, NULL, (LPBYTE)&TaskManagerSettings, &dwSize);
834 
835     /*
836      * ATM, the 'ImageName' column is always visible
837      * (and grayed in configuration dialog)
838      * This will avoid troubles if the registry gets corrupted.
839      */
840     TaskManagerSettings.Column_ImageName = TRUE;
841 
842     /* Close the key */
843     RegCloseKey(hKey);
844 }
845 
SaveSettings(void)846 void SaveSettings(void)
847 {
848     HKEY hKey;
849     WCHAR szSubKey[] = L"Software\\ReactOS\\TaskManager";
850 
851     /* Open (or create) the key */
852     if (RegCreateKeyExW(HKEY_CURRENT_USER, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
853         return;
854     /* Save the settings */
855     RegSetValueExW(hKey, L"Preferences", 0, REG_BINARY, (LPBYTE)&TaskManagerSettings, sizeof(TASKMANAGER_SETTINGS));
856     /* Close the key */
857     RegCloseKey(hKey);
858 }
859 
TaskManager_OnRestoreMainWindow(void)860 void TaskManager_OnRestoreMainWindow(void)
861 {
862     BOOL OnTop;
863 
864     OnTop = ((GetWindowLongPtrW(hMainWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0);
865 
866     OpenIcon(hMainWnd);
867     SetForegroundWindow(hMainWnd);
868     SetWindowPos(hMainWnd, (OnTop ? HWND_TOPMOST : HWND_TOP), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
869 }
870 
TaskManager_OnMenuSelect(HWND hWnd,UINT nItemID,UINT nFlags,HMENU hSysMenu)871 void TaskManager_OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
872 {
873     WCHAR str[100] = L"";
874 
875     /*
876      * Reset the status bar if we close the current menu, or
877      * we open the system menu or hover above a menu separator.
878      * Adapted from comctl32!MenuHelp().
879      */
880     if ((LOWORD(nFlags) == 0xFFFF && hSysMenu == NULL) ||
881         (nFlags & (MF_SEPARATOR | MF_SYSMENU)))
882     {
883         /* Set the status bar for multiple-parts output */
884         SendMessageW(hStatusWnd, SB_SIMPLE, (WPARAM)FALSE, (LPARAM)0);
885         bTrackMenu = FALSE;
886 
887         /* Trigger update of status bar columns and performance page asynchronously */
888         RefreshPerformancePage();
889         return;
890     }
891 
892     /* Otherwise, retrieve the appropriate menu hint string */
893     if (LoadStringW(hInst, nItemID, str, _countof(str)))
894     {
895         /* First newline terminates actual string */
896         LPWSTR lpsz = wcschr(str, '\n');
897         if (lpsz != NULL)
898             *lpsz = '\0';
899     }
900 
901     /* Set the status bar for single-part output, if needed... */
902     if (!bTrackMenu)
903         SendMessageW(hStatusWnd, SB_SIMPLE, (WPARAM)TRUE, (LPARAM)0);
904     bTrackMenu = TRUE;
905 
906     /* ... and display the menu hint */
907     SendMessageW(hStatusWnd, SB_SETTEXT, SB_SIMPLEID | SBT_NOBORDERS, (LPARAM)str);
908 }
909 
TaskManager_OnViewUpdateSpeed(DWORD dwSpeed)910 void TaskManager_OnViewUpdateSpeed(DWORD dwSpeed)
911 {
912     HMENU  hMenu;
913     HMENU  hViewMenu;
914     HMENU  hUpdateSpeedMenu;
915 
916     hMenu = GetMenu(hMainWnd);
917     hViewMenu = GetSubMenu(hMenu, 2);
918     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
919 
920     TaskManagerSettings.UpdateSpeed = dwSpeed;
921     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, dwSpeed, MF_BYCOMMAND);
922 
923     KillTimer(hMainWnd, 1);
924 
925     SetUpdateSpeed(hMainWnd);
926 }
927 
TaskManager_OnTabWndSelChange(void)928 void TaskManager_OnTabWndSelChange(void)
929 {
930     int    i;
931     HMENU  hMenu;
932     HMENU  hOptionsMenu;
933     HMENU  hViewMenu;
934     HMENU  hSubMenu;
935     WCHAR  szTemp[256];
936     SYSTEM_INFO sysInfo;
937 
938     hMenu = GetMenu(hMainWnd);
939     hViewMenu = GetSubMenu(hMenu, 2);
940     hOptionsMenu = GetSubMenu(hMenu, 1);
941     TaskManagerSettings.ActiveTabPage = TabCtrl_GetCurSel(hTabWnd);
942     for (i = GetMenuItemCount(hViewMenu) - 1; i > 2; i--) {
943         hSubMenu = GetSubMenu(hViewMenu, i);
944         if (hSubMenu)
945             DestroyMenu(hSubMenu);
946         RemoveMenu(hViewMenu, i, MF_BYPOSITION);
947     }
948     RemoveMenu(hOptionsMenu, 3, MF_BYPOSITION);
949     if (hWindowMenu)
950         DestroyMenu(hWindowMenu);
951     switch (TaskManagerSettings.ActiveTabPage) {
952     case 0:
953         ShowWindow(hApplicationPage, SW_SHOW);
954         ShowWindow(hProcessPage, SW_HIDE);
955         ShowWindow(hPerformancePage, SW_HIDE);
956         BringWindowToTop(hApplicationPage);
957 
958         LoadStringW(hInst, IDS_MENU_LARGEICONS, szTemp, 256);
959         AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_LARGE, szTemp);
960 
961         LoadStringW(hInst, IDS_MENU_SMALLICONS, szTemp, 256);
962         AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SMALL, szTemp);
963 
964         LoadStringW(hInst, IDS_MENU_DETAILS, szTemp, 256);
965         AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_DETAILS, szTemp);
966 
967         if (GetMenuItemCount(hMenu) <= 5) {
968             hWindowMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_WINDOWSMENU));
969 
970             LoadStringW(hInst, IDS_MENU_WINDOWS, szTemp, 256);
971             InsertMenuW(hMenu, 3, MF_BYPOSITION|MF_POPUP, (UINT_PTR) hWindowMenu, szTemp);
972 
973             DrawMenuBar(hMainWnd);
974         }
975         CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, TaskManagerSettings.ViewMode, MF_BYCOMMAND);
976 
977         /*
978          * Give the application list control focus
979          */
980         if (!bWasKeyboardInput)
981             SetFocus(hApplicationPageListCtrl);
982         break;
983 
984     case 1:
985         ShowWindow(hApplicationPage, SW_HIDE);
986         ShowWindow(hProcessPage, SW_SHOW);
987         ShowWindow(hPerformancePage, SW_HIDE);
988         BringWindowToTop(hProcessPage);
989 
990         LoadStringW(hInst, IDS_MENU_SELECTCOLUMNS, szTemp, 256);
991         AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SELECTCOLUMNS, szTemp);
992 
993         LoadStringW(hInst, IDS_MENU_16BITTASK, szTemp, 256);
994         AppendMenuW(hOptionsMenu, MF_STRING, ID_OPTIONS_SHOW16BITTASKS, szTemp);
995 
996         if (TaskManagerSettings.Show16BitTasks)
997             CheckMenuItem(hOptionsMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED);
998         if (GetMenuItemCount(hMenu) > 5)
999         {
1000             DeleteMenu(hMenu, 3, MF_BYPOSITION);
1001             DrawMenuBar(hMainWnd);
1002         }
1003         /*
1004          * Give the process list control focus
1005          */
1006         if (!bWasKeyboardInput)
1007             SetFocus(hProcessPageListCtrl);
1008         break;
1009 
1010     case 2:
1011         ShowWindow(hApplicationPage, SW_HIDE);
1012         ShowWindow(hProcessPage, SW_HIDE);
1013         ShowWindow(hPerformancePage, SW_SHOW);
1014         BringWindowToTop(hPerformancePage);
1015         if (GetMenuItemCount(hMenu) > 5) {
1016             DeleteMenu(hMenu, 3, MF_BYPOSITION);
1017             DrawMenuBar(hMainWnd);
1018         }
1019 
1020         GetSystemInfo(&sysInfo);
1021 
1022         /* Hide CPU graph options on single CPU systems */
1023         if (sysInfo.dwNumberOfProcessors > 1)
1024         {
1025             hSubMenu = CreatePopupMenu();
1026 
1027             LoadStringW(hInst, IDS_MENU_ONEGRAPHALLCPUS, szTemp, 256);
1028             AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHALL, szTemp);
1029 
1030             LoadStringW(hInst, IDS_MENU_ONEGRAPHPERCPU, szTemp, 256);
1031             AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, szTemp);
1032 
1033             LoadStringW(hInst, IDS_MENU_CPUHISTORY, szTemp, 256);
1034             AppendMenuW(hViewMenu, MF_STRING|MF_POPUP, (UINT_PTR) hSubMenu, szTemp);
1035 
1036             if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
1037                 CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
1038             else
1039                 CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
1040         }
1041 
1042         LoadStringW(hInst, IDS_MENU_SHOWKERNELTIMES, szTemp, 256);
1043         AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SHOWKERNELTIMES, szTemp);
1044 
1045         if (TaskManagerSettings.ShowKernelTimes)
1046             CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
1047         else
1048             CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
1049 
1050         /*
1051          * Give the tab control focus
1052          */
1053         if (!bWasKeyboardInput)
1054             SetFocus(hTabWnd);
1055         break;
1056     }
1057 }
1058 
ConfirmMessageBox(HWND hWnd,LPCWSTR Text,LPCWSTR Title,UINT Type)1059 BOOL ConfirmMessageBox(HWND hWnd, LPCWSTR Text, LPCWSTR Title, UINT Type)
1060 {
1061     UINT positive = ((Type & 0xF) <= MB_OKCANCEL ? IDOK : IDYES);
1062     if (GetKeyState(VK_SHIFT) < 0)
1063         return TRUE;
1064     return (MessageBoxW(hWnd, Text, Title, Type) == positive);
1065 }
1066 
ShowWin32Error(DWORD dwError)1067 VOID ShowWin32Error(DWORD dwError)
1068 {
1069     LPWSTR lpMessageBuffer;
1070 
1071     if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1072                        NULL,
1073                        dwError,
1074                        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
1075                        (LPWSTR)&lpMessageBuffer,
1076                        0, NULL) != 0)
1077     {
1078         MessageBoxW(hMainWnd, lpMessageBuffer, NULL, MB_OK | MB_ICONERROR);
1079         if (lpMessageBuffer) LocalFree(lpMessageBuffer);
1080     }
1081 }
1082 
GetLastErrorText(LPWSTR lpszBuf,DWORD dwSize)1083 LPWSTR GetLastErrorText(LPWSTR lpszBuf, DWORD dwSize)
1084 {
1085     DWORD  dwRet;
1086     LPWSTR lpszTemp = NULL;
1087 
1088     dwRet = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
1089                            NULL,
1090                            GetLastError(),
1091                            LANG_NEUTRAL,
1092                            (LPWSTR)&lpszTemp,
1093                            0,
1094                            NULL );
1095 
1096     /* supplied buffer is not long enough */
1097     if (!dwRet || ( (long)dwSize < (long)dwRet+14)) {
1098         lpszBuf[0] = L'\0';
1099     } else {
1100         lpszTemp[lstrlenW(lpszTemp)-2] = L'\0';  /*remove cr and newline character */
1101         wsprintfW(lpszBuf, L"%s (0x%x)", lpszTemp, (int)GetLastError());
1102     }
1103     if (lpszTemp) {
1104         LocalFree((HLOCAL)lpszTemp);
1105     }
1106     return lpszBuf;
1107 }
1108 
EndLocalThread(HANDLE * hThread,DWORD dwThread)1109 DWORD EndLocalThread(HANDLE *hThread, DWORD dwThread)
1110 {
1111     DWORD dwExitCodeThread = 0;
1112 
1113     if (*hThread != NULL) {
1114         PostThreadMessage(dwThread,WM_QUIT,0,0);
1115         for (;;) {
1116             MSG msg;
1117 
1118             if (WAIT_OBJECT_0 == WaitForSingleObject(*hThread, 500))
1119                 break;
1120             while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
1121                 TranslateMessage(&msg);
1122                 DispatchMessage(&msg);
1123             }
1124         }
1125         GetExitCodeThread(*hThread, &dwExitCodeThread);
1126         CloseHandle(*hThread);
1127         *hThread = NULL;
1128     }
1129     return dwExitCodeThread;
1130 }
1131 
1132