Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

929 lines
26 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. taskman.c
  5. Abstract:
  6. This file contains the source for the windows Task Manager.
  7. Taskman basically is a dialog box, which enumerates active windows
  8. keep in the user window manager, then sets active focus to the selected
  9. dialog box element(ie active window).
  10. --*/
  11. // Has to be unicode because InternalGetWindowText
  12. // user routine is strictly so.
  13. #include "taskman.h"
  14. #include "progman.h"
  15. #include "security.h"
  16. //#ifdef FE_IME // 2-Jun-92, by eichim
  17. #include <winnls32.h>
  18. //#endif
  19. #include <port1632.h>
  20. extern HINSTANCE hAppInstance;
  21. #define MAXPATHFIELD 260
  22. TCHAR szTMPathField[MAXPATHFIELD];
  23. TCHAR szTMDirField[MAXPATHFIELD];
  24. TCHAR szTMTitle[MAXPATHFIELD];
  25. TCHAR szTMMessage[MAXMSGBOXLEN];
  26. TCHAR szTMUserHomeDir[MAXPATHFIELD];
  27. TCHAR szTMWindowsDirectory[MAXPATHFIELD];
  28. TCHAR szTMOOMExitMsg[64];
  29. TCHAR szTMOOMExitTitle[32];
  30. VOID SetDefButton(HWND hwndDlg, INT idButton);
  31. // registry key for groups
  32. BOOL bChangedDefaultButton;
  33. INT MyX = 0;
  34. INT MyY = 0;
  35. BOOL fMsgBox = FALSE;
  36. VOID
  37. HideWindow(HWND hwnd)
  38. {
  39. if (!fMsgBox) {
  40. if (!fNoRun) {
  41. SetDlgItemText(ghwndTMDialog, IDD_TMPATH, TEXT(""));
  42. }
  43. // redundant? why do they do the reverse twice for show below?
  44. ShowWindow(ghwndTMDialog, SW_HIDE);
  45. SetWindowPos(ghwndTMDialog, HWND_NOTOPMOST, 0, 0, 0, 0,
  46. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  47. // Erase dark border from depressed pushbuttons
  48. SendMessage(GetDlgItem(hwnd, IDCANCEL), // IDCANCEL
  49. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  50. SendMessage(GetDlgItem(hwnd, IDD_TERMINATE),
  51. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  52. SendMessage(GetDlgItem(hwnd, IDD_CASCADE),
  53. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  54. SendMessage(GetDlgItem(hwnd, IDD_TILE),
  55. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  56. SendMessage(GetDlgItem(hwnd, IDD_ARRANGEICONS),
  57. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  58. }
  59. }
  60. /*
  61. * We call HideTasklist() when we want to remove the tasklist window
  62. * from the screen but not select another window (ie. when we're about
  63. * to select another app. We call ShowWindow(SW_HIDE) directly when
  64. * we're doing something like tiling or cascading so a window other than
  65. * the tasklist will become the foreground window.
  66. */
  67. VOID HideTasklist(VOID)
  68. {
  69. if (!fNoRun) {
  70. SetDlgItemText(ghwndTMDialog, IDD_TMPATH, TEXT(""));
  71. }
  72. SetWindowPos(ghwndTMDialog, HWND_TOP, 0, 0, 0, 0, SWP_HIDEWINDOW |
  73. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
  74. }
  75. VOID ShowTasklist(
  76. POINT pt)
  77. {
  78. if (!fMsgBox) {
  79. /*
  80. * Retract the drop down listbox.
  81. */
  82. if (!fNoRun) {
  83. SendDlgItemMessage(ghwndTMDialog, IDD_TMPATH,
  84. CB_SHOWDROPDOWN,0,0);
  85. }
  86. SetWindowPos(ghwndTMDialog, HWND_TOPMOST, pt.x, pt.y, 0, 0,
  87. SWP_NOSIZE | SWP_NOACTIVATE );
  88. //
  89. // WinCim disables the Taskman window which make it behave strangely on NT
  90. //
  91. EnableWindow(ghwndTMDialog, TRUE);
  92. SetForegroundWindow(ghwndTMDialog);
  93. ShowWindow(ghwndTMDialog, SW_NORMAL);
  94. }
  95. }
  96. /*** ActivateSelectedWindow -- Calls user, to set active window, selected
  97. * by the user.
  98. *
  99. *
  100. * ActivateSelectedWindow(HWND hwndLB)
  101. *
  102. * ENTRY - HWND hwndLB - handle to window, which is to become the active
  103. * window, with focus.
  104. * EXIT -
  105. * SYNOPSIS - This function takes the hwnd passed into it, calls user
  106. * to set active focus to that window.
  107. * WARNINGS -
  108. * EFFECTS -
  109. *
  110. */
  111. VOID ActivateSelectedWindow(
  112. HWND hwndLB)
  113. {
  114. INT nIndex;
  115. HWND hwndT;
  116. HWND hwndLastActive;
  117. DWORD lTemp;
  118. /*
  119. * Get the hwnd of the item which was selected.
  120. */
  121. nIndex = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0);
  122. hwndT = (HWND)SendMessage(hwndLB, LB_GETITEMDATA, nIndex, 0);
  123. if (!IsWindow(hwndT)) {
  124. /*
  125. * We gotta make sure the window is valid before doing stuff with it.
  126. * An app may terminate itself in the background rendering these
  127. * window handles invalid.
  128. */
  129. goto Beep;
  130. }
  131. /*
  132. * Switch to that task.
  133. * HACK! Activate the window in the hwndLastActive field of the WndStruct.
  134. */
  135. hwndLastActive = GetLastActivePopup(hwndT);
  136. if (!IsWindow(hwndLastActive)) {
  137. goto Beep;
  138. }
  139. /*
  140. * But only if it isn't disabled.
  141. */
  142. lTemp = GetWindowLong(hwndLastActive, GWL_STYLE);
  143. if (!(lTemp & WS_DISABLED)) {
  144. /*
  145. * HACK!! Use SwitchToThisWindow() to bring dialog parents as well.
  146. */
  147. SwitchToThisWindow(hwndLastActive, TRUE);
  148. } else {
  149. Beep:
  150. MessageBeep(0);
  151. }
  152. }
  153. /*** DoEndTask --
  154. *
  155. * void DoEndTask( HWND hwnd )
  156. */
  157. VOID DoEndTask(
  158. HWND hwnd )
  159. {
  160. TCHAR szMsgBoxText[MAXMSGBOXLEN];
  161. TCHAR szTempField[MAXTASKNAMELEN];
  162. INT nch;
  163. DWORD dwProcessId = 0;
  164. /*
  165. * We don't want to let someone do an EndTask on progman or EndTask of
  166. * a EndTask dialog (which would make progman die)
  167. */
  168. GetWindowThreadProcessId(hwnd, &dwProcessId);
  169. if (dwProcessId == GetCurrentProcessId()) {
  170. MessageBeep(MB_OK);
  171. return;
  172. }
  173. if (!EndTask(hwnd, FALSE, FALSE)) {
  174. /* App does not want to close, ask user if
  175. * he wants to blow it away
  176. */
  177. InternalGetWindowText(hwnd, szTempField, MAXTASKNAMELEN);
  178. /* Load the message box string, it is very long (greater than 255 chars
  179. * which is why we load it in two pieces
  180. */
  181. nch = LoadString(NULL, IDS_MSGBOXSTR1, szMsgBoxText, MAXMSGBOXLEN);
  182. LoadString(NULL, IDS_MSGBOXSTR2, &szMsgBoxText[nch], MAXMSGBOXLEN-nch);
  183. if( MessageBox( NULL, szMsgBoxText, szTempField,
  184. MB_SETFOREGROUND | MB_SYSTEMMODAL | MB_YESNO ) == IDYES) {
  185. EndTask(hwnd, FALSE, TRUE);
  186. }
  187. }
  188. }
  189. /*** CallEndTask -- A separate thread to instigate EndTask
  190. *
  191. * CallEndTask( HWND hwnd );
  192. *
  193. * ENTRY - HWND hwnd - window handle for the task to be killed
  194. * EXIT -
  195. * SYNOPSIS - This function calls EndTask on the given window to kill the
  196. * task that owns that window.
  197. *
  198. * WARNINGS -
  199. * EFFECTS - Kills the task that owns hwnd.
  200. *
  201. */
  202. DWORD CallEndTask(
  203. HWND hwnd)
  204. {
  205. DoEndTask(hwnd);
  206. return 0;
  207. }
  208. /*** TaskmanDlgProc -- Dialog Procedure for Taskman Window
  209. *
  210. *
  211. *
  212. * TaskmanDlgProc(HWND hDlg, WORD wMSG, DWORD wParam, LPARAM lparam)
  213. *
  214. * ENTRY - HWND hhDlg - handle to dialog box.
  215. * WORD wMsg - message to be acted upon.
  216. * DWORD wParam - value specific to wMsg.
  217. * LPARAM lparam - value specific to wMsg.
  218. *
  219. * EXIT - True if success, False if not.
  220. * SYNOPSIS - Dialog box message processing function.
  221. *
  222. * WARNINGS -
  223. * EFFECTS -
  224. *
  225. */
  226. INT_PTR TaskmanDlgProc(
  227. HWND hwnd,
  228. UINT wMsg,
  229. WPARAM wParam,
  230. LPARAM lparam)
  231. {
  232. int nIndex;
  233. RECT rc;
  234. HWND hwndLB;
  235. HWND hwndNext;
  236. TCHAR szTempField[MAXTASKNAMELEN];
  237. POINT pt;
  238. HKEY hKey;
  239. DWORD dwDisp;
  240. DWORD dwDataType, dwMaxFiles=INIT_MAX_FILES, dwMaxFilesSize, dwCount;
  241. TCHAR szFileEntry[20];
  242. TCHAR szFullPath[MAXPATHFIELD];
  243. hwndLB = GetDlgItem(hwnd, IDD_TASKLISTBOX);
  244. switch (wMsg) {
  245. case WM_INITDIALOG:
  246. /*
  247. * call private api to mark task man as a system app. This causes
  248. * it to be killed after all other non-system apps during shutdown.
  249. */
  250. GetWindowRect(hwnd, &rc);
  251. dxTaskman = rc.right - rc.left;
  252. dyTaskman = rc.bottom - rc.top;
  253. dxScreen = GetSystemMetrics(SM_CXSCREEN);
  254. dyScreen = GetSystemMetrics(SM_CYSCREEN);
  255. pt.x = (dxScreen - dxTaskman) / 2;
  256. pt.y = (dyScreen - dyTaskman) / 2;
  257. SetWindowPos(hwnd, HWND_NOTOPMOST, pt.x, pt.y, 0, 0,
  258. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  259. SendDlgItemMessage(hwnd, IDD_TMPATH, EM_LIMITTEXT, MAXPATHFIELD-4, 0L);
  260. szTMPathField[0] = TEXT('\0');
  261. bChangedDefaultButton = FALSE;
  262. return FALSE;
  263. case WM_SHOWWINDOW:
  264. /*
  265. * If we're being shown fill in the listbox. We do this here
  266. * rather than in WM_ACTIVATE process so we can do it while the
  267. * dialog is still invisible.
  268. */
  269. if (wParam != 0) {
  270. /*
  271. * First delete any previous entries.
  272. */
  273. while ((int)SendMessage(hwndLB, LB_DELETESTRING, 0, 0) != LB_ERR);
  274. /*
  275. * Search the window list for enabled top level windows.
  276. */
  277. hwndNext = GetWindow(hwnd, GW_HWNDFIRST);
  278. while (hwndNext) {
  279. /*
  280. * Only add non-owned, visible, non-Taskman, Top Level Windows.
  281. */
  282. if ((hwndNext != hwnd) && (IsWindowVisible(hwndNext)) &&
  283. (!GetWindow(hwndNext, GW_OWNER))) {
  284. if (InternalGetWindowText(hwndNext, szTempField, MAXTASKNAMELEN )) {
  285. nIndex = (int)SendMessage(hwndLB, LB_ADDSTRING, 0,
  286. (LPARAM)(LPTSTR)szTempField);
  287. SendMessage(hwndLB, LB_SETITEMDATA, nIndex,
  288. (LPARAM)hwndNext);
  289. }
  290. }
  291. hwndNext = GetWindow(hwndNext, GW_HWNDNEXT);
  292. }
  293. SendMessage(hwndLB, LB_SETCURSEL, 0, 0);
  294. //
  295. // Set the default button to "Switch To"
  296. //
  297. SetDefButton(hwnd,IDD_SWITCH);
  298. //
  299. // Load the combobox with the recently used files.
  300. //
  301. if (GetDlgItem(hwnd, IDD_TMPATH)) {
  302. //
  303. // FIrst empty the combo box from the last time.
  304. //
  305. SendDlgItemMessage (hwnd, IDD_TMPATH,
  306. CB_RESETCONTENT, 0, 0);
  307. //
  308. // Load the combobox with recently used files from the registry.
  309. //
  310. // Query the max number of files first.
  311. //
  312. if (RegCreateKeyEx (HKEY_CURRENT_USER, FILES_KEY, 0, 0,
  313. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  314. NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
  315. if (dwDisp == REG_OPENED_EXISTING_KEY) {
  316. //
  317. // Query the max number of entries
  318. //
  319. dwMaxFilesSize = sizeof (DWORD);
  320. if (RegQueryValueEx (hKey, MAXFILES_ENTRY, NULL, &dwDataType,
  321. (LPBYTE)&dwMaxFiles, &dwMaxFilesSize) == ERROR_SUCCESS) {
  322. //
  323. // Now Query each entry and add it to the list box.
  324. //
  325. for (dwCount=0; dwCount < dwMaxFiles; dwCount++) {
  326. wsprintf (szFileEntry, FILE_ENTRY, dwCount);
  327. dwMaxFilesSize = MAXPATHFIELD+1;
  328. if (RegQueryValueEx (hKey, szFileEntry, NULL, &dwDataType,
  329. (LPBYTE) szFullPath, &dwMaxFilesSize) == ERROR_SUCCESS) {
  330. //
  331. // Found an entry. Add it to the combo box.
  332. //
  333. SendDlgItemMessage (hwnd, IDD_TMPATH,
  334. CB_ADDSTRING, 0,
  335. (LPARAM)szFullPath);
  336. } else {
  337. break;
  338. }
  339. }
  340. }
  341. } else {
  342. //
  343. // We are working with a new key, so we need to
  344. // set the default number of files.
  345. //
  346. RegSetValueEx (hKey, MAXFILES_ENTRY, 0, REG_DWORD,
  347. (CONST BYTE *) &dwMaxFiles, sizeof (DWORD));
  348. }
  349. //
  350. // Close the registry key
  351. //
  352. RegCloseKey (hKey);
  353. }
  354. }
  355. //
  356. // Disable the Run button and set the focus to the
  357. // listbox.
  358. //
  359. EnableWindow(GetDlgItem(hwnd, IDD_RUN), FALSE);
  360. SetFocus(hwndLB);
  361. }
  362. break;
  363. case WM_ACTIVATE:
  364. /*
  365. * If we're being deactivated clear the listbox so we
  366. * can fill it in afresh when we're re-activated.
  367. */
  368. if (wParam == 0) {
  369. /*
  370. * If we're not already invisible, hide ourself.
  371. */
  372. if (IsWindowVisible(hwnd)) {
  373. HideWindow(hwnd);
  374. }
  375. }
  376. if (!bChangedDefaultButton) {
  377. SetDefButton(hwnd,IDD_SWITCH);
  378. }
  379. break;
  380. case WM_ACTIVATEAPP:
  381. if (wParam)
  382. return FALSE;
  383. /*
  384. * If we are not visible when we get this message it is because
  385. * we are already in the process of terminating. If we don't
  386. * ignore this we get into a weird race condition and the frame
  387. * of the window being activated doesn't get fully drawn. (BG)
  388. */
  389. if (IsWindowVisible(hwnd)) {
  390. HideWindow(hwnd);
  391. }
  392. break;
  393. case WM_WININICHANGE:
  394. //
  395. // Check if the user's environment variables have changed, if so
  396. // regenerate the environment, so that new apps started from
  397. // taskman will have the latest environment.
  398. //
  399. if (lparam && (!lstrcmpi((LPTSTR)lparam, (LPTSTR) TEXT("Environment")))) {
  400. PVOID pEnv;
  401. RegenerateUserEnvironment(&pEnv, TRUE);
  402. break;
  403. }
  404. else {
  405. return FALSE;
  406. }
  407. case MYCBN_SELCHANGE:
  408. if (!fNoRun) {
  409. if (GetDlgItemText(hwnd, IDD_TMPATH, (LPTSTR)szTMPathField, MAXPATHFIELD)) {
  410. EnableWindow(GetDlgItem(hwnd, IDD_RUN), TRUE);
  411. if (!bChangedDefaultButton) {
  412. SetDefButton (hwnd, IDD_RUN);
  413. bChangedDefaultButton = TRUE;
  414. }
  415. } else {
  416. EnableWindow(GetDlgItem(hwnd, IDD_RUN), FALSE);
  417. if (bChangedDefaultButton) {
  418. SetDefButton (hwnd, IDD_SWITCH);
  419. bChangedDefaultButton = FALSE;
  420. }
  421. }
  422. }
  423. break;
  424. case WM_COMMAND:
  425. switch(LOWORD(wParam)) {
  426. case IDD_TASKLISTBOX:
  427. switch(HIWORD(wParam)) {
  428. case LBN_DBLCLK:
  429. HideTasklist();
  430. ActivateSelectedWindow(hwndLB);
  431. break;
  432. //#ifdef FE_IME // 2-Jun-92, by eichim
  433. // {
  434. // NOTE: bOpen should be TRUE and the ime should be disabled
  435. // for the tasklistbox but when we tab to the edit control it
  436. // needs to be enabled.
  437. case LBN_SETFOCUS:
  438. WINNLSEnableIME((HWND)NULL, FALSE);
  439. break;
  440. case LBN_KILLFOCUS:
  441. WINNLSEnableIME((HWND)NULL, TRUE);
  442. break;
  443. // }
  444. //#endif // FE_IME
  445. default:
  446. // Always change the default button to Switch when we tab to
  447. // the task listbox
  448. //
  449. if (!fNoRun) {
  450. if (bChangedDefaultButton) {
  451. SetDefButton (hwnd, IDD_SWITCH);
  452. bChangedDefaultButton = FALSE;
  453. }
  454. }
  455. return FALSE;
  456. }
  457. break;
  458. case IDD_TMPATH:
  459. PostMessage (hwnd, MYCBN_SELCHANGE, 0, 0);
  460. break;
  461. case IDOK:
  462. if (!bChangedDefaultButton) {
  463. goto Switchem;
  464. }
  465. case IDD_RUN:
  466. if (!fNoRun) {
  467. TCHAR szFilename[MAXPATHFIELD];
  468. WORD ret;
  469. BOOL bMinOnRunSave;
  470. //
  471. // Run this app in the user's home directory
  472. //
  473. SetCurrentDirectory(szOriginalDirectory);
  474. GetDlgItemText(hwnd, IDD_TMPATH, szTMPathField, MAXPATHFIELD);
  475. DoEnvironmentSubst(szTMPathField, MAXPATHFIELD);
  476. GetDirectoryFromPath(szTMPathField, szTMDirField);
  477. if (*szTMDirField) {
  478. // Convert path into a .\foo.exe style thing.
  479. lstrcpy(szFilename, TEXT(".\\"));
  480. // Tag the filename and params on to the end of the dot slash.
  481. GetFilenameFromPath(szTMPathField, szFilename+2);
  482. if (*(szFilename+2) == TEXT('"') ) {
  483. SheRemoveQuotes(szFilename+2);
  484. CheckEscapes(szFilename, CharSizeOf(szFilename));
  485. }
  486. }
  487. else {
  488. GetFilenameFromPath(szTMPathField, szFilename);
  489. }
  490. //
  491. // Don't minimize ProgMan when exec'ing a program from taskman.
  492. //
  493. bMinOnRunSave = bMinOnRun;
  494. bMinOnRun = FALSE;
  495. ret = ExecProgram(szFilename, szTMDirField, szFilename, FALSE, 0, 0, 0);
  496. //
  497. // Reset Minimized on Run
  498. //
  499. bMinOnRun = bMinOnRunSave;
  500. //
  501. // reset Progman's working directory.
  502. //
  503. SetCurrentDirectory(szWindowsDirectory);
  504. if (ret) {
  505. fMsgBox = TRUE;
  506. MyMessageBox( hwnd, IDS_EXECERRTITLE, ret, szTMPathField,
  507. MB_SYSTEMMODAL | MB_OK | MB_ICONEXCLAMATION );
  508. fMsgBox = FALSE;
  509. SetFocus(GetDlgItem(hwnd, IDD_TMPATH));
  510. } else {
  511. GetDlgItemText(hwnd, IDD_TMPATH, szTMPathField, MAXPATHFIELD);
  512. SaveRecentFileList (hwnd, szTMPathField, IDD_TMPATH);
  513. HideWindow(hwnd);
  514. }
  515. }
  516. break;
  517. Switchem:
  518. case IDD_SWITCH:
  519. HideTasklist();
  520. ActivateSelectedWindow(hwndLB);
  521. break;
  522. case IDCANCEL:
  523. HideWindow(hwnd);
  524. break;
  525. case IDD_TERMINATE:
  526. /*
  527. * Get the hwnd of the item which was selected.
  528. */
  529. nIndex = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0);
  530. hwndNext = (HWND)SendMessage(hwndLB, LB_GETITEMDATA, nIndex, 0);
  531. if (!IsWindow(hwndNext)) {
  532. HideWindow(hwnd);
  533. MessageBeep(0);
  534. break;
  535. }
  536. {
  537. /* Always activate the window first. This prevents
  538. * apps from going to Beep mode. Failing to do this
  539. * can cause re-entrancy problems in the app if we
  540. * do this again before activating the app.
  541. *
  542. * However, don't do this if it is a old app task.
  543. */
  544. #ifdef WIN16 /* if NTWIN, then always do this, as is no winoldapp */
  545. if (!IsWinoldapTask(GetTaskFromHwnd(hwndNext)))
  546. #endif
  547. HideWindow(hwnd);
  548. ActivateSelectedWindow(hwndLB);
  549. {
  550. DWORD idt;
  551. HANDLE hThread;
  552. hThread = CreateThread(NULL, 0,
  553. (LPTHREAD_START_ROUTINE)CallEndTask,
  554. (LPVOID)hwndNext, 0,
  555. &idt);
  556. if (hThread == NULL) {
  557. /*
  558. * Can not create thread, just call EndTask
  559. * syncronously
  560. */
  561. DoEndTask( hwndNext );
  562. } else {
  563. CloseHandle(hThread);
  564. }
  565. }
  566. }
  567. break;
  568. case IDD_TILE:
  569. case IDD_CASCADE:
  570. {
  571. HWND hwndDesktop;
  572. HideWindow(hwnd);
  573. hwndDesktop = GetDesktopWindow();
  574. if (wParam == IDD_CASCADE) {
  575. CascadeChildWindows(hwndDesktop, 0);
  576. } else {
  577. /*
  578. * If shift is down, tile vertically, else horizontally.
  579. */
  580. TileChildWindows(hwndDesktop, ((GetKeyState(VK_SHIFT) &
  581. 0x8000) ? MDITILE_HORIZONTAL : MDITILE_VERTICAL));
  582. }
  583. break;
  584. }
  585. case IDD_ARRANGEICONS:
  586. /*
  587. * Let's restore the saved bits before ArrangeIcons
  588. * FIX for Bug #4884; --SANKAR-- 10-02-89
  589. */
  590. HideWindow(hwnd);
  591. ArrangeIconicWindows(GetDesktopWindow());
  592. break;
  593. }
  594. break;
  595. case WM_CLOSE:
  596. /*
  597. * If wParam != 0, this is a shutdown request, so exit.
  598. */
  599. if (wParam != 0)
  600. ExitProcess(0);
  601. return FALSE;
  602. break;
  603. case WM_HOTKEY:
  604. if (wParam == 1) {
  605. pt.x = (dxScreen - dxTaskman) / 2;
  606. pt.y = (dyScreen - dyTaskman) / 2;
  607. ShowTasklist(pt);
  608. }
  609. break;
  610. case WM_LOGOFF:
  611. PostQuitMessage(0);
  612. break;
  613. default:
  614. return FALSE;
  615. }
  616. return TRUE;
  617. }
  618. //*************************************************************
  619. //
  620. // SetDefButton()
  621. //
  622. // Purpose: Sets the default button
  623. //
  624. // Parameters: HWND hDlg - Window handle of dialog box
  625. // INT idButton - ID of button
  626. //
  627. // Return: void
  628. //
  629. //*************************************************************
  630. VOID SetDefButton(HWND hwndDlg, INT idButton)
  631. {
  632. LRESULT lr;
  633. if (HIWORD(lr = SendMessage(hwndDlg, DM_GETDEFID, 0, 0)) == DC_HASDEFID)
  634. {
  635. HWND hwndOldDefButton = GetDlgItem(hwndDlg, LOWORD(lr));
  636. SendMessage (hwndOldDefButton,
  637. BM_SETSTYLE,
  638. MAKEWPARAM(BS_PUSHBUTTON, 0),
  639. MAKELPARAM(TRUE, 0));
  640. }
  641. SendMessage( hwndDlg, DM_SETDEFID, idButton, 0L );
  642. SendMessage( GetDlgItem(hwndDlg, idButton),
  643. BM_SETSTYLE,
  644. MAKEWPARAM( BS_DEFPUSHBUTTON, 0 ),
  645. MAKELPARAM( TRUE, 0 ));
  646. }
  647. BOOL
  648. InitTaskman()
  649. {
  650. WNDCLASS wc;
  651. /*
  652. * First set the priority of taskman so it is higher than foreground apps
  653. * that spin in loops - this way it'll always come up when you hit
  654. * ctrl-esc.
  655. */
  656. SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  657. wc.style = 0;
  658. wc.lpfnWndProc = DefDlgProc;
  659. wc.cbClsExtra = 0;
  660. wc.cbWndExtra = DLGWINDOWEXTRA;
  661. wc.hInstance = hAppInstance;
  662. wc.hIcon = LoadIcon(hAppInstance, MAKEINTRESOURCE(PROGMANICON));
  663. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  664. wc.hbrBackground = NULL;
  665. wc.lpszMenuName = NULL;
  666. wc.lpszClassName = TEXT("TakoHachi");
  667. RegisterClass(&wc);
  668. {
  669. //
  670. // Set the working set size to 200k.
  671. //
  672. QUOTA_LIMITS QuotaLimits;
  673. NTSTATUS status;
  674. status = NtQueryInformationProcess( NtCurrentProcess(),
  675. ProcessQuotaLimits,
  676. &QuotaLimits,
  677. sizeof(QUOTA_LIMITS),
  678. NULL );
  679. if (NT_SUCCESS(status)) {
  680. QuotaLimits.MinimumWorkingSetSize = 300 * 1024;
  681. QuotaLimits.MaximumWorkingSetSize = 372 * 1024;
  682. NtSetInformationProcess( NtCurrentProcess(),
  683. ProcessQuotaLimits,
  684. &QuotaLimits,
  685. sizeof(QUOTA_LIMITS) );
  686. }
  687. }
  688. /*
  689. * Taskman will work in the windows directory, and switch to the
  690. * original directory (home directory) before execing programs.
  691. * This is to prevent weird popups if a UNC original directory is
  692. * disconnected.
  693. */
  694. GetCurrentDirectory(MAXPATHFIELD, szTMUserHomeDir);
  695. GetWindowsDirectory(szTMWindowsDirectory, MAXPATHFIELD);
  696. SetCurrentDirectory(szTMWindowsDirectory);
  697. if (fNoRun) {
  698. ghwndTMDialog = CreateDialog(hAppInstance, MAKEINTRESOURCE(WMPTASKMANDLG), NULL,
  699. TaskmanDlgProc);
  700. } else {
  701. ghwndTMDialog = CreateDialog(hAppInstance, MAKEINTRESOURCE(PWRTASKMANDLG), NULL,
  702. TaskmanDlgProc);
  703. }
  704. if (ghwndTMDialog == NULL)
  705. return(FALSE);
  706. LoadString(hAppInstance, IDS_OOMEXITTITLE, szTMOOMExitTitle, 32);
  707. LoadString(hAppInstance, IDS_OOMEXITMSG, szTMOOMExitMsg, 64);
  708. if (!RegisterHotKey(ghwndTMDialog, 1, MOD_CONTROL, VK_ESCAPE) ||
  709. !RegisterTasklist(ghwndTMDialog)) {
  710. DestroyWindow(ghwndTMDialog);
  711. return(FALSE);
  712. }
  713. return(TRUE);
  714. }
  715. VOID
  716. TMMain()
  717. {
  718. MSG msg;
  719. LPSTR lpszCmdLine = NULL;
  720. int nCmdShow = SW_SHOWNORMAL;
  721. if (InitTaskman()) {
  722. while (GetMessage(&msg, (HWND)NULL, (UINT)0, (UINT)0)) {
  723. if (!IsDialogMessage(ghwndTMDialog, &msg)) {
  724. if ((msg.message == WM_SYSCOMMAND) && (msg.wParam == SC_TASKLIST)) {
  725. POINT pt;
  726. GetCursorPos(&pt);
  727. pt.x = max(pt.x - (dyTaskman / 2), 0);
  728. pt.x = min(pt.x, dxScreen - dxTaskman);
  729. pt.y = max(pt.y - (GetSystemMetrics(SM_CYCAPTION) * 2), 0);
  730. pt.y = min(pt.y, dyScreen - dyTaskman);
  731. ShowTasklist(pt);
  732. continue;
  733. } else {
  734. //
  735. // We need to have a regular message loop in order
  736. // to handle the DDE messages generated by spawning
  737. // an application via an association.
  738. //
  739. TranslateMessage (&msg);
  740. DispatchMessage (&msg);
  741. }
  742. }
  743. }
  744. }
  745. }