Update Korean translations.
[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_RESTORE:
148             TaskManager_OnRestoreMainWindow();
149             break;
150         case ID_VIEW_LARGE:
151             ApplicationPage_OnViewLargeIcons();
152             break;
153         case ID_VIEW_SMALL:
154             ApplicationPage_OnViewSmallIcons();
155             break;
156         case ID_VIEW_DETAILS:
157             ApplicationPage_OnViewDetails();
158             break;
159         case ID_VIEW_SHOWKERNELTIMES:
160             PerformancePage_OnViewShowKernelTimes();
161             break;
162         case ID_VIEW_CPUHISTORY_ONEGRAPHALL:
163             PerformancePage_OnViewCPUHistoryOneGraphAll();
164             break;
165         case ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU:
166             PerformancePage_OnViewCPUHistoryOneGraphPerCPU();
167             break;
168         case ID_VIEW_UPDATESPEED_HIGH:
169             TaskManager_OnViewUpdateSpeedHigh();
170             break;
171         case ID_VIEW_UPDATESPEED_NORMAL:
172             TaskManager_OnViewUpdateSpeedNormal();
173             break;
174         case ID_VIEW_UPDATESPEED_LOW:
175             TaskManager_OnViewUpdateSpeedLow();
176             break;
177         case ID_VIEW_UPDATESPEED_PAUSED:
178             TaskManager_OnViewUpdateSpeedPaused();
179             break;
180         case ID_VIEW_SELECTCOLUMNS:
181             ProcessPage_OnViewSelectColumns();
182             break;
183         case ID_VIEW_REFRESH:
184             PostMessage(hDlg, WM_TIMER, 0, 0);
185             break;
186         case ID_WINDOWS_TILEHORIZONTALLY:
187             ApplicationPage_OnWindowsTileHorizontally();
188             break;
189         case ID_WINDOWS_TILEVERTICALLY:
190             ApplicationPage_OnWindowsTileVertically();
191             break;
192         case ID_WINDOWS_MINIMIZE:
193             ApplicationPage_OnWindowsMinimize();
194             break;
195         case ID_WINDOWS_MAXIMIZE:
196             ApplicationPage_OnWindowsMaximize();
197             break;
198         case ID_WINDOWS_CASCADE:
199             ApplicationPage_OnWindowsCascade();
200             break;
201         case ID_WINDOWS_BRINGTOFRONT:
202             ApplicationPage_OnWindowsBringToFront();
203             break;
204         case ID_APPLICATION_PAGE_SWITCHTO:
205             ApplicationPage_OnSwitchTo();
206             break;
207         case ID_APPLICATION_PAGE_ENDTASK:
208             ApplicationPage_OnEndTask();
209             break;
210         case ID_APPLICATION_PAGE_GOTOPROCESS:
211             ApplicationPage_OnGotoProcess();
212             break;
213         case ID_PROCESS_PAGE_ENDPROCESS:
214             ProcessPage_OnEndProcess();
215             break;
216         case ID_PROCESS_PAGE_ENDPROCESSTREE:
217             ProcessPage_OnEndProcessTree();
218             break;
219         case ID_PROCESS_PAGE_DEBUG:
220             ProcessPage_OnDebug();
221             break;
222         case ID_PROCESS_PAGE_SETAFFINITY:
223             ProcessPage_OnSetAffinity();
224             break;
225         case ID_PROCESS_PAGE_SETPRIORITY_REALTIME:
226             ProcessPage_OnSetPriorityRealTime();
227             break;
228         case ID_PROCESS_PAGE_SETPRIORITY_HIGH:
229             ProcessPage_OnSetPriorityHigh();
230             break;
231         case ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL:
232             ProcessPage_OnSetPriorityAboveNormal();
233             break;
234         case ID_PROCESS_PAGE_SETPRIORITY_NORMAL:
235             ProcessPage_OnSetPriorityNormal();
236             break;
237         case ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL:
238             ProcessPage_OnSetPriorityBelowNormal();
239             break;
240         case ID_PROCESS_PAGE_SETPRIORITY_LOW:
241             ProcessPage_OnSetPriorityLow();
242             break;
243         case ID_PROCESS_PAGE_DEBUGCHANNELS:
244             ProcessPage_OnDebugChannels();
245             break;
246         case ID_HELP_ABOUT:
247             OnAbout();
248             break;
249         case ID_FILE_EXIT:
250             EndDialog(hDlg, IDOK);
251             break;
252         }     
253         break;
254
255     case WM_ONTRAYICON:
256         switch(lParam)
257         {
258         case WM_RBUTTONDOWN:
259             {
260             POINT pt;
261             BOOL OnTop;
262             HMENU hMenu, hPopupMenu;
263             
264             GetCursorPos(&pt);
265             
266             OnTop = ((GetWindowLong(hMainWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0);
267             
268             hMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_TRAY_POPUP));
269             hPopupMenu = GetSubMenu(hMenu, 0);
270             
271             if(IsWindowVisible(hMainWnd))
272             {
273               DeleteMenu(hPopupMenu, ID_RESTORE, MF_BYCOMMAND);
274             }
275             else
276             {
277               SetMenuDefaultItem(hPopupMenu, ID_RESTORE, FALSE);
278             }
279             
280             if(OnTop)
281             {
282               CheckMenuItem(hPopupMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND | MF_CHECKED);
283             }
284             
285             SetForegroundWindow(hMainWnd);
286             TrackPopupMenuEx(hPopupMenu, 0, pt.x, pt.y, hMainWnd, NULL);
287             
288             DestroyMenu(hMenu);
289             break;
290             }
291         case WM_LBUTTONDBLCLK:
292             TaskManager_OnRestoreMainWindow();
293             break;
294         }
295         break;
296
297     case WM_NOTIFY:
298         idctrl = (int)wParam;
299         pnmh = (LPNMHDR)lParam;
300         if ((pnmh->hwndFrom == hTabWnd) &&
301             (pnmh->idFrom == IDC_TAB) &&
302             (pnmh->code == TCN_SELCHANGE))
303         {
304             TaskManager_OnTabWndSelChange();
305         }
306         break;
307
308     case WM_NCPAINT:
309         hdc = GetDC(hDlg);
310         GetClientRect(hDlg, &rc);
311         Draw3dRect(hdc, rc.left, rc.top, rc.right, rc.top + 2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
312         ReleaseDC(hDlg, hdc);
313         break;
314
315     case WM_PAINT:
316         hdc = BeginPaint(hDlg, &ps);
317         GetClientRect(hDlg, &rc);
318         Draw3dRect(hdc, rc.left, rc.top, rc.right, rc.top + 2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
319         EndPaint(hDlg, &ps);
320         break;
321
322     case WM_SIZING:
323         /* Make sure the user is sizing the dialog */
324         /* in an acceptable range */
325         pRC = (LPRECT)lParam;
326         if ((wParam == WMSZ_LEFT) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_BOTTOMLEFT)) {
327             /* If the width is too small enlarge it to the minimum */
328             if (nMinimumWidth > (pRC->right - pRC->left))
329                 pRC->left = pRC->right - nMinimumWidth;
330         } else {
331             /* If the width is too small enlarge it to the minimum */
332             if (nMinimumWidth > (pRC->right - pRC->left))
333                 pRC->right = pRC->left + nMinimumWidth;
334         }
335         if ((wParam == WMSZ_TOP) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_TOPRIGHT)) {
336             /* If the height is too small enlarge it to the minimum */
337             if (nMinimumHeight > (pRC->bottom - pRC->top))
338                 pRC->top = pRC->bottom - nMinimumHeight;
339         } else {
340             /* If the height is too small enlarge it to the minimum */
341             if (nMinimumHeight > (pRC->bottom - pRC->top))
342                 pRC->bottom = pRC->top + nMinimumHeight;
343         }
344         return TRUE;
345         break;
346
347     case WM_SIZE:
348         /* Handle the window sizing in it's own function */
349         OnSize(wParam, LOWORD(lParam), HIWORD(lParam));
350         break;
351
352     case WM_MOVE:
353         /* Handle the window moving in it's own function */
354         OnMove(wParam, LOWORD(lParam), HIWORD(lParam));
355         break;
356
357     case WM_DESTROY:
358         ShowWindow(hDlg, SW_HIDE);
359         TrayIcon_ShellRemoveTrayIcon();
360         wp.length = sizeof(WINDOWPLACEMENT);
361         GetWindowPlacement(hDlg, &wp);
362         TaskManagerSettings.Left = wp.rcNormalPosition.left;
363         TaskManagerSettings.Top = wp.rcNormalPosition.top;
364         TaskManagerSettings.Right = wp.rcNormalPosition.right;
365         TaskManagerSettings.Bottom = wp.rcNormalPosition.bottom;
366         if (IsZoomed(hDlg) || (wp.flags & WPF_RESTORETOMAXIMIZED))
367             TaskManagerSettings.Maximized = TRUE;
368         else
369             TaskManagerSettings.Maximized = FALSE;
370         return DefWindowProc(hDlg, message, wParam, lParam);
371         
372     case WM_TIMER:
373         /* Refresh the performance data */
374         PerfDataRefresh();
375         RefreshApplicationPage();
376         RefreshProcessPage();
377         RefreshPerformancePage();
378         TrayIcon_ShellUpdateTrayIcon();
379         break;
380
381     case WM_ENTERMENULOOP:
382         TaskManager_OnEnterMenuLoop(hDlg);
383         break;
384     case WM_EXITMENULOOP:
385         TaskManager_OnExitMenuLoop(hDlg);
386         break;
387     case WM_MENUSELECT:
388         TaskManager_OnMenuSelect(hDlg, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
389         break;
390     }
391
392     return 0;
393 }
394
395 void FillSolidRect(HDC hDC, LPCRECT lpRect, COLORREF clr)
396 {
397     SetBkColor(hDC, clr);
398     ExtTextOut(hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
399 }
400
401 void FillSolidRect2(HDC hDC, int x, int y, int cx, int cy, COLORREF clr)
402 {
403     RECT rect;
404
405     SetBkColor(hDC, clr);
406     rect.left = x;
407     rect.top = y;
408     rect.right = x + cx;
409     rect.bottom = y + cy;
410     ExtTextOut(hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
411 }
412
413 void Draw3dRect(HDC hDC, int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight)
414 {
415     FillSolidRect2(hDC, x, y, cx - 1, 1, clrTopLeft);
416     FillSolidRect2(hDC, x, y, 1, cy - 1, clrTopLeft);
417     FillSolidRect2(hDC, x + cx, y, -1, cy, clrBottomRight);
418     FillSolidRect2(hDC, x, y + cy, cx, -1, clrBottomRight);
419 }
420
421 void Draw3dRect2(HDC hDC, LPRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight)
422 {
423     Draw3dRect(hDC, lpRect->left, lpRect->top, lpRect->right - lpRect->left,
424         lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
425 }
426
427 void Font_DrawText(HDC hDC, LPCTSTR lpszText, int x, int y)
428 {
429     HDC        hFontDC;
430     HBITMAP    hFontBitmap;
431     HBITMAP    hOldBitmap;
432     int        i;
433
434     hFontDC = CreateCompatibleDC(hDC);
435     hFontBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_FONT));
436     hOldBitmap = (HBITMAP)SelectObject(hFontDC, hFontBitmap);
437
438     for (i = 0; i < (int)_tcslen(lpszText); i++) {
439         if ((lpszText[i] >= '0') && (lpszText[i] <= '9')) {
440             BitBlt(hDC, x + (i * 8), y, 8, 11, hFontDC, (lpszText[i] - '0') * 8, 0, SRCCOPY);
441         }
442         else if (lpszText[i] == 'K')
443         {
444             BitBlt(hDC, x + (i * 8), y, 8, 11, hFontDC, 80, 0, SRCCOPY);
445         }
446         else if (lpszText[i] == '%')
447         {
448             BitBlt(hDC, x + (i * 8), y, 8, 11, hFontDC, 88, 0, SRCCOPY);
449         }
450     }
451     SelectObject(hFontDC, hOldBitmap);
452     DeleteObject(hFontBitmap);
453     DeleteDC(hFontDC);
454 }
455
456 BOOL OnCreate(HWND hWnd)
457 {
458     HMENU   hMenu;
459     HMENU   hEditMenu;
460     HMENU   hViewMenu;
461     HMENU   hUpdateSpeedMenu;
462     HMENU   hCPUHistoryMenu;
463     int     nActivePage;
464     int     nParts[3];
465     RECT    rc;
466     TCHAR   szTemp[256];
467     TCITEM  item;
468
469     SendMessage(hMainWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(hInst, MAKEINTRESOURCE(IDI_TASKMANAGER)));
470
471     /* Initialize the Windows Common Controls DLL */
472     InitCommonControls();
473
474     /* Get the minimum window sizes */
475     GetWindowRect(hWnd, &rc);
476     nMinimumWidth = (rc.right - rc.left);
477     nMinimumHeight = (rc.bottom - rc.top);
478
479     /* Create the status bar */
480     hStatusWnd = CreateStatusWindow(WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|SBT_NOBORDERS, _T(""), hWnd, STATUS_WINDOW);
481     if(!hStatusWnd)
482         return FALSE;
483
484     /* Create the status bar panes */
485     nParts[0] = 100;
486     nParts[1] = 210;
487     nParts[2] = 400;
488     SendMessage(hStatusWnd, SB_SETPARTS, 3, (long)nParts);
489
490     /* Create tab pages */
491     hTabWnd = GetDlgItem(hWnd, IDC_TAB);
492 #if 1
493     hApplicationPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_APPLICATION_PAGE), hWnd, ApplicationPageWndProc);
494     hProcessPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PROCESS_PAGE), hWnd, ProcessPageWndProc);
495     hPerformancePage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PERFORMANCE_PAGE), hWnd, PerformancePageWndProc);
496 #else
497     hApplicationPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_APPLICATION_PAGE), hTabWnd, ApplicationPageWndProc);
498     hProcessPage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PROCESS_PAGE), hTabWnd, ProcessPageWndProc);
499     hPerformancePage = CreateDialog(hInst, MAKEINTRESOURCE(IDD_PERFORMANCE_PAGE), hTabWnd, PerformancePageWndProc);
500 #endif
501
502     /* Insert tabs */
503     _tcscpy(szTemp, _T("Applications"));
504     memset(&item, 0, sizeof(TCITEM));
505     item.mask = TCIF_TEXT;
506     item.pszText = szTemp;
507     TabCtrl_InsertItem(hTabWnd, 0, &item);
508     _tcscpy(szTemp, _T("Processes"));
509     memset(&item, 0, sizeof(TCITEM));
510     item.mask = TCIF_TEXT;
511     item.pszText = szTemp;
512     TabCtrl_InsertItem(hTabWnd, 1, &item);
513     _tcscpy(szTemp, _T("Performance"));
514     memset(&item, 0, sizeof(TCITEM));
515     item.mask = TCIF_TEXT;
516     item.pszText = szTemp;
517     TabCtrl_InsertItem(hTabWnd, 2, &item);
518
519     /* Size everything correctly */
520     GetClientRect(hWnd, &rc);
521     nOldWidth = rc.right;
522     nOldHeight = rc.bottom;
523     /* nOldStartX = rc.left; */
524     /*nOldStartY = rc.top;  */
525
526 #define PAGE_OFFSET_LEFT    17
527 #define PAGE_OFFSET_TOP     72
528 #define PAGE_OFFSET_WIDTH   (PAGE_OFFSET_LEFT*2)
529 #define PAGE_OFFSET_HEIGHT  (PAGE_OFFSET_TOP+32)
530
531     if ((TaskManagerSettings.Left != 0) ||
532         (TaskManagerSettings.Top != 0) ||
533         (TaskManagerSettings.Right != 0) ||
534         (TaskManagerSettings.Bottom != 0))
535     {
536         MoveWindow(hWnd, TaskManagerSettings.Left, TaskManagerSettings.Top, TaskManagerSettings.Right - TaskManagerSettings.Left, TaskManagerSettings.Bottom - TaskManagerSettings.Top, TRUE);
537 #ifdef __GNUC__TEST__
538         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);
539         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);
540         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);
541 #endif
542     }
543     if (TaskManagerSettings.Maximized)
544         ShowWindow(hWnd, SW_MAXIMIZE);
545
546     /* Set the always on top style */
547     hMenu = GetMenu(hWnd);
548     hEditMenu = GetSubMenu(hMenu, 1);
549     hViewMenu = GetSubMenu(hMenu, 2);
550     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
551     hCPUHistoryMenu = GetSubMenu(hViewMenu, 7);
552
553     /* Check or uncheck the always on top menu item */
554     if (TaskManagerSettings.AlwaysOnTop) {
555         CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_CHECKED);
556         SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
557     } else {
558         CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_UNCHECKED);
559         SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
560     }
561
562     /* Check or uncheck the minimize on use menu item */
563     if (TaskManagerSettings.MinimizeOnUse)
564         CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_CHECKED);
565     else
566         CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_UNCHECKED);
567
568     /* Check or uncheck the hide when minimized menu item */
569     if (TaskManagerSettings.HideWhenMinimized)
570         CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_CHECKED);
571     else
572         CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_UNCHECKED);
573
574     /* Check or uncheck the show 16-bit tasks menu item */
575     if (TaskManagerSettings.Show16BitTasks)
576         CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED);
577     else
578         CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_UNCHECKED);
579
580     if (TaskManagerSettings.View_LargeIcons)
581         CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
582     else if (TaskManagerSettings.View_SmallIcons)
583         CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
584     else
585         CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);
586
587     if (TaskManagerSettings.ShowKernelTimes)
588         CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
589     else
590         CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
591
592     if (TaskManagerSettings.UpdateSpeed == 1)
593         CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_HIGH, MF_BYCOMMAND);
594     else if (TaskManagerSettings.UpdateSpeed == 2)
595         CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_NORMAL, MF_BYCOMMAND);
596     else if (TaskManagerSettings.UpdateSpeed == 4)
597         CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_LOW, MF_BYCOMMAND);
598     else
599         CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_PAUSED, MF_BYCOMMAND);
600
601     if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
602         CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
603     else
604         CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
605
606     nActivePage = TaskManagerSettings.ActiveTabPage;
607     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 0);
608     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 1);
609     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 2);
610     TabCtrl_SetCurFocus/*Sel*/(hTabWnd, nActivePage);
611
612     if (TaskManagerSettings.UpdateSpeed == 1)
613         SetTimer(hWnd, 1, 1000, NULL);
614     else if (TaskManagerSettings.UpdateSpeed == 2)
615         SetTimer(hWnd, 1, 2000, NULL);
616     else if (TaskManagerSettings.UpdateSpeed == 4)
617         SetTimer(hWnd, 1, 4000, NULL);
618
619     /*
620      * Refresh the performance data
621      * Sample it twice so we can establish
622      * the delta values & cpu usage
623      */
624     PerfDataRefresh();
625     PerfDataRefresh();
626
627     RefreshApplicationPage();
628     RefreshProcessPage();
629     RefreshPerformancePage();
630
631     TrayIcon_ShellAddTrayIcon();
632
633     return TRUE;
634 }
635
636 /* OnMove()
637  * This function handles all the moving events for the application
638  * It moves every child window that needs moving
639  */
640 void OnMove( UINT nType, int cx, int cy )
641 {
642 #ifdef __GNUC__TEST__
643     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);
644     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);
645     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);
646 #endif
647 }
648
649 /* OnSize()
650  * This function handles all the sizing events for the application
651  * It re-sizes every window, and child window that needs re-sizing
652  */
653 void OnSize( UINT nType, int cx, int cy )
654 {
655     int     nParts[3];
656     int     nXDifference;
657     int     nYDifference;
658     RECT    rc;
659
660     if (nType == SIZE_MINIMIZED)
661     {
662         if(TaskManagerSettings.HideWhenMinimized)
663         {
664           ShowWindow(hMainWnd, SW_HIDE);
665         }
666         return;
667     }
668
669     nXDifference = cx - nOldWidth;
670     nYDifference = cy - nOldHeight;
671     nOldWidth = cx;
672     nOldHeight = cy;
673
674     /* Update the status bar size */
675     GetWindowRect(hStatusWnd, &rc);
676     SendMessage(hStatusWnd, WM_SIZE, nType, MAKELPARAM(cx, cy + (rc.bottom - rc.top)));
677
678     /* Update the status bar pane sizes */
679     nParts[0] = bInMenuLoop ? -1 : 100;
680     nParts[1] = 210;
681     nParts[2] = cx;
682     SendMessage(hStatusWnd, SB_SETPARTS, bInMenuLoop ? 1 : 3, (long)nParts);
683
684     /* Resize the tab control */
685     GetWindowRect(hTabWnd, &rc);
686     cx = (rc.right - rc.left) + nXDifference;
687     cy = (rc.bottom - rc.top) + nYDifference;
688     SetWindowPos(hTabWnd, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
689
690     /* Resize the application page */
691     GetWindowRect(hApplicationPage, &rc);
692     cx = (rc.right - rc.left) + nXDifference;
693     cy = (rc.bottom - rc.top) + nYDifference;
694     SetWindowPos(hApplicationPage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
695     
696     /* Resize the process page */
697     GetWindowRect(hProcessPage, &rc);
698     cx = (rc.right - rc.left) + nXDifference;
699     cy = (rc.bottom - rc.top) + nYDifference;
700     SetWindowPos(hProcessPage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
701     
702     /* Resize the performance page */
703     GetWindowRect(hPerformancePage, &rc);
704     cx = (rc.right - rc.left) + nXDifference;
705     cy = (rc.bottom - rc.top) + nYDifference;
706     SetWindowPos(hPerformancePage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
707 }
708
709 void LoadSettings(void)
710 {
711     HKEY    hKey;
712     TCHAR   szSubKey[] = _T("Software\\Wine\\TaskManager");
713     int     i;
714     DWORD   dwSize;
715
716     /* Window size & position settings */
717     TaskManagerSettings.Maximized = FALSE;
718     TaskManagerSettings.Left = 0;
719     TaskManagerSettings.Top = 0;
720     TaskManagerSettings.Right = 0;
721     TaskManagerSettings.Bottom = 0;
722
723     /* Tab settings */
724     TaskManagerSettings.ActiveTabPage = 0;
725
726     /* Options menu settings */
727     TaskManagerSettings.AlwaysOnTop = FALSE;
728     TaskManagerSettings.MinimizeOnUse = TRUE;
729     TaskManagerSettings.HideWhenMinimized = TRUE;
730     TaskManagerSettings.Show16BitTasks = TRUE;
731
732     /* Update speed settings */
733     TaskManagerSettings.UpdateSpeed = 2;
734
735     /* Applications page settings */
736     TaskManagerSettings.View_LargeIcons = FALSE;
737     TaskManagerSettings.View_SmallIcons = FALSE;
738     TaskManagerSettings.View_Details = TRUE;
739
740     /* Processes page settings */
741     TaskManagerSettings.ShowProcessesFromAllUsers = FALSE; /* Server-only? */
742     TaskManagerSettings.Column_ImageName = TRUE;
743     TaskManagerSettings.Column_PID = TRUE;
744     TaskManagerSettings.Column_CPUUsage = TRUE;
745     TaskManagerSettings.Column_CPUTime = TRUE;
746     TaskManagerSettings.Column_MemoryUsage = TRUE;
747     TaskManagerSettings.Column_MemoryUsageDelta = FALSE;
748     TaskManagerSettings.Column_PeakMemoryUsage = FALSE;
749     TaskManagerSettings.Column_PageFaults = FALSE;
750     TaskManagerSettings.Column_USERObjects = FALSE;
751     TaskManagerSettings.Column_IOReads = FALSE;
752     TaskManagerSettings.Column_IOReadBytes = FALSE;
753     TaskManagerSettings.Column_SessionID = FALSE; /* Server-only? */
754     TaskManagerSettings.Column_UserName = FALSE; /* Server-only? */
755     TaskManagerSettings.Column_PageFaultsDelta = FALSE;
756     TaskManagerSettings.Column_VirtualMemorySize = FALSE;
757     TaskManagerSettings.Column_PagedPool = FALSE;
758     TaskManagerSettings.Column_NonPagedPool = FALSE;
759     TaskManagerSettings.Column_BasePriority = FALSE;
760     TaskManagerSettings.Column_HandleCount = FALSE;
761     TaskManagerSettings.Column_ThreadCount = FALSE;
762     TaskManagerSettings.Column_GDIObjects = FALSE;
763     TaskManagerSettings.Column_IOWrites = FALSE;
764     TaskManagerSettings.Column_IOWriteBytes = FALSE;
765     TaskManagerSettings.Column_IOOther = FALSE;
766     TaskManagerSettings.Column_IOOtherBytes = FALSE;
767
768     for (i = 0; i < 25; i++) {
769         TaskManagerSettings.ColumnOrderArray[i] = i;
770     }
771     TaskManagerSettings.ColumnSizeArray[0] = 105;
772     TaskManagerSettings.ColumnSizeArray[1] = 50;
773     TaskManagerSettings.ColumnSizeArray[2] = 107;
774     TaskManagerSettings.ColumnSizeArray[3] = 70;
775     TaskManagerSettings.ColumnSizeArray[4] = 35;
776     TaskManagerSettings.ColumnSizeArray[5] = 70;
777     TaskManagerSettings.ColumnSizeArray[6] = 70;
778     TaskManagerSettings.ColumnSizeArray[7] = 100;
779     TaskManagerSettings.ColumnSizeArray[8] = 70;
780     TaskManagerSettings.ColumnSizeArray[9] = 70;
781     TaskManagerSettings.ColumnSizeArray[10] = 70;
782     TaskManagerSettings.ColumnSizeArray[11] = 70;
783     TaskManagerSettings.ColumnSizeArray[12] = 70;
784     TaskManagerSettings.ColumnSizeArray[13] = 70;
785     TaskManagerSettings.ColumnSizeArray[14] = 60;
786     TaskManagerSettings.ColumnSizeArray[15] = 60;
787     TaskManagerSettings.ColumnSizeArray[16] = 60;
788     TaskManagerSettings.ColumnSizeArray[17] = 60;
789     TaskManagerSettings.ColumnSizeArray[18] = 60;
790     TaskManagerSettings.ColumnSizeArray[19] = 70;
791     TaskManagerSettings.ColumnSizeArray[20] = 70;
792     TaskManagerSettings.ColumnSizeArray[21] = 70;
793     TaskManagerSettings.ColumnSizeArray[22] = 70;
794     TaskManagerSettings.ColumnSizeArray[23] = 70;
795     TaskManagerSettings.ColumnSizeArray[24] = 70;
796
797     TaskManagerSettings.SortColumn = 1;
798     TaskManagerSettings.SortAscending = TRUE;
799
800     /* Performance page settings */
801     TaskManagerSettings.CPUHistory_OneGraphPerCPU = TRUE;
802     TaskManagerSettings.ShowKernelTimes = FALSE;
803
804     /* Open the key */
805     /* @@ Wine registry key: HKCU\Software\Wine\TaskManager */
806     if (RegOpenKeyEx(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
807         return;
808     /* Read the settings */
809     dwSize = sizeof(TASKMANAGER_SETTINGS);
810     RegQueryValueEx(hKey, _T("Preferences"), NULL, NULL, (LPBYTE)&TaskManagerSettings, &dwSize);
811
812     /* Close the key */
813     RegCloseKey(hKey);
814 }
815
816 void SaveSettings(void)
817 {
818     HKEY hKey;
819     TCHAR szSubKey3[] = _T("Software\\Wine\\TaskManager");
820
821     /* Open (or create) the key */
822
823     /* @@ Wine registry key: HKCU\Software\Wine\TaskManager */
824     if (RegCreateKeyEx(HKEY_CURRENT_USER, szSubKey3, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
825         return;
826     /* Save the settings */
827     RegSetValueEx(hKey, _T("Preferences"), 0, REG_BINARY, (LPBYTE)&TaskManagerSettings, sizeof(TASKMANAGER_SETTINGS));
828     /* Close the key */
829     RegCloseKey(hKey);
830 }
831
832 void TaskManager_OnRestoreMainWindow(void)
833 {
834   HMENU hMenu, hOptionsMenu;
835   BOOL OnTop;
836
837   hMenu = GetMenu(hMainWnd);
838   hOptionsMenu = GetSubMenu(hMenu, OPTIONS_MENU_INDEX);
839   OnTop = ((GetWindowLong(hMainWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0);
840   
841   OpenIcon(hMainWnd);
842   SetForegroundWindow(hMainWnd);
843   SetWindowPos(hMainWnd, (OnTop ? HWND_TOPMOST : HWND_TOP), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
844 }
845
846 void TaskManager_OnEnterMenuLoop(HWND hWnd)
847 {
848     int nParts;
849
850     /* Update the status bar pane sizes */
851     nParts = -1;
852     SendMessage(hStatusWnd, SB_SETPARTS, 1, (long)&nParts);
853     bInMenuLoop = TRUE;
854     SendMessage(hStatusWnd, SB_SETTEXT, (WPARAM)0, (LPARAM)_T(""));
855 }
856
857 void TaskManager_OnExitMenuLoop(HWND hWnd)
858 {
859     RECT  rc;
860     int   nParts[3];
861     TCHAR text[260];
862
863     bInMenuLoop = FALSE;
864     /* Update the status bar pane sizes */
865     GetClientRect(hWnd, &rc);
866     nParts[0] = 100;
867     nParts[1] = 210;
868     nParts[2] = rc.right;
869     SendMessage(hStatusWnd, SB_SETPARTS, 3, (long)nParts);
870     SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)_T(""));
871     wsprintf(text, _T("CPU Usage: %3d%%"), PerfDataGetProcessorUsage());
872     SendMessage(hStatusWnd, SB_SETTEXT, 1, (LPARAM)text);
873     wsprintf(text, _T("Processes: %d"), PerfDataGetProcessCount());
874     SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text);
875 }
876
877 void TaskManager_OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
878 {
879     TCHAR str[100];
880
881     _tcscpy(str, TEXT(""));
882     if (LoadString(hInst, nItemID, str, 100)) {
883         /* load appropriate string */
884         LPTSTR lpsz = str;
885         /* first newline terminates actual string */
886         lpsz = _tcschr(lpsz, '\n');
887         if (lpsz != NULL)
888             *lpsz = '\0';
889     }
890     SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)str);
891 }
892
893 void TaskManager_OnViewUpdateSpeedHigh(void)
894 {
895     HMENU hMenu;
896     HMENU hViewMenu;
897     HMENU hUpdateSpeedMenu;
898
899     hMenu = GetMenu(hMainWnd);
900     hViewMenu = GetSubMenu(hMenu, 2);
901     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
902
903     TaskManagerSettings.UpdateSpeed = 1;
904     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_HIGH, MF_BYCOMMAND);
905
906     KillTimer(hMainWnd, 1);
907     SetTimer(hMainWnd, 1, 1000, NULL);
908 }
909
910 void TaskManager_OnViewUpdateSpeedNormal(void)
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 = 2;
921     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_NORMAL, MF_BYCOMMAND);
922
923     KillTimer(hMainWnd, 1);
924     SetTimer(hMainWnd, 1, 2000, NULL);
925 }
926
927 void TaskManager_OnViewUpdateSpeedLow(void)
928 {
929     HMENU hMenu;
930     HMENU hViewMenu;
931     HMENU hUpdateSpeedMenu;
932
933     hMenu = GetMenu(hMainWnd);
934     hViewMenu = GetSubMenu(hMenu, 2);
935     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
936
937     TaskManagerSettings.UpdateSpeed = 4;
938     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_LOW, MF_BYCOMMAND);
939
940     KillTimer(hMainWnd, 1);
941     SetTimer(hMainWnd, 1, 4000, NULL);
942 }
943
944 void TaskManager_OnViewRefresh(void)
945 {
946     PostMessage(hMainWnd, WM_TIMER, 0, 0);
947 }
948
949 void TaskManager_OnViewUpdateSpeedPaused(void)
950 {
951     HMENU hMenu;
952     HMENU hViewMenu;
953     HMENU hUpdateSpeedMenu;
954
955     hMenu = GetMenu(hMainWnd);
956     hViewMenu = GetSubMenu(hMenu, 2);
957     hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
958     TaskManagerSettings.UpdateSpeed = 0;
959     CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, ID_VIEW_UPDATESPEED_PAUSED, MF_BYCOMMAND);
960     KillTimer(hMainWnd, 1);
961 }
962
963 void TaskManager_OnTabWndSelChange(void)
964 {
965     int   i;
966     HMENU hMenu;
967     HMENU hOptionsMenu;
968     HMENU hViewMenu;
969     HMENU hSubMenu;
970
971     hMenu = GetMenu(hMainWnd);
972     hViewMenu = GetSubMenu(hMenu, 2);
973     hOptionsMenu = GetSubMenu(hMenu, 1);
974     TaskManagerSettings.ActiveTabPage = TabCtrl_GetCurSel(hTabWnd);
975     for (i = GetMenuItemCount(hViewMenu) - 1; i > 2; i--) {
976         hSubMenu = GetSubMenu(hViewMenu, i);
977         if (hSubMenu)
978             DestroyMenu(hSubMenu);
979         RemoveMenu(hViewMenu, i, MF_BYPOSITION);
980     }
981     RemoveMenu(hOptionsMenu, 3, MF_BYPOSITION);
982     switch (TaskManagerSettings.ActiveTabPage) {
983     case 0:
984         ShowWindow(hApplicationPage, SW_SHOW);
985         ShowWindow(hProcessPage, SW_HIDE);
986         ShowWindow(hPerformancePage, SW_HIDE);
987         BringWindowToTop(hApplicationPage);
988         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_LARGE, _T("Lar&ge Icons"));
989         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_SMALL, _T("S&mall Icons"));
990         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_DETAILS, _T("&Details"));
991
992         if (GetMenuItemCount(hMenu) <= 4) {
993             hSubMenu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_WINDOWSMENU));
994             InsertMenu(hMenu, 3, MF_BYPOSITION|MF_POPUP, (UINT)hSubMenu, _T("&Windows"));
995             DrawMenuBar(hMainWnd);
996         }
997         if (TaskManagerSettings.View_LargeIcons)
998             CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_LARGE, MF_BYCOMMAND);
999         else if (TaskManagerSettings.View_SmallIcons)
1000             CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_SMALL, MF_BYCOMMAND);
1001         else
1002             CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, ID_VIEW_DETAILS, MF_BYCOMMAND);
1003         /*
1004          * Give the application list control focus
1005          */
1006         SetFocus(hApplicationPageListCtrl);
1007         break;
1008
1009     case 1:
1010         ShowWindow(hApplicationPage, SW_HIDE);
1011         ShowWindow(hProcessPage, SW_SHOW);
1012         ShowWindow(hPerformancePage, SW_HIDE);
1013         BringWindowToTop(hProcessPage);
1014         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_SELECTCOLUMNS, _T("&Select Columns..."));
1015         AppendMenu(hOptionsMenu, MF_STRING, ID_OPTIONS_SHOW16BITTASKS, _T("&Show 16-bit tasks"));
1016         if (TaskManagerSettings.Show16BitTasks)
1017             CheckMenuItem(hOptionsMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED);
1018         if (GetMenuItemCount(hMenu) > 4)
1019         {
1020             RemoveMenu(hMenu, 3, MF_BYPOSITION);
1021             DrawMenuBar(hMainWnd);
1022         }
1023         /*
1024          * Give the process list control focus
1025          */
1026         SetFocus(hProcessPageListCtrl);
1027         break;
1028
1029     case 2:
1030         ShowWindow(hApplicationPage, SW_HIDE);
1031         ShowWindow(hProcessPage, SW_HIDE);
1032         ShowWindow(hPerformancePage, SW_SHOW);
1033         BringWindowToTop(hPerformancePage);
1034         if (GetMenuItemCount(hMenu) > 4) {
1035             RemoveMenu(hMenu, 3, MF_BYPOSITION);
1036             DrawMenuBar(hMainWnd);
1037         }
1038         hSubMenu = CreatePopupMenu();
1039         AppendMenu(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHALL, _T("&One Graph, All CPUs"));
1040         AppendMenu(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, _T("One Graph &Per CPU"));
1041         AppendMenu(hViewMenu, MF_STRING|MF_POPUP, (UINT)hSubMenu, _T("&CPU History"));
1042         AppendMenu(hViewMenu, MF_STRING, ID_VIEW_SHOWKERNELTIMES, _T("&Show Kernel Times"));
1043         if (TaskManagerSettings.ShowKernelTimes)
1044             CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
1045         else
1046             CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
1047         if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
1048             CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
1049         else
1050             CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
1051         /*
1052          * Give the tab control focus
1053          */
1054         SetFocus(hTabWnd);
1055         break;
1056     }
1057 }
1058
1059 LPTSTR GetLastErrorText(LPTSTR lpszBuf, DWORD dwSize)
1060 {
1061     DWORD  dwRet;
1062     LPTSTR lpszTemp = NULL;
1063
1064     dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
1065                            NULL,
1066                            GetLastError(),
1067                            LANG_NEUTRAL,
1068                            (LPTSTR)&lpszTemp,
1069                            0,
1070                            NULL );
1071
1072     /* supplied buffer is not long enough */
1073     if (!dwRet || ( (long)dwSize < (long)dwRet+14)) {
1074         lpszBuf[0] = TEXT('\0');
1075     } else {
1076         lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0');  /*remove cr and newline character */
1077         _stprintf(lpszBuf, TEXT("%s (0x%x)"), lpszTemp, (int)GetLastError());
1078     }
1079     if (lpszTemp) {
1080         LocalFree((HLOCAL)lpszTemp);
1081     }
1082     return lpszBuf;
1083 }