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