e0ff5c23628c0f2df454070f0c48ed10d24b7ba8
[reactos.git] / base / applications / 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 * 2005 Klemens Friedl <frik85@reactos.at>
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 Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include <precomp.h>
25
26 #define STATUS_WINDOW 2001
27
28 /* Global Variables: */
29 HINSTANCE hInst; /* current instance */
30
31 HWND hMainWnd; /* Main Window */
32 HWND hStatusWnd; /* Status Bar Window */
33 HWND hTabWnd; /* Tab Control Window */
34
35 int nMinimumWidth; /* Minimum width of the dialog (OnSize()'s cx) */
36 int nMinimumHeight; /* Minimum height of the dialog (OnSize()'s cy) */
37
38 int nOldWidth; /* Holds the previous client area width */
39 int nOldHeight; /* Holds the previous client area height */
40
41 BOOL bInMenuLoop = FALSE; /* Tells us if we are in the menu loop */
42
43 TASKMANAGER_SETTINGS TaskManagerSettings;
44
45
46 int APIENTRY wWinMain(HINSTANCE hInstance,
47 HINSTANCE hPrevInstance,
48 LPWSTR lpCmdLine,
49 int nCmdShow)
50 {
51 HANDLE hProcess;
52 HANDLE hToken;
53 TOKEN_PRIVILEGES tkp;
54 HANDLE hMutex;
55
56 /* check wether we're already running or not */
57 hMutex = CreateMutexW(NULL, TRUE, L"taskmgrros");
58 if ((!hMutex) || (GetLastError() == ERROR_ALREADY_EXISTS))
59 return 1;
60
61 /* Initialize global variables */
62 hInst = hInstance;
63
64 /* Change our priority class to HIGH */
65 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
66 SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS);
67 CloseHandle(hProcess);
68
69 /* Now lets get the SE_DEBUG_NAME privilege
70 * so that we can debug processes
71 */
72
73 /* Get a token for this process. */
74 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
75 /* Get the LUID for the debug privilege. */
76 LookupPrivilegeValueW(NULL, SE_DEBUG_NAME, &tkp.Privileges[0].Luid);
77
78 tkp.PrivilegeCount = 1; /* one privilege to set */
79 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
80
81 /* Get the debug privilege for this process. */
82 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
83 CloseHandle(hToken);
84 }
85
86 /* Load our settings from the registry */
87 LoadSettings();
88
89 /* Initialize perf data */
90 if (!PerfDataInitialize()) {
91 return -1;
92 }
93
94 DialogBoxW(hInst, (LPCWSTR)IDD_TASKMGR_DIALOG, NULL, TaskManagerWndProc);
95
96 /* Save our settings to the registry */
97 SaveSettings();
98 PerfDataUninitialize();
99 return 0;
100 }
101
102 /* Message handler for dialog box. */
103 INT_PTR CALLBACK
104 TaskManagerWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
105 {
106 #if 0
107 HDC hdc;
108 PAINTSTRUCT ps;
109 RECT rc;
110 #endif
111 LPRECT pRC;
112 int idctrl;
113 LPNMHDR pnmh;
114 WINDOWPLACEMENT wp;
115
116 switch (message) {
117 case WM_INITDIALOG:
118 hMainWnd = hDlg;
119 return OnCreate(hDlg);
120
121 case WM_COMMAND:
122 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
123 EndDialog(hDlg, LOWORD(wParam));
124 return TRUE;
125 }
126 /* Process menu commands */
127 switch (LOWORD(wParam))
128 {
129 case ID_FILE_NEW:
130 TaskManager_OnFileNew();
131 break;
132 case ID_OPTIONS_ALWAYSONTOP:
133 TaskManager_OnOptionsAlwaysOnTop();
134 break;
135 case ID_OPTIONS_MINIMIZEONUSE:
136 TaskManager_OnOptionsMinimizeOnUse();
137 break;
138 case ID_OPTIONS_HIDEWHENMINIMIZED:
139 TaskManager_OnOptionsHideWhenMinimized();
140 break;
141 case ID_OPTIONS_SHOW16BITTASKS:
142 TaskManager_OnOptionsShow16BitTasks();
143 break;
144 case ID_RESTORE:
145 TaskManager_OnRestoreMainWindow();
146 break;
147 case ID_VIEW_LARGE:
148 case ID_VIEW_SMALL:
149 case ID_VIEW_DETAILS:
150 ApplicationPage_OnView(LOWORD(wParam));
151 break;
152 case ID_VIEW_SHOWKERNELTIMES:
153 PerformancePage_OnViewShowKernelTimes();
154 break;
155 case ID_VIEW_CPUHISTORY_ONEGRAPHALL:
156 PerformancePage_OnViewCPUHistoryOneGraphAll();
157 break;
158 case ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU:
159 PerformancePage_OnViewCPUHistoryOneGraphPerCPU();
160 break;
161 case ID_VIEW_UPDATESPEED_HIGH:
162 case ID_VIEW_UPDATESPEED_NORMAL:
163 case ID_VIEW_UPDATESPEED_LOW:
164 case ID_VIEW_UPDATESPEED_PAUSED:
165 TaskManager_OnViewUpdateSpeed(LOWORD(wParam));
166 break;
167 case ID_VIEW_SELECTCOLUMNS:
168 ProcessPage_OnViewSelectColumns();
169 break;
170 case ID_VIEW_REFRESH:
171 PostMessageW(hDlg, WM_TIMER, 0, 0);
172 break;
173 case ID_WINDOWS_TILEHORIZONTALLY:
174 ApplicationPage_OnWindowsTile(MDITILE_HORIZONTAL);
175 break;
176 case ID_WINDOWS_TILEVERTICALLY:
177 ApplicationPage_OnWindowsTile(MDITILE_VERTICAL);
178 break;
179 case ID_WINDOWS_MINIMIZE:
180 ApplicationPage_OnWindowsMinimize();
181 break;
182 case ID_WINDOWS_MAXIMIZE:
183 ApplicationPage_OnWindowsMaximize();
184 break;
185 case ID_WINDOWS_CASCADE:
186 ApplicationPage_OnWindowsCascade();
187 break;
188 case ID_WINDOWS_BRINGTOFRONT:
189 ApplicationPage_OnWindowsBringToFront();
190 break;
191 case ID_APPLICATION_PAGE_SWITCHTO:
192 ApplicationPage_OnSwitchTo();
193 break;
194 case ID_APPLICATION_PAGE_ENDTASK:
195 ApplicationPage_OnEndTask();
196 break;
197 case ID_APPLICATION_PAGE_GOTOPROCESS:
198 ApplicationPage_OnGotoProcess();
199 break;
200 case ID_PROCESS_PAGE_ENDPROCESS:
201 ProcessPage_OnEndProcess();
202 break;
203 case ID_PROCESS_PAGE_ENDPROCESSTREE:
204 ProcessPage_OnEndProcessTree();
205 break;
206 case ID_PROCESS_PAGE_DEBUG:
207 ProcessPage_OnDebug();
208 break;
209 case ID_PROCESS_PAGE_SETAFFINITY:
210 ProcessPage_OnSetAffinity();
211 break;
212 case ID_PROCESS_PAGE_SETPRIORITY_REALTIME:
213 DoSetPriority(REALTIME_PRIORITY_CLASS);
214 break;
215 case ID_PROCESS_PAGE_SETPRIORITY_HIGH:
216 DoSetPriority(HIGH_PRIORITY_CLASS);
217 break;
218 case ID_PROCESS_PAGE_SETPRIORITY_ABOVENORMAL:
219 DoSetPriority(ABOVE_NORMAL_PRIORITY_CLASS);
220 break;
221 case ID_PROCESS_PAGE_SETPRIORITY_NORMAL:
222 DoSetPriority(NORMAL_PRIORITY_CLASS);
223 break;
224 case ID_PROCESS_PAGE_SETPRIORITY_BELOWNORMAL:
225 DoSetPriority(BELOW_NORMAL_PRIORITY_CLASS);
226 break;
227 case ID_PROCESS_PAGE_SETPRIORITY_LOW:
228 DoSetPriority(IDLE_PRIORITY_CLASS);
229 break;
230 case ID_PROCESS_PAGE_DEBUGCHANNELS:
231 ProcessPage_OnDebugChannels();
232 break;
233 case ID_HELP_ABOUT:
234 OnAbout();
235 break;
236 case ID_FILE_EXIT:
237 EndDialog(hDlg, IDOK);
238 break;
239 }
240 break;
241
242 case WM_ONTRAYICON:
243 switch(lParam)
244 {
245 case WM_RBUTTONDOWN:
246 {
247 POINT pt;
248 BOOL OnTop;
249 HMENU hMenu, hPopupMenu;
250
251 GetCursorPos(&pt);
252
253 OnTop = ((GetWindowLongPtrW(hMainWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0);
254
255 hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_TRAY_POPUP));
256 hPopupMenu = GetSubMenu(hMenu, 0);
257
258 if(IsWindowVisible(hMainWnd))
259 {
260 DeleteMenu(hPopupMenu, ID_RESTORE, MF_BYCOMMAND);
261 }
262 else
263 {
264 SetMenuDefaultItem(hPopupMenu, ID_RESTORE, FALSE);
265 }
266
267 if(OnTop)
268 {
269 CheckMenuItem(hPopupMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND | MF_CHECKED);
270 } else
271 {
272 CheckMenuItem(hPopupMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND | MF_UNCHECKED);
273 }
274
275 SetForegroundWindow(hMainWnd);
276 TrackPopupMenuEx(hPopupMenu, 0, pt.x, pt.y, hMainWnd, NULL);
277
278 DestroyMenu(hMenu);
279 break;
280 }
281 case WM_LBUTTONDBLCLK:
282 TaskManager_OnRestoreMainWindow();
283 break;
284 }
285 break;
286
287 case WM_NOTIFY:
288 idctrl = (int)wParam;
289 pnmh = (LPNMHDR)lParam;
290 if ((pnmh->hwndFrom == hTabWnd) &&
291 (pnmh->idFrom == IDC_TAB) &&
292 (pnmh->code == TCN_SELCHANGE))
293 {
294 TaskManager_OnTabWndSelChange();
295 }
296 break;
297 #if 0
298 case WM_NCPAINT:
299 hdc = GetDC(hDlg);
300 GetClientRect(hDlg, &rc);
301 Draw3dRect(hdc, rc.left, rc.top, rc.right, rc.top + 2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
302 ReleaseDC(hDlg, hdc);
303 break;
304
305 case WM_PAINT:
306 hdc = BeginPaint(hDlg, &ps);
307 GetClientRect(hDlg, &rc);
308 Draw3dRect(hdc, rc.left, rc.top, rc.right, rc.top + 2, GetSysColor(COLOR_3DSHADOW), GetSysColor(COLOR_3DHILIGHT));
309 EndPaint(hDlg, &ps);
310 break;
311 #endif
312 case WM_SIZING:
313 /* Make sure the user is sizing the dialog */
314 /* in an acceptable range */
315 pRC = (LPRECT)lParam;
316 if ((wParam == WMSZ_LEFT) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_BOTTOMLEFT)) {
317 /* If the width is too small enlarge it to the minimum */
318 if (nMinimumWidth > (pRC->right - pRC->left))
319 pRC->left = pRC->right - nMinimumWidth;
320 } else {
321 /* If the width is too small enlarge it to the minimum */
322 if (nMinimumWidth > (pRC->right - pRC->left))
323 pRC->right = pRC->left + nMinimumWidth;
324 }
325 if ((wParam == WMSZ_TOP) || (wParam == WMSZ_TOPLEFT) || (wParam == WMSZ_TOPRIGHT)) {
326 /* If the height is too small enlarge it to the minimum */
327 if (nMinimumHeight > (pRC->bottom - pRC->top))
328 pRC->top = pRC->bottom - nMinimumHeight;
329 } else {
330 /* If the height is too small enlarge it to the minimum */
331 if (nMinimumHeight > (pRC->bottom - pRC->top))
332 pRC->bottom = pRC->top + nMinimumHeight;
333 }
334 return TRUE;
335 break;
336
337 case WM_SIZE:
338 /* Handle the window sizing in it's own function */
339 OnSize(wParam, LOWORD(lParam), HIWORD(lParam));
340 break;
341
342 case WM_MOVE:
343 /* Handle the window moving in it's own function */
344 OnMove(wParam, LOWORD(lParam), HIWORD(lParam));
345 break;
346
347 case WM_DESTROY:
348 ShowWindow(hDlg, SW_HIDE);
349 TrayIcon_ShellRemoveTrayIcon();
350 wp.length = sizeof(WINDOWPLACEMENT);
351 GetWindowPlacement(hDlg, &wp);
352 TaskManagerSettings.Left = wp.rcNormalPosition.left;
353 TaskManagerSettings.Top = wp.rcNormalPosition.top;
354 TaskManagerSettings.Right = wp.rcNormalPosition.right;
355 TaskManagerSettings.Bottom = wp.rcNormalPosition.bottom;
356 if (IsZoomed(hDlg) || (wp.flags & WPF_RESTORETOMAXIMIZED))
357 TaskManagerSettings.Maximized = TRUE;
358 else
359 TaskManagerSettings.Maximized = FALSE;
360 return DefWindowProcW(hDlg, message, wParam, lParam);
361
362 case WM_TIMER:
363 /* Refresh the performance data */
364 PerfDataRefresh();
365 RefreshApplicationPage();
366 RefreshProcessPage();
367 RefreshPerformancePage();
368 TrayIcon_ShellUpdateTrayIcon();
369 break;
370
371 case WM_ENTERMENULOOP:
372 TaskManager_OnEnterMenuLoop(hDlg);
373 break;
374 case WM_EXITMENULOOP:
375 TaskManager_OnExitMenuLoop(hDlg);
376 break;
377 case WM_MENUSELECT:
378 TaskManager_OnMenuSelect(hDlg, LOWORD(wParam), HIWORD(wParam), (HMENU)lParam);
379 break;
380 }
381
382 return 0;
383 }
384
385 void FillSolidRect(HDC hDC, LPCRECT lpRect, COLORREF clr)
386 {
387 SetBkColor(hDC, clr);
388 ExtTextOutW(hDC, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL);
389 }
390
391 void FillSolidRect2(HDC hDC, int x, int y, int cx, int cy, COLORREF clr)
392 {
393 RECT rect;
394
395 SetBkColor(hDC, clr);
396 rect.left = x;
397 rect.top = y;
398 rect.right = x + cx;
399 rect.bottom = y + cy;
400 ExtTextOutW(hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
401 }
402
403 void Draw3dRect(HDC hDC, int x, int y, int cx, int cy, COLORREF clrTopLeft, COLORREF clrBottomRight)
404 {
405 FillSolidRect2(hDC, x, y, cx - 1, 1, clrTopLeft);
406 FillSolidRect2(hDC, x, y, 1, cy - 1, clrTopLeft);
407 FillSolidRect2(hDC, x + cx, y, -1, cy, clrBottomRight);
408 FillSolidRect2(hDC, x, y + cy, cx, -1, clrBottomRight);
409 }
410
411 void Draw3dRect2(HDC hDC, LPRECT lpRect, COLORREF clrTopLeft, COLORREF clrBottomRight)
412 {
413 Draw3dRect(hDC, lpRect->left, lpRect->top, lpRect->right - lpRect->left,
414 lpRect->bottom - lpRect->top, clrTopLeft, clrBottomRight);
415 }
416
417 static void SetUpdateSpeed(HWND hWnd)
418 {
419 /* Setup update speed (pause=fall down) */
420 switch (TaskManagerSettings.UpdateSpeed) {
421 case ID_VIEW_UPDATESPEED_HIGH:
422 SetTimer(hWnd, 1, 1000, NULL);
423 break;
424 case ID_VIEW_UPDATESPEED_NORMAL:
425 SetTimer(hWnd, 1, 2000, NULL);
426 break;
427 case ID_VIEW_UPDATESPEED_LOW:
428 SetTimer(hWnd, 1, 4000, NULL);
429 break;
430 }
431 }
432
433 BOOL OnCreate(HWND hWnd)
434 {
435 HMENU hMenu;
436 HMENU hEditMenu;
437 HMENU hViewMenu;
438 HMENU hUpdateSpeedMenu;
439 HMENU hCPUHistoryMenu;
440 int nActivePage;
441 int nParts[3];
442 RECT rc;
443 WCHAR szTemp[256];
444 TCITEM item;
445
446 SendMessageW(hMainWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIconW(hInst, MAKEINTRESOURCEW(IDI_TASKMANAGER)));
447
448 /* Initialize the Windows Common Controls DLL */
449 InitCommonControls();
450
451 /* Get the minimum window sizes */
452 GetWindowRect(hWnd, &rc);
453 nMinimumWidth = (rc.right - rc.left);
454 nMinimumHeight = (rc.bottom - rc.top);
455
456 /* Create the status bar */
457 hStatusWnd = CreateStatusWindow(WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|SBT_NOBORDERS, L"", hWnd, STATUS_WINDOW);
458 if(!hStatusWnd)
459 return FALSE;
460
461 /* Create the status bar panes */
462 nParts[0] = STATUS_SIZE1;
463 nParts[1] = STATUS_SIZE2;
464 nParts[2] = STATUS_SIZE3;
465 SendMessageW(hStatusWnd, SB_SETPARTS, 3, (LPARAM) (LPINT) nParts);
466
467 /* Create tab pages */
468 hTabWnd = GetDlgItem(hWnd, IDC_TAB);
469 #if 1
470 hApplicationPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_APPLICATION_PAGE), hWnd, ApplicationPageWndProc);
471 hProcessPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PROCESS_PAGE), hWnd, ProcessPageWndProc);
472 hPerformancePage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PERFORMANCE_PAGE), hWnd, PerformancePageWndProc);
473 #else
474 hApplicationPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_APPLICATION_PAGE), hTabWnd, ApplicationPageWndProc);
475 hProcessPage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PROCESS_PAGE), hTabWnd, ProcessPageWndProc);
476 hPerformancePage = CreateDialogW(hInst, MAKEINTRESOURCEW(IDD_PERFORMANCE_PAGE), hTabWnd, PerformancePageWndProc);
477 #endif
478
479 /* Insert tabs */
480 LoadStringW(hInst, IDS_TAB_APPS, szTemp, 256);
481 memset(&item, 0, sizeof(TCITEM));
482 item.mask = TCIF_TEXT;
483 item.pszText = szTemp;
484 (void)TabCtrl_InsertItem(hTabWnd, 0, &item);
485 LoadStringW(hInst, IDS_TAB_PROCESSES, szTemp, 256);
486 memset(&item, 0, sizeof(TCITEM));
487 item.mask = TCIF_TEXT;
488 item.pszText = szTemp;
489 (void)TabCtrl_InsertItem(hTabWnd, 1, &item);
490 LoadStringW(hInst, IDS_TAB_PERFORMANCE, szTemp, 256);
491 memset(&item, 0, sizeof(TCITEM));
492 item.mask = TCIF_TEXT;
493 item.pszText = szTemp;
494 (void)TabCtrl_InsertItem(hTabWnd, 2, &item);
495
496 /* Size everything correctly */
497 GetClientRect(hWnd, &rc);
498 nOldWidth = rc.right;
499 nOldHeight = rc.bottom;
500 /* nOldStartX = rc.left; */
501 /*nOldStartY = rc.top; */
502
503 #define PAGE_OFFSET_LEFT 17
504 #define PAGE_OFFSET_TOP 72
505 #define PAGE_OFFSET_WIDTH (PAGE_OFFSET_LEFT*2)
506 #define PAGE_OFFSET_HEIGHT (PAGE_OFFSET_TOP+32)
507
508 if ((TaskManagerSettings.Left != 0) ||
509 (TaskManagerSettings.Top != 0) ||
510 (TaskManagerSettings.Right != 0) ||
511 (TaskManagerSettings.Bottom != 0))
512 {
513 MoveWindow(hWnd, TaskManagerSettings.Left, TaskManagerSettings.Top, TaskManagerSettings.Right - TaskManagerSettings.Left, TaskManagerSettings.Bottom - TaskManagerSettings.Top, TRUE);
514 #ifdef __GNUC__TEST__
515 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);
516 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);
517 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);
518 #endif
519 }
520 if (TaskManagerSettings.Maximized)
521 ShowWindow(hWnd, SW_MAXIMIZE);
522
523 /* Set the always on top style */
524 hMenu = GetMenu(hWnd);
525 hEditMenu = GetSubMenu(hMenu, 1);
526 hViewMenu = GetSubMenu(hMenu, 2);
527 hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
528 hCPUHistoryMenu = GetSubMenu(hViewMenu, 7);
529
530 /* Check or uncheck the always on top menu item */
531 if (TaskManagerSettings.AlwaysOnTop) {
532 CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_CHECKED);
533 SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
534 } else {
535 CheckMenuItem(hEditMenu, ID_OPTIONS_ALWAYSONTOP, MF_BYCOMMAND|MF_UNCHECKED);
536 SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
537 }
538
539 /* Check or uncheck the minimize on use menu item */
540 if (TaskManagerSettings.MinimizeOnUse)
541 CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_CHECKED);
542 else
543 CheckMenuItem(hEditMenu, ID_OPTIONS_MINIMIZEONUSE, MF_BYCOMMAND|MF_UNCHECKED);
544
545 /* Check or uncheck the hide when minimized menu item */
546 if (TaskManagerSettings.HideWhenMinimized)
547 CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_CHECKED);
548 else
549 CheckMenuItem(hEditMenu, ID_OPTIONS_HIDEWHENMINIMIZED, MF_BYCOMMAND|MF_UNCHECKED);
550
551 /* Check or uncheck the show 16-bit tasks menu item */
552 if (TaskManagerSettings.Show16BitTasks)
553 CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED);
554 else
555 CheckMenuItem(hEditMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_UNCHECKED);
556
557 /* Set the view mode */
558 CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, TaskManagerSettings.ViewMode, MF_BYCOMMAND);
559
560 if (TaskManagerSettings.ShowKernelTimes)
561 CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
562 else
563 CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
564
565 CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, TaskManagerSettings.UpdateSpeed, MF_BYCOMMAND);
566
567 if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
568 CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
569 else
570 CheckMenuRadioItem(hCPUHistoryMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
571
572 nActivePage = TaskManagerSettings.ActiveTabPage;
573 TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 0);
574 TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 1);
575 TabCtrl_SetCurFocus/*Sel*/(hTabWnd, 2);
576 TabCtrl_SetCurFocus/*Sel*/(hTabWnd, nActivePage);
577
578 /* Setup update speed */
579 SetUpdateSpeed(hWnd);
580
581 /*
582 * Refresh the performance data
583 * Sample it twice so we can establish
584 * the delta values & cpu usage
585 */
586 PerfDataRefresh();
587 PerfDataRefresh();
588
589 RefreshApplicationPage();
590 RefreshProcessPage();
591 RefreshPerformancePage();
592
593 TrayIcon_ShellAddTrayIcon();
594
595 return TRUE;
596 }
597
598 /* OnMove()
599 * This function handles all the moving events for the application
600 * It moves every child window that needs moving
601 */
602 void OnMove( WPARAM nType, int cx, int cy )
603 {
604 #ifdef __GNUC__TEST__
605 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);
606 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);
607 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);
608 #endif
609 }
610
611 /* OnSize()
612 * This function handles all the sizing events for the application
613 * It re-sizes every window, and child window that needs re-sizing
614 */
615 void OnSize( WPARAM nType, int cx, int cy )
616 {
617 int nParts[3];
618 int nXDifference;
619 int nYDifference;
620 RECT rc;
621
622 if (nType == SIZE_MINIMIZED)
623 {
624 if(TaskManagerSettings.HideWhenMinimized)
625 {
626 ShowWindow(hMainWnd, SW_HIDE);
627 }
628 return;
629 }
630
631 nXDifference = cx - nOldWidth;
632 nYDifference = cy - nOldHeight;
633 nOldWidth = cx;
634 nOldHeight = cy;
635
636 /* Update the status bar size */
637 GetWindowRect(hStatusWnd, &rc);
638 SendMessageW(hStatusWnd, WM_SIZE, nType, MAKELPARAM(cx,rc.bottom - rc.top));
639
640 /* Update the status bar pane sizes */
641 nParts[0] = bInMenuLoop ? -1 : STATUS_SIZE1;
642 nParts[1] = STATUS_SIZE2;
643 nParts[2] = cx;
644 SendMessageW(hStatusWnd, SB_SETPARTS, bInMenuLoop ? 1 : 3, (LPARAM) (LPINT) nParts);
645
646 /* Resize the tab control */
647 GetWindowRect(hTabWnd, &rc);
648 cx = (rc.right - rc.left) + nXDifference;
649 cy = (rc.bottom - rc.top) + nYDifference;
650 SetWindowPos(hTabWnd, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
651
652 /* Resize the application page */
653 GetWindowRect(hApplicationPage, &rc);
654 cx = (rc.right - rc.left) + nXDifference;
655 cy = (rc.bottom - rc.top) + nYDifference;
656 SetWindowPos(hApplicationPage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
657
658 /* Resize the process page */
659 GetWindowRect(hProcessPage, &rc);
660 cx = (rc.right - rc.left) + nXDifference;
661 cy = (rc.bottom - rc.top) + nYDifference;
662 SetWindowPos(hProcessPage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
663
664 /* Resize the performance page */
665 GetWindowRect(hPerformancePage, &rc);
666 cx = (rc.right - rc.left) + nXDifference;
667 cy = (rc.bottom - rc.top) + nYDifference;
668 SetWindowPos(hPerformancePage, NULL, 0, 0, cx, cy, SWP_NOACTIVATE|SWP_NOOWNERZORDER|SWP_NOMOVE|SWP_NOZORDER);
669 }
670
671 void LoadSettings(void)
672 {
673 HKEY hKey;
674 WCHAR szSubKey[] = L"Software\\ReactOS\\TaskManager";
675 int i;
676 DWORD dwSize;
677
678 /* Window size & position settings */
679 TaskManagerSettings.Maximized = FALSE;
680 TaskManagerSettings.Left = 0;
681 TaskManagerSettings.Top = 0;
682 TaskManagerSettings.Right = 0;
683 TaskManagerSettings.Bottom = 0;
684
685 /* Tab settings */
686 TaskManagerSettings.ActiveTabPage = 0;
687
688 /* Options menu settings */
689 TaskManagerSettings.AlwaysOnTop = FALSE;
690 TaskManagerSettings.MinimizeOnUse = TRUE;
691 TaskManagerSettings.HideWhenMinimized = TRUE;
692 TaskManagerSettings.Show16BitTasks = TRUE;
693
694 /* Update speed settings */
695 TaskManagerSettings.UpdateSpeed = ID_VIEW_UPDATESPEED_NORMAL;
696
697 /* Applications page settings */
698 TaskManagerSettings.ViewMode = ID_VIEW_DETAILS;
699
700 /* Processes page settings */
701 TaskManagerSettings.ShowProcessesFromAllUsers = FALSE; /* Server-only? */
702
703 for (i = 0; i < COLUMN_NMAX; i++) {
704 TaskManagerSettings.Columns[i] = ColumnPresets[i].bDefaults;
705 TaskManagerSettings.ColumnOrderArray[i] = i;
706 TaskManagerSettings.ColumnSizeArray[i] = ColumnPresets[i].size;
707 }
708
709 TaskManagerSettings.SortColumn = COLUMN_IMAGENAME;
710 TaskManagerSettings.SortAscending = TRUE;
711
712 /* Performance page settings */
713 TaskManagerSettings.CPUHistory_OneGraphPerCPU = TRUE;
714 TaskManagerSettings.ShowKernelTimes = FALSE;
715
716 /* Open the key */
717 if (RegOpenKeyExW(HKEY_CURRENT_USER, szSubKey, 0, KEY_READ, &hKey) != ERROR_SUCCESS)
718 return;
719 /* Read the settings */
720 dwSize = sizeof(TASKMANAGER_SETTINGS);
721 RegQueryValueExW(hKey, L"Preferences", NULL, NULL, (LPBYTE)&TaskManagerSettings, &dwSize);
722
723 /*
724 * ATM, the 'ImageName' column is always visible
725 * (and grayed in configuration dialog)
726 * This will avoid troubles if the registry gets corrupted.
727 */
728 TaskManagerSettings.Column_ImageName = TRUE;
729
730 /* Close the key */
731 RegCloseKey(hKey);
732 }
733
734 void SaveSettings(void)
735 {
736 HKEY hKey;
737 WCHAR szSubKey1[] = L"Software";
738 WCHAR szSubKey2[] = L"Software\\ReactOS";
739 WCHAR szSubKey3[] = L"Software\\ReactOS\\TaskManager";
740
741 /* Open (or create) the key */
742 hKey = NULL;
743 RegCreateKeyExW(HKEY_CURRENT_USER, szSubKey1, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
744 RegCloseKey(hKey);
745 hKey = NULL;
746 RegCreateKeyExW(HKEY_CURRENT_USER, szSubKey2, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL);
747 RegCloseKey(hKey);
748 hKey = NULL;
749 if (RegCreateKeyExW(HKEY_CURRENT_USER, szSubKey3, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) != ERROR_SUCCESS)
750 return;
751 /* Save the settings */
752 RegSetValueExW(hKey, L"Preferences", 0, REG_BINARY, (LPBYTE)&TaskManagerSettings, sizeof(TASKMANAGER_SETTINGS));
753 /* Close the key */
754 RegCloseKey(hKey);
755 }
756
757 void TaskManager_OnRestoreMainWindow(void)
758 {
759 HMENU hMenu, hOptionsMenu;
760 BOOL OnTop;
761
762 hMenu = GetMenu(hMainWnd);
763 hOptionsMenu = GetSubMenu(hMenu, OPTIONS_MENU_INDEX);
764 OnTop = ((GetWindowLongPtrW(hMainWnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0);
765
766 OpenIcon(hMainWnd);
767 SetForegroundWindow(hMainWnd);
768 SetWindowPos(hMainWnd, (OnTop ? HWND_TOPMOST : HWND_TOP), 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW);
769 }
770
771 void TaskManager_OnEnterMenuLoop(HWND hWnd)
772 {
773 int nParts;
774
775 /* Update the status bar pane sizes */
776 nParts = -1;
777 SendMessageW(hStatusWnd, SB_SETPARTS, 1, (LPARAM) (LPINT)&nParts);
778 bInMenuLoop = TRUE;
779 SendMessageW(hStatusWnd, SB_SETTEXT, (WPARAM)0, (LPARAM)L"");
780 }
781
782 void TaskManager_OnExitMenuLoop(HWND hWnd)
783 {
784 RECT rc;
785 int nParts[3];
786 WCHAR text[260];
787 WCHAR szCpuUsage[256], szProcesses[256];
788
789 LoadStringW(hInst, IDS_STATUS_CPUUSAGE, szCpuUsage, 256);
790 LoadStringW(hInst, IDS_STATUS_PROCESSES, szProcesses, 256);
791
792 bInMenuLoop = FALSE;
793 /* Update the status bar pane sizes */
794 GetClientRect(hWnd, &rc);
795 nParts[0] = STATUS_SIZE1;
796 nParts[1] = STATUS_SIZE2;
797 nParts[2] = rc.right;
798 SendMessageW(hStatusWnd, SB_SETPARTS, 3, (LPARAM) (LPINT) nParts);
799 SendMessageW(hStatusWnd, SB_SETTEXT, 0, (LPARAM)L"");
800 wsprintfW(text, szCpuUsage, PerfDataGetProcessorUsage());
801 SendMessageW(hStatusWnd, SB_SETTEXT, 1, (LPARAM)text);
802 wsprintfW(text, szProcesses, PerfDataGetProcessCount());
803 SendMessageW(hStatusWnd, SB_SETTEXT, 0, (LPARAM)text);
804 }
805
806 void TaskManager_OnMenuSelect(HWND hWnd, UINT nItemID, UINT nFlags, HMENU hSysMenu)
807 {
808 WCHAR str[100];
809
810 wcscpy(str, L"");
811 if (LoadStringW(hInst, nItemID, str, 100)) {
812 /* load appropriate string */
813 LPWSTR lpsz = str;
814 /* first newline terminates actual string */
815 lpsz = wcschr(lpsz, '\n');
816 if (lpsz != NULL)
817 *lpsz = '\0';
818 }
819 SendMessageW(hStatusWnd, SB_SETTEXT, 0, (LPARAM)str);
820 }
821
822 void TaskManager_OnViewUpdateSpeed(DWORD dwSpeed)
823 {
824 HMENU hMenu;
825 HMENU hViewMenu;
826 HMENU hUpdateSpeedMenu;
827
828 hMenu = GetMenu(hMainWnd);
829 hViewMenu = GetSubMenu(hMenu, 2);
830 hUpdateSpeedMenu = GetSubMenu(hViewMenu, 1);
831
832 TaskManagerSettings.UpdateSpeed = dwSpeed;
833 CheckMenuRadioItem(hUpdateSpeedMenu, ID_VIEW_UPDATESPEED_HIGH, ID_VIEW_UPDATESPEED_PAUSED, dwSpeed, MF_BYCOMMAND);
834
835 KillTimer(hMainWnd, 1);
836
837 SetUpdateSpeed(hMainWnd);
838 }
839
840 void TaskManager_OnViewRefresh(void)
841 {
842 PostMessageW(hMainWnd, WM_TIMER, 0, 0);
843 }
844
845 void TaskManager_OnTabWndSelChange(void)
846 {
847 int i;
848 HMENU hMenu;
849 HMENU hOptionsMenu;
850 HMENU hViewMenu;
851 HMENU hSubMenu;
852 WCHAR szTemp[256];
853
854 hMenu = GetMenu(hMainWnd);
855 hViewMenu = GetSubMenu(hMenu, 2);
856 hOptionsMenu = GetSubMenu(hMenu, 1);
857 TaskManagerSettings.ActiveTabPage = TabCtrl_GetCurSel(hTabWnd);
858 for (i = GetMenuItemCount(hViewMenu) - 1; i > 2; i--) {
859 hSubMenu = GetSubMenu(hViewMenu, i);
860 if (hSubMenu)
861 DestroyMenu(hSubMenu);
862 RemoveMenu(hViewMenu, i, MF_BYPOSITION);
863 }
864 RemoveMenu(hOptionsMenu, 3, MF_BYPOSITION);
865 switch (TaskManagerSettings.ActiveTabPage) {
866 case 0:
867 ShowWindow(hApplicationPage, SW_SHOW);
868 ShowWindow(hProcessPage, SW_HIDE);
869 ShowWindow(hPerformancePage, SW_HIDE);
870 BringWindowToTop(hApplicationPage);
871
872 LoadStringW(hInst, IDS_MENU_LARGEICONS, szTemp, 256);
873 AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_LARGE, szTemp);
874
875 LoadStringW(hInst, IDS_MENU_SMALLICONS, szTemp, 256);
876 AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SMALL, szTemp);
877
878 LoadStringW(hInst, IDS_MENU_DETAILS, szTemp, 256);
879 AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_DETAILS, szTemp);
880
881 if (GetMenuItemCount(hMenu) <= 4) {
882 hSubMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(IDR_WINDOWSMENU));
883
884 LoadStringW(hInst, IDS_MENU_WINDOWS, szTemp, 256);
885 InsertMenuW(hMenu, 3, MF_BYPOSITION|MF_POPUP, (UINT_PTR) hSubMenu, szTemp);
886
887 DrawMenuBar(hMainWnd);
888 }
889 CheckMenuRadioItem(hViewMenu, ID_VIEW_LARGE, ID_VIEW_DETAILS, TaskManagerSettings.ViewMode, MF_BYCOMMAND);
890
891 /*
892 * Give the application list control focus
893 */
894 SetFocus(hApplicationPageListCtrl);
895 break;
896
897 case 1:
898 ShowWindow(hApplicationPage, SW_HIDE);
899 ShowWindow(hProcessPage, SW_SHOW);
900 ShowWindow(hPerformancePage, SW_HIDE);
901 BringWindowToTop(hProcessPage);
902
903 LoadStringW(hInst, IDS_MENU_SELECTCOLUMNS, szTemp, 256);
904 AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SELECTCOLUMNS, szTemp);
905
906 LoadStringW(hInst, IDS_MENU_16BITTASK, szTemp, 256);
907 AppendMenuW(hOptionsMenu, MF_STRING, ID_OPTIONS_SHOW16BITTASKS, szTemp);
908
909 if (TaskManagerSettings.Show16BitTasks)
910 CheckMenuItem(hOptionsMenu, ID_OPTIONS_SHOW16BITTASKS, MF_BYCOMMAND|MF_CHECKED);
911 if (GetMenuItemCount(hMenu) > 4)
912 {
913 DeleteMenu(hMenu, 3, MF_BYPOSITION);
914 DrawMenuBar(hMainWnd);
915 }
916 /*
917 * Give the process list control focus
918 */
919 SetFocus(hProcessPageListCtrl);
920 break;
921
922 case 2:
923 ShowWindow(hApplicationPage, SW_HIDE);
924 ShowWindow(hProcessPage, SW_HIDE);
925 ShowWindow(hPerformancePage, SW_SHOW);
926 BringWindowToTop(hPerformancePage);
927 if (GetMenuItemCount(hMenu) > 4) {
928 DeleteMenu(hMenu, 3, MF_BYPOSITION);
929 DrawMenuBar(hMainWnd);
930 }
931 hSubMenu = CreatePopupMenu();
932
933 LoadStringW(hInst, IDS_MENU_ONEGRAPHALLCPUS, szTemp, 256);
934 AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHALL, szTemp);
935
936 LoadStringW(hInst, IDS_MENU_ONEGRAPHPERCPU, szTemp, 256);
937 AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, szTemp);
938
939 LoadStringW(hInst, IDS_MENU_CPUHISTORY, szTemp, 256);
940 AppendMenuW(hViewMenu, MF_STRING|MF_POPUP, (UINT_PTR) hSubMenu, szTemp);
941
942 LoadStringW(hInst, IDS_MENU_SHOWKERNELTIMES, szTemp, 256);
943 AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SHOWKERNELTIMES, szTemp);
944
945 if (TaskManagerSettings.ShowKernelTimes)
946 CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
947 else
948 CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
949 if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
950 CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
951 else
952 CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
953 /*
954 * Give the tab control focus
955 */
956 SetFocus(hTabWnd);
957 break;
958 }
959 }
960
961 LPWSTR GetLastErrorText(LPWSTR lpszBuf, DWORD dwSize)
962 {
963 DWORD dwRet;
964 LPWSTR lpszTemp = NULL;
965
966 dwRet = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
967 NULL,
968 GetLastError(),
969 LANG_NEUTRAL,
970 (LPWSTR)&lpszTemp,
971 0,
972 NULL );
973
974 /* supplied buffer is not long enough */
975 if (!dwRet || ( (long)dwSize < (long)dwRet+14)) {
976 lpszBuf[0] = L'\0';
977 } else {
978 lpszTemp[lstrlenW(lpszTemp)-2] = L'\0'; /*remove cr and newline character */
979 wsprintfW(lpszBuf, L"%s (0x%x)", lpszTemp, (int)GetLastError());
980 }
981 if (lpszTemp) {
982 LocalFree((HLOCAL)lpszTemp);
983 }
984 return lpszBuf;
985 }