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