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.

1637 lines
42 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. #define UNICODE
  12. #include "taskman.h"
  13. #include <port1632.h>
  14. #include <shellapi.h>
  15. #include <shlapip.h>
  16. //LATER find correct define for NT
  17. #if !defined(NTWIN) && !defined(DOSWIN32) && !defined(WIN16)
  18. #define NTWIN 1
  19. #endif
  20. #define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
  21. #define MAXPATHFIELD 260
  22. #define INIT_MAX_FILES 4
  23. #define FILES_KEY L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager\\Recent File List"
  24. #define MAXFILES_ENTRY L"Max Files"
  25. #define FILE_ENTRY L"File%lu"
  26. #define WM_CONTENTSCHANGED (WM_USER+5)
  27. TCHAR szPathField[MAXPATHFIELD];
  28. TCHAR szDirField[MAXPATHFIELD];
  29. TCHAR szTitle[MAXPATHFIELD];
  30. TCHAR szMessage[MAXMSGBOXLEN];
  31. TCHAR szUserHomeDir[MAXPATHFIELD];
  32. TCHAR szWindowsDirectory[MAXPATHFIELD];
  33. TCHAR szOOMExitMsg[64] = TEXT("Close an application and try again."); // 64
  34. TCHAR szOOMExitTitle[32] = TEXT("Extremely Low on Memory"); // 32
  35. TCHAR szNoRun[] = TEXT("NoRun");
  36. // registry key for groups
  37. HANDLE hInst;
  38. BOOL bChangedDefaultButton;
  39. INT_PTR APIENTRY TaskmanDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam);
  40. WORD APIENTRY ExecProgram(LPTSTR lpszPath,LPTSTR lpDir,LPTSTR lpTitle);
  41. void APIENTRY SaveRecentFileList (HWND, LPTSTR);
  42. VOID GetPathInfo(PTSTR szPath,PTSTR *pszFileName,PTSTR *pszExt,WORD *pich,BOOL *pfUnc);
  43. VOID GetFilenameFromPath(PTSTR szPath, PTSTR szFilename);
  44. VOID GetDirectoryFromPath(PTSTR szFilePath, PTSTR szDir);
  45. BOOL IsUserAdmin();
  46. BOOL OKToExec();
  47. BOOL TestTokenForAdmin(HANDLE Token);
  48. VOID SetDefButton(HWND hwndDlg, INT idButton);
  49. WINUSERAPI VOID SwitchToThisWindow(HWND, BOOL);
  50. INT MyMessageBox(HWND hWnd,WORD idTitle,WORD idMessage,PWSTR psz,WORD wStyle);
  51. INT MyX = 0;
  52. INT MyY = 0;
  53. INT dxTaskman;
  54. INT dyTaskman;
  55. INT dxScreen;
  56. INT dyScreen;
  57. HWND ghwndDialog;
  58. BOOL fExecOK = TRUE;
  59. BOOL fMsgBox = FALSE;
  60. PVOID Alloc(
  61. DWORD Bytes)
  62. {
  63. HANDLE hMem;
  64. PVOID Buffer;
  65. hMem = LocalAlloc(LMEM_MOVEABLE, Bytes + sizeof(hMem));
  66. if (hMem == NULL) {
  67. return(NULL);
  68. }
  69. Buffer = LocalLock(hMem);
  70. if (Buffer == NULL) {
  71. LocalFree(hMem);
  72. return(NULL);
  73. }
  74. *((PHANDLE)Buffer) = hMem;
  75. return (PVOID)(((PHANDLE)Buffer)+1);
  76. }
  77. BOOL Free(
  78. PVOID Buffer)
  79. {
  80. HANDLE hMem;
  81. hMem = *(((PHANDLE)Buffer) - 1);
  82. LocalUnlock(hMem);
  83. return(LocalFree(hMem) == NULL);
  84. }
  85. VOID
  86. HideWindow(HWND hwnd)
  87. {
  88. if (!fMsgBox) {
  89. if (fExecOK) {
  90. SetDlgItemText(ghwndDialog, IDD_PATH, TEXT(""));
  91. }
  92. // redundant? why do they do the reverse twice for show below?
  93. ShowWindow(ghwndDialog, SW_HIDE);
  94. SetWindowPos(ghwndDialog, HWND_NOTOPMOST, 0, 0, 0, 0,
  95. SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
  96. }
  97. // Erase dark border from depressed pushbuttons
  98. SendMessage(GetDlgItem(hwnd, IDCANCEL), // IDCANCEL
  99. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  100. SendMessage(GetDlgItem(hwnd, IDD_TERMINATE),
  101. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  102. SendMessage(GetDlgItem(hwnd, IDD_CASCADE),
  103. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  104. SendMessage(GetDlgItem(hwnd, IDD_TILE),
  105. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  106. SendMessage(GetDlgItem(hwnd, IDD_ARRANGEICONS),
  107. BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
  108. }
  109. /*
  110. * We call HideTasklist() when we want to remove the tasklist window
  111. * from the screen but not select another window (ie. when we're about
  112. * to select another app. We call ShowWindow(SW_HIDE) directly when
  113. * we're doing something like tiling or cascading so a window other than
  114. * the tasklist will become the foreground window.
  115. */
  116. VOID HideTasklist(VOID)
  117. {
  118. if (fExecOK) {
  119. SetDlgItemText(ghwndDialog, IDD_PATH, TEXT(""));
  120. }
  121. SetWindowPos(ghwndDialog, HWND_TOP, 0, 0, 0, 0, SWP_HIDEWINDOW |
  122. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
  123. }
  124. VOID ShowTasklist(
  125. POINT pt)
  126. {
  127. /*
  128. * Retract the drop down listbox.
  129. */
  130. if (fExecOK) {
  131. SendDlgItemMessage(ghwndDialog, IDD_PATH,
  132. CB_SHOWDROPDOWN,0,0);
  133. }
  134. SetWindowPos(ghwndDialog, HWND_TOPMOST, pt.x, pt.y, 0, 0,
  135. SWP_NOSIZE | SWP_NOACTIVATE );
  136. SetForegroundWindow(ghwndDialog);
  137. ShowWindow(ghwndDialog, SW_NORMAL);
  138. }
  139. /*** ActivateSelectedWindow -- Calls user, to set active window, selected
  140. * by the user.
  141. *
  142. *
  143. * ActivateSelectedWindow(HWND hwndLB)
  144. *
  145. * ENTRY - HWND hwndLB - handle to window, which is to become the active
  146. * window, with focus.
  147. * EXIT -
  148. * SYNOPSIS - This function takes the hwnd passed into it, calls user
  149. * to set active focus to that window.
  150. * WARNINGS -
  151. * EFFECTS -
  152. *
  153. */
  154. VOID ActivateSelectedWindow(
  155. HWND hwndLB)
  156. {
  157. INT nIndex;
  158. HWND hwndT;
  159. HWND hwndLastActive;
  160. DWORD lTemp;
  161. /*
  162. * Get the hwnd of the item which was selected.
  163. */
  164. nIndex = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0);
  165. hwndT = (HWND)SendMessage(hwndLB, LB_GETITEMDATA, nIndex, 0);
  166. if (!IsWindow(hwndT)) {
  167. /*
  168. * We gotta make sure the window is valid before doing stuff with it.
  169. * An app may terminate itself in the background rendering these
  170. * window handles invalid.
  171. */
  172. goto Beep;
  173. }
  174. /*
  175. * Switch to that task.
  176. * HACK! Activate the window in the hwndLastActive field of the WndStruct.
  177. */
  178. hwndLastActive = GetLastActivePopup(hwndT);
  179. if (!IsWindow(hwndLastActive)) {
  180. goto Beep;
  181. }
  182. /*
  183. * But only if it isn't disabled.
  184. */
  185. lTemp = GetWindowLong(hwndLastActive, GWL_STYLE);
  186. if (!(lTemp & WS_DISABLED)) {
  187. /*
  188. * HACK!! Use SwitchToThisWindow() to bring dialog parents as well.
  189. */
  190. SwitchToThisWindow(hwndLastActive, TRUE);
  191. } else {
  192. Beep:
  193. MessageBeep(0);
  194. }
  195. }
  196. #ifdef NTWIN
  197. /*** DoEndTask --
  198. *
  199. * void DoEndTask( HWND hwnd )
  200. */
  201. VOID DoEndTask(
  202. HWND hwnd )
  203. {
  204. TCHAR szMsgBoxText[MAXMSGBOXLEN];
  205. TCHAR szTempField[MAXTASKNAMELEN];
  206. INT nch;
  207. if (!EndTask(hwnd, FALSE, FALSE)) {
  208. /* App does not want to close, ask user if
  209. * he wants to blow it away
  210. */
  211. InternalGetWindowText(hwnd, (LPTSTR)szTempField, MAXTASKNAMELEN);
  212. /* Load the message box string, it is very long (greater than 255 chars
  213. * which is why we load it in two pieces
  214. */
  215. nch = LoadString(NULL, IDS_MSGBOXSTR1, szMsgBoxText, MAXMSGBOXLEN);
  216. LoadString(NULL, IDS_MSGBOXSTR2, &szMsgBoxText[nch], MAXMSGBOXLEN-nch);
  217. if( MessageBox( NULL, szMsgBoxText, szTempField,
  218. MB_SETFOREGROUND | MB_SYSTEMMODAL | MB_YESNO ) == IDYES) {
  219. EndTask(hwnd, FALSE, TRUE);
  220. }
  221. }
  222. }
  223. /*** CallEndTask -- A separate thread to instigate EndTask
  224. *
  225. * CallEndTask( HWND hwnd );
  226. *
  227. * ENTRY - HWND hwnd - window handle for the task to be killed
  228. * EXIT -
  229. * SYNOPSIS - This function calls EndTask on the given window to kill the
  230. * task that owns that window.
  231. *
  232. * WARNINGS -
  233. * EFFECTS - Kills the task that owns hwnd.
  234. *
  235. */
  236. DWORD CallEndTask(
  237. HWND hwnd)
  238. {
  239. DoEndTask(hwnd);
  240. ExitThread(0);
  241. return 0; /* placate compiler */
  242. }
  243. #endif
  244. /*** TaskmanDlgProc -- Dialog Procedure for Taskman Window
  245. *
  246. *
  247. *
  248. * TaskmanDlgProc(HWND hDlg, WORD wMSG, DWORD wParam, LPARAM lParam)
  249. *
  250. * ENTRY - HWND hhDlg - handle to dialog box.
  251. * WORD wMsg - message to be acted upon.
  252. * DWORD wParam - value specific to wMsg.
  253. * LPARAM lParam - value specific to wMsg.
  254. *
  255. * EXIT - True if success, False if not.
  256. * SYNOPSIS - Dialog box message processing function.
  257. *
  258. * WARNINGS -
  259. * EFFECTS -
  260. *
  261. */
  262. INT_PTR TaskmanDlgProc(
  263. HWND hwnd,
  264. UINT wMsg,
  265. WPARAM wParam,
  266. LPARAM lParam)
  267. {
  268. int nIndex;
  269. RECT rc;
  270. HWND hwndLB;
  271. HWND hwndNext;
  272. TCHAR szTempField[MAXTASKNAMELEN];
  273. POINT pt;
  274. HKEY hKey;
  275. DWORD dwDisp;
  276. DWORD dwDataType, dwMaxFiles=INIT_MAX_FILES, dwMaxFilesSize, dwCount;
  277. TCHAR szFileEntry[20];
  278. TCHAR szFullPath[MAXPATHFIELD];
  279. #ifndef NTWIN
  280. LONG lTemp;
  281. #endif
  282. hwndLB = GetDlgItem(hwnd, IDD_TASKLISTBOX);
  283. switch (wMsg) {
  284. case WM_INITDIALOG:
  285. /*
  286. * call private api to mark task man as a system app. This causes
  287. * it to be killed after all other non-system apps during shutdown.
  288. */
  289. // MarkProcess(MP_SYSTEMAPP);
  290. GetWindowRect(hwnd, &rc);
  291. dxTaskman = rc.right - rc.left;
  292. dyTaskman = rc.bottom - rc.top;
  293. dxScreen = GetSystemMetrics(SM_CXSCREEN);
  294. dyScreen = GetSystemMetrics(SM_CYSCREEN);
  295. pt.x = (dxScreen - dxTaskman) / 2;
  296. pt.y = (dyScreen - dyTaskman) / 2;
  297. SetWindowPos(hwnd, HWND_NOTOPMOST, pt.x, pt.y, 0, 0,
  298. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  299. SendDlgItemMessage(hwnd, IDD_PATH, EM_LIMITTEXT, MAXPATHFIELD-4, 0L);
  300. szPathField[0] = TEXT('\0');
  301. bChangedDefaultButton = FALSE;
  302. return FALSE;
  303. case WM_SHOWWINDOW:
  304. /*
  305. * If we're being shown fill in the listbox. We do this here
  306. * rather than in WM_ACTIVATE process so we can do it while the
  307. * dialog is still invisible.
  308. */
  309. if (wParam != 0) {
  310. DWORD pidTaskMan = GetCurrentProcessId();
  311. /*
  312. * First delete any previous entries.
  313. */
  314. while ((int)SendMessage(hwndLB, LB_DELETESTRING, 0, 0) != LB_ERR);
  315. /*
  316. * Search the window list for enabled top level windows.
  317. */
  318. hwndNext = GetWindow(hwnd, GW_HWNDFIRST);
  319. while (hwndNext) {
  320. /*
  321. * Only add non-owned, visible, non-Taskman, Top Level Windows.
  322. */
  323. if ((hwndNext != hwnd) && (IsWindowVisible(hwndNext)) &&
  324. (!GetWindow(hwndNext, GW_OWNER))) {
  325. DWORD pidNext;
  326. GetWindowThreadProcessId(hwndNext, &pidNext);
  327. if (pidNext != pidTaskMan) {
  328. if (InternalGetWindowText(hwndNext, (LPTSTR)szTempField,
  329. MAXTASKNAMELEN)) {
  330. nIndex = (int)SendMessage(hwndLB, LB_ADDSTRING, 0,
  331. (DWORD_PTR)(LPTSTR)szTempField);
  332. SendMessage(hwndLB, LB_SETITEMDATA, nIndex,
  333. (DWORD_PTR)hwndNext);
  334. }
  335. }
  336. }
  337. hwndNext = GetWindow(hwndNext, GW_HWNDNEXT);
  338. }
  339. SendMessage(hwndLB, LB_SETCURSEL, 0, 0);
  340. //
  341. // Set the default button to "Switch To"
  342. //
  343. SetDefButton(hwnd,IDD_SWITCH);
  344. //
  345. // Load the combobox with the recently used files.
  346. //
  347. if (GetDlgItem(hwnd, IDD_PATH)) {
  348. //
  349. // FIrst empty the combo box from the last time.
  350. //
  351. SendDlgItemMessage (hwnd, IDD_PATH,
  352. CB_RESETCONTENT, 0, 0);
  353. //
  354. // Load the combobox with recently used files from the registry.
  355. //
  356. // Query the max number of files first.
  357. //
  358. if (RegCreateKeyEx (HKEY_CURRENT_USER, FILES_KEY, 0, 0,
  359. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  360. NULL, &hKey, &dwDisp) == ERROR_SUCCESS) {
  361. if (dwDisp == REG_OPENED_EXISTING_KEY) {
  362. //
  363. // Query the max number of entries
  364. //
  365. dwMaxFilesSize = sizeof (DWORD);
  366. if (RegQueryValueEx (hKey, MAXFILES_ENTRY, NULL, &dwDataType,
  367. (LPBYTE)&dwMaxFiles, &dwMaxFilesSize) == ERROR_SUCCESS) {
  368. //
  369. // Now Query each entry and add it to the list box.
  370. //
  371. for (dwCount=0; dwCount < dwMaxFiles; dwCount++) {
  372. wsprintf (szFileEntry, FILE_ENTRY, dwCount);
  373. dwMaxFilesSize = MAXPATHFIELD+1;
  374. if (RegQueryValueEx (hKey, szFileEntry, NULL, &dwDataType,
  375. (LPBYTE) szFullPath, &dwMaxFilesSize) == ERROR_SUCCESS) {
  376. //
  377. // Found an entry. Add it to the combo box.
  378. //
  379. SendDlgItemMessage (hwnd, IDD_PATH,
  380. CB_ADDSTRING, 0,
  381. (LPARAM)szFullPath);
  382. } else {
  383. break;
  384. }
  385. }
  386. }
  387. } else {
  388. //
  389. // We are working with a new key, so we need to
  390. // set the default number of files.
  391. //
  392. RegSetValueEx (hKey, MAXFILES_ENTRY, 0, REG_DWORD,
  393. (CONST BYTE *) &dwMaxFiles, sizeof (DWORD));
  394. }
  395. //
  396. // Close the registry key
  397. //
  398. RegCloseKey (hKey);
  399. }
  400. }
  401. //
  402. // Disable the Run button and set the focus to the
  403. // listbox.
  404. //
  405. EnableWindow(GetDlgItem(hwnd, IDD_RUN), FALSE);
  406. SetFocus(hwndLB);
  407. }
  408. break;
  409. case WM_ACTIVATE:
  410. /*
  411. * If we're being deactivated clear the listbox so we
  412. * can fill it in afresh when we're re-activated.
  413. */
  414. if (wParam == 0) {
  415. /*
  416. * If we're not already invisible, hide ourself.
  417. */
  418. if (IsWindowVisible(hwnd)) {
  419. HideWindow(hwnd);
  420. }
  421. }
  422. if (!bChangedDefaultButton) {
  423. SetDefButton(hwnd,IDD_SWITCH);
  424. }
  425. break;
  426. case WM_ACTIVATEAPP:
  427. if (wParam)
  428. return FALSE;
  429. /*
  430. * If we are not visible when we get this message it is because
  431. * we are already in the process of terminating. If we don't
  432. * ignore this we get into a weird race condition and the frame
  433. * of the window being activated doesn't get fully drawn. (BG)
  434. */
  435. if (IsWindowVisible(hwnd)) {
  436. HideWindow(hwnd);
  437. }
  438. break;
  439. #ifdef JAPAN // bug fix
  440. //
  441. // Do nothing. Let the progman main thread do the work.
  442. //
  443. #else // not JAPAN
  444. case WM_WININICHANGE:
  445. //
  446. // Check if the user's environment variables have changed, if so
  447. // regenerate the environment, so that new apps started from
  448. // taskman will have the latest environment.
  449. //
  450. if (lParam && (!lstrcmpi((LPTSTR)lParam, (LPTSTR) TEXT("Environment")))) {
  451. PVOID pEnv;
  452. RegenerateUserEnvironment(&pEnv, TRUE);
  453. break;
  454. }
  455. else {
  456. return FALSE;
  457. }
  458. #endif // JAPAN
  459. case WM_CONTENTSCHANGED:
  460. if (fExecOK) {
  461. if (GetDlgItemText(hwnd, IDD_PATH, (LPTSTR)szPathField, MAXPATHFIELD)) {
  462. EnableWindow(GetDlgItem(hwnd, IDD_RUN), TRUE);
  463. if (!bChangedDefaultButton) {
  464. SetDefButton(hwnd,IDD_RUN);
  465. bChangedDefaultButton = TRUE;
  466. }
  467. } else {
  468. EnableWindow(GetDlgItem(hwnd, IDD_RUN), FALSE);
  469. if (bChangedDefaultButton) {
  470. SetDefButton(hwnd,IDD_SWITCH);
  471. bChangedDefaultButton = FALSE;
  472. }
  473. }
  474. }
  475. break;
  476. case WM_COMMAND:
  477. switch(LOWORD(wParam)) {
  478. case IDD_TASKLISTBOX:
  479. switch(HIWORD(wParam)) {
  480. case LBN_DBLCLK:
  481. HideTasklist();
  482. ActivateSelectedWindow(hwndLB);
  483. break;
  484. default:
  485. return FALSE;
  486. }
  487. break;
  488. case IDD_PATH:
  489. PostMessage (hwnd, WM_CONTENTSCHANGED, 0, 0);
  490. break;
  491. case IDOK:
  492. if (!bChangedDefaultButton) {
  493. goto Switchem;
  494. }
  495. case IDD_RUN:
  496. if (fExecOK) {
  497. TCHAR szFilename[MAXPATHFIELD+4];
  498. WORD ret;
  499. GetDlgItemText(hwnd, IDD_PATH, szPathField, MAXPATHFIELD);
  500. DoEnvironmentSubst(szPathField, MAXPATHFIELD);
  501. GetDirectoryFromPath(szPathField, szDirField);
  502. if (*szDirField) {
  503. // Convert path into a .\foo.exe style thing.
  504. lstrcpy(szFilename, L".\\");
  505. // Tag the filename and params on to the end of the dot slash.
  506. GetFilenameFromPath(szPathField, szFilename+2);
  507. if (*(szFilename+2) == L'"' ) {
  508. SheRemoveQuotes(szFilename+2);
  509. CheckEscapes(szFilename, ARRAYSIZE(szFilename));
  510. }
  511. }
  512. else {
  513. GetFilenameFromPath(szPathField, szFilename);
  514. }
  515. ret = ExecProgram(szFilename, szDirField, szFilename);
  516. if (ret) {
  517. fMsgBox = TRUE;
  518. MyMessageBox( hwnd, IDS_EXECERRTITLE, ret, szPathField,
  519. MB_SYSTEMMODAL | MB_OK | MB_ICONEXCLAMATION );
  520. fMsgBox = FALSE;
  521. SetFocus(GetDlgItem(hwnd, IDD_PATH));
  522. } else {
  523. GetDlgItemText(hwnd, IDD_PATH, szPathField, MAXPATHFIELD);
  524. SaveRecentFileList (hwnd, szPathField);
  525. HideWindow(hwnd);
  526. }
  527. }
  528. break;
  529. Switchem:
  530. case IDD_SWITCH:
  531. HideTasklist();
  532. ActivateSelectedWindow(hwndLB);
  533. break;
  534. case IDCANCEL:
  535. HideWindow(hwnd);
  536. break;
  537. case IDD_TERMINATE:
  538. /*
  539. * Get the hwnd of the item which was selected.
  540. */
  541. nIndex = (int)SendMessage(hwndLB, LB_GETCURSEL, 0, 0);
  542. hwndNext = (HWND)SendMessage(hwndLB, LB_GETITEMDATA, nIndex, 0);
  543. if (!IsWindow(hwndNext)) {
  544. HideWindow(hwnd);
  545. MessageBeep(0);
  546. break;
  547. }
  548. #ifndef NTWIN /* Since NTWIN uses WM_ENDSESSION to kill the app,
  549. * It is OK to kill it when it is disabled
  550. */
  551. /*
  552. * Test if the toplevel window is disabled. If it is
  553. * diabled, we don't want to send a WM_CLOSE message to
  554. * the parent. This is because the app could have a dialog
  555. * box up and it's not expecting a CLOSE message...
  556. * Nasty rips can happen... Instead, active the window so
  557. * that the user can dismis any dialog box or fix whatever
  558. * is causing the top level window to be disabled...
  559. */
  560. lTemp = GetWindowLong(hwndNext, GWL_STYLE);
  561. if (lTemp & WS_DISABLED) {
  562. HideTasklist();
  563. MessageBeep(0);
  564. ActivateSelectedWindow(hwndLB);
  565. } else
  566. #endif
  567. {
  568. /* Always activate the window first. This prevents
  569. * apps from going to Beep mode. Failing to do this
  570. * can cause re-entrancy problems in the app if we
  571. * do this again before activating the app.
  572. *
  573. * However, don't do this if it is a old app task.
  574. */
  575. #ifdef WIN16 /* if NTWIN, then always do this, as is no winoldapp */
  576. if (!IsWinoldapTask(GetTaskFromHwnd(hwndNext)))
  577. #endif
  578. HideWindow(hwnd);
  579. ActivateSelectedWindow(hwndLB);
  580. #ifdef NTWIN
  581. {
  582. DWORD idt;
  583. HANDLE hThread;
  584. hThread = CreateThread(NULL, 0,
  585. (LPTHREAD_START_ROUTINE)CallEndTask,
  586. (LPVOID)hwndNext, 0,
  587. &idt);
  588. if (hThread == NULL) {
  589. /*
  590. * Can not create thread, just call EndTask
  591. * syncronously
  592. */
  593. DoEndTask( hwndNext );
  594. } else {
  595. CloseHandle(hThread);
  596. }
  597. }
  598. #else
  599. EndTask(hwndNext, FALSE, FALSE);
  600. #endif
  601. }
  602. break;
  603. case IDD_TILE:
  604. case IDD_CASCADE:
  605. {
  606. HWND hwndDesktop;
  607. HideWindow(hwnd);
  608. hwndDesktop = GetDesktopWindow();
  609. if (wParam == IDD_CASCADE) {
  610. CascadeChildWindows(hwndDesktop, 0);
  611. } else {
  612. /*
  613. * If shift is down, tile vertically, else horizontally.
  614. */
  615. TileChildWindows(hwndDesktop, ((GetKeyState(VK_SHIFT) &
  616. 0x8000) ? MDITILE_HORIZONTAL : MDITILE_VERTICAL));
  617. }
  618. break;
  619. }
  620. case IDD_ARRANGEICONS:
  621. /*
  622. * Let's restore the saved bits before ArrangeIcons
  623. * FIX for Bug #4884; --SANKAR-- 10-02-89
  624. */
  625. HideWindow(hwnd);
  626. ArrangeIconicWindows(GetDesktopWindow());
  627. break;
  628. }
  629. break;
  630. case WM_CLOSE:
  631. /*
  632. * If wParam != 0, this is a shutdown request, so exit.
  633. */
  634. if (wParam != 0)
  635. ExitProcess(0);
  636. return FALSE;
  637. break;
  638. case WM_HOTKEY:
  639. if (wParam == 1) {
  640. pt.x = (dxScreen - dxTaskman) / 2;
  641. pt.y = (dyScreen - dyTaskman) / 2;
  642. ShowTasklist(pt);
  643. }
  644. break;
  645. case WM_LOGOFF:
  646. PostQuitMessage(0);
  647. break;
  648. default:
  649. return FALSE;
  650. }
  651. return TRUE;
  652. lParam;
  653. }
  654. //*************************************************************
  655. //
  656. // SetDefButton()
  657. //
  658. // Purpose: Sets the default button
  659. //
  660. // Parameters: HWND hDlg - Window handle of dialog box
  661. // INT idButton - ID of button
  662. //
  663. // Return: void
  664. //
  665. //*************************************************************
  666. VOID SetDefButton(HWND hwndDlg, INT idButton)
  667. {
  668. LRESULT lr;
  669. if (HIWORD(lr = SendMessage(hwndDlg, DM_GETDEFID, 0, 0)) == DC_HASDEFID)
  670. {
  671. HWND hwndOldDefButton = GetDlgItem(hwndDlg, LOWORD(lr));
  672. SendMessage (hwndOldDefButton,
  673. BM_SETSTYLE,
  674. MAKEWPARAM(BS_PUSHBUTTON, 0),
  675. MAKELPARAM(TRUE, 0));
  676. }
  677. SendMessage( hwndDlg, DM_SETDEFID, idButton, 0L );
  678. SendMessage( GetDlgItem(hwndDlg, idButton),
  679. BM_SETSTYLE,
  680. MAKEWPARAM( BS_DEFPUSHBUTTON, 0 ),
  681. MAKELPARAM( TRUE, 0 ));
  682. }
  683. /*** SaveRecentFileList -- Save the list of recently used files
  684. *
  685. * void APIENTRY SaveRecentFileList (HWND hwnd, LPTSTR szCurrentFile);
  686. *
  687. *
  688. *
  689. * ENTRY - HWND hwnd - handle to dialog box.
  690. * LPTSTR szCurrentFile - pointer to selected filename
  691. *
  692. * EXIT -
  693. * SYNOPSIS -
  694. *
  695. * WARNINGS -
  696. * EFFECTS -
  697. *
  698. */
  699. void APIENTRY SaveRecentFileList (HWND hwnd, LPTSTR szCurrentFile)
  700. {
  701. HKEY hKey;
  702. DWORD dwDisp;
  703. DWORD dwDataType, dwMaxFiles=INIT_MAX_FILES, dwMaxFilesSize, dwCount;
  704. TCHAR szFileEntry[20];
  705. DWORD dwEnd=0;
  706. DWORD dwFileNum=0;
  707. DWORD dwDup;
  708. static TCHAR szRecentFilePath[MAXPATHFIELD+1];
  709. //
  710. // Open registry key
  711. //
  712. if ( RegCreateKeyEx (HKEY_CURRENT_USER, FILES_KEY, 0, 0,
  713. REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE,
  714. NULL, &hKey, &dwDisp) != ERROR_SUCCESS) {
  715. return;
  716. }
  717. //
  718. // Query the max number of files to save first.
  719. //
  720. dwMaxFilesSize = sizeof (DWORD);
  721. RegQueryValueEx (hKey, MAXFILES_ENTRY, NULL, &dwDataType,
  722. (LPBYTE)&dwMaxFiles, &dwMaxFilesSize);
  723. //
  724. // If the user request 0 entries, then exit now.
  725. //
  726. if (dwMaxFiles == 0) {
  727. RegCloseKey (hKey);
  728. return;
  729. }
  730. //
  731. // Find out how many items are in the list box.
  732. //
  733. dwEnd = (DWORD)SendDlgItemMessage (hwnd, IDD_PATH, CB_GETCOUNT, 0, 0);
  734. //
  735. // If the max number of items we want to save is less than the
  736. // number of entries, then change the ending point.
  737. //
  738. if (dwMaxFiles < dwEnd) {
  739. dwEnd = dwMaxFiles;
  740. }
  741. //
  742. // Add the first entry (the current file)
  743. //
  744. wsprintf (szFileEntry, FILE_ENTRY, dwFileNum++);
  745. dwMaxFilesSize = MAXPATHFIELD+1;
  746. RegSetValueEx (hKey, szFileEntry, 0, REG_SZ, (CONST BYTE *)szCurrentFile,
  747. sizeof (TCHAR) * (lstrlen (szCurrentFile)+1));
  748. //
  749. // Check for a duplicate string.
  750. //
  751. dwDup = (DWORD)SendDlgItemMessage (hwnd, IDD_PATH, CB_FINDSTRING,
  752. (WPARAM) -1, (LPARAM) szCurrentFile);
  753. //
  754. // If we already have dwMaxFiles in the list and we don't have any
  755. // duplicates, then we only want to save dwMaxFiles - 1 entries
  756. // (drop the last entry).
  757. //
  758. //
  759. if ( (dwEnd == dwMaxFiles) && (dwDup == CB_ERR) ) {
  760. dwEnd--;
  761. }
  762. //
  763. // Now loop through the remaining entries
  764. //
  765. for (dwCount=0; dwCount < dwEnd; dwCount++) {
  766. //
  767. // Check to see if we are at the duplicate entry. If
  768. // so skip on to the next item.
  769. //
  770. if ((dwDup != CB_ERR) && (dwCount == dwDup)) {
  771. continue;
  772. }
  773. //
  774. // Get an entry out of the listbox.
  775. //
  776. SendDlgItemMessage (hwnd, IDD_PATH, CB_GETLBTEXT, (WPARAM) dwCount,
  777. (LPARAM) szRecentFilePath);
  778. //
  779. // If we get a NULL string, break out of the loop.
  780. //
  781. if (!(*szRecentFilePath) || !szRecentFilePath) {
  782. break;
  783. }
  784. //
  785. // Build the entry name
  786. //
  787. wsprintf (szFileEntry, FILE_ENTRY, dwFileNum);
  788. dwMaxFilesSize = MAXPATHFIELD+1;
  789. //
  790. // Save the entry
  791. //
  792. RegSetValueEx (hKey, szFileEntry, 0, REG_SZ,(CONST BYTE *) szRecentFilePath,
  793. sizeof (TCHAR) * (lstrlen (szRecentFilePath)+1));
  794. //
  795. // Increment our current file number
  796. //
  797. dwFileNum++;
  798. }
  799. //
  800. // Close the key
  801. //
  802. RegCloseKey (hKey);
  803. }
  804. /*** Main -- Program entry point (was WinMain).
  805. *
  806. *
  807. *
  808. * Main(int argc, char *argv[], char *envp[])
  809. *
  810. * ENTRY - int argc - argument count.
  811. * char *argv[] - argument list.
  812. * char *envp[] - environment.
  813. *
  814. * EXIT - TRUE if success, FALSE if not.
  815. * SYNOPSIS - Parses command line, for position to place dialog box, if no
  816. * position (came from ctl/esc) then center on screen.
  817. * Also make sure only one instance of taskman.
  818. *
  819. * WARNINGS -
  820. * EFFECTS -
  821. */
  822. INT __cdecl main(
  823. INT argc,
  824. CHAR *argv[],
  825. CHAR *envp[])
  826. {
  827. MSG msg;
  828. /*
  829. * First set the priority of taskman so it is higher than foreground apps
  830. * that spin in loops - this way it'll always come up when you hit
  831. * ctrl-esc.
  832. */
  833. hInst = GetModuleHandle(NULL);
  834. SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
  835. {
  836. //
  837. // Set the working set size to 200k.
  838. //
  839. QUOTA_LIMITS QuotaLimits;
  840. NTSTATUS status;
  841. status = NtQueryInformationProcess( NtCurrentProcess(),
  842. ProcessQuotaLimits,
  843. &QuotaLimits,
  844. sizeof(QUOTA_LIMITS),
  845. NULL );
  846. if (NT_SUCCESS(status)) {
  847. QuotaLimits.MinimumWorkingSetSize = 300 * 1024;
  848. QuotaLimits.MaximumWorkingSetSize = 372 * 1024;
  849. NtSetInformationProcess( NtCurrentProcess(),
  850. ProcessQuotaLimits,
  851. &QuotaLimits,
  852. sizeof(QUOTA_LIMITS) );
  853. }
  854. }
  855. /*
  856. * Taskman will work in the windows directory, and switch to the
  857. * original directory (home directory) before execing programs.
  858. * This is to prevent weird popups if a UNC original directory is
  859. * disconnected.
  860. */
  861. GetCurrentDirectory(MAXPATHFIELD, szUserHomeDir);
  862. GetWindowsDirectory(szWindowsDirectory, MAXPATHFIELD);
  863. SetCurrentDirectory(szWindowsDirectory);
  864. fExecOK = OKToExec();
  865. if (!IsUserAdmin() && !fExecOK) {
  866. ghwndDialog = CreateDialog(hInst, MAKEINTRESOURCE(WMPTASKMANDLG), NULL,
  867. TaskmanDlgProc);
  868. } else {
  869. ghwndDialog = CreateDialog(hInst, MAKEINTRESOURCE(PWRTASKMANDLG), NULL,
  870. TaskmanDlgProc);
  871. }
  872. if (ghwndDialog == NULL)
  873. return 0;
  874. LoadString(hInst, IDS_OOMEXITTITLE, szOOMExitTitle, 32);
  875. LoadString(hInst, IDS_OOMEXITMSG, szOOMExitMsg, 64);
  876. if (!RegisterHotKey(ghwndDialog, 1, MOD_CONTROL, VK_ESCAPE) ||
  877. !RegisterTasklist(ghwndDialog)) {
  878. goto exit;
  879. }
  880. while (GetMessage(&msg, (HWND)NULL, (UINT)0, (UINT)0)) {
  881. if (!IsDialogMessage(ghwndDialog, &msg)) {
  882. if ((msg.message == WM_SYSCOMMAND) && (msg.wParam == SC_TASKLIST)) {
  883. POINT pt;
  884. GetCursorPos(&pt);
  885. pt.x = max(pt.x - (dyTaskman / 2), 0);
  886. pt.x = min(pt.x, dxScreen - dxTaskman);
  887. pt.y = max(pt.y - (GetSystemMetrics(SM_CYCAPTION) * 2), 0);
  888. pt.y = min(pt.y, dyScreen - dyTaskman);
  889. ShowTasklist(pt);
  890. } else {
  891. //
  892. // We need to have a regular message loop in order
  893. // to handle the DDE messages generated by spawning
  894. // an application via an association.
  895. //
  896. TranslateMessage (&msg);
  897. DispatchMessage (&msg);
  898. }
  899. }
  900. }
  901. exit:
  902. DestroyWindow(ghwndDialog);
  903. return 0;
  904. argc;
  905. argv;
  906. envp;
  907. }
  908. WORD APIENTRY
  909. ExecProgram(
  910. LPTSTR lpszPath,
  911. LPTSTR lpDir,
  912. LPTSTR lpTitle
  913. )
  914. {
  915. WORD ret;
  916. HCURSOR hCursor;
  917. LPTSTR lpP;
  918. TCHAR cSeparator;
  919. TCHAR lpReservedFormat[] = TEXT("dde.%d,hotkey.%d");
  920. TCHAR lpReserved[100]; // used for DDE request of icons from console apps
  921. // add for passing the hotkey associated with an item.
  922. HANDLE hProcess;
  923. ret = 0;
  924. /*
  925. * Set the current directory to the user's home directory if possible.
  926. */
  927. SetCurrentDirectory(szUserHomeDir);
  928. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  929. /* Don't mess with the mouse state; unless we're on a mouseless system.
  930. */
  931. if (!GetSystemMetrics(SM_MOUSEPRESENT))
  932. ShowCursor(TRUE);
  933. /* skip leading spaces
  934. */
  935. while (*lpszPath == TEXT(' '))
  936. lpszPath++;
  937. /* skip past path
  938. */
  939. lpP = lpszPath;
  940. if (*lpszPath == TEXT('"')) {
  941. cSeparator = TEXT('"');
  942. lpP++;
  943. }
  944. else {
  945. cSeparator = TEXT(' ');
  946. }
  947. for (; *lpP && *lpP != cSeparator; lpP = CharNext(lpP))
  948. ;
  949. if (*lpP == TEXT('"')) {
  950. lpP++;
  951. }
  952. /* if stuff on end, separate it
  953. */
  954. if (*lpP)
  955. *lpP++ = 0;
  956. /* Try to exec 'szCommandLine'. */
  957. /*changed order, since wPendINstance is a 32b HANDLE, and ret is WORD*/
  958. if (!lpP)
  959. lpP = TEXT("");
  960. wsprintf(lpReserved, lpReservedFormat, 0, 0);
  961. ret = (WORD)RealShellExecute(ghwndDialog, NULL, lpszPath, lpP,
  962. lpDir, NULL, lpTitle, lpReserved,
  963. (WORD)SW_SHOWNORMAL, &hProcess);
  964. /*BUG BUG these are DOS exec function return codes, no map yet to NT return codes!*/
  965. switch (ret) {
  966. case 0:
  967. case SE_ERR_OOM: // 8
  968. ret = IDS_NOMEMORYMSG;
  969. break;
  970. case SE_ERR_FNF: // 2
  971. ret = IDS_FILENOTFOUNDMSG;
  972. break;
  973. case SE_ERR_PNF: // 3
  974. ret = IDS_BADPATHMSG;
  975. break;
  976. case 4:
  977. ret = IDS_MANYOPENFILESMSG;
  978. break;
  979. case 5:
  980. ret = IDS_ACCESSDENIED;
  981. break;
  982. case 10:
  983. ret = IDS_NEWWINDOWSMSG;
  984. break;
  985. case 12:
  986. ret = IDS_OS2APPMSG;
  987. break;
  988. case 15:
  989. /* KERNEL has already put up a messagebox for this one. */
  990. ret = 0;
  991. break;
  992. case 16:
  993. ret = IDS_MULTIPLEDSMSG;
  994. break;
  995. case 18:
  996. ret = IDS_PMODEONLYMSG;
  997. break;
  998. case 19:
  999. ret = IDS_COMPRESSEDEXE;
  1000. break;
  1001. case 20:
  1002. ret = IDS_INVALIDDLL;
  1003. break;
  1004. case SE_ERR_SHARE:
  1005. ret = IDS_SHAREERROR;
  1006. break;
  1007. case SE_ERR_ASSOCINCOMPLETE:
  1008. ret = IDS_ASSOCINCOMPLETE;
  1009. break;
  1010. case SE_ERR_DDETIMEOUT:
  1011. case SE_ERR_DDEFAIL:
  1012. case SE_ERR_DDEBUSY:
  1013. ret = IDS_DDEFAIL;
  1014. break;
  1015. case SE_ERR_NOASSOC:
  1016. ret = IDS_NOASSOCMSG;
  1017. break;
  1018. default:
  1019. ret = 0;
  1020. break;
  1021. }
  1022. if (!GetSystemMetrics(SM_MOUSEPRESENT)) {
  1023. /*
  1024. * We want to turn the mouse off here on mouseless systems, but
  1025. * the mouse will already have been turned off by USER if the
  1026. * app has GP'd so make sure everything's kosher.
  1027. */
  1028. if (ShowCursor(FALSE) != -1)
  1029. ShowCursor(TRUE);
  1030. }
  1031. SetCursor(hCursor);
  1032. /*
  1033. * Reset the working directory to the windows directory.
  1034. */
  1035. SetCurrentDirectory(szWindowsDirectory);
  1036. return(ret);
  1037. }
  1038. VOID
  1039. GetDirectoryFromPath(
  1040. PTSTR szFilePath,
  1041. PTSTR szDir)
  1042. {
  1043. PTSTR pFileName;
  1044. PTSTR pExt;
  1045. WORD ich;
  1046. BOOL fUnc;
  1047. *szDir = TEXT('\0');
  1048. /* Get info about file path. */
  1049. GetPathInfo(szFilePath, &pFileName, &pExt, &ich, &fUnc);
  1050. /* UNC paths don't (conceptually to Progman) have a directory component. */
  1051. if (fUnc)
  1052. return;
  1053. /* Does it have a directory component ? */
  1054. if (pFileName != szFilePath) { // Yep.
  1055. /* copy path to temp. */
  1056. if (*szFilePath == TEXT('"')) {
  1057. szFilePath++;
  1058. }
  1059. lstrcpy(szDir, szFilePath);
  1060. /* check path style. */
  1061. if (ich <= 3 && *(szDir+1) == TEXT(':')) {
  1062. /*
  1063. * The path is "c:\foo.c" or "c:foo.c" style.
  1064. * Don't remove the last slash/colon, just the filename.
  1065. */
  1066. szDir[pFileName-szFilePath] = TEXT('\0');
  1067. }
  1068. else if (ich == 1) {
  1069. /*
  1070. * something like "\foo.c"
  1071. * Don't remove the last slash/colon, just the filename.
  1072. */
  1073. szDir[pFileName-szFilePath] = TEXT('\0');
  1074. }
  1075. else {
  1076. /*
  1077. * The filepath is a full normal path.
  1078. * Could be something like "..\foo.c" or ".\foo.c" though.
  1079. * Stomp on the last slash to get just the path.
  1080. */
  1081. szDir[pFileName-szFilePath-1] = TEXT('\0');
  1082. }
  1083. }
  1084. /* else just a filename with no path. */
  1085. }
  1086. VOID
  1087. GetFilenameFromPath(
  1088. PTSTR szPath,
  1089. PTSTR szFilename)
  1090. {
  1091. DWORD dummy;
  1092. PTSTR pFileName;
  1093. BOOL fUNC;
  1094. GetPathInfo(szPath, &pFileName, (PTSTR*) &dummy, (WORD*) &dummy,
  1095. &fUNC);
  1096. /* If it's a UNC then the 'filename' part is the whole thing. */
  1097. if (fUNC || (szPath == pFileName))
  1098. lstrcpy(szFilename, szPath);
  1099. else {
  1100. if (*szPath == TEXT('"')) {
  1101. *szFilename++ = TEXT('"');
  1102. }
  1103. lstrcpy(szFilename, pFileName);
  1104. }
  1105. }
  1106. VOID
  1107. GetPathInfo(
  1108. PTSTR szPath,
  1109. PTSTR *pszFileName,
  1110. PTSTR *pszExt,
  1111. WORD *pich,
  1112. BOOL *pfUnc)
  1113. {
  1114. TCHAR *pch; // Temp variable.
  1115. WORD ich = 0; // Temp.
  1116. BOOL InQuotes;
  1117. *pszExt = NULL; // If no extension, return NULL.
  1118. *pszFileName = szPath; // If no seperate filename component, return path.
  1119. *pich = 0;
  1120. *pfUnc = FALSE; // Default to not UNC style.
  1121. //
  1122. // Check if path is in quotes.
  1123. //
  1124. if (InQuotes = (*szPath == TEXT('"'))) {
  1125. szPath++;
  1126. }
  1127. // Check for UNC style paths.
  1128. if (*szPath == TEXT('\\') && *(szPath+1) == TEXT('\\'))
  1129. *pfUnc = TRUE;
  1130. // Search forward to find the last backslash or colon in the path.
  1131. // While we're at it, look for the last dot.
  1132. for (pch = szPath; *pch; pch = CharNext(pch)) {
  1133. if ((*pch == TEXT(' ')) && (!InQuotes)) {
  1134. // Found a space - stop here.
  1135. break;
  1136. }
  1137. if (*pch == TEXT('"')) {
  1138. // Found a the second quote - stop here.
  1139. pch++;
  1140. break;
  1141. }
  1142. if (*pch == TEXT('\\') || *pch == TEXT(':')) {
  1143. // Found it, record ptr to it and it's index.
  1144. *pszFileName = pch+1;
  1145. *pich = ich + (WORD)1;
  1146. }
  1147. if (*pch == TEXT('.')) {
  1148. // Found a dot.
  1149. *pszExt = pch;
  1150. }
  1151. ich++;
  1152. }
  1153. /* Check that the last dot is part of the last filename. */
  1154. if (*pszExt < *pszFileName)
  1155. *pszExt = NULL;
  1156. }
  1157. BOOL
  1158. IsUserAdmin()
  1159. {
  1160. BOOL UserIsAdmin = FALSE;
  1161. HANDLE Token;
  1162. PSID AdminAliasSid = NULL;
  1163. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  1164. //
  1165. // Get the token of the current process.
  1166. //
  1167. if (!OpenProcessToken(
  1168. GetCurrentProcess(),
  1169. TOKEN_QUERY,
  1170. &Token) ) {
  1171. return(FALSE);
  1172. }
  1173. UserIsAdmin = TestTokenForAdmin(Token);
  1174. CloseHandle(Token);
  1175. return(UserIsAdmin);
  1176. }
  1177. BOOL
  1178. TestTokenForAdmin(
  1179. HANDLE Token
  1180. )
  1181. {
  1182. NTSTATUS Status;
  1183. DWORD InfoLength;
  1184. PTOKEN_GROUPS TokenGroupList;
  1185. DWORD GroupIndex;
  1186. PSID AdminSid;
  1187. BOOL FoundAdmin;
  1188. SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
  1189. //
  1190. // Get a list of groups in the token
  1191. //
  1192. Status = NtQueryInformationToken(
  1193. Token, // Handle
  1194. TokenGroups, // TokenInformationClass
  1195. NULL, // TokenInformation
  1196. 0, // TokenInformationLength
  1197. &InfoLength // ReturnLength
  1198. );
  1199. if ((Status != STATUS_SUCCESS) && (Status != STATUS_BUFFER_TOO_SMALL)) {
  1200. return(FALSE);
  1201. }
  1202. TokenGroupList = Alloc(InfoLength);
  1203. if (TokenGroupList == NULL) {
  1204. return(FALSE);
  1205. }
  1206. Status = NtQueryInformationToken(
  1207. Token, // Handle
  1208. TokenGroups, // TokenInformationClass
  1209. TokenGroupList, // TokenInformation
  1210. InfoLength, // TokenInformationLength
  1211. &InfoLength // ReturnLength
  1212. );
  1213. if (!NT_SUCCESS(Status)) {
  1214. LocalFree(TokenGroupList);
  1215. return(FALSE);
  1216. }
  1217. //
  1218. // Create the admin sid
  1219. //
  1220. Status = RtlAllocateAndInitializeSid(
  1221. &SystemSidAuthority, 2,
  1222. SECURITY_BUILTIN_DOMAIN_RID,
  1223. DOMAIN_ALIAS_RID_ADMINS,
  1224. 0, 0, 0, 0, 0, 0,
  1225. &AdminSid);
  1226. if (!NT_SUCCESS(Status)) {
  1227. Free(TokenGroupList);
  1228. return(FALSE);
  1229. }
  1230. //
  1231. // Search group list for admin alias
  1232. //
  1233. FoundAdmin = FALSE;
  1234. for (GroupIndex=0; GroupIndex < TokenGroupList->GroupCount; GroupIndex++ ) {
  1235. if (RtlEqualSid(TokenGroupList->Groups[GroupIndex].Sid, AdminSid)) {
  1236. FoundAdmin = TRUE;
  1237. break;
  1238. }
  1239. }
  1240. //
  1241. // Tidy up
  1242. //
  1243. RtlFreeSid(AdminSid);
  1244. Free(TokenGroupList);
  1245. return(FoundAdmin);
  1246. }
  1247. BOOL
  1248. OKToExec()
  1249. {
  1250. TCHAR szRestrict[] = TEXT("Restrictions");
  1251. TCHAR szProgramManager[] = TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Program Manager");
  1252. HKEY hkeyProgramManager = NULL; // progman.ini key
  1253. HKEY hkeyPMRestrict = NULL;
  1254. DWORD cbData, dwType;
  1255. BOOL fNoRun = FALSE;
  1256. /*
  1257. * Create/Open the registry keys corresponding to progman.ini sections.
  1258. */
  1259. if (!RegCreateKeyEx(HKEY_CURRENT_USER, szProgramManager, 0, szProgramManager, 0,
  1260. KEY_READ | KEY_WRITE, NULL, &hkeyProgramManager, NULL)) {
  1261. RegCreateKeyEx(hkeyProgramManager, szRestrict, 0, szProgramManager, 0,
  1262. KEY_READ, NULL, &hkeyPMRestrict, NULL);
  1263. } else {
  1264. return(FALSE);
  1265. }
  1266. if (hkeyPMRestrict) {
  1267. cbData = sizeof(fNoRun);
  1268. RegQueryValueEx(hkeyPMRestrict, szNoRun, 0, &dwType, (LPBYTE)&fNoRun,
  1269. &cbData);
  1270. }
  1271. if (hkeyPMRestrict) {
  1272. RegCloseKey(hkeyPMRestrict);
  1273. hkeyPMRestrict = NULL;
  1274. }
  1275. RegCloseKey(hkeyProgramManager);
  1276. return(!fNoRun);
  1277. }
  1278. INT
  1279. MyMessageBox(
  1280. HWND hWnd,
  1281. WORD idTitle,
  1282. WORD idMessage,
  1283. PWSTR psz,
  1284. WORD wStyle)
  1285. {
  1286. WCHAR szTempField[MAXMSGBOXLEN];
  1287. INT iMsgResult;
  1288. if (!LoadString(hInst, idTitle, szTitle, ARRAYSIZE(szTitle))){
  1289. goto MessageBoxOOM;
  1290. }
  1291. if (idMessage < 32){
  1292. if (!LoadString(hInst, IDS_UNKNOWNMSG, szTempField, ARRAYSIZE(szTempField))){
  1293. goto MessageBoxOOM;
  1294. }
  1295. wsprintf(szMessage, szTempField, idMessage);
  1296. }
  1297. else{
  1298. if (!LoadString(hInst, idMessage, szTempField, ARRAYSIZE(szTempField)))
  1299. goto MessageBoxOOM;
  1300. if (psz) {
  1301. wsprintf(szMessage, szTempField, (LPTSTR)psz);
  1302. }
  1303. else
  1304. lstrcpy(szMessage, szTempField);
  1305. }
  1306. iMsgResult = MessageBox(hWnd, szMessage, szTitle, wStyle );
  1307. if (iMsgResult == -1){
  1308. MessageBoxOOM:
  1309. MessageBox(hWnd, szOOMExitMsg, szOOMExitTitle, MB_SYSTEMMODAL | MB_ICONHAND | MB_OK);
  1310. }
  1311. return(iMsgResult);
  1312. }