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.

879 lines
23 KiB

  1. /*
  2. * pmcomman.c - program manager
  3. *
  4. * Copyright (c) 1991, Microsoft Corporation
  5. *
  6. * DESCRIPTION
  7. *
  8. * This file is for support of program manager under NT Windows.
  9. * This file is/was ported from pmcomman.c (program manager).
  10. *
  11. * MODIFICATION HISTORY
  12. * Initial Version: x/x/90 Author Unknown, since he didn't feel
  13. * like commenting the code...
  14. *
  15. * NT 32b Version: 1/22/91 Jeff Pack Intitial port to begin.
  16. * 6/15/91 JohanneC re-ported.
  17. *
  18. */
  19. #include "progman.h"
  20. /*** IsRemoteDrive -- tests to see if drive is a remote drive
  21. *
  22. *
  23. * BOOL APIENTRY IsRemoteDrive(wDrive)
  24. *
  25. * ENTRY - int wDrive - drive number to test
  26. *
  27. * EXIT - BOOL xxx - returns TRUE if remote, false if not.
  28. *
  29. * SYNOPSIS - calls GetDriveType to determine if media is remote or not.
  30. *
  31. * WARNINGS -
  32. * EFFECTS -
  33. *
  34. */
  35. BOOL APIENTRY IsRemoteDrive(int wDrive)
  36. {
  37. TCHAR pszdrive[5] = TEXT("c:\\"); /*default string value*/
  38. pszdrive[0] = (TCHAR)wDrive + (TCHAR)TEXT('A'); /*convert wDrive (0-25) to drive letter*/
  39. /*and place in string to pass to GetDriveType*/
  40. return((BOOL) (GetDriveType(pszdrive) == DRIVE_REMOTE));
  41. }
  42. /*** IsRemovableDrive -- tests to see if drive is removable
  43. *
  44. *
  45. * BOOL APIENTRY IsRemovableDrive( int wDrive)
  46. *
  47. * ENTRY - int wDrive - drive number to test
  48. *
  49. * EXIT - BOOL xxx - returns TRUE if removable, false if not.
  50. *
  51. * SYNOPSIS - calls GetDriveType to determine if media is removable or not.
  52. *
  53. * WARNINGS -
  54. * EFFECTS -
  55. *
  56. */
  57. BOOL APIENTRY IsRemovableDrive( int wDrive)
  58. {
  59. TCHAR pszdrive[5] = TEXT("c:\\"); /*default string value*/
  60. pszdrive[0] = (TCHAR)wDrive + (TCHAR)TEXT('A'); /*convert wDrive (0-25) to drive letter*/
  61. /*and place in string to pass to GetDriveType*/
  62. return((BOOL)(GetDriveType(pszdrive) == DRIVE_REMOVABLE));
  63. }
  64. /*** BuildDescription --
  65. *
  66. *
  67. * VOID APIENTRY BuildDescription(LPTSTR szName, LPTSTR szPath)
  68. *
  69. * ENTRY - LPTSTR szName
  70. * LPTSTR szPath
  71. *
  72. * EXIT - VOID xxx -
  73. *
  74. * SYNOPSIS -
  75. *
  76. * WARNINGS - sordid coding style BUG BUG assumes 8.3 filename convention
  77. * EFFECTS -
  78. *
  79. */
  80. VOID APIENTRY BuildDescription(LPTSTR szName, LPTSTR szPath)
  81. {
  82. TCHAR ch;
  83. TCHAR ch2 = 0;
  84. LPTSTR p;
  85. LPTSTR p2;
  86. LPTSTR p3 = NULL;
  87. //When User creating new icon with command line added quote (such as "a b.exe")
  88. // and no description, then invalid description ("a b) added new icon.
  89. BOOL bQuote = FALSE;
  90. if (*szPath == TEXT('"') && *(szPath+lstrlen(szPath)-1) == TEXT('"')) {
  91. bQuote = TRUE;
  92. *(szPath+lstrlen(szPath)-1) = TEXT('\0');
  93. szPath++;
  94. }
  95. p = p2 = szPath;
  96. /* Scan the string looking for the last filename. */
  97. while (*p) {
  98. if (*p == TEXT('\\'))
  99. p2 = p+1;
  100. else if (*p == TEXT('.'))
  101. p3 = p;
  102. p = CharNext(p);
  103. }
  104. if (!p3)
  105. p3 = p;
  106. ch = *p3;
  107. *p3 = TEXT('\0');
  108. if (lstrlen(p2) > MAXITEMNAMELEN) {
  109. ch2 = *(p2 + MAXITEMNAMELEN);
  110. *(p2 + MAXITEMNAMELEN) = TEXT('\0');
  111. }
  112. lstrcpy(szName, p2);
  113. *p3 = ch;
  114. if (ch2) {
  115. *(p2 + MAXITEMNAMELEN) = ch2;
  116. }
  117. if( bQuote )
  118. *(szPath+lstrlen(szPath)) = TEXT('"');
  119. CharUpper(szName);
  120. CharLower(CharNext(szName));
  121. }
  122. /* Returns 0 for success. Otherwise returns a IDS_ string code. */
  123. /*** ExecProgram -- exec program function
  124. *
  125. *
  126. * WORD APIENTRY ExecProgram(LPTSTR lpszPath, LPTSTR lpDir, LPTSTR lpTitle, BOOL bLoadIt)
  127. *
  128. * ENTRY - LPTSTR lpszPath -
  129. * LPTSTR lpDir -
  130. * BOOL bLoadIt -
  131. *
  132. * EXIT - BOOL xxx - returns (0)FALSE if successful, else returns
  133. * IDS_ string code.
  134. *
  135. * SYNOPSIS -
  136. *
  137. * WARNINGS -
  138. * EFFECTS -
  139. *
  140. */
  141. WORD APIENTRY ExecProgram (
  142. LPTSTR lpszPath,
  143. LPTSTR lpDir,
  144. LPTSTR lpTitle,
  145. BOOL bLoadIt,
  146. DWORD dwDDEId,
  147. WORD wHotKeyId,
  148. BOOL bNewVDM
  149. )
  150. {
  151. WORD ret;
  152. WORD wNTVDMFlags=0;
  153. HCURSOR hCursor;
  154. LPTSTR lpP;
  155. TCHAR cSeparator;
  156. TCHAR lpReservedFormat[] = TEXT("dde.%d,hotkey.%d,ntvdm.%d");
  157. TCHAR lpReserved[100]; // used for DDE request of icons from console apps
  158. // add for passing the hotkey associated with an item.
  159. DWORD OldErrorMode;
  160. ret = 0;
  161. //hPendingWindow = NULL;
  162. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  163. /* Don't mess with the mouse state; unless we're on a mouseless system.
  164. */
  165. if (!GetSystemMetrics(SM_MOUSEPRESENT))
  166. ShowCursor(TRUE);
  167. /* skip leading spaces
  168. */
  169. while (*lpszPath == TEXT(' '))
  170. lpszPath++;
  171. /* skip past path
  172. */
  173. lpP = lpszPath;
  174. if (*lpszPath == TEXT('"')) {
  175. cSeparator = TEXT('"');
  176. lpP++;
  177. }
  178. else {
  179. cSeparator = TEXT(' ');
  180. }
  181. for (; *lpP && *lpP != cSeparator; lpP = CharNext(lpP))
  182. ;
  183. if (*lpP == TEXT('"')) {
  184. lpP++;
  185. }
  186. /* if stuff on end, separate it
  187. */
  188. if (*lpP)
  189. *lpP++ = 0;
  190. /* Try to exec 'szCommandLine'. */
  191. fInExec = TRUE;
  192. /*changed order, since wPendINstance is a 32b HANDLE, and ret is WORD*/
  193. if (!lpP)
  194. lpP = TEXT("");
  195. // Setup this flags variable so NTVDM can overwrite pif information
  196. // if user has specified info in the icon properties.
  197. if (lpDir && *lpDir)
  198. wNTVDMFlags |= PROPERTY_HAS_CURDIR;
  199. if (wHotKeyId)
  200. wNTVDMFlags |= PROPERTY_HAS_HOTKEY;
  201. if (lpTitle && *lpTitle)
  202. wNTVDMFlags |= PROPERTY_HAS_TITLE;
  203. wsprintf(lpReserved, lpReservedFormat, dwDDEId, wHotKeyId, wNTVDMFlags);
  204. OldErrorMode = SetErrorMode(0);
  205. ret = (WORD)RealShellExecuteEx(hwndProgman, NULL, lpszPath, lpP,
  206. lpDir, NULL, lpTitle, lpReserved,
  207. (WORD)(bLoadIt ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL), NULL,
  208. bNewVDM ? EXEC_SEPARATE_VDM : 0);
  209. SetErrorMode(OldErrorMode);
  210. fInExec = FALSE;
  211. // Unfortunately we are still using the 0 - 31 error code
  212. // combinations instead of the NT error codes. SE_ERR_OOM
  213. // is the default case for all errors in RealShellExecuteExW,
  214. // thus displaying an out of memory error is probably bogus.
  215. // We can call GetLastError ourselves to get the _real_ error.
  216. //
  217. // Special cases:
  218. //
  219. // 1) If you have a really deep directory structure(70 chars), and you
  220. // try to spawn a WOW app from it CreateProcess will fail with
  221. // and error of ERROR_INVALID_PARAMETER. We'll grab this case,
  222. // and map it into the bad path message since it is the closest.
  223. if (ret == SE_ERR_OOM)
  224. {
  225. DWORD dwResult = GetLastError();
  226. if (dwResult == ERROR_INVALID_PARAMETER)
  227. ret = SE_ERR_PNF;
  228. }
  229. /*BUG BUG these are DOS exec function return codes, no map yet to NT return codes!*/
  230. switch (ret) {
  231. case 0:
  232. case SE_ERR_OOM: // 8
  233. ret = IDS_NOMEMORYMSG;
  234. break;
  235. case SE_ERR_FNF: // 2
  236. ret = IDS_FILENOTFOUNDMSG;
  237. break;
  238. case SE_ERR_PNF: // 3
  239. ret = IDS_BADPATHMSG;
  240. break;
  241. case 4:
  242. ret = IDS_MANYOPENFILESMSG;
  243. break;
  244. case 5:
  245. ret = IDS_ACCESSDENIED;
  246. break;
  247. case 10:
  248. ret = IDS_NEWWINDOWSMSG;
  249. break;
  250. case 12:
  251. ret = IDS_OS2APPMSG;
  252. break;
  253. case 15:
  254. /* KERNEL has already put up a messagebox for this one. */
  255. ret = 0;
  256. break;
  257. case 16:
  258. ret = IDS_MULTIPLEDSMSG;
  259. break;
  260. case 18:
  261. ret = IDS_PMODEONLYMSG;
  262. break;
  263. case 19:
  264. ret = IDS_COMPRESSEDEXE;
  265. break;
  266. case 20:
  267. ret = IDS_INVALIDDLL;
  268. break;
  269. case ERROR_NOT_ENOUGH_QUOTA:
  270. case STATUS_PAGEFILE_QUOTA:
  271. ret = IDS_INSUFFICIENTQUOTA;
  272. break;
  273. case SE_ERR_SHARE:
  274. ret = IDS_SHAREERROR;
  275. break;
  276. case SE_ERR_ASSOCINCOMPLETE:
  277. ret = IDS_ASSOCINCOMPLETE;
  278. break;
  279. case SE_ERR_DDETIMEOUT:
  280. case SE_ERR_DDEFAIL:
  281. case SE_ERR_DDEBUSY:
  282. ret = IDS_DDEFAIL;
  283. break;
  284. case SE_ERR_NOASSOC:
  285. ret = IDS_NOASSOCMSG;
  286. break;
  287. default:
  288. if (ret < 32)
  289. goto EPExit;
  290. if (bMinOnRun && !bLoadIt)
  291. ShowWindow(hwndProgman, SW_SHOWMINNOACTIVE);
  292. ret = 0;
  293. }
  294. EPExit:
  295. if (!GetSystemMetrics(SM_MOUSEPRESENT)) {
  296. /*
  297. * We want to turn the mouse off here on mouseless systems, but
  298. * the mouse will already have been turned off by USER if the
  299. * app has GP'd so make sure everything's kosher.
  300. */
  301. if (ShowCursor(FALSE) != -1)
  302. ShowCursor(TRUE);
  303. }
  304. SetCursor(hCursor);
  305. return(ret);
  306. }
  307. /*** SelectionType --
  308. *
  309. *
  310. * WORD APIENTRY SelectionType(VOID)
  311. *
  312. * ENTRY - VOID
  313. *
  314. * EXIT - WORD xxx -
  315. *
  316. *
  317. * SYNOPSIS -
  318. *
  319. * WARNINGS -
  320. * EFFECTS -
  321. *
  322. */
  323. WORD APIENTRY SelectionType(VOID)
  324. {
  325. /* If no groups, return GROUP type (so user can create one). */
  326. if (!pCurrentGroup)
  327. return(TYPE_PERSGROUP);
  328. if (IsIconic(pCurrentGroup->hwnd))
  329. if (pCurrentGroup->fCommon)
  330. return(TYPE_COMMONGROUP);
  331. else
  332. return(TYPE_PERSGROUP);
  333. return(TYPE_ITEM);
  334. }
  335. /*** ExecItem --
  336. *
  337. *
  338. * VOID APIENTRY ExecItem(PGROUP pGroup, PITEM pItem, BOOL fShift, BOOL fStartup)
  339. *
  340. * ENTRY - PGROUP pGroup -
  341. * PITEM pItem -
  342. *
  343. * EXIT - VOID
  344. *
  345. *
  346. * SYNOPSIS -
  347. *
  348. * WARNINGS -
  349. * EFFECTS -
  350. *
  351. */
  352. VOID APIENTRY ExecItem(PGROUP pGroup, PITEM pItem, BOOL fShift, BOOL fStartup)
  353. {
  354. WORD ret;
  355. TCHAR szCommand[MAXITEMPATHLEN + 1];
  356. TCHAR szDir[2*(MAXITEMPATHLEN + 1)];
  357. TCHAR szTemp[MAXMESSAGELEN+1];
  358. TCHAR *szTitle;
  359. GROUPDEF *lpgd;
  360. //
  361. // Exec the item in the user's home directory.
  362. //
  363. SetCurrentDirectory(szOriginalDirectory);
  364. GetItemCommand(pGroup,pItem,szCommand,szDir);
  365. if (fShift) {
  366. fShift = GetKeyState(VK_SHIFT) < (SHORT)0;
  367. }
  368. ret = (WORD)((WORD)fShift || GroupFlag(pGroup, pItem, (WORD)ID_MINIMIZE));
  369. wPendingHotKey = GroupFlag(pGroup, pItem, (WORD)ID_HOTKEY);
  370. pExecingGroup = pGroup;
  371. pExecingItem = pItem;
  372. DoEnvironmentSubst(szCommand, MAXITEMPATHLEN + 1);
  373. DoEnvironmentSubst(szDir, 2 * (MAXITEMPATHLEN + 1));
  374. // REVIEW Check the working directory first because the user may
  375. // still want to try to run the app even with an invalid working
  376. // dir.
  377. // Check working directory.
  378. GetCurrentDirectory(MAXMESSAGELEN+1, szTemp);
  379. SheRemoveQuotes(szDir);
  380. // Allow dir field to be NULL without error.
  381. if (szDir && *szDir) {
  382. // NB The VPD call is because SCD sometimes returns success even
  383. // if the drive is invalid. SCD returns FALSE on success.
  384. if ((!ValidPathDrive(szDir) ||
  385. !SetCurrentDirectory(szDir)) &&
  386. !fStartup) {
  387. if (MyMessageBox(hwndProgman, IDS_BADPATHTITLE, IDS_BADPATHMSG3, NULL, MB_OKCANCEL | MB_DEFBUTTON2 | MB_ICONEXCLAMATION) == IDCANCEL)
  388. goto Exit;
  389. }
  390. }
  391. SetCurrentDirectory(szTemp);
  392. //OemToChar(szDir, szDir);
  393. if ((lpgd = LockGroup(pGroup->hwnd)) == NULL)
  394. return;
  395. szTitle = (TCHAR *)PTR(lpgd, ((LPITEMDEF)ITEM(lpgd, pItem->iItem))->pName);
  396. if (!dwDDEAppId || (dwDDEAppId != pItem->dwDDEId)) {
  397. dwDDEAppId++;
  398. }
  399. pItem->dwDDEId = dwDDEAppId;
  400. ret = ExecProgram(szCommand, szDir, szTitle, ret, dwDDEAppId,
  401. GroupFlag(pGroup, pItem, ID_HOTKEY),
  402. GroupFlag(pGroup, pItem, ID_NEWVDM) );
  403. UnlockGroup(pGroup->hwnd);
  404. pExecingGroup = NULL;
  405. pExecingItem = NULL;
  406. // Check for errors.
  407. if (ret) {
  408. if (fStartup) {
  409. /*
  410. * This exec is for an item in the startup group, the error
  411. * message will need to be patched up by adding a comment
  412. * after the path bit.
  413. */
  414. szTemp[0] = TEXT('\'');
  415. lstrcpy(&szTemp[1], szCommand);
  416. LoadString(hAppInstance, IDS_STARTUPERR, szCommand, CharSizeOf(szCommand));
  417. lstrcat(szTemp, szCommand);
  418. lstrcpy(szCommand, szTemp);
  419. }
  420. MyMessageBox(hwndProgman, IDS_EXECERRTITLE, ret, szCommand, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
  421. }
  422. Exit:
  423. SetCurrentDirectory(szWindowsDirectory);
  424. }
  425. VOID RemoveAnsiGroups()
  426. {
  427. HMENU hMenu;
  428. FILETIME ft;
  429. TCHAR szGroupKey[MAXKEYLEN];
  430. DWORD cchGroupKey = CharSizeOf(szGroupKey);
  431. HCURSOR hCursor;
  432. INT i = 0;
  433. if (!MyDialogBox(UPDATEGROUPSDLG, hwndProgman, UpdateGroupsDlgProc)) {
  434. return;
  435. }
  436. if (RegOpenKeyEx(HKEY_CURRENT_USER, szAnsiProgramGroups, 0,
  437. KEY_READ | DELETE, &hkeyAnsiProgramGroups) != ERROR_SUCCESS) {
  438. return;
  439. }
  440. hCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  441. ShowCursor(TRUE);
  442. while (!RegEnumKeyEx(hkeyAnsiProgramGroups, i, szGroupKey, &cchGroupKey, 0, 0, 0, &ft)) {
  443. if (cchGroupKey) {
  444. if (RegDeleteKey(hkeyAnsiProgramGroups, szGroupKey))
  445. i++;
  446. }
  447. cchGroupKey = CharSizeOf(szGroupKey);
  448. }
  449. RegCloseKey(hkeyAnsiProgramGroups);
  450. if (!RegDeleteKey(HKEY_CURRENT_USER, szAnsiProgramGroups)) {
  451. //
  452. // Change Options menu: remove the 'Update Program Groups' menu item
  453. //
  454. if (pCurrentGroup &&
  455. GetWindowLong(pCurrentGroup->hwnd, GWL_STYLE) & WS_MAXIMIZE) {
  456. hMenu = GetSubMenu(GetMenu(hwndProgman), 2);
  457. }
  458. else {
  459. hMenu = GetSubMenu(GetMenu(hwndProgman), 1);
  460. }
  461. DeleteMenu(hMenu, 6, MF_BYPOSITION);
  462. DeleteMenu(hMenu, 5, MF_BYPOSITION);
  463. DrawMenuBar(hwndProgman);
  464. }
  465. RegDeleteKey(hkeyProgramManager, TEXT("Groups"));
  466. RegDeleteValue(hkeyPMSettings, szAnsiOrder);
  467. ShowCursor(FALSE);
  468. SetCursor(hCursor);
  469. }
  470. /*** ProgmanCommandProc --
  471. *
  472. *
  473. * BOOL APIENTRY ProgmanCommandProc(register HWND hwnd, WORD wMsg,
  474. * register WPARAM wParam, LPARAM lParam)
  475. *
  476. * ENTRY - HWND hWnd
  477. * WORD wMsg
  478. * WPARAM wParam
  479. * LPARAM lParam
  480. * EXIT - BOOL xxx - returns info, or zero, for nothing to return
  481. *
  482. * SYNOPSIS - ???
  483. *
  484. * WARNINGS -
  485. * EFFECTS -
  486. *
  487. */
  488. BOOL APIENTRY ProgmanCommandProc(HWND hwnd, WPARAM wParam, LPARAM lParam)
  489. {
  490. BOOL bMaxed;
  491. WORD wHelpCmd;
  492. HMENU hMenu;
  493. LPTSTR psz;
  494. HWND hwndMdiActive;
  495. hwndMdiActive = (HWND)SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L);
  496. if (hwndMdiActive != NULL)
  497. bMaxed = (GetWindowLong(hwndMdiActive, GWL_STYLE) & WS_MAXIMIZE) ? TRUE : FALSE;
  498. else
  499. bMaxed = 0;
  500. dwContext = (DWORD)(IDH_HELPFIRST + wParam);
  501. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  502. case IDM_OPEN:
  503. if (!pCurrentGroup)
  504. break;
  505. if (SelectionType() == TYPE_ITEM)
  506. ExecItem(pCurrentGroup,pCurrentGroup->pItems,TRUE, FALSE);
  507. else
  508. SendMessage(pCurrentGroup->hwnd, WM_SYSCOMMAND, SC_RESTORE, 0L);
  509. break;
  510. case IDM_NEW:
  511. if (fNoFileMenu)
  512. break;
  513. if (dwEditLevel == 1)
  514. goto PCPNewItem;
  515. if (dwEditLevel > 1)
  516. break;
  517. if (MyDialogBox(CHOOSERDLG, hwndProgman, ChooserDlgProc)) {
  518. switch (wNewSelection) {
  519. case TYPE_PERSGROUP:
  520. case TYPE_COMMONGROUP:
  521. MyDialogBox(GROUPDLG, hwndProgman, NewGroupDlgProc);
  522. break;
  523. case TYPE_ITEM:
  524. PCPNewItem:
  525. /*
  526. * We are creating a new program item.
  527. */
  528. MyDialogBox(ITEMDLG, hwndProgman, NewItemDlgProc);
  529. break;
  530. }
  531. }
  532. break;
  533. case IDM_MOVE:
  534. if (fNoFileMenu)
  535. break;
  536. MyDialogBox(MOVECOPYDLG, hwndProgman, MoveItemDlgProc);
  537. break;
  538. case IDM_COPY:
  539. if (fNoFileMenu)
  540. break;
  541. MyDialogBox(MOVECOPYDLG, hwndProgman, CopyItemDlgProc);
  542. break;
  543. case IDM_DELETE:
  544. if (fNoFileMenu)
  545. break;
  546. switch (SelectionType()) {
  547. case TYPE_ITEM:
  548. if (pCurrentGroup->pItems) {
  549. wParam = IDS_CONFIRMDELITEMMSG;
  550. GetItemText(pCurrentGroup, pCurrentGroup->pItems, szNameField, 0);
  551. psz = szNameField;
  552. break;
  553. }
  554. /*** FALL THRU ***/
  555. case TYPE_PERSGROUP:
  556. case TYPE_COMMONGROUP:
  557. wParam = IDS_CONFIRMDELGROUPMSG;
  558. GetWindowText(pCurrentGroup->hwnd, (LPTSTR)szNameField, MAXITEMPATHLEN);
  559. psz = szNameField;
  560. break;
  561. }
  562. if (MyMessageBox(hwndProgman, (WORD)IDS_CONFIRMDELTITLE, (WORD)wParam,
  563. psz, (WORD)(MB_YESNO | MB_ICONEXCLAMATION)) == IDYES) {
  564. if (wParam == (WPARAM)IDS_CONFIRMDELITEMMSG) {
  565. DeleteItem(pCurrentGroup,pCurrentGroup->pItems);
  566. } else {
  567. DeleteGroup(pCurrentGroup->hwnd);
  568. }
  569. }
  570. break;
  571. case IDM_PROPS:
  572. if (fNoFileMenu)
  573. break;
  574. switch (SelectionType()) {
  575. case TYPE_ITEM:
  576. if (pCurrentGroup->pItems) {
  577. MyDialogBox(ITEMDLG, hwndProgman, EditItemDlgProc);
  578. break;
  579. }
  580. /*** FALL THRU ***/
  581. case TYPE_PERSGROUP:
  582. case TYPE_COMMONGROUP:
  583. {
  584. LPGROUPDEF lpgd;
  585. lpgd = LockGroup(pCurrentGroup->hwnd);
  586. if (lpgd == 0L) {
  587. break;
  588. }
  589. lstrcpy(szNameField, (LPTSTR) PTR(lpgd, lpgd->pName));
  590. UnlockGroup(pCurrentGroup->hwnd);
  591. MyDialogBox(GROUPDLG, hwndProgman, EditGroupDlgProc);
  592. break;
  593. }
  594. }
  595. break;
  596. case IDM_RUN:
  597. if (fNoFileMenu)
  598. break;
  599. MyDialogBox(RUNDLG, hwndProgman, RunDlgProc);
  600. break;
  601. case IDM_EXIT:
  602. if (fNoFileMenu)
  603. break;
  604. PostMessage(hwndProgman, WM_CLOSE, 0, (LPARAM)-1);
  605. break;
  606. case IDM_SHUTDOWN:
  607. if (fNoFileMenu)
  608. break;
  609. /* Don't close if restricted. */
  610. if (fNoClose)
  611. break;
  612. if (bExitWindows) {
  613. fExiting = TRUE;
  614. SetWindowLong (hwndProgman, GWL_EXITING, 1);
  615. /* Call the ShutdownDialog API. */
  616. ShutdownDialog(hAppInstance, hwndProgman);
  617. /* User clicked cancel or some app refused the ExitWindows... */
  618. fExiting = FALSE;
  619. SetWindowLong (hwndProgman, GWL_EXITING, 0);
  620. }
  621. break;
  622. case IDM_AUTOARRANGE:
  623. bAutoArrange = !bAutoArrange;
  624. /* Check/Uncheck the menu item. */
  625. hMenu = GetSubMenu(GetMenu(hwndProgman), IDM_OPTIONS + (int)bMaxed - (int)fNoFileMenu);
  626. CheckMenuItem(hMenu, GET_WM_COMMAND_ID(wParam, lParam),
  627. (WORD)(bAutoArrange ? MF_CHECKED : MF_UNCHECKED));
  628. if (hkeyPMSettings)
  629. RegSetValueEx(hkeyPMSettings, szAutoArrange, 0, REG_DWORD, (LPBYTE)&bAutoArrange, sizeof(bAutoArrange));
  630. if (bAutoArrange) {
  631. HWND hwndT;
  632. for (hwndT=GetWindow(hwndMDIClient, GW_CHILD); hwndT;
  633. hwndT=GetWindow(hwndT, GW_HWNDNEXT)) {
  634. if (GetWindow(hwndT, GW_OWNER))
  635. continue;
  636. ArrangeItems(hwndT);
  637. }
  638. }
  639. break;
  640. case IDM_MINONRUN:
  641. bMinOnRun = !bMinOnRun;
  642. /* Check/Uncheck the menu item. */
  643. hMenu = GetSubMenu(GetMenu(hwndProgman), IDM_OPTIONS + (int)bMaxed - (int)fNoFileMenu);
  644. CheckMenuItem(hMenu, GET_WM_COMMAND_ID(wParam, lParam),
  645. (WORD)(bMinOnRun ? MF_CHECKED : MF_UNCHECKED));
  646. if (hkeyPMSettings)
  647. RegSetValueEx(hkeyPMSettings,
  648. szMinOnRun,
  649. 0,
  650. REG_DWORD,
  651. (LPBYTE)&bMinOnRun,
  652. sizeof(bMinOnRun));
  653. break;
  654. case IDM_SAVESETTINGS:
  655. bSaveSettings = !bSaveSettings;
  656. /* Check/Uncheck the menu item. */
  657. hMenu = GetSubMenu(GetMenu(hwndProgman), IDM_OPTIONS + (int)bMaxed - (int)fNoFileMenu);
  658. CheckMenuItem(hMenu, GET_WM_COMMAND_ID(wParam, lParam),
  659. (UINT)(bSaveSettings ? MF_CHECKED : MF_UNCHECKED));
  660. if (hkeyPMSettings)
  661. RegSetValueEx(hkeyPMSettings,
  662. szSaveSettings,
  663. 0,
  664. REG_DWORD,
  665. (LPBYTE)&bSaveSettings,
  666. sizeof(bSaveSettings));
  667. break;
  668. case IDM_SAVENOW:
  669. WriteINIFile();
  670. break;
  671. case IDM_ANSIGROUPS:
  672. RemoveAnsiGroups();
  673. break;
  674. case IDM_CASCADE:
  675. SendMessage(hwndMDIClient, WM_MDICASCADE, 0, 0L);
  676. break;
  677. case IDM_TILE:
  678. SendMessage(hwndMDIClient, WM_MDITILE, 0, 0L);
  679. break;
  680. case IDM_ARRANGEICONS:
  681. if (SelectionType() != TYPE_ITEM)
  682. SendMessage(hwndMDIClient, WM_MDIICONARRANGE, 0, 0L);
  683. else
  684. ArrangeItems(pCurrentGroup->hwnd);
  685. break;
  686. case IDM_HELPINDEX:
  687. wHelpCmd = HELP_INDEX;
  688. wParam = 0;
  689. goto ACPCallHelp;
  690. case IDM_HELPSEARCH:
  691. wHelpCmd = HELP_PARTIALKEY;
  692. wParam = (WPARAM)szNULL;
  693. goto ACPCallHelp;
  694. case IDM_HELPHELP:
  695. wHelpCmd = HELP_HELPONHELP;
  696. wParam = 0;
  697. ACPCallHelp:
  698. SetCurrentDirectory(szOriginalDirectory);
  699. if (!WinHelp(hwndProgman, szProgmanHelp, wHelpCmd, (DWORD)wParam)) {
  700. MyMessageBox(hwndProgman, IDS_APPTITLE, IDS_WINHELPERR, NULL, MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL);
  701. }
  702. SetCurrentDirectory(szWindowsDirectory);
  703. break;
  704. case IDM_ABOUT:
  705. {
  706. TCHAR szTitle[40];
  707. LoadString(hAppInstance, IDS_APPTITLE, szTitle, CharSizeOf(szTitle));
  708. if (ShellAbout(hwndProgman, szTitle, NULL, NULL) == -1)
  709. MessageBox(hwndProgman, szOOMExitMsg, szOOMExitTitle, MB_ICONHAND | MB_SYSTEMMODAL | MB_OK);
  710. break;
  711. }
  712. default:
  713. return(FALSE);
  714. }
  715. return(TRUE);
  716. }