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