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