Authors: Thomas Weidenmueller <wine-patches@reactsoft.com>, Filip Navara <xnavara...
[wine] / programs / taskmgr / taskmgr.c
1 /*
2  *  ReactOS Task Manager
3  *
4  * taskmgr.c : Defines the entry point for the application.
5  *
6  *  Copyright (C) 1999 - 2001  Brian Palmer  <brianp@reactos.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #define WIN32_LEAN_AND_MEAN    /* Exclude rarely-used stuff from Windows headers */
24 #include <windows.h>
25 #include <commctrl.h>
26 #include <stdlib.h>
27 #include <malloc.h>
28 #include <memory.h>
29 #include <tchar.h>
30 #include <stdio.h>
31 #include <winnt.h>
32
33 #include "resource.h"
34 #include "taskmgr.h"
35 #include "perfdata.h"
36 #include "column.h"
37
38 #define STATUS_WINDOW   2001
39
40 /* Global Variables: */
41 HINSTANCE hInst;                 /* current instance */
42
43 HWND hMainWnd;                   /* Main Window */
44 HWND hStatusWnd;                 /* Status Bar Window */
45 HWND hTabWnd;                    /* Tab Control Window */
46
47 int  nMinimumWidth;              /* Minimum width of the dialog (OnSize()'s cx) */
48 int  nMinimumHeight;             /* Minimum height of the dialog (OnSize()'s cy) */
49
50 int  nOldWidth;                  /* Holds the previous client area width */
51 int  nOldHeight;                 /* Holds the previous client area height */
52
53 BOOL bInMenuLoop = FALSE;        /* Tells us if we are in the menu loop */
54
55 TASKMANAGER_SETTINGS TaskManagerSettings;
56
57
58 int APIENTRY WinMain(HINSTANCE hInstance,
59                      HINSTANCE hPrevInstance,
60                      LPSTR     lpCmdLine,
61                      int       nCmdShow)
62 {
63     HANDLE hProcess;
64     HANDLE hToken; 
65     TOKEN_PRIVILEGES tkp; 
66
67     /* Initialize global variables */
68     hInst = hInstance;
69
70     /* Change our priority class to HIGH */
71     hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
72     SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);
73     CloseHandle(hProcess);
74
75     /* Now let's get the SE_DEBUG_NAME privilege
76      * so that we can debug processes 
77      */
78
79     /* Get a token for this process.  */
80     if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
81         /* Get the LUID for the debug privilege.  */
82         LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid); 
83
84         tkp.PrivilegeCount = 1;  /* one privilege to set */
85         tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 
86
87         /* Get the debug privilege for this process. */
88         AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); 
89     }
90
91     /* Load our settings from the registry */
92     LoadSettings();
93
94     /* Initialize perf data */
95     if (!PerfDataInitialize()) {
96         return -1;
97     }
98
99     DialogBox(hInst, (LPCTSTR)IDD_TASKMGR_DIALOG, NULL, TaskManagerWndProc);
100  
101     /* Save our settings to the registry */
102     SaveSettings();
103     PerfDataUninitialize();
104     return 0;
105 }
106
107 /* Message handler for dialog box. */
108 INT_PTR CALLBACK
109 TaskManagerWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
110 {
111     HDC             hdc;
112     PAINTSTRUCT     ps;
113     LPRECT          pRC;
114     RECT            rc;
115     int             idctrl;
116     LPNMHDR         pnmh;
117     WINDOWPLACEMENT wp;
118
119     switch (message) {
120     case WM_INITDIALOG:
121         hMainWnd = hDlg;
122         return OnCreate(hDlg);
123
124     case WM_COMMAND:
125         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
126             EndDialog(hDlg, LOWORD(wParam));
127             return TRUE;
128         }
129         /* Process menu commands */
130         switch (LOWORD(wParam))
131         {
132         case ID_FILE_NEW:
133             TaskManager_OnFileNew();
134             break;
135         case ID_OPTIONS_ALWAYSONTOP:
136             TaskManager_OnOptionsAlwaysOnTop();
137             break;
138         case ID_OPTIONS_MINIMIZEONUSE:
139             TaskManager_OnOptionsMinimizeOnUse();
140             break;
141         case ID_OPTIONS_HIDEWHENMINIMIZED:
142             TaskManager_OnOptionsHideWhenMinimized();
143             break;
144         case ID_OPTIONS_SHOW16BITTASKS:
145             TaskManager_OnOptionsShow16BitTasks();
146             break;
147         case ID_VIEW_LARGE:
148             ApplicationPage_OnViewLargeIcons();
149             break;
150         case ID_VIEW_SMALL:
151             ApplicationPage_OnViewSmallIcons();
152             break;
153         case ID_VIEW_DETAILS:
154             ApplicationPage_OnViewDetails();
155             break;
156         case ID_VIEW_SHOWKERNELTIMES:
157             PerformancePage_OnViewShowKernelTimes();
158             break;
159         case ID_VIEW_CPUHISTORY_ONEGRAPHALL:
160             PerformancePage_OnViewCPUHistoryOneGraphAll();
161             break;
162         case ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU:
163             PerformancePage_OnViewCPUHistoryOneGraphPerCPU();
164             break;
165         case ID_VIEW_UPDATESPEED_HIGH:
166             TaskManager_OnViewUpdateSpeedHigh();
167             break;
168         case ID_VIEW_UPDATESPEED_NORMAL:
169             TaskManager_OnViewUpdateSpeedNormal();
170             break;
171         case ID_VIEW_UPDATESPEED_LOW:
172             TaskManager_OnViewUpdateSpeedLow();
173             break;
174         case ID_VIEW_UPDATESPEED_PAUSED:
175             TaskManager_OnViewUpdateSpeedPaused();
176             break;
177         case ID_VIEW_SELECTCOLUMNS:
178             ProcessPage_OnViewSelectColumns();
179             break;
180         case ID_VIEW_REFRESH:
181             PostMessage(hDlg, WM_TIMER, 0, 0);
182             break;
183         case ID_WINDOWS_TILEHORIZONTALLY:
184             ApplicationPage_OnWindowsTileHorizontally();
185             break;
186         case ID_WINDOWS_TILEVERTICALLY:
187             ApplicationPage_OnWindowsTileVertically();
188             break;
189         case ID_WINDOWS_MINIMIZE:
190             ApplicationPage_OnWindowsMinimize();
191             break;
192         case ID_WINDOWS_MAXIMIZE:
193             ApplicationPage_OnWindowsMaximize();
194             break;
195         case ID_WINDOWS_CASCADE:
196             ApplicationPage_OnWindowsCascade();
197             break;
198         case ID_WINDOWS_BRINGTOFRONT:
199             ApplicationPage_OnWindowsBringToFront();
200             break;
201         case ID_APPLICATION_PAGE_SWITCHTO:
202             ApplicationPage_OnSwitchTo();
203             break;
204         case ID_APPLICATION_PAGE_ENDTASK:
205             ApplicationPage_OnEndTask();
206             break;
207         case ID_APPLICATION_PAGE_GOTOPROCESS:
208             ApplicationPage_OnGotoProcess();
209             break;
210         case ID_PROCESS_PAGE_ENDPROCESS:
211             ProcessPage_OnEndProcess();
212             break;
213         case ID_PROCESS_PAGE_ENDPROCESSTREE:
214             ProcessPage_OnEndProcessTree();
215             break;
216         case ID_PROCESS_PAGE_DEBUG:
217             ProcessPage_OnDebug();
218             break;
219         case ID_PROCESS_PAGE_SETAFFINITY:
220             ProcessPage_OnSetAffinity();
221             break;
222         case ID_PROCESS_PAGE_SETPRIORITY_REALTIME:
223             ProcessPage_OnSetPriorityRealTime();
224             break;
225         case ID_PROCESS_PAGE_SETPRIORITY_HIGH:
226             ProcessPage_OnSetPriorityHigh();
227             break;
228         case ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL:
229             ProcessPage_OnSetPriorityAboveNormal();
230             break;
231         case ID_PROCESS_PAGE_SETPRIORITY_NORMAL:
232             ProcessPage_OnSetPriorityNormal();
233             break;
234         case ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL:
235             ProcessPage_OnSetPriorityBelowNormal();
236             break;
237         case ID_PROCESS_PAGE_SETPRIORITY_LOW:
238             ProcessPage_OnSetPriorityLow();
239             break;
240         case ID_PROCESS_PAGE_DEBUGCHANNELS:
241             ProcessPage_OnDebugChannels();
242             break;
243         case ID_HELP_ABOUT:
244             OnAbout();
245             break;
246         case ID_FILE_EXIT:
247             DestroyWindow(hDlg);
248             break;
249         }     
250         break;
251
252     case WM_NOTIFY:
253         idctrl = (int)wParam;
254         pnmh = (LPNMHDR)lParam;
255         if ((pnmh->hwndFrom == hTabWnd) &&
256             (pnmh->idFrom == IDC_TAB) &&
257             (pnmh->code == TCN_SELCHANGE))
258         {
259             TaskManager_OnTabWndSelChange();
260         }
261         break;
262
263     case WM_NCPAINT:
264         hdc = GetDC(hDlg);
265         GetClientRect(hDlg, &rc);
266         Draw3dRect(hdc, rc.left, rc.top, rc.right, rc.top + 2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
267         ReleaseDC(hDlg, hdc);
268         break;
269
270     case WM_PAINT:
271         hdc = BeginPaint(hDlg, &ps);
272         GetClientRect(hDlg, &rc);
273         Draw3dRect(hdc, rc.left, rc.top, rc.right, rc.top + 2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
274         EndPaint(hDlg, &ps);
275         break;
276
277     case WM_SIZING:
278         /* Make sure the user is sizing the dialog */
279         /* in an acceptable range */
280         pRC = (LPRECT)lParam;
281         if ((wParam == WMSZ_LEFT) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_BOTTOMLEFT)) {
282             /* If the width is too small enlarge it to the minimum */
283             if (nMinimumWidth > (pRC->right - pRC->left))
284                 pRC->left = pRC->right - nMinimumWidth;
285         } else {
286             /* If the width is too small enlarge it to the minimum */
287             if (nMinimumWidth > (pRC->right - pRC->left))
288                 pRC->right = pRC->left + nMinimumWidth;
289         }
290         if ((wParam == WMSZ_TOP) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_TOPRIGHT)) {
291             /* If the height is too small enlarge it to the minimum */
292             if (nMinimumHeight > (pRC->bottom - pRC->top))
293                 pRC->top = pRC->bottom - nMinimumHeight;
294         } else {
295             /* If the height is too small enlarge it to the minimum */
296             if (nMinimumHeight > (pRC->bottom - pRC->top))
297                 pRC->bottom = pRC->top + nMinimumHeight;
298         }
299         return TRUE;
300         break;
301
302     case WM_SIZE:
303         /* Handle the window sizing in it's own function */
304         OnSize(wParam, LOWORD(lParam), HIWORD(lParam));
305         break;
306
307     case WM_MOVE:
308         /* Handle the window moving in it's own function */
309         OnMove(wParam, LOWORD(lParam), HIWORD(lParam));
310         break;
311
312     case WM_DESTROY:
313         ShowWindow(hDlg, SW_HIDE);
314         TrayIcon_ShellRemoveTrayIcon();
315         wp.length = sizeof(WINDOWPLACEMENT);
316         GetWindowPlacement(hDlg, &wp);
317         TaskManagerSettings.Left = wp.rcNormalPosition.left;
318         TaskManagerSettings.Top = wp.rcNormalPosition.top;
319         TaskManagerSettings.Right = wp.rcNormalPosition.right;
320         TaskManagerSettings.Bottom = wp.rcNormalPosition.bottom;
321         if (IsZoomed(hDlg) || (wp.flags & WPF_RESTORETOMAXIMIZED))
322             TaskManagerSettings.Maximized = TRUE;
323         else
324             TaskManagerSettings.Maximized = FALSE;
325         return DefWindowProc(hDlg, message, wParam, lParam);
326         
327     case WM_TIMER:
328         /* Refresh the performance data */
329         PerfDataRefresh();
330         RefreshApplicationPage();
331         RefreshProcessPage();
332         RefreshPerformancePage();
333         TrayIcon_ShellUpdateTrayIcon();
334         break;
335
336     case WM_ENTERMENULOOP:
337         TaskManager_OnEnterMenuLoop(hDlg);
338         break;
339     case WM_EXITMENULOOP:
340         TaskManager_OnExitMenuLoop(hDlg);
341         break;
342     case WM_MENUSELECT:
343         TaskManager_OnMenuSelect(hDlg, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
344         break;
345     }
346
347     return 0;
348 }
349
350 void FillSolidRect(HDC hDC, LPCRECT lpRect, COLORREF clr)
351 {
352     SetBkColor(hDC, clr);
353     ExtTextOut(hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
354 }
355
356 void FillSolidRect2(HDC hDC, int x, int y, int cx, int cy, COLORREF clr)
357 {
358     RECT rect;
359
360     SetBkColor(hDC, clr);
361     rect.left = x;
362     rect.top = y;
363     rect.right = x + cx;
364     rect.bottom = y + cy;
365     ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
366 }
367
368 void Draw3dRect(HDC hDC, int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight)
369 {
370     FillSolidRect2(hDC, x, y, cx - 1, 1, clrTopLeft);
371     FillSolidRect2(hDC, x, y, 1, cy - 1, clrTopLeft);
372     FillSolidRect2(hDC, x + cx, y, -1, cy, clrBottomRight);
373     FillSolidRect2(hDC, x, y + cy, cx, -1, clrBottomRight);
374 }
375
376 void Draw3dRect2(HDC hDC, LPRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight)
377 {
378     Draw3dRect(hDC, lpRect->left, lpRect->top, lpRect->right - lpRect->left,
379         lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
380 }
381
382 void Font_DrawText(HDC hDC, LPCTSTR lpszText, int x, int y)
383 {
384     HDC        hFontDC;
385     HBITMAP    hFontBitmap;
386     HBITMAP    hOldBitmap;
387     int        i;
388
389     hFontDC = CreateCompatibleDC(hDC);
390     hFontBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FONT));
391     hOldBitmap = (HBITMAP)SelectObject(hFontDC, hFontBitmap);
392
393     for (i = 0; i < (int)_tcslen(lpszText); i++) {
394         if ((lpszText[i] >= '0') && (lpszText[i] <= '9')) {
395             BitBlt(hDC, x + (i * 8), y, 8, 11, hFontDC, (lpszText[i] - '0') * 8, 0, SRCCOPY);
396         }
397         else if (lpszText[i] == 'K')
398         {
399             BitBlt(hDC, x + (i * 8), y, 8, 11, hFontDC, 80, 0, SRCCOPY);
400         }
401         else if (lpszText[i] == '%')
402         {
403             BitBlt(hDC, x + (i * 8), y, 8, 11, hFontDC, 88, 0, SRCCOPY);
404         }
405     }
406     SelectObject(hFontDC, hOldBitmap);
407     DeleteObject(hFontBitmap);
408     DeleteDC(hFontDC);
409 }
410
411 BOOL OnCreate(HWND hWnd)
412 {
413     HMENU   hMenu;
414     HMENU   hEditMenu;
415     HMENU   hViewMenu;
416     HMENU   hUpdateSpeedMenu;
417     HMENU   hCPUHistoryMenu;
418     int     nActivePage;
419     int     nParts[3];
420     RECT    rc;
421     TCHAR   szTemp[256];
422     TCITEM  item;
423
424     SendMessage(hMainWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_TASKMANAGER)));
425
426     /* Initialize the Windows Common Controls DLL */
427     InitCommonControls();
428
429     /* Get the minimum window sizes */
430     GetWindowRect(hWnd, &rc);
431     nMinimumWidth = (rc.right - rc.left);
432     nMinimumHeight = (rc.bottom - rc.top);
433
434     /* Create the status bar */
435     hStatusWnd = CreateStatusWindow(WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|SBT_NOBORDERS, _T(""), hWnd, STATUS_WINDOW);
436     if(!hStatusWnd)
437         return FALSE;
438
439     /* Create the status bar panes */
440     nParts[0] = 100;
441     nParts[1] = 210;
442     nParts[2] = 400;
443     SendMessage(hStatusWnd, SB_SETPARTS, 3, (long)nParts);
444
445     /* Create tab pages */
446     hTabWnd = GetDlgItem(hWnd, IDC_TAB);
447 #if 1
448     hApplicationPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_APPLICATION_PAGE), hWnd, ApplicationPageWndProc);
449     hProcessPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PROCESS_PAGE), hWnd, ProcessPageWndProc);
450     hPerformancePage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PERFORMANCE_PAGE), hWnd, PerformancePageWndProc);
451 #else
452     hApplicationPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_APPLICATION_PAGE), hTabWnd, ApplicationPageWndProc);
453     hProcessPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PROCESS_PAGE), hTabWnd, ProcessPageWndProc);
454     hPerformancePage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PERFORMANCE_PAGE), hTabWnd, PerformancePageWndProc);
455 #endif
456
457     /* Insert tabs */
458     _tcscpy(szTemp, _T("Applications"));
459     memset(&item, 0, sizeof(TCITEM));
460     item.mask = TCIF_TEXT;
461     item.pszText = szTemp;
462     TabCtrl_InsertItem(hTabWnd, 0, &item);
463     _tcscpy(szTemp, _T("Processes"));
464     memset(&item, 0, sizeof(TCITEM));
465     item.mask = TCIF_TEXT;
466     item.pszText = szTemp;
467     TabCtrl_InsertItem(hTabWnd, 1, &item);
468     _tcscpy(szTemp, _T("Performance"));
469     memset(&item, 0, sizeof(TCITEM));
470     item.mask = TCIF_TEXT;
471     item.pszText = szTemp;
472     TabCtrl_InsertItem(hTabWnd, 2, &item);
473
474     /* Size everything correctly */
475     GetClientRect(hWnd, &rc);
476     nOldWidth = rc.right;
477     nOldHeight = rc.bottom;
478     /* nOldStartX = rc.left; */
479     /*nOldStartY = rc.top;  */
480
481 #define PAGE_OFFSET_LEFT    17
482 #define PAGE_OFFSET_TOP     72
483 #define PAGE_OFFSET_WIDTH   (PAGE_OFFSET_LEFT*2)
484 #define PAGE_OFFSET_HEIGHT  (PAGE_OFFSET_TOP+32)
485
486     if ((TaskManagerSettings.Left != 0) ||
487         (TaskManagerSettings.Top != 0) ||
488         (TaskManagerSettings.Right != 0) ||
489         (TaskManagerSettings.Bottom != 0))
490     {
491         MoveWindow(hWnd, TaskManagerSettings.Left, TaskManagerSettings.Top, TaskManagerSettings.Right - TaskManagerSettings.Left, TaskManagerSettings.Bottom - TaskManagerSettings.Top, TRUE);
492 #ifdef __GNUC__TEST__
493         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);
494         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);
495         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);
496 #endif
497     }
498     if (TaskManagerSettings.Maximized)
499         ShowWindow(hWnd, SW_MAXIMIZE);
500
501     /* Set the always on top style */
502     hMenu = GetMenu(hWnd);
503     hEditMenu = GetSubMenu(hMenu, 1);
504     hViewMenu = GetSubMenu(hMenu, 2);
505     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
506     hCPUHistoryMenu = GetSubMenu(hViewMenu, 7);
507
508     /* Check or uncheck the always on top menu item */
509     if (TaskManagerSettings.AlwaysOnTop) {
510         CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_CHECKED);
511         SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
512     } else {
513         CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_UNCHECKED);
514         SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
515     }
516
517     /* Check or uncheck the minimize on use menu item */
518     if (TaskManagerSettings.MinimizeOnUse)
519         CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_CHECKED);
520     else
521         CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_UNCHECKED);
522
523     /* Check or uncheck the hide when minimized menu item */
524     if (TaskManagerSettings.HideWhenMinimized)
525         CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_CHECKED);
526     else
527         CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_UNCHECKED);
528
529     /* Check or uncheck the show 16-bit tasks menu item */
530     if (TaskManagerSettings.Show16BitTasks)
531         CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED);
532     else
533         CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_UNCHECKED);
534
535     if (TaskManagerSettings.View_LargeIcons)
536         CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
537     else if (TaskManagerSettings.View_SmallIcons)
538         CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
539     else
540         CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);
541
542     if (TaskManagerSettings.ShowKernelTimes)
543         CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
544     else
545         CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
546
547     if (TaskManagerSettings.UpdateSpeed == 1)
548         CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_HIGH, MF_BYCOMMAND);
549     else if (TaskManagerSettings.UpdateSpeed == 2)
550         CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_NORMAL, MF_BYCOMMAND);
551     else if (TaskManagerSettings.UpdateSpeed == 4)
552         CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_LOW, MF_BYCOMMAND);
553     else
554         CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_PAUSED, MF_BYCOMMAND);
555
556     if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
557         CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
558     else
559         CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
560
561     nActivePage = TaskManagerSettings.ActiveTabPage;
562     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 0);
563     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 1);
564     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 2);
565     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, nActivePage);
566
567     if (TaskManagerSettings.UpdateSpeed == 0)
568         KillTimer(hWnd, 1);
569     else if (TaskManagerSettings.UpdateSpeed == 1)
570     {
571         KillTimer(hWnd, 1);
572         SetTimer(hWnd, 1, 1000, NULL);
573     }
574     else if (TaskManagerSettings.UpdateSpeed == 2)
575     {
576         KillTimer(hWnd, 1);
577         SetTimer(hWnd, 1, 2000, NULL);
578     }
579     else if (TaskManagerSettings.UpdateSpeed == 4)
580     {
581         KillTimer(hWnd, 1);
582         SetTimer(hWnd, 1, 4000, NULL);
583     }
584
585     /*
586      * Refresh the performance data
587      * Sample it twice so we can establish
588      * the delta values & cpu usage
589      */
590     PerfDataRefresh();
591     PerfDataRefresh();
592
593     RefreshApplicationPage();
594     RefreshProcessPage();
595     RefreshPerformancePage();
596
597     TrayIcon_ShellAddTrayIcon();
598
599     return TRUE;
600 }
601
602 /* OnMove()
603  * This function handles all the moving events for the application
604  * It moves every child window that needs moving
605  */
606 void OnMove( UINT nType, int cx, int cy )
607 {
608 #ifdef __GNUC__TEST__
609     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);
610     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);
611     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);
612 #endif
613 }
614
615 /* OnSize()
616  * This function handles all the sizing events for the application
617  * It re-sizes every window, and child window that needs re-sizing
618  */
619 void OnSize( UINT nType, int cx, int cy )
620 {
621     int     nParts[3];
622     int     nXDifference;
623     int     nYDifference;
624     RECT    rc;
625
626     if (nType == SIZE_MINIMIZED)
627         return;
628
629     nXDifference = cx - nOldWidth;
630     nYDifference = cy - nOldHeight;
631     nOldWidth = cx;
632     nOldHeight = cy;
633
634     /* Update the status bar size */
635     GetWindowRect(hStatusWnd, &rc);
636     SendMessage(hStatusWnd, WM_SIZE, nType, MAKELPARAM(cx, cy + (rc.bottom - rc.top)));
637
638     /* Update the status bar pane sizes */
639     nParts[0] = bInMenuLoop ? -1 : 100;
640     nParts[1] = 210;
641     nParts[2] = cx;
642     SendMessage(hStatusWnd, SB_SETPARTS, bInMenuLoop ? 1 : 3, (long)nParts);
643
644     /* Resize the tab control */
645     GetWindowRect(hTabWnd, &rc);
646     cx = (rc.right - rc.left) + nXDifference;
647     cy = (rc.bottom - rc.top) + nYDifference;
648     SetWindowPos(hTabWnd, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
649
650     /* Resize the application page */
651     GetWindowRect(hApplicationPage, &rc);
652     cx = (rc.right - rc.left) + nXDifference;
653     cy = (rc.bottom - rc.top) + nYDifference;
654     SetWindowPos(hApplicationPage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
655     
656     /* Resize the process page */
657     GetWindowRect(hProcessPage, &rc);
658     cx = (rc.right - rc.left) + nXDifference;
659     cy = (rc.bottom - rc.top) + nYDifference;
660     SetWindowPos(hProcessPage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
661     
662     /* Resize the performance page */
663     GetWindowRect(hPerformancePage, &rc);
664     cx = (rc.right - rc.left) + nXDifference;
665     cy = (rc.bottom - rc.top) + nYDifference;
666     SetWindowPos(hPerformancePage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
667 }
668
669 void LoadSettings(void)
670 {
671     HKEY    hKey;
672     TCHAR   szSubKey[] = _T("Software\\Wine\\TaskManager");
673     int     i;
674     DWORD   dwSize;
675
676     /* Window size & position settings */
677     TaskManagerSettings.Maximized = FALSE;
678     TaskManagerSettings.Left = 0;
679     TaskManagerSettings.Top = 0;
680     TaskManagerSettings.Right = 0;
681     TaskManagerSettings.Bottom = 0;
682
683     /* Tab settings */
684     TaskManagerSettings.ActiveTabPage = 0;
685
686     /* Options menu settings */
687     TaskManagerSettings.AlwaysOnTop = FALSE;
688     TaskManagerSettings.MinimizeOnUse = TRUE;
689     TaskManagerSettings.HideWhenMinimized = TRUE;
690     TaskManagerSettings.Show16BitTasks = TRUE;
691
692     /* Update speed settings */
693     TaskManagerSettings.UpdateSpeed = 2;
694
695     /* Applications page settings */
696     TaskManagerSettings.View_LargeIcons = FALSE;
697     TaskManagerSettings.View_SmallIcons = FALSE;
698     TaskManagerSettings.View_Details = TRUE;
699
700     /* Processes page settings */
701     TaskManagerSettings.ShowProcessesFromAllUsers = FALSE; /* Server-only? */
702     TaskManagerSettings.Column_ImageName = TRUE;
703     TaskManagerSettings.Column_PID = TRUE;
704     TaskManagerSettings.Column_CPUUsage = TRUE;
705     TaskManagerSettings.Column_CPUTime = TRUE;
706     TaskManagerSettings.Column_MemoryUsage = TRUE;
707     TaskManagerSettings.Column_MemoryUsageDelta = FALSE;
708     TaskManagerSettings.Column_PeakMemoryUsage = FALSE;
709     TaskManagerSettings.Column_PageFaults = FALSE;
710     TaskManagerSettings.Column_USERObjects = FALSE;
711     TaskManagerSettings.Column_IOReads = FALSE;
712     TaskManagerSettings.Column_IOReadBytes = FALSE;
713     TaskManagerSettings.Column_SessionID = FALSE; /* Server-only? */
714     TaskManagerSettings.Column_UserName = FALSE; /* Server-only? */
715     TaskManagerSettings.Column_PageFaultsDelta = FALSE;
716     TaskManagerSettings.Column_VirtualMemorySize = FALSE;
717     TaskManagerSettings.Column_PagedPool = FALSE;
718     TaskManagerSettings.Column_NonPagedPool = FALSE;
719     TaskManagerSettings.Column_BasePriority = FALSE;
720     TaskManagerSettings.Column_HandleCount = FALSE;
721     TaskManagerSettings.Column_ThreadCount = FALSE;
722     TaskManagerSettings.Column_GDIObjects = FALSE;
723     TaskManagerSettings.Column_IOWrites = FALSE;
724     TaskManagerSettings.Column_IOWriteBytes = FALSE;
725     TaskManagerSettings.Column_IOOther = FALSE;
726     TaskManagerSettings.Column_IOOtherBytes = FALSE;
727
728     for (i = 0; i < 25; i++) {
729         TaskManagerSettings.ColumnOrderArray[i] = i;
730     }
731     TaskManagerSettings.ColumnSizeArray[0] = 105;
732     TaskManagerSettings.ColumnSizeArray[1] = 50;
733     TaskManagerSettings.ColumnSizeArray[2] = 107;
734     TaskManagerSettings.ColumnSizeArray[3] = 70;
735     TaskManagerSettings.ColumnSizeArray[4] = 35;
736     TaskManagerSettings.ColumnSizeArray[5] = 70;
737     TaskManagerSettings.ColumnSizeArray[6] = 70;
738     TaskManagerSettings.ColumnSizeArray[7] = 100;
739     TaskManagerSettings.ColumnSizeArray[8] = 70;
740     TaskManagerSettings.ColumnSizeArray[9] = 70;
741     TaskManagerSettings.ColumnSizeArray[10] = 70;
742     TaskManagerSettings.ColumnSizeArray[11] = 70;
743     TaskManagerSettings.ColumnSizeArray[12] = 70;
744     TaskManagerSettings.ColumnSizeArray[13] = 70;
745     TaskManagerSettings.ColumnSizeArray[14] = 60;
746     TaskManagerSettings.ColumnSizeArray[15] = 60;
747     TaskManagerSettings.ColumnSizeArray[16] = 60;
748     TaskManagerSettings.ColumnSizeArray[17] = 60;
749     TaskManagerSettings.ColumnSizeArray[18] = 60;
750     TaskManagerSettings.ColumnSizeArray[19] = 70;
751     TaskManagerSettings.ColumnSizeArray[20] = 70;
752     TaskManagerSettings.ColumnSizeArray[21] = 70;
753     TaskManagerSettings.ColumnSizeArray[22] = 70;
754     TaskManagerSettings.ColumnSizeArray[23] = 70;
755     TaskManagerSettings.ColumnSizeArray[24] = 70;
756
757     TaskManagerSettings.SortColumn = 1;
758     TaskManagerSettings.SortAscending = TRUE;
759
760     /* Performance page settings */
761     TaskManagerSettings.CPUHistory_OneGraphPerCPU = TRUE;
762     TaskManagerSettings.ShowKernelTimes = FALSE;
763
764     /* Open the key */
765     /* @@ Wine registry key: HKCU\Software\Wine\TaskManager */
766     if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
767         return;
768     /* Read the settings */
769     dwSize = sizeof(TASKMANAGER_SETTINGS);
770     RegQueryValueEx(hKey, _T("Preferences"), NULL, NULL, (LPBYTE)&TaskManagerSettings, &dwSize);
771
772     /* Close the key */
773     RegCloseKey(hKey);
774 }
775
776 void SaveSettings(void)
777 {
778     HKEY hKey;
779     TCHAR szSubKey3[] = _T("Software\\Wine\\TaskManager");
780
781     /* Open (or create) the key */
782
783     /* @@ Wine registry key: HKCU\Software\Wine\TaskManager */
784     if (RegCreateKeyEx(HKEY_CURRENT_USER, szSubKey3, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
785         return;
786     /* Save the settings */
787     RegSetValueEx(hKey, _T("Preferences"), 0, REG_BINARY, (LPBYTE)&TaskManagerSettings, sizeof(TASKMANAGER_SETTINGS));
788     /* Close the key */
789     RegCloseKey(hKey);
790 }
791
792 void TaskManager_OnEnterMenuLoop(HWND hWnd)
793 {
794     int nParts;
795
796     /* Update the status bar pane sizes */
797     nParts = -1;
798     SendMessage(hStatusWnd, SB_SETPARTS, 1, (long)&nParts);
799     bInMenuLoop = TRUE;
800     SendMessage(hStatusWnd, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
801 }
802
803 void TaskManager_OnExitMenuLoop(HWND hWnd)
804 {
805     RECT  rc;
806     int   nParts[3];
807     TCHAR text[260];
808
809     bInMenuLoop = FALSE;
810     /* Update the status bar pane sizes */
811     GetClientRect(hWnd, &rc);
812     nParts[0] = 100;
813     nParts[1] = 210;
814     nParts[2] = rc.right;
815     SendMessage(hStatusWnd, SB_SETPARTS, 3, (long)nParts);
816     SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)_T(""));
817     wsprintf(text, _T("CPU Usage: %3d%%"), PerfDataGetProcessorUsage());
818     SendMessage(hStatusWnd, SB_SETTEXT, 1, (LPARAM)text);
819     wsprintf(text, _T("Processes: %d"), PerfDataGetProcessCount());
820     SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text);
821 }
822
823 void TaskManager_OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
824 {
825     TCHAR str[100];
826
827     _tcscpy(str, TEXT(""));
828     if (LoadString(hInst, nItemID, str, 100)) {
829         /* load appropriate string */
830         LPTSTR lpsz = str;
831         /* first newline terminates actual string */
832         lpsz = _tcschr(lpsz, '\n');
833         if (lpsz != NULL)
834             *lpsz = '\0';
835     }
836     SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)str);
837 }
838
839 void TaskManager_OnViewUpdateSpeedHigh(void)
840 {
841     HMENU hMenu;
842     HMENU hViewMenu;
843     HMENU hUpdateSpeedMenu;
844
845     hMenu = GetMenu(hMainWnd);
846     hViewMenu = GetSubMenu(hMenu, 2);
847     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
848
849     TaskManagerSettings.UpdateSpeed = 1;
850     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_HIGH, MF_BYCOMMAND);
851
852     KillTimer(hMainWnd, 1);
853     SetTimer(hMainWnd, 1, 1000, NULL);
854 }
855
856 void TaskManager_OnViewUpdateSpeedNormal(void)
857 {
858     HMENU hMenu;
859     HMENU hViewMenu;
860     HMENU hUpdateSpeedMenu;
861
862     hMenu = GetMenu(hMainWnd);
863     hViewMenu = GetSubMenu(hMenu, 2);
864     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
865
866     TaskManagerSettings.UpdateSpeed = 2;
867     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_NORMAL, MF_BYCOMMAND);
868
869     KillTimer(hMainWnd, 1);
870     SetTimer(hMainWnd, 1, 2000, NULL);
871 }
872
873 void TaskManager_OnViewUpdateSpeedLow(void)
874 {
875     HMENU hMenu;
876     HMENU hViewMenu;
877     HMENU hUpdateSpeedMenu;
878
879     hMenu = GetMenu(hMainWnd);
880     hViewMenu = GetSubMenu(hMenu, 2);
881     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
882
883     TaskManagerSettings.UpdateSpeed = 4;
884     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_LOW, MF_BYCOMMAND);
885
886     KillTimer(hMainWnd, 1);
887     SetTimer(hMainWnd, 1, 4000, NULL);
888 }
889
890 void TaskManager_OnViewRefresh(void)
891 {
892     PostMessage(hMainWnd, WM_TIMER, 0, 0);
893 }
894
895 void TaskManager_OnViewUpdateSpeedPaused(void)
896 {
897     HMENU hMenu;
898     HMENU hViewMenu;
899     HMENU hUpdateSpeedMenu;
900
901     hMenu = GetMenu(hMainWnd);
902     hViewMenu = GetSubMenu(hMenu, 2);
903     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
904     TaskManagerSettings.UpdateSpeed = 0;
905     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_PAUSED, MF_BYCOMMAND);
906     KillTimer(hMainWnd, 1);
907 }
908
909 void TaskManager_OnTabWndSelChange(void)
910 {
911     int   i;
912     HMENU hMenu;
913     HMENU hOptionsMenu;
914     HMENU hViewMenu;
915     HMENU hSubMenu;
916
917     hMenu = GetMenu(hMainWnd);
918     hViewMenu = GetSubMenu(hMenu, 2);
919     hOptionsMenu = GetSubMenu(hMenu, 1);
920     TaskManagerSettings.ActiveTabPage = TabCtrl_GetCurSel(hTabWnd);
921     for (i = GetMenuItemCount(hViewMenu) - 1; i > 2; i--) {
922         hSubMenu = GetSubMenu(hViewMenu, i);
923         if (hSubMenu)
924             DestroyMenu(hSubMenu);
925         RemoveMenu(hViewMenu, i, MF_BYPOSITION);
926     }
927     RemoveMenu(hOptionsMenu, 3, MF_BYPOSITION);
928     switch (TaskManagerSettings.ActiveTabPage) {
929     case 0:
930         ShowWindow(hApplicationPage, SW_SHOW);
931         ShowWindow(hProcessPage, SW_HIDE);
932         ShowWindow(hPerformancePage, SW_HIDE);
933         BringWindowToTop(hApplicationPage);
934         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_LARGE, _T("Lar&ge Icons"));
935         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_SMALL, _T("S&mall Icons"));
936         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_DETAILS, _T("&Details"));
937
938         if (GetMenuItemCount(hMenu) <= 4) {
939             hSubMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_WINDOWSMENU));
940             InsertMenu(hMenu, 3, MF_BYPOSITION|MF_POPUP, (UINT)hSubMenu, _T("&Windows"));
941             DrawMenuBar(hMainWnd);
942         }
943         if (TaskManagerSettings.View_LargeIcons)
944             CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
945         else if (TaskManagerSettings.View_SmallIcons)
946             CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
947         else
948             CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);
949         /*
950          * Give the application list control focus
951          */
952         SetFocus(hApplicationPageListCtrl);
953         break;
954
955     case 1:
956         ShowWindow(hApplicationPage, SW_HIDE);
957         ShowWindow(hProcessPage, SW_SHOW);
958         ShowWindow(hPerformancePage, SW_HIDE);
959         BringWindowToTop(hProcessPage);
960         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_SELECTCOLUMNS, _T("&Select Columns..."));
961         AppendMenu(hOptionsMenu, MF_STRING, ID_OPTIONS_SHOW16BITTASKS, _T("&Show 16-bit tasks"));
962         if (TaskManagerSettings.Show16BitTasks)
963             CheckMenuItem(hOptionsMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED);
964         if (GetMenuItemCount(hMenu) > 4)
965         {
966             RemoveMenu(hMenu, 3, MF_BYPOSITION);
967             DrawMenuBar(hMainWnd);
968         }
969         /*
970          * Give the process list control focus
971          */
972         SetFocus(hProcessPageListCtrl);
973         break;
974
975     case 2:
976         ShowWindow(hApplicationPage, SW_HIDE);
977         ShowWindow(hProcessPage, SW_HIDE);
978         ShowWindow(hPerformancePage, SW_SHOW);
979         BringWindowToTop(hPerformancePage);
980         if (GetMenuItemCount(hMenu) > 4) {
981             RemoveMenu(hMenu, 3, MF_BYPOSITION);
982             DrawMenuBar(hMainWnd);
983         }
984         hSubMenu = CreatePopupMenu();
985         AppendMenu(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHALL, _T("&One Graph, All CPUs"));
986         AppendMenu(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, _T("One Graph &Per CPU"));
987         AppendMenu(hViewMenu, MF_STRING|MF_POPUP, (UINT)hSubMenu, _T("&CPU History"));
988         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_SHOWKERNELTIMES, _T("&Show Kernel Times"));
989         if (TaskManagerSettings.ShowKernelTimes)
990             CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
991         else
992             CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
993         if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
994             CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
995         else
996             CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
997         /*
998          * Give the tab control focus
999          */
1000         SetFocus(hTabWnd);
1001         break;
1002     }
1003 }
1004
1005 LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize)
1006 {
1007     DWORD  dwRet;
1008     LPTSTR lpszTemp = NULL;
1009
1010     dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
1011                            NULL,
1012                            GetLastError(),
1013                            LANG_NEUTRAL,
1014                            (LPTSTR)&lpszTemp,
1015                            0,
1016                            NULL );
1017
1018     /* supplied buffer is not long enough */
1019     if (!dwRet || ( (long)dwSize < (long)dwRet+14)) {
1020         lpszBuf[0] = TEXT('\0');
1021     } else {
1022         lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0');  /*remove cr and newline character */
1023         _stprintf(lpszBuf, TEXT("%s (0x%x)"), lpszTemp, (int)GetLastError());
1024     }
1025     if (lpszTemp) {
1026         LocalFree((HLOCAL)lpszTemp);
1027     }
1028     return lpszBuf;
1029 }