Leaked source code of windows server 2003
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.

1452 lines
45 KiB

  1. //
  2. // Browse.C
  3. //
  4. // Copyright (C) Microsoft, 1994,1995 All Rights Reserved.
  5. //
  6. // History:
  7. // ral 5/23/94 - First pass
  8. // 3/20/95 [stevecat] - NT port & real clean up, unicode, etc.
  9. //
  10. //
  11. #include "priv.h"
  12. #include "appwiz.h"
  13. #include "util.h"
  14. #include <uastrfnc.h>
  15. #include <tsappcmp.h> // for TermsrvAppInstallMode
  16. // Copied from shelldll\ole2dup.h
  17. #define GUIDSTR_MAX (1+ 8 + 1 + 4 + 1 + 4 + 1 + 4 + 1 + 12 + 1 + 1)
  18. //
  19. // Initialize the browse property sheet. Limit the size of the edit control.
  20. //
  21. void BrowseInitPropSheet(HWND hDlg, LPARAM lParam)
  22. {
  23. LPWIZDATA lpwd = InitWizSheet(hDlg, lParam, 0);
  24. Edit_LimitText(GetDlgItem(hDlg, IDC_COMMAND), ARRAYSIZE(lpwd->szExeName)-1);
  25. if (FAILED(SHAutoComplete(GetDlgItem(hDlg, IDC_COMMAND), 0)))
  26. {
  27. TraceMsg(TF_WARNING, "%s", "WARNING: Create Shortcut wizard won't AutoComplete because: 1) bad registry, 2) bad OleInit, or 3) Out of memory.");
  28. }
  29. }
  30. //
  31. // Sets the appropriate wizard buttons. If there's any text in the
  32. // edit control then Next is enabled. Otherwise, Next and Back are both
  33. // grey.
  34. //
  35. void SetBrowseButtons(LPWIZDATA lpwd)
  36. {
  37. BOOL fIsText = GetWindowTextLength(GetDlgItem(lpwd->hwnd, IDC_COMMAND)) > 0;
  38. BOOL fIsSetup = (lpwd->dwFlags & WDFLAG_SETUPWIZ);
  39. int iBtns = fIsSetup ? PSWIZB_BACK : 0;
  40. if (fIsSetup)
  41. {
  42. // Are we running Terminal Service? Is this user an Admin?
  43. if (IsTerminalServicesRunning() && IsUserAnAdmin())
  44. {
  45. lpwd->bTermSrvAndAdmin = TRUE;
  46. iBtns |= fIsText ? PSWIZB_NEXT : PSWIZB_DISABLEDFINISH;
  47. }
  48. else
  49. iBtns |= fIsText ? PSWIZB_FINISH : PSWIZB_DISABLEDFINISH;
  50. }
  51. else
  52. {
  53. if (fIsText)
  54. {
  55. iBtns |= PSWIZB_NEXT;
  56. }
  57. }
  58. PropSheet_SetWizButtons(GetParent(lpwd->hwnd), iBtns);
  59. }
  60. //
  61. // NOTES: 1) This function assumes that lpwd->hwnd has already been set to
  62. // the dialogs hwnd. 2) This function is called from NextPushed
  63. // if the application specified can not be found.
  64. //
  65. // BrowseSetActive enables the next button and sets the focus to the edit
  66. // control by posting a POKEFOCUS message.
  67. //
  68. void BrowseSetActive(LPWIZDATA lpwd)
  69. {
  70. //
  71. // NOTE: We re-use the szProgDesc string since it will always be reset
  72. // when this page is activated. Use it to construct a command line.
  73. //
  74. #define szCmdLine lpwd->szProgDesc
  75. StringCchCopy(szCmdLine, ARRAYSIZE(szCmdLine), lpwd->szExeName);
  76. PathQuoteSpaces(szCmdLine);
  77. if (lpwd->szParams[0] != 0)
  78. {
  79. StringCchCat(szCmdLine, ARRAYSIZE(szCmdLine), TEXT(" "));
  80. StringCchCat(szCmdLine, ARRAYSIZE(szCmdLine), lpwd->szParams);
  81. }
  82. Edit_SetText(GetDlgItem(lpwd->hwnd, IDC_COMMAND), szCmdLine);
  83. if (lpwd->dwFlags & WDFLAG_SETUPWIZ)
  84. {
  85. int iHaveHeader = IsTerminalServicesRunning() ? IDS_TSHAVESETUPPRG : IDS_HAVESETUPPRG;
  86. int iHeader = szCmdLine[0] != 0 ? iHaveHeader : IDS_NOSETUPPRG;
  87. TCHAR szInstruct[MAX_PATH];
  88. LoadString(g_hinst, iHeader, szInstruct, ARRAYSIZE(szInstruct));
  89. Static_SetText(GetDlgItem(lpwd->hwnd, IDC_SETUPMSG), szInstruct);
  90. }
  91. SetBrowseButtons(lpwd);
  92. PostMessage(lpwd->hwnd, WMPRIV_POKEFOCUS, 0, 0);
  93. szCmdLine[0] = 0; // Reset progdesc to empty string
  94. #undef szCmdLine
  95. }
  96. //
  97. // Returns TRUE if able to get properties for szExeName from PifMgr. The
  98. // program properties will be read into lpwd->PropPrg.
  99. //
  100. BOOL ReadPifProps(LPWIZDATA lpwd)
  101. {
  102. HANDLE hPifProp;
  103. LPTSTR lpszName = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  104. hPifProp = PifMgr_OpenProperties(lpszName, NULL, 0, OPENPROPS_INHIBITPIF);
  105. if (!hPifProp)
  106. {
  107. TraceMsg(TF_ERROR, "%s", "Unable to open properties for DOS exe.");
  108. }
  109. if (hPifProp == 0)
  110. return(FALSE);
  111. PifMgr_GetProperties(hPifProp, (LPSTR)GROUP_PRG, &(lpwd->PropPrg),
  112. sizeof(lpwd->PropPrg), GETPROPS_NONE);
  113. PifMgr_CloseProperties(hPifProp, CLOSEPROPS_DISCARD);
  114. return(TRUE);
  115. }
  116. //
  117. // Returns TRUE if lpwd->szExeName points to a valid exe type. It also sets
  118. // the appropriate flags, such as APPKNOWN and DOSAPP in the wizdata structure
  119. // if the exe is valid.
  120. //
  121. void DetermineExeType(LPWIZDATA lpwd)
  122. {
  123. DWORD dwExeType;
  124. LPTSTR lpszName = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  125. lpwd->dwFlags &= ~(WDFLAG_APPKNOWN | WDFLAG_DOSAPP);
  126. dwExeType = (DWORD)SHGetFileInfo(lpszName, 0, NULL, 0, SHGFI_EXETYPE);
  127. if (LOWORD(dwExeType) != ('M' | ('Z' << 8)))
  128. {
  129. lpwd->dwFlags |= WDFLAG_APPKNOWN;
  130. if (lstrcmpi(PathFindExtension(lpszName), c_szPIF) == 0)
  131. {
  132. lpwd->dwFlags |= WDFLAG_DOSAPP;
  133. }
  134. }
  135. else
  136. {
  137. lpwd->dwFlags |= WDFLAG_DOSAPP;
  138. if (ReadPifProps(lpwd))
  139. {
  140. if ((lpwd->PropPrg.flPrgInit & PRGINIT_INFSETTINGS) ||
  141. ((lpwd->PropPrg.flPrgInit &
  142. (PRGINIT_NOPIF | PRGINIT_DEFAULTPIF)) == 0))
  143. {
  144. lpwd->dwFlags |= WDFLAG_APPKNOWN;
  145. }
  146. }
  147. }
  148. }
  149. //
  150. // Removes the filename extension (if any) from the string.
  151. //
  152. void StripExt(LPTSTR lpsz)
  153. {
  154. if(lpsz)
  155. {
  156. LPTSTR pExt = PathFindExtension(lpsz);
  157. if (*pExt)
  158. *pExt = 0; // null out the "."
  159. }
  160. }
  161. //
  162. // Sets the working directory as appropriate for the file type.
  163. //
  164. void FindWorkingDir(LPWIZDATA lpwd)
  165. {
  166. LPTSTR lpszName = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  167. TCHAR szWindir[ MAX_PATH ];
  168. DWORD dwLen;
  169. if (PathIsUNC(lpszName) || PathIsDirectory(lpszName))
  170. {
  171. lpwd->szWorkingDir[0] = 0;
  172. }
  173. else
  174. {
  175. StringCchCopy(lpwd->szWorkingDir, ARRAYSIZE(lpwd->szWorkingDir), lpszName);
  176. PathRemoveFileSpec(lpwd->szWorkingDir);
  177. }
  178. //
  179. // Okay, at this point we should have the absolute path for the
  180. // working directory of the link. On NT, if the working dir happens to be for
  181. // something in the %Windir% directory (or a subdir of %windir%),
  182. // then store the path as %windir%\blah\blah\blah instead of as an
  183. // absolute path. This will help with interoperability of shortcuts
  184. // across different machines, etc. But only do this for shortcuts that
  185. // are already marked as having expandable env strings...
  186. //
  187. if (lpwd->dwFlags & WDFLAG_EXPSZ)
  188. {
  189. dwLen = ExpandEnvironmentStrings( TEXT("%windir%"),
  190. szWindir,
  191. ARRAYSIZE(szWindir)
  192. );
  193. if (dwLen &&
  194. dwLen < ARRAYSIZE(szWindir) &&
  195. lstrlen(szWindir) <= lstrlen(lpwd->szWorkingDir)
  196. )
  197. {
  198. //
  199. // we use dwLen-1 because dwLen includes the '\0' character
  200. //
  201. if (CompareString( LOCALE_SYSTEM_DEFAULT,
  202. NORM_IGNORECASE,
  203. szWindir, dwLen-1 ,
  204. lpwd->szWorkingDir, dwLen-1
  205. ) == 2)
  206. {
  207. TCHAR szWorkingDir[ MAX_PATH ];
  208. //
  209. // We should substitute the env variable for the
  210. // actual string here...
  211. //
  212. StringCchCopy(szWorkingDir, ARRAYSIZE(szWorkingDir), lpwd->szWorkingDir);
  213. StringCchCopy(lpwd->szWorkingDir, ARRAYSIZE(lpwd->szWorkingDir), TEXT("%windir%"));
  214. // 8 == lstrlen("%windir%")
  215. StringCchCopy( lpwd->szWorkingDir + 12, ARRAYSIZE(lpwd->szWorkingDir)-12, szWorkingDir+dwLen-1 );
  216. }
  217. }
  218. }
  219. }
  220. #ifndef NO_NEW_SHORTCUT_HOOK
  221. //
  222. // Returns:
  223. // Hook result or error.
  224. //
  225. // S_OK:
  226. // *pnshhk is the INewShortcutHook of the object to use to save the new Shortcut.
  227. // szProgDesc[] and szExt[] are filled in.
  228. // szExeName[] may be translated.
  229. // otherwise:
  230. // *pnshhk is NULL.
  231. // szProgDesc[] and szExt[] are empty strings.
  232. //
  233. HRESULT QueryNewLinkHandler(LPWIZDATA lpwd, LPCLSID pclsidHook)
  234. {
  235. HRESULT hr;
  236. IUnknown *punk;
  237. LPTSTR lpszName = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  238. lpwd->pnshhk = NULL;
  239. lpwd->pnshhkA = NULL;
  240. *(lpwd->szProgDesc) = TEXT('\0');
  241. *(lpwd->szExt) = TEXT('\0');
  242. hr = CoCreateInstance(pclsidHook, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, &punk);
  243. if (hr == S_OK)
  244. {
  245. INewShortcutHook *pnshhk;
  246. hr = punk->lpVtbl->QueryInterface(punk, &IID_INewShortcutHook, &pnshhk);
  247. if (hr == S_OK)
  248. {
  249. hr = pnshhk->lpVtbl->SetReferent(pnshhk, lpszName, lpwd->hwnd);
  250. if (hr == S_OK)
  251. {
  252. hr = pnshhk->lpVtbl->SetFolder(pnshhk, lpwd->lpszFolder);
  253. if (hr == S_OK)
  254. {
  255. hr = pnshhk->lpVtbl->GetName(pnshhk, lpwd->szProgDesc,
  256. ARRAYSIZE(lpwd->szProgDesc));
  257. if (hr == S_OK)
  258. {
  259. hr = pnshhk->lpVtbl->GetExtension(pnshhk, lpwd->szExt,
  260. ARRAYSIZE(lpwd->szExt));
  261. if (hr == S_OK)
  262. hr = pnshhk->lpVtbl->GetReferent(pnshhk, lpszName,
  263. ARRAYSIZE(lpwd->szExeName));
  264. }
  265. }
  266. }
  267. if (hr == S_OK)
  268. lpwd->pnshhk = pnshhk;
  269. else
  270. pnshhk->lpVtbl->Release(pnshhk);
  271. }
  272. else
  273. {
  274. INewShortcutHookA *pnshhkA;
  275. hr = punk->lpVtbl->QueryInterface(punk, &IID_INewShortcutHookA, &pnshhkA);
  276. if (hr == S_OK)
  277. {
  278. UINT cFolderA = WideCharToMultiByte(CP_ACP,0,lpwd->lpszFolder,-1,NULL,0,0,0)+1;
  279. LPSTR lpszFolderA = (LPSTR)LocalAlloc(LPTR,cFolderA*SIZEOF(CHAR));
  280. if (NULL == lpszFolderA)
  281. {
  282. hr = E_OUTOFMEMORY;
  283. }
  284. else
  285. {
  286. CHAR szNameA[MAX_PATH];
  287. CHAR szProgDescA[MAX_PATH];
  288. CHAR szExtA[MAX_PATH];
  289. WideCharToMultiByte(CP_ACP, 0,
  290. lpszName, -1,
  291. szNameA, ARRAYSIZE(szNameA),
  292. 0, 0);
  293. WideCharToMultiByte(CP_ACP, 0,
  294. lpwd->lpszFolder, -1,
  295. lpszFolderA, cFolderA,
  296. 0, 0);
  297. hr = pnshhkA->lpVtbl->SetReferent(pnshhkA, szNameA, lpwd->hwnd);
  298. if (hr == S_OK)
  299. {
  300. hr = pnshhkA->lpVtbl->SetFolder(pnshhkA, lpszFolderA);
  301. if (hr == S_OK)
  302. {
  303. hr = pnshhkA->lpVtbl->GetName(pnshhkA, szProgDescA,
  304. ARRAYSIZE(szProgDescA));
  305. if (hr == S_OK)
  306. {
  307. MultiByteToWideChar(CP_ACP, 0,
  308. szProgDescA, -1,
  309. lpwd->szProgDesc, ARRAYSIZE(lpwd->szProgDesc));
  310. hr = pnshhkA->lpVtbl->GetExtension(pnshhkA, szExtA,
  311. ARRAYSIZE(szExtA));
  312. if (hr == S_OK)
  313. {
  314. MultiByteToWideChar(CP_ACP, 0,
  315. szExtA, -1,
  316. lpwd->szExt, ARRAYSIZE(lpwd->szExt));
  317. hr = pnshhkA->lpVtbl->GetReferent(pnshhkA, szNameA,
  318. ARRAYSIZE(szNameA));
  319. MultiByteToWideChar(CP_ACP, 0,
  320. szExtA, -1,
  321. lpszName, ARRAYSIZE(lpwd->szExeName));
  322. }
  323. }
  324. }
  325. }
  326. if (hr == S_OK)
  327. lpwd->pnshhkA = pnshhkA;
  328. else
  329. pnshhkA->lpVtbl->Release(pnshhkA);
  330. LocalFree(lpszFolderA);
  331. }
  332. }
  333. }
  334. punk->lpVtbl->Release(punk);
  335. }
  336. return(hr);
  337. }
  338. const TCHAR c_szNewLinkHandlers[] = REGSTR_PATH_EXPLORER TEXT("\\NewShortcutHandlers");
  339. //
  340. // Sets lpwd->pnshhk to NULL for CLSID_ShellLink (default) or to the
  341. // INewShortcutHook of the object to be used.
  342. //
  343. // If lpwd->pnshhk is returned non-NULL, szProgDesc[] and szExt[] are also
  344. // filled in.
  345. //
  346. void DetermineLinkHandler(LPWIZDATA lpwd)
  347. {
  348. HKEY hkeyHooks;
  349. // Lose any previously saved external new Shortcut handler.
  350. if (lpwd->pnshhk)
  351. {
  352. lpwd->pnshhk->lpVtbl->Release(lpwd->pnshhk);
  353. lpwd->pnshhk = NULL;
  354. }
  355. if (lpwd->pnshhkA)
  356. {
  357. lpwd->pnshhkA->lpVtbl->Release(lpwd->pnshhkA);
  358. lpwd->pnshhkA = NULL;
  359. }
  360. //
  361. // Enumerate the list of new link handlers. Each new link handler is
  362. // registered as a GUID value under c_szNewLinkHandlers.
  363. //
  364. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szNewLinkHandlers, 0, KEY_READ, &hkeyHooks)
  365. == ERROR_SUCCESS)
  366. {
  367. DWORD dwiValue;
  368. TCHAR szCLSID[GUIDSTR_MAX];
  369. DWORD dwcbCLSIDLen;
  370. //
  371. // Invoke each hook. A hook returns S_FALSE if it does not wish to
  372. // handle the new link. Stop if a hook returns S_OK.
  373. //
  374. for (dwcbCLSIDLen = ARRAYSIZE(szCLSID), dwiValue = 0;
  375. RegEnumValue(hkeyHooks, dwiValue, szCLSID, &dwcbCLSIDLen, NULL,
  376. NULL, NULL, NULL) == ERROR_SUCCESS;
  377. dwcbCLSIDLen = ARRAYSIZE(szCLSID), dwiValue++)
  378. {
  379. CLSID clsidHook;
  380. if (SHCLSIDFromString(szCLSID, &clsidHook) == S_OK &&
  381. QueryNewLinkHandler(lpwd, &clsidHook) == S_OK)
  382. break;
  383. }
  384. RegCloseKey(hkeyHooks);
  385. }
  386. return;
  387. }
  388. #endif
  389. //
  390. // Returns TRUE if it's OK to go to the next wizard dialog.
  391. //
  392. BOOL NextPushed(LPWIZDATA lpwd)
  393. {
  394. GetDlgItemText(lpwd->hwnd, IDC_COMMAND, lpwd->szExeName, ARRAYSIZE(lpwd->szExeName));
  395. // Is the string a path with spaces, without arguments, but isn't correctly
  396. // quoted? NT #d: >C:\Program Files\Windows NT\dialer.exe< is treated like
  397. // "C:\Program" with "Files\Windows NT\dialer.exe" as args.
  398. if (PathFileExists(lpwd->szExeName))
  399. {
  400. // Yes, so let's quote it so we don't treat the stuff after
  401. // the space like args.
  402. PathQuoteSpaces(lpwd->szExeName);
  403. }
  404. PathRemoveBlanks(lpwd->szExeName);
  405. if (lpwd->szExeName[0] != 0)
  406. {
  407. BOOL bUNC;
  408. LPTSTR lpszTarget = NULL;
  409. HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  410. LPTSTR lpszArgs = PathGetArgs(lpwd->szExeName);
  411. StringCchCopy(lpwd->szParams, ARRAYSIZE(lpwd->szParams), lpszArgs);
  412. if (*lpszArgs)
  413. {
  414. *(lpszArgs - 1) = 0; // clobber the ' ' in the exe name field
  415. }
  416. ExpandEnvironmentStrings( lpwd->szExeName,
  417. lpwd->szExpExeName,
  418. ARRAYSIZE(lpwd->szExpExeName)
  419. );
  420. lpwd->szExpExeName[ MAX_PATH-1 ] = TEXT('\0');
  421. if (lstrcmp(lpwd->szExeName, lpwd->szExpExeName))
  422. lpwd->dwFlags |= WDFLAG_EXPSZ;
  423. lpszTarget = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  424. PathUnquoteSpaces(lpszTarget);
  425. if (lpwd->dwFlags & WDFLAG_EXPSZ)
  426. PathUnquoteSpaces(lpwd->szExeName);
  427. lpwd->dwFlags &= ~WDFLAG_COPYLINK;
  428. #ifndef NO_NEW_SHORTCUT_HOOK
  429. //
  430. // Figure out who wants to handle this string as a link referent.
  431. //
  432. DetermineLinkHandler(lpwd);
  433. if (lpwd->pnshhk)
  434. {
  435. //
  436. // We are using an external link handler. Skip file system
  437. // validation.
  438. //
  439. lpwd->dwFlags |= WDFLAG_APPKNOWN;
  440. SetCursor(hcurOld);
  441. return(TRUE);
  442. }
  443. if (lpwd->pnshhkA)
  444. {
  445. //
  446. // We are using an external link handler. Skip file system
  447. // validation.
  448. //
  449. lpwd->dwFlags |= WDFLAG_APPKNOWN;
  450. SetCursor(hcurOld);
  451. return(TRUE);
  452. }
  453. #endif
  454. bUNC = PathIsUNC(lpszTarget);
  455. if (bUNC && !SHValidateUNC(lpwd->hwnd, lpszTarget, FALSE))
  456. goto Done;
  457. //
  458. // If the user tries to make a link to A:\ and there's no disk
  459. // in the drive, PathResolve would fail. So, for drive roots, we
  460. // don't try to resolve it.
  461. //
  462. if ((PathIsRoot(lpszTarget) && !bUNC &&
  463. DriveType(DRIVEID(lpszTarget))) ||
  464. PathResolve(lpszTarget, NULL,
  465. PRF_VERIFYEXISTS | PRF_TRYPROGRAMEXTENSIONS))
  466. {
  467. //
  468. // If we found a PIF file then we'll try to convert it to the
  469. // name of the file it points to.
  470. //
  471. if (lstrcmpi(PathFindExtension(lpszTarget), c_szPIF) == 0)
  472. {
  473. if (!ReadPifProps(lpwd))
  474. {
  475. goto Done;
  476. }
  477. MultiByteToWideChar(CP_ACP, 0, lpwd->PropPrg.achCmdLine, -1,
  478. lpszTarget, ARRAYSIZE(lpwd->szExeName));
  479. PathRemoveArgs(lpszTarget);
  480. if (!PathResolve(lpszTarget, NULL,
  481. PRF_VERIFYEXISTS | PRF_TRYPROGRAMEXTENSIONS))
  482. {
  483. goto Done;
  484. }
  485. }
  486. //
  487. // Okay, at this point we should have the absolute path for the
  488. // target of the link. On NT, if the target happens to be for
  489. // something in the %Windir% directory (or a subdir of %Windir%),
  490. // AND the user didn't type in an expandable path already, then
  491. // store the path as %windir%\blah\blah\blah instead of as an
  492. // absolute path. This will help with interoperability of shortcuts
  493. // across different machines, etc.
  494. //
  495. if (!(lpwd->dwFlags & WDFLAG_EXPSZ))
  496. {
  497. TCHAR szWindir[ MAX_PATH ];
  498. DWORD dwLen;
  499. //
  500. // What did the user type in?
  501. //
  502. GetDlgItemText(lpwd->hwnd, IDC_COMMAND, szWindir, ARRAYSIZE(szWindir));
  503. if (ualstrcmpi(szWindir, lpwd->szExeName)==0)
  504. {
  505. //
  506. // If we didn't change it, it means the user typed in an
  507. // exact path. In that case, don't try to map anyting.
  508. //
  509. goto LinkToALinkCase;
  510. }
  511. dwLen = ExpandEnvironmentStrings( TEXT("%windir%"),
  512. szWindir,
  513. ARRAYSIZE(szWindir)
  514. );
  515. if (dwLen &&
  516. dwLen < ARRAYSIZE(szWindir) &&
  517. lstrlen(szWindir) <= lstrlen(lpszTarget)
  518. )
  519. {
  520. //
  521. // we use dwLen-1 because dwLen includes the '\0' character
  522. //
  523. if (CompareString( LOCALE_SYSTEM_DEFAULT,
  524. NORM_IGNORECASE,
  525. szWindir, dwLen-1 ,
  526. lpszTarget, dwLen-1
  527. ) == 2)
  528. {
  529. //
  530. // We should substitute the env variable for the
  531. // actual string here...
  532. //
  533. StringCchCopy(lpwd->szExpExeName, ARRAYSIZE(lpwd->szExpExeName), lpwd->szExeName);
  534. StringCchCopy(lpwd->szExeName, ARRAYSIZE(lpwd->szExeName), TEXT("%windir%"));
  535. // 8 == lstrlen("%windir%")
  536. StringCchCopy( lpwd->szExeName + 8, ARRAYSIZE(lpwd->szExeName)-8, lpwd->szExpExeName+dwLen-1 );
  537. lpwd->dwFlags |= WDFLAG_EXPSZ;
  538. lpszTarget = lpwd->szExpExeName;
  539. }
  540. }
  541. }
  542. //
  543. // Okay, at this point we should have the absolute path for the
  544. // target of the link. On NT, if the target happens to be for
  545. // something in the %Windir% directory (or a subdir of %Windir%),
  546. // AND the user didn't type in an expandable path already, then
  547. // store the path as %windir%\blah\blah\blah instead of as an
  548. // absolute path. This will help with interoperability of shortcuts
  549. // across different machines, etc.
  550. //
  551. if (!(lpwd->dwFlags & WDFLAG_EXPSZ))
  552. {
  553. TCHAR szWindir[ MAX_PATH ];
  554. DWORD dwLen;
  555. //
  556. // What did the user type in?
  557. //
  558. GetDlgItemText(lpwd->hwnd, IDC_COMMAND, szWindir, ARRAYSIZE(szWindir));
  559. if (ualstrcmpi(szWindir, lpwd->szExeName)==0)
  560. {
  561. //
  562. // If we didn't change it, it means the user typed in an
  563. // exact path. In that case, don't try to map anyting.
  564. //
  565. goto LinkToALinkCase;
  566. }
  567. dwLen = ExpandEnvironmentStrings( TEXT("%windir%"),
  568. szWindir,
  569. ARRAYSIZE(szWindir)
  570. );
  571. if (dwLen &&
  572. dwLen < ARRAYSIZE(szWindir) &&
  573. lstrlen(szWindir) <= lstrlen(lpszTarget)
  574. )
  575. {
  576. //
  577. // we use dwLen-1 because dwLen includes the '\0' character
  578. //
  579. if (CompareString( LOCALE_SYSTEM_DEFAULT,
  580. NORM_IGNORECASE,
  581. szWindir, dwLen-1 ,
  582. lpszTarget, dwLen-1
  583. ) == 2)
  584. {
  585. //
  586. // We should substitute the env variable for the
  587. // actual string here...
  588. //
  589. StringCchCopy(lpwd->szExpExeName, ARRAYSIZE(lpwd->szExpExeName), lpwd->szExeName);
  590. StringCchCopy(lpwd->szExeName, ARRAYSIZE(lpwd->szExeName), TEXT("%windir%"));
  591. // 8 == lstrlen("%windir%")
  592. StringCchCopy( lpwd->szExeName + 8, ARRAYSIZE(lpwd->szExeName)-8, lpwd->szExpExeName+dwLen-1 );
  593. lpwd->dwFlags |= WDFLAG_EXPSZ;
  594. lpszTarget = lpwd->szExpExeName;
  595. }
  596. }
  597. }
  598. LinkToALinkCase:
  599. //
  600. // Really, really obscure case. The user creates "New Shortcut" and
  601. // tries to point it to itself. Don't allow it. We'd be confused
  602. // later. Since it's so obscure, just give a generic error about
  603. // "Can't find this file"
  604. //
  605. if (!(lpwd->lpszOriginalName &&
  606. lstrcmpi(lpwd->lpszOriginalName, lpszTarget) == 0))
  607. {
  608. DetermineExeType(lpwd);
  609. FindWorkingDir(lpwd);
  610. lpwd->szProgDesc[0] = 0; // Reset description
  611. // EVEN IF WE DON'T RECREATE IT HERE!
  612. if (lpwd->lpszFolder && lpwd->lpszFolder[0] != 0 &&
  613. !DetermineDefaultTitle(lpwd))
  614. {
  615. goto Done;
  616. }
  617. if (lpwd->dwFlags & WDFLAG_EXPSZ)
  618. {
  619. LPTSTR lpszExt = PathFindExtension( lpwd->szExeName );
  620. if (!(*lpszExt))
  621. {
  622. // do simple check to make sure there was a file name
  623. // at the end of the original entry. we assume that
  624. // if we got this far, lpszExt points to the end of
  625. // the string pointed to by lpwd->szExeName, and that
  626. // lpwd->szExeName has at least one character in it.
  627. if (lpwd->szExeName &&
  628. (*lpwd->szExeName) &&
  629. (*(lpszExt-1)!=TEXT('%'))
  630. )
  631. {
  632. lstrcpy( lpszExt, PathFindExtension( lpszTarget ) );
  633. }
  634. }
  635. }
  636. SetCursor(hcurOld);
  637. return(TRUE);
  638. }
  639. }
  640. Done:
  641. SetCursor(hcurOld);
  642. ShellMessageBox(g_hinst, lpwd->hwnd, MAKEINTRESOURCE(IDS_BADPATHMSG), 0, MB_OK | MB_ICONEXCLAMATION, lpwd->szExeName);
  643. }
  644. BrowseSetActive(lpwd);
  645. return(FALSE);
  646. }
  647. //
  648. // Returns TRUE if it's OK to run the setup program.
  649. //
  650. BOOL SetupCleanupExePath(LPWIZDATA lpwd)
  651. {
  652. BOOL fValidPrg = FALSE;
  653. GetDlgItemText(lpwd->hwnd, IDC_COMMAND, lpwd->szExeName, ARRAYSIZE(lpwd->szExeName));
  654. // Is the string a path with spaces, without arguments, but isn't correctly
  655. // quoted? NT #d: >C:\Program Files\Windows NT\dialer.exe< is treated like
  656. // "C:\Program" with "Files\Windows NT\dialer.exe" as args.
  657. if (PathFileExists(lpwd->szExeName))
  658. {
  659. // Yes, so let's quote it so we don't treat the stuff after
  660. // the space like args.
  661. PathQuoteSpaces(lpwd->szExeName);
  662. }
  663. PathRemoveBlanks(lpwd->szExeName);
  664. if (lpwd->szExeName[0] != 0)
  665. {
  666. LPTSTR lpszTarget = NULL;
  667. LPTSTR lpszArgs = NULL;
  668. HCURSOR hcurOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
  669. ExpandEnvironmentStrings( lpwd->szExeName,
  670. lpwd->szExpExeName,
  671. ARRAYSIZE(lpwd->szExpExeName)
  672. );
  673. if (lstrcmp(lpwd->szExeName, lpwd->szExpExeName))
  674. lpwd->dwFlags |= WDFLAG_EXPSZ;
  675. lpszTarget = (lpwd->dwFlags & WDFLAG_EXPSZ) ? lpwd->szExpExeName : lpwd->szExeName;
  676. lpszArgs = PathGetArgs(lpszTarget);
  677. StringCchCopy(lpwd->szParams, ARRAYSIZE(lpwd->szParams), lpszArgs);
  678. if (*lpszArgs)
  679. {
  680. *(lpszArgs - 1) = 0; // clobber the ' ' in the exe name field
  681. }
  682. PathUnquoteSpaces(lpszTarget);
  683. if (lpwd->dwFlags & WDFLAG_EXPSZ)
  684. PathUnquoteSpaces(lpwd->szExeName);
  685. if (PathResolve(lpszTarget, NULL,
  686. PRF_VERIFYEXISTS | PRF_TRYPROGRAMEXTENSIONS))
  687. {
  688. LPTSTR lpszExt = PathFindExtension( lpszTarget );
  689. fValidPrg = TRUE;
  690. FindWorkingDir(lpwd);
  691. if (lpwd->dwFlags & WDFLAG_EXPSZ)
  692. {
  693. if (!(*lpszExt))
  694. {
  695. lstrcpy( lpszExt, PathFindExtension( lpszTarget ) );
  696. }
  697. }
  698. if ((*lpszExt) && lpwd->bTermSrvAndAdmin && (!lstrcmpi(lpszExt, TEXT(".msi"))))
  699. {
  700. StringCchCat(lpwd->szParams, ARRAYSIZE(lpwd->szParams), TEXT(" ALLUSERS=1"));
  701. }
  702. PathQuoteSpaces( lpszTarget );
  703. }
  704. SetCursor(hcurOld);
  705. }
  706. if (!fValidPrg)
  707. {
  708. ShellMessageBox(g_hinst, lpwd->hwnd, MAKEINTRESOURCE(IDS_BADPATHMSG), 0, MB_OK | MB_ICONEXCLAMATION, lpwd->szExeName);
  709. BrowseSetActive(lpwd);
  710. }
  711. return(fValidPrg);
  712. }
  713. BOOL DetermineDefaultTitle(LPWIZDATA lpwd)
  714. {
  715. TCHAR szFullName[MAX_PATH];
  716. BOOL fCopy;
  717. LPTSTR lpszName;
  718. lpwd->dwFlags &= ~WDFLAG_COPYLINK;
  719. if (lpwd->dwFlags & WDFLAG_EXPSZ)
  720. lpszName = lpwd->szExpExeName;
  721. else
  722. lpszName = lpwd->szExeName;
  723. if (!SHGetNewLinkInfo(lpszName, lpwd->lpszFolder, szFullName,
  724. &fCopy, 0))
  725. {
  726. //
  727. // failure...
  728. //
  729. return(FALSE);
  730. }
  731. lpszName = PathFindFileName(szFullName);
  732. StripExt(lpszName);
  733. lstrcpyn(lpwd->szProgDesc, lpszName, ARRAYSIZE(lpwd->szProgDesc));
  734. //
  735. // We will never copy PIF files since they often do not contain
  736. // the appropriate current directory. This is becuase they are
  737. // automatically created when you run a DOS application from the
  738. // shell.
  739. //
  740. if ((lpwd->dwFlags & WDFLAG_DOSAPP) == 0)
  741. {
  742. if (fCopy)
  743. {
  744. lpwd->dwFlags |= WDFLAG_COPYLINK;
  745. }
  746. #ifndef NO_NEW_SHORTCUT_HOOK
  747. StringCchCopy(lpwd->szExt, ARRAYSIZE(lpwd->szExt), c_szLNK);
  748. }
  749. else
  750. {
  751. StringCchCopy(lpwd->szExt, ARRAYSIZE(lpwd->szExt), c_szPIF);
  752. #endif
  753. }
  754. return(TRUE);
  755. }
  756. //
  757. // paranoia: evaluate each time in case it is installed after ARP was first open, but
  758. // before it is closed and re-opened
  759. //
  760. BOOL MSI_IsMSIAvailable()
  761. {
  762. BOOL bAvailable = FALSE;
  763. HINSTANCE hinst = LoadLibraryA("MSI.DLL");
  764. if (hinst)
  765. {
  766. bAvailable = TRUE;
  767. FreeLibrary(hinst);
  768. }
  769. return bAvailable;
  770. }
  771. //
  772. // Call the common dialog code for File Open
  773. //
  774. BOOL BrowseForExe(HWND hwnd, LPTSTR pszName, DWORD cchName, LPCTSTR pszInitDir)
  775. {
  776. TCHAR szExt[80];
  777. TCHAR szFilter[200];
  778. TCHAR szTitle[80];
  779. TCHAR szBootDir[64];
  780. // we want to pass in an initial directory since GetFileNameFromBrowse
  781. // try to determine an initial directory by doing a PathRemoveFileSpec
  782. // on pszName. If pszName is already a directory then the last directory
  783. // is removed (even though it's not a file). E.g.: "c:\winnt" -> "c:\"
  784. lstrcpyn(szBootDir, pszInitDir, ARRAYSIZE(szBootDir));
  785. if (MSI_IsMSIAvailable())
  786. LoadAndStrip(IDS_BROWSEFILTERMSI, szFilter, ARRAYSIZE(szFilter));
  787. else
  788. LoadAndStrip(IDS_BROWSEFILTER, szFilter, ARRAYSIZE(szFilter));
  789. LoadString(g_hinst, IDS_BROWSEEXT, szExt, ARRAYSIZE(szExt));
  790. LoadString(g_hinst, IDS_BROWSETITLE, szTitle, ARRAYSIZE(szTitle));
  791. // we need to set pszName to NULL or else GetFileNameFromBrowse will use it
  792. // to find the initial directory even though we explicitly pass in an initial
  793. // dir.
  794. *pszName = 0;
  795. return(GetFileNameFromBrowse(hwnd, pszName, cchName,
  796. szBootDir, szExt, szFilter, szTitle));
  797. }
  798. //
  799. // Use the common open dialog to browse for program. Used by SetupBrowseDlgProc
  800. //
  801. void BrowsePushed(LPWIZDATA lpwd)
  802. {
  803. LPTSTR lpszName;
  804. DWORD cchName = 0;
  805. GetDlgItemText(lpwd->hwnd, IDC_COMMAND, lpwd->szExeName, ARRAYSIZE(lpwd->szExeName));
  806. ExpandEnvironmentStrings( lpwd->szExeName, lpwd->szExpExeName, ARRAYSIZE(lpwd->szExpExeName) );
  807. if (lstrcmp(lpwd->szExeName, lpwd->szExpExeName))
  808. lpwd->dwFlags |= WDFLAG_EXPSZ;
  809. if (lpwd->dwFlags & WDFLAG_EXPSZ)
  810. {
  811. lpszName = lpwd->szExpExeName;
  812. cchName = ARRAYSIZE(lpwd->szExpExeName);
  813. }
  814. else
  815. {
  816. lpszName = lpwd->szExeName;
  817. cchName = ARRAYSIZE(lpwd->szExeName);
  818. }
  819. if (BrowseForExe(lpwd->hwnd, lpszName, cchName, lpszName))
  820. {
  821. lpwd->szParams[0] = 0;
  822. BrowseSetActive(lpwd);
  823. }
  824. }
  825. void EnableOKButton(HWND hwndDlg, LPITEMIDLIST pidl)
  826. {
  827. DWORD dwFlags = SFGAO_FILESYSTEM;
  828. WCHAR szName[MAX_PATH] = L"";
  829. HRESULT hr = E_FAIL;
  830. if (pidl)
  831. {
  832. if (SUCCEEDED(SHGetNameAndFlags(pidl, SHGDN_FORPARSING, szName, ARRAYSIZE(szName), &dwFlags)))
  833. {
  834. if ((dwFlags & SFGAO_FILESYSTEM) != 0 ||
  835. !lstrncmp(szName, L"\\\\", 2))
  836. {
  837. hr = S_OK;
  838. }
  839. }
  840. }
  841. if (SUCCEEDED(hr))
  842. {
  843. // Path is either a valid local path
  844. // or a valid network path, enable the ok button
  845. SendMessage(hwndDlg, BFFM_ENABLEOK, (WPARAM)0, (LPARAM)1);
  846. }
  847. else
  848. {
  849. // Path does not exist, disable the ok button
  850. // This could be My Computer or an empty floppy drive etc...
  851. SendMessage(hwndDlg, BFFM_ENABLEOK, (WPARAM)0, (LPARAM)0);
  852. }
  853. }
  854. int CALLBACK BrowseCallbackProc(
  855. HWND hwnd,
  856. UINT uMsg,
  857. LPARAM lParam,
  858. LPARAM lpData
  859. )
  860. {
  861. LPITEMIDLIST pidlNavigate;
  862. switch (uMsg)
  863. {
  864. case BFFM_INITIALIZED:
  865. // Check if we should navigate to a folder on initialize
  866. pidlNavigate = (LPITEMIDLIST) lpData;
  867. if (pidlNavigate != NULL)
  868. {
  869. // Yes! We have a folder to navigate to; send the message
  870. SendMessage(hwnd, BFFM_SETSELECTION, (WPARAM) FALSE, (LPARAM) pidlNavigate);
  871. }
  872. EnableOKButton(hwnd, pidlNavigate);
  873. break;
  874. case BFFM_SELCHANGED:
  875. // Check if we should enable/disable the Ok button
  876. pidlNavigate = (LPITEMIDLIST)lParam;
  877. if (pidlNavigate != NULL)
  878. {
  879. EnableOKButton(hwnd, pidlNavigate);
  880. }
  881. }
  882. return 0;
  883. }
  884. // This implementation of 'Browse' uses SHBrowseForFolder to find a file or folder
  885. // for the shortcut wizard - used by BrowseDlgProc
  886. void BrowseForFileOrFolder(LPWIZDATA lpwd)
  887. {
  888. TCHAR szBrowseTitle[256];
  889. TCHAR szName[MAX_PATH];
  890. BROWSEINFO bi = {0};
  891. LPITEMIDLIST pidlSelected;
  892. LPITEMIDLIST pidlStartBrowse;
  893. IShellFolder* pdesktop;
  894. // Try to start the browse at a location indicated by the typed-in command line,
  895. // if possible
  896. GetDlgItemText(lpwd->hwnd, IDC_COMMAND, lpwd->szExeName, ARRAYSIZE(lpwd->szExeName));
  897. // ..Get the desktop folder
  898. if (SUCCEEDED(SHGetDesktopFolder(&pdesktop)))
  899. {
  900. // ..Now try to parse the path the user entered into a pidl to start at
  901. ULONG chEaten;
  902. if (FAILED(pdesktop->lpVtbl->ParseDisplayName(pdesktop, lpwd->hwnd, NULL,
  903. lpwd->szExeName, &chEaten, &pidlStartBrowse, NULL)))
  904. {
  905. // The path the user entered didn't make any sense
  906. // pidlStartBrowse should already be NULL, but we want to make sure
  907. pidlStartBrowse = NULL;
  908. }
  909. // Now we can continue and display the browse window
  910. // Load the title string for the browse window
  911. LoadString(g_hinst, IDS_FILEFOLDERBROWSE_TITLE, szBrowseTitle, ARRAYSIZE(szBrowseTitle));
  912. // Note that bi = {0} for all other members except:
  913. bi.hwndOwner = lpwd->hwnd;
  914. bi.pszDisplayName = szName;
  915. bi.lpszTitle = szBrowseTitle;
  916. bi.ulFlags = BIF_BROWSEINCLUDEFILES | BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
  917. // Ensure the pidl we want to start at is passed to the callback function
  918. bi.lpfn = BrowseCallbackProc;
  919. bi.lParam = (LPARAM) pidlStartBrowse;
  920. pidlSelected = SHBrowseForFolder(&bi);
  921. if (pidlSelected != NULL)
  922. {
  923. STRRET strret;
  924. if (SUCCEEDED(pdesktop->lpVtbl->GetDisplayNameOf(pdesktop, pidlSelected, SHGDN_NORMAL | SHGDN_FORPARSING, &strret)))
  925. {
  926. StrRetToBuf(&strret, pidlSelected, lpwd->szExeName, ARRAYSIZE(lpwd->szExeName));
  927. // Assume no parameters for this new file
  928. lpwd->szParams[0] = 0;
  929. // Populate the text box with the new file, etc.
  930. BrowseSetActive(lpwd);
  931. }
  932. // Free the pidl
  933. ILFree(pidlSelected);
  934. }
  935. if (pidlStartBrowse != NULL)
  936. {
  937. ILFree(pidlStartBrowse);
  938. }
  939. pdesktop->lpVtbl->Release(pdesktop);
  940. }
  941. else
  942. {
  943. // This really shouldn't happen; SHGetDesktopdesktop failed; out of memory?
  944. }
  945. }
  946. //
  947. // Main dialog procedure for first page of shortcut wizard.
  948. //
  949. //
  950. // Note that there are now two BrowseDlgProcs, the one below and
  951. // 'SetupBrowseDlgProc'. This is because BrowseDlgProc now uses
  952. // a different method for implementing the 'Browse' button and I
  953. // wanted to do this without affecting the Setup Wizard which will
  954. // now use SetupBrowseDlgProc. - dsheldon 6/16/98
  955. //
  956. BOOL_PTR CALLBACK BrowseDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
  957. {
  958. NMHDR FAR *lpnm = NULL;
  959. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  960. LPWIZDATA lpwd = NULL;
  961. if (lpPropSheet)
  962. {
  963. lpwd = (LPWIZDATA)lpPropSheet->lParam;
  964. }
  965. switch(message)
  966. {
  967. case WM_NOTIFY:
  968. lpnm = (NMHDR FAR *)lParam;
  969. if(lpnm)
  970. {
  971. switch(lpnm->code)
  972. {
  973. case PSN_SETACTIVE:
  974. if(lpwd)
  975. {
  976. lpwd->hwnd = hDlg;
  977. if (lpwd->dwFlags & WDFLAG_NOBROWSEPAGE)
  978. {
  979. SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  980. }
  981. else
  982. {
  983. BrowseSetActive(lpwd);
  984. }
  985. }
  986. break;
  987. case PSN_WIZNEXT:
  988. if(lpwd)
  989. {
  990. if (!NextPushed(lpwd) ||
  991. ((lpwd->dwFlags & WDFLAG_SETUPWIZ) && !SetupCleanupExePath(lpwd)))
  992. {
  993. SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  994. }
  995. }
  996. break;
  997. case PSN_WIZFINISH:
  998. if(lpwd)
  999. {
  1000. BOOL ForceWx86;
  1001. #ifdef WX86
  1002. ForceWx86 = bWx86Enabled && bForceX86Env;
  1003. #else
  1004. ForceWx86 = FALSE;
  1005. #endif
  1006. if (!SetupCleanupExePath(lpwd) ||
  1007. !ExecSetupProg(lpwd, ForceWx86, TRUE))
  1008. {
  1009. BrowseSetActive(lpwd);
  1010. SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  1011. }
  1012. }
  1013. break;
  1014. case PSN_RESET:
  1015. if(lpwd)
  1016. {
  1017. CleanUpWizData(lpwd);
  1018. }
  1019. break;
  1020. default:
  1021. return FALSE;
  1022. }
  1023. }
  1024. break;
  1025. case WM_INITDIALOG:
  1026. BrowseInitPropSheet(hDlg, lParam);
  1027. break;
  1028. case WMPRIV_POKEFOCUS:
  1029. {
  1030. HWND hCmd = GetDlgItem(hDlg, IDC_COMMAND);
  1031. SetFocus(hCmd);
  1032. Edit_SetSel(hCmd, 0, -1);
  1033. break;
  1034. }
  1035. case WM_DESTROY:
  1036. case WM_HELP:
  1037. case WM_CONTEXTMENU:
  1038. break;
  1039. case WM_COMMAND:
  1040. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1041. {
  1042. case IDHELP:
  1043. break;
  1044. case IDC_COMMAND:
  1045. switch (GET_WM_COMMAND_CMD(wParam, lParam))
  1046. {
  1047. case EN_CHANGE:
  1048. if(lpwd)
  1049. {
  1050. SetBrowseButtons(lpwd);
  1051. }
  1052. break;
  1053. }
  1054. break;
  1055. case IDC_BROWSE:
  1056. if(lpwd)
  1057. {
  1058. BrowseForFileOrFolder(lpwd);
  1059. }
  1060. break;
  1061. } // end of switch on WM_COMMAND
  1062. break;
  1063. default:
  1064. return FALSE;
  1065. } // end of switch on message
  1066. return TRUE;
  1067. } // BrowseDlgProc
  1068. BOOL_PTR CALLBACK SetupBrowseDlgProc(HWND hDlg, UINT message , WPARAM wParam, LPARAM lParam)
  1069. {
  1070. NMHDR FAR *lpnm = NULL;
  1071. LPPROPSHEETPAGE lpPropSheet = (LPPROPSHEETPAGE)(GetWindowLongPtr(hDlg, DWLP_USER));
  1072. LPWIZDATA lpwd = NULL;
  1073. if (lpPropSheet)
  1074. {
  1075. lpwd = (LPWIZDATA)lpPropSheet->lParam;
  1076. }
  1077. switch(message)
  1078. {
  1079. case WM_NOTIFY:
  1080. lpnm = (NMHDR FAR *)lParam;
  1081. if(lpnm)
  1082. {
  1083. switch(lpnm->code)
  1084. {
  1085. BOOL bForceWx86;
  1086. case PSN_SETACTIVE:
  1087. if(lpwd)
  1088. {
  1089. lpwd->hwnd = hDlg;
  1090. if (lpwd->dwFlags & WDFLAG_NOBROWSEPAGE)
  1091. {
  1092. SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  1093. }
  1094. else
  1095. {
  1096. BrowseSetActive(lpwd);
  1097. }
  1098. }
  1099. break;
  1100. case PSN_WIZNEXT:
  1101. if(lpwd)
  1102. {
  1103. // Remember the previous "InstallMode"
  1104. lpwd->bPrevMode = TermsrvAppInstallMode();
  1105. // Set the "InstallMode"
  1106. SetTermsrvAppInstallMode(TRUE);
  1107. #ifdef WX86
  1108. bForceWx86 = bWx86Enabled && bForceX86Env;
  1109. #else
  1110. bForceWx86 = FALSE;
  1111. #endif
  1112. if (!NextPushed(lpwd) || !SetupCleanupExePath(lpwd) ||
  1113. !ExecSetupProg(lpwd, bForceWx86, FALSE))
  1114. {
  1115. SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  1116. }
  1117. }
  1118. break;
  1119. case PSN_WIZFINISH:
  1120. if(lpwd)
  1121. {
  1122. #ifdef WX86
  1123. bForceWx86 = bWx86Enabled && bForceX86Env;
  1124. #else
  1125. bForceWx86 = FALSE;
  1126. #endif
  1127. if (!SetupCleanupExePath(lpwd) ||
  1128. !ExecSetupProg(lpwd, bForceWx86, TRUE))
  1129. {
  1130. BrowseSetActive(lpwd);
  1131. SetDlgMsgResult(hDlg, WM_NOTIFY, -1);
  1132. }
  1133. }
  1134. break;
  1135. case PSN_RESET:
  1136. if(lpwd)
  1137. {
  1138. CleanUpWizData(lpwd);
  1139. }
  1140. break;
  1141. default:
  1142. return FALSE;
  1143. }
  1144. }
  1145. break;
  1146. case WM_INITDIALOG:
  1147. BrowseInitPropSheet(hDlg, lParam);
  1148. break;
  1149. case WMPRIV_POKEFOCUS:
  1150. {
  1151. HWND hCmd = GetDlgItem(hDlg, IDC_COMMAND);
  1152. SetFocus(hCmd);
  1153. Edit_SetSel(hCmd, 0, -1);
  1154. break;
  1155. }
  1156. case WM_DESTROY:
  1157. case WM_HELP:
  1158. case WM_CONTEXTMENU:
  1159. break;
  1160. case WM_COMMAND:
  1161. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1162. {
  1163. case IDHELP:
  1164. break;
  1165. case IDC_COMMAND:
  1166. switch (GET_WM_COMMAND_CMD(wParam, lParam))
  1167. {
  1168. case EN_CHANGE:
  1169. if(lpwd)
  1170. {
  1171. SetBrowseButtons(lpwd);
  1172. }
  1173. break;
  1174. }
  1175. break;
  1176. case IDC_BROWSE:
  1177. if(lpwd)
  1178. {
  1179. BrowsePushed(lpwd);
  1180. }
  1181. break;
  1182. } // end of switch on WM_COMMAND
  1183. break;
  1184. default:
  1185. return FALSE;
  1186. } // end of switch on message
  1187. return TRUE;
  1188. } // SetupBrowseDlgProc