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