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.

911 lines
24 KiB

  1. //
  2. // APPWIZ.C Application installation wizard CPL
  3. //
  4. // Copyright (C) Microsoft, 1994,1995 All Rights Reserved.
  5. //
  6. // History:
  7. // ral 5/23/94 - First pass
  8. // ral 8/09/94 - Clean up
  9. // 3/20/95 [stevecat] - NT port & real clean up, unicode, etc.
  10. //
  11. //
  12. #include "priv.h"
  13. #include "appwiz.h"
  14. #include <cpl.h>
  15. #include "util.h"
  16. #include "resource.h"
  17. #include <tsappcmp.h> // for TermsrvAppInstallMode
  18. #ifdef WINNT
  19. //
  20. // (tedm) Header files for Setup
  21. //
  22. #include <setupapi.h>
  23. #include <syssetup.h>
  24. #endif
  25. TCHAR const c_szPIF[] = TEXT(".pif");
  26. TCHAR const c_szLNK[] = TEXT(".lnk");
  27. #ifdef WX86
  28. BOOL
  29. IsWx86Enabled(
  30. VOID
  31. )
  32. //
  33. // Consults the registry to determine if Wx86 is enabled in the system
  34. // NOTE: this should be changed post SUR to call kernel32 which maintanes
  35. // this information, Instead of reading the registry each time.
  36. //
  37. {
  38. LONG Error;
  39. HKEY hKey;
  40. WCHAR ValueBuffer[MAX_PATH];
  41. DWORD ValueSize;
  42. DWORD dwType;
  43. Error = RegOpenKeyW(HKEY_LOCAL_MACHINE,
  44. L"System\\CurrentControlSet\\Control\\Wx86",
  45. &hKey
  46. );
  47. if (Error != ERROR_SUCCESS) {
  48. return FALSE;
  49. }
  50. ValueSize = sizeof(ValueBuffer);
  51. Error = RegQueryValueExW(hKey,
  52. L"cmdline",
  53. NULL,
  54. &dwType,
  55. (LPBYTE)ValueBuffer,
  56. &ValueSize
  57. );
  58. RegCloseKey(hKey);
  59. return (Error == ERROR_SUCCESS &&
  60. dwType == REG_SZ &&
  61. ValueSize &&
  62. *ValueBuffer
  63. );
  64. }
  65. #endif
  66. const LPCTSTR g_szStartPages[] = { TEXT("remove"), TEXT("install"), TEXT("configurewindows") };
  67. int ParseStartParams(LPCTSTR pcszStart)
  68. {
  69. int iStartPage = 0;
  70. if (IsInRange(*pcszStart, TEXT('0'), TEXT('9')))
  71. return StrToInt(pcszStart);
  72. if (g_bRunOnNT5)
  73. {
  74. int i;
  75. for (i = 0; i < ARRAYSIZE(g_szStartPages); i++)
  76. {
  77. if (!StrCmpI(g_szStartPages[i], pcszStart))
  78. {
  79. iStartPage = i;
  80. break;
  81. }
  82. }
  83. }
  84. return iStartPage;
  85. }
  86. LONG CALLBACK CPlApplet(HWND hwnd, UINT Msg, LPARAM lParam1, LPARAM lParam2 )
  87. {
  88. UINT nStartPage = MAX_PAGES;
  89. // not currently used by chicago LPNEWCPLINFO lpNewCPlInfo;
  90. LPTSTR lpStartPage;
  91. switch (Msg)
  92. {
  93. case CPL_INIT:
  94. return TRUE;
  95. case CPL_GETCOUNT:
  96. return 1;
  97. case CPL_INQUIRE:
  98. #define lpCPlInfo ((LPCPLINFO)lParam2)
  99. lpCPlInfo->idIcon = IDI_CPLICON;
  100. lpCPlInfo->idName = IDS_NAME;
  101. lpCPlInfo->idInfo = IDS_INFO;
  102. lpCPlInfo->lData = 0;
  103. #undef lpCPlInfo
  104. break;
  105. case CPL_DBLCLK:
  106. #ifndef DOWNLEVEL
  107. OpenAppMgr(hwnd, 0);
  108. #else
  109. InstallCPL(hwnd, 0);
  110. #endif
  111. break;
  112. case CPL_STARTWPARMS:
  113. lpStartPage = (LPTSTR)lParam2;
  114. if (*lpStartPage)
  115. nStartPage = ParseStartParams(lpStartPage);
  116. //
  117. // Make sure that the requested starting page is less than the max page
  118. // for the selected applet.
  119. if (nStartPage >= MAX_PAGES) return FALSE;
  120. #ifndef DOWNLEVEL
  121. OpenAppMgr(hwnd, nStartPage);
  122. #else
  123. InstallCPL(hwnd, nStartPage);
  124. #endif
  125. return TRUE; // return non-zero to indicate message handled
  126. default:
  127. return FALSE;
  128. }
  129. return TRUE;
  130. } // CPlApplet
  131. #ifdef DOWNLEVEL
  132. //
  133. // This is the addpage which gets called back by external components (yay)
  134. //
  135. BOOL CALLBACK _AddExternalPage(HPROPSHEETPAGE hpage, LPARAM lParam)
  136. {
  137. PROPSHEETHEADER FAR * ppsh = (PROPSHEETHEADER FAR *)lParam;
  138. if( hpage && ( ppsh->nPages < MAX_PAGES ) )
  139. {
  140. ppsh->phpage[ppsh->nPages++] = hpage;
  141. return TRUE;
  142. }
  143. return FALSE;
  144. }
  145. #endif // DOWNLEVEL
  146. //
  147. // Adds a page to a property sheet.
  148. //
  149. void AddPage(LPPROPSHEETHEADER ppsh, UINT id, DLGPROC pfn, LPWIZDATA lpwd, DWORD dwPageFlags)
  150. {
  151. if (ppsh->nPages < MAX_PAGES)
  152. {
  153. PROPSHEETPAGE psp;
  154. psp.dwSize = sizeof(psp);
  155. psp.dwFlags = dwPageFlags;
  156. psp.hInstance = g_hinst;
  157. psp.pszTemplate = MAKEINTRESOURCE(id);
  158. psp.pfnDlgProc = pfn;
  159. psp.lParam = (LPARAM)lpwd;
  160. ppsh->phpage[ppsh->nPages] = CreatePropertySheetPage(&psp);
  161. if (ppsh->phpage[ppsh->nPages])
  162. ppsh->nPages++;
  163. }
  164. } // AddPage
  165. #ifdef DOWNLEVEL
  166. //
  167. // Main control panel entry point. Displays a property sheet with
  168. //
  169. void InstallCPL(HWND hwnd, UINT nStartPage)
  170. {
  171. WIZDATA wd;
  172. HPROPSHEETPAGE rPages[MAX_PAGES];
  173. PROPSHEETHEADER psh;
  174. int iPrshtResult;
  175. memset(&wd, 0, sizeof(wd));
  176. //PROPSHEETHEADER_V1_SIZE: needs to run on downlevel platform (NT4, Win95)
  177. psh.dwSize = PROPSHEETHEADER_V1_SIZE;
  178. psh.dwFlags = PSH_PROPTITLE;
  179. psh.hwndParent = hwnd;
  180. psh.hInstance = g_hinst;
  181. psh.pszCaption = MAKEINTRESOURCE(IDS_NAME);
  182. psh.nPages = 0;
  183. psh.nStartPage = nStartPage;
  184. psh.phpage = rPages;
  185. //
  186. // If there's no net install list then we'll decrement the start page
  187. // by 1 so that the tab numbers can remain constant.
  188. //
  189. if (AppListGetInfName(&wd))
  190. {
  191. AddPage(&psh, DLG_APPLIST, AppListDlgProc, &wd, PSP_DEFAULT);
  192. }
  193. else
  194. {
  195. if (psh.nStartPage > 0)
  196. {
  197. psh.nStartPage--;
  198. }
  199. }
  200. AddPage(&psh, DLG_INSTUNINSTALL, InstallUninstallDlgProc, &wd, PSP_DEFAULT);
  201. #ifdef WINNT
  202. //
  203. // (tedm)
  204. //
  205. // Setup on NT is completely different. No calling into 16-bit DLLs, etc.
  206. // Just ask the system setup module for its optional components page.
  207. //
  208. SetupCreateOptionalComponentsPage(_AddExternalPage,(LPARAM)&psh);
  209. #else
  210. // Have (16-bit) SETUPX add the Optional Components page
  211. SHAddPages16( NULL, TEXT("SETUPX.DLL,SUOCPage"), _AddExternalPage,
  212. (LPARAM)&psh );
  213. // Have (16-bit) SETUPX add the Emergency Boot Disk page
  214. SHAddPages16( NULL, TEXT("SETUPX.DLL,SUEBDPage"), _AddExternalPage,
  215. (LPARAM)&psh );
  216. #endif
  217. iPrshtResult = (int)PropertySheet(&psh);
  218. switch(iPrshtResult)
  219. {
  220. case ID_PSRESTARTWINDOWS:
  221. case ID_PSREBOOTSYSTEM:
  222. RestartDialogEx(hwnd, NULL,
  223. iPrshtResult == ID_PSRESTARTWINDOWS ?
  224. EW_RESTARTWINDOWS : EW_REBOOTSYSTEM,
  225. SHTDN_REASON_FLAG_PLANNED |
  226. SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
  227. SHTDN_REASON_MINOR_RECONFIG);
  228. break;
  229. }
  230. }
  231. #endif // DOWNLEVEL
  232. // This function disables auto-run during the add from floppy or CD wizard.
  233. // It is a subclass of the property sheet window.
  234. LRESULT CALLBACK WizParentWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
  235. UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
  236. {
  237. static UINT msgQueryCancelAutoPlay = 0;
  238. if (!msgQueryCancelAutoPlay)
  239. msgQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  240. if (uMsg == msgQueryCancelAutoPlay)
  241. {
  242. return TRUE; // Yes, cancel auto-play when wizard is running
  243. }
  244. else
  245. {
  246. return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  247. }
  248. }
  249. // The following callback is specified when a wizard wants to disable auto-run.
  250. // The callback subclasses the wizard's window, to catch the QueryCancelAutoRun
  251. // message sent by the shell when it wants to auto-run a CD.
  252. int CALLBACK DisableAutoRunCallback(HWND hwnd, UINT uMsg, LPARAM lParam)
  253. {
  254. if (uMsg == PSCB_INITIALIZED)
  255. {
  256. SetWindowSubclass(hwnd, WizParentWindowProc, 0, 0);
  257. }
  258. return 0;
  259. }
  260. //
  261. // Common code used by the Link and Setup wizards to initialize the
  262. // property sheet header and wizard data.
  263. //
  264. void InitWizHeaders(LPPROPSHEETHEADER ppd,
  265. HPROPSHEETPAGE *rPages,
  266. LPWIZDATA lpwd, int iBmpID, DWORD dwFlags)
  267. {
  268. lpwd->hbmpWizard = LoadBitmap(g_hinst, MAKEINTRESOURCE(iBmpID));
  269. //PROPSHEETHEADER_V1_SIZE: needs to run on downlevel platform (NT4, Win95)
  270. ppd->dwSize = PROPSHEETHEADER_V1_SIZE;
  271. ppd->dwFlags = dwFlags;
  272. ppd->hwndParent = lpwd->hwnd;
  273. ppd->hInstance = g_hinst;
  274. ppd->pszCaption = NULL;
  275. ppd->nPages = 0;
  276. ppd->nStartPage = 0;
  277. ppd->phpage = rPages;
  278. if (lpwd->dwFlags & WDFLAG_NOAUTORUN)
  279. {
  280. ppd->dwFlags |= PSH_USECALLBACK;
  281. ppd->pfnCallback = DisableAutoRunCallback;
  282. }
  283. }
  284. //
  285. // Called when a wizard is dismissed. Cleans up any garbage left behind.
  286. //
  287. void FreeWizData(LPWIZDATA lpwd)
  288. {
  289. if (lpwd->hbmpWizard)
  290. {
  291. DeleteObject(lpwd->hbmpWizard);
  292. lpwd->hbmpWizard = NULL;
  293. }
  294. }
  295. typedef struct _WIZPAGE {
  296. int id;
  297. DLGPROC pfn;
  298. } WIZPAGE;
  299. //
  300. // Common code used by the Link Wizard and App Wizard (PIF
  301. // wizard).
  302. //
  303. BOOL DoWizard(LPWIZDATA lpwd, int iIDBitmap, const WIZPAGE *wp, int PageCount,
  304. DWORD dwWizardFlags, DWORD dwPageFlags)
  305. {
  306. HPROPSHEETPAGE rPages[MAX_PAGES];
  307. PROPSHEETHEADER psh;
  308. int i;
  309. HWND hwnd, hwndT;
  310. BOOL bResult = FALSE;
  311. BOOL bChangedIcon = FALSE;
  312. HICON hicoPrev;
  313. if (SUCCEEDED(CoInitialize(NULL)))
  314. {
  315. InitWizHeaders(&psh, rPages, lpwd, iIDBitmap, dwWizardFlags);
  316. for (i = 0; i < PageCount; i++)
  317. {
  318. AddPage(&psh, wp[i].id, wp[i].pfn, lpwd, dwPageFlags);
  319. }
  320. // Walk up the parent/owner chain until we find the master owner.
  321. //
  322. // We need to walk the parent chain because sometimes we are given
  323. // a child window as our lpwd->hwnd. And we need to walk the owner
  324. // chain in order to find the owner whose icon will be used for
  325. // Alt+Tab.
  326. //
  327. // GetParent() returns either the parent or owner. Normally this is
  328. // annoying, but we luck out and it's exactly what we want.
  329. hwnd = lpwd->hwnd;
  330. while ((hwndT = GetParent(hwnd)) != NULL)
  331. {
  332. hwnd = hwndT;
  333. }
  334. // If the master owner isn't visible we can futz his icon without
  335. // screwing up his appearance.
  336. if (!IsWindowVisible(hwnd))
  337. {
  338. HICON hicoNew = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_CPLICON));
  339. hicoPrev = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoNew);
  340. bChangedIcon = TRUE;
  341. }
  342. bResult = (BOOL)PropertySheet(&psh);
  343. FreeWizData(lpwd);
  344. // Clean up our icon now that we're done
  345. if (bChangedIcon)
  346. {
  347. // Put the old icon back
  348. HICON hicoNew = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoPrev);
  349. if (hicoNew)
  350. DestroyIcon(hicoNew);
  351. }
  352. CoUninitialize();
  353. }
  354. return bResult;
  355. }
  356. //
  357. //The same as DoWizard except that it returns FALSE only in case of an error.
  358. //Used by SetupWizard.
  359. //(DoWizard is buggy. In case of an error it may return either 0 or -1 and it
  360. // returns 0 when user hits "Cancel" button)
  361. //
  362. BOOL DoWizard2(LPWIZDATA lpwd, int iIDBitmap, const WIZPAGE *wp, int PageCount,
  363. DWORD dwWizardFlags, DWORD dwPageFlags)
  364. {
  365. HPROPSHEETPAGE rPages[MAX_PAGES];
  366. PROPSHEETHEADER psh;
  367. int i;
  368. HWND hwnd, hwndT;
  369. BOOL bResult = FALSE;
  370. BOOL bChangedIcon = FALSE;
  371. HICON hicoPrev;
  372. //
  373. //No support for modeless dialogs
  374. //
  375. ASSERT(!(dwWizardFlags & PSH_MODELESS));
  376. if(dwWizardFlags & PSH_MODELESS)
  377. {
  378. return FALSE;
  379. }
  380. if (SUCCEEDED(CoInitialize(NULL)))
  381. {
  382. InitWizHeaders(&psh, rPages, lpwd, iIDBitmap, dwWizardFlags);
  383. for (i = 0; i < PageCount; i++)
  384. {
  385. AddPage(&psh, wp[i].id, wp[i].pfn, lpwd, dwPageFlags);
  386. }
  387. // Walk up the parent/owner chain until we find the master owner.
  388. //
  389. // We need to walk the parent chain because sometimes we are given
  390. // a child window as our lpwd->hwnd. And we need to walk the owner
  391. // chain in order to find the owner whose icon will be used for
  392. // Alt+Tab.
  393. //
  394. // GetParent() returns either the parent or owner. Normally this is
  395. // annoying, but we luck out and it's exactly what we want.
  396. hwnd = lpwd->hwnd;
  397. while ((hwndT = GetParent(hwnd)) != NULL)
  398. {
  399. hwnd = hwndT;
  400. }
  401. // If the master owner isn't visible we can futz his icon without
  402. // screwing up his appearance.
  403. if (!IsWindowVisible(hwnd))
  404. {
  405. HICON hicoNew = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_CPLICON));
  406. hicoPrev = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoNew);
  407. bChangedIcon = TRUE;
  408. }
  409. bResult = (PropertySheet(&psh) != -1);
  410. FreeWizData(lpwd);
  411. // Clean up our icon now that we're done
  412. if (bChangedIcon)
  413. {
  414. // Put the old icon back
  415. HICON hicoNew = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoPrev);
  416. if (hicoNew)
  417. DestroyIcon(hicoNew);
  418. }
  419. CoUninitialize();
  420. }
  421. return bResult;
  422. }
  423. //
  424. // Link Wizard
  425. //
  426. BOOL LinkWizard(LPWIZDATA lpwd)
  427. {
  428. BOOL fSuccess;
  429. static const WIZPAGE wp[] = {
  430. {DLG_BROWSE, BrowseDlgProc},
  431. {DLG_PICKFOLDER, PickFolderDlgProc},
  432. {DLG_GETTITLE, GetTitleDlgProc},
  433. {DLG_PICKICON, PickIconDlgProc},
  434. {DLG_WHICHCFG, PickConfigDlgProc},
  435. {DLG_RMOPTIONS, ConfigOptionsDlgProc} };
  436. // Don't set lpwd->hwnd to NULL!
  437. // We must create the link wizard with a parent or you end up with one
  438. // thread displaying two independent top-level windows and things get
  439. // really weird really fast.
  440. fSuccess = DoWizard(lpwd, IDB_SHORTCUTBMP, wp, ARRAYSIZE(wp),
  441. PSH_PROPTITLE | PSH_NOAPPLYNOW | PSH_WIZARD_LITE,
  442. PSP_DEFAULT | PSP_HIDEHEADER);
  443. return fSuccess;
  444. }
  445. BOOL SetupWizard(LPWIZDATA lpwd)
  446. {
  447. // This is what the user normally sees when using the Add/Remove Programs
  448. // control panel.
  449. static const WIZPAGE wp_normal[] = {
  450. {DLG_SETUP, SetupDlgProc},
  451. {DLG_SETUPBROWSE, SetupBrowseDlgProc},
  452. #ifndef DOWNLEVEL
  453. #ifdef WINNT
  454. {DLG_CHGUSRFINISH_PREV, ChgusrFinishPrevDlgProc},
  455. {DLG_CHGUSRFINISH, ChgusrFinishDlgProc}
  456. #endif // WINNT
  457. #endif // DOWNLEVEL
  458. };
  459. // This is the wizard that is used when the user double clicks on a setup
  460. // program and the shell uses us to enter Install Mode if Terminal Server
  461. // is installed.
  462. static const WIZPAGE wp_TSAutoInstall[] = {
  463. #ifndef DOWNLEVEL
  464. #ifdef WINNT
  465. {DLG_CHGUSRFINISH_PREV, ChgusrFinishPrevDlgProc},
  466. {DLG_CHGUSRFINISH, ChgusrFinishDlgProc}
  467. #endif // WINNT
  468. #endif // DOWNLEVEL
  469. };
  470. BOOL fResult;
  471. static const WIZPAGE * pwpToUse = wp_normal;
  472. DWORD dwPages = ARRAYSIZE(wp_normal);
  473. if (WDFLAG_AUTOTSINSTALLUI & lpwd->dwFlags)
  474. {
  475. pwpToUse = wp_TSAutoInstall;
  476. dwPages = ARRAYSIZE(wp_TSAutoInstall);
  477. }
  478. lpwd->dwFlags |= WDFLAG_SETUPWIZ;
  479. if (g_bRunOnNT5)
  480. {
  481. fResult = DoWizard2(lpwd, IDB_INSTALLBMP, pwpToUse, dwPages,
  482. PSH_PROPTITLE | PSH_NOAPPLYNOW | PSH_WIZARD_LITE,
  483. PSP_DEFAULT | PSP_HIDEHEADER);
  484. }
  485. else
  486. {
  487. fResult = DoWizard2(lpwd, IDB_LEGACYINSTALLBMP, pwpToUse, dwPages,
  488. PSH_PROPTITLE | PSH_NOAPPLYNOW | PSH_WIZARD,
  489. PSP_DEFAULT);
  490. }
  491. lpwd->dwFlags &= ~WDFLAG_SETUPWIZ;
  492. return(fResult);
  493. }
  494. STDAPI InstallAppFromFloppyOrCDROMEx(IN HWND hwnd, IN OPTIONAL DWORD dwAdditionalFlags,
  495. IN LPCWSTR lpApplicationName, // name of executable module
  496. IN LPCWSTR lpCommandLine, // command line string
  497. IN LPSECURITY_ATTRIBUTES lpProcessAttributes,
  498. IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
  499. IN BOOL bInheritHandles, // handle inheritance flag
  500. IN DWORD dwCreationFlags, // creation flags
  501. IN LPVOID lpEnvironment, // new environment block
  502. IN LPCWSTR lpCurrentDirectory, // current directory name
  503. IN LPSTARTUPINFOW lpStartupInfo,
  504. IN LPPROCESS_INFORMATION lpProcessInformation)
  505. {
  506. WIZDATA wd = {0};
  507. HRESULT hr = S_OK;
  508. BOOL bModeChanged = FALSE;
  509. wd.hwnd = hwnd;
  510. wd.dwFlags |= (WDFLAG_NOAUTORUN | dwAdditionalFlags);
  511. #ifdef WINNT
  512. if (IsTerminalServicesRunning() && !IsUserAnAdmin())
  513. {
  514. ShellMessageBox(g_hinst, hwnd, MAKEINTRESOURCE(IDS_RESTRICTION),
  515. MAKEINTRESOURCE(IDS_NAME), MB_OK | MB_ICONEXCLAMATION);
  516. return S_FALSE;
  517. }
  518. if (WDFLAG_AUTOTSINSTALLUI & wd.dwFlags)
  519. {
  520. // Remember the previous "InstallMode"
  521. wd.bPrevMode = TermsrvAppInstallMode();
  522. // Set the "InstallMode"
  523. SetTermsrvAppInstallMode(TRUE);
  524. if (!CreateProcessW(lpApplicationName, (LPWSTR)lpCommandLine, lpProcessAttributes, lpThreadAttributes,
  525. bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo,
  526. lpProcessInformation))
  527. {
  528. SetTermsrvAppInstallMode(wd.bPrevMode);
  529. hr = E_FAIL;
  530. }
  531. bModeChanged = TRUE;
  532. }
  533. #endif
  534. if (SUCCEEDED(hr) && !SetupWizard(&wd))
  535. {
  536. if(bModeChanged)
  537. {
  538. //
  539. //SetupWizard that suppose to return system to EXECUTE mode failed.
  540. //make sure that it does not remain in INSTALL mode.
  541. //
  542. SetTermsrvAppInstallMode(wd.bPrevMode);
  543. }
  544. hr = E_FAIL;
  545. }
  546. return hr;
  547. }
  548. STDAPI InstallAppFromFloppyOrCDROM(HWND hwnd)
  549. {
  550. return InstallAppFromFloppyOrCDROMEx(hwnd, 0, NULL, NULL, NULL, NULL, FALSE, 0, NULL, NULL, NULL, NULL);
  551. }
  552. //
  553. //
  554. //
  555. BOOL MSDOSPropOnlyWizard(LPWIZDATA lpwd)
  556. {
  557. static const WIZPAGE wp[] = { {DLG_RMOPTIONS, ConfigOptionsDlgProc} };
  558. lpwd->dwFlags |= WDFLAG_PIFPROP;
  559. return DoWizard(lpwd, IDB_DOSCONFIG, wp, ARRAYSIZE(wp), PSH_PROPTITLE | PSH_WIZARD,
  560. PSP_DEFAULT);
  561. }
  562. //
  563. // RUNDLL entry point to create a new link. An empty file has already been
  564. // created and is the only parameter passed in lpszCmdLine.
  565. //
  566. // hAppInstance is never used.
  567. void WINAPI NewLinkHere_Common(HWND hwnd, HINSTANCE hAppInstance, LPTSTR lpszCmdLine, int nCmdShow)
  568. {
  569. WIZDATA wd;
  570. TCHAR szFolder[MAX_PATH];
  571. memset(&wd, 0, sizeof(wd));
  572. wd.hwnd = hwnd;
  573. wd.dwFlags |= WDFLAG_LINKHEREWIZ | WDFLAG_DONTOPENFLDR;
  574. wd.lpszOriginalName = lpszCmdLine;
  575. lstrcpyn(szFolder, lpszCmdLine, ARRAYSIZE(szFolder));
  576. PathRemoveFileSpec(szFolder);
  577. wd.lpszFolder = szFolder;
  578. //
  579. // If the filename passed in is not valid then we'll just silently fail.
  580. //
  581. if (PathFileExists(lpszCmdLine))
  582. {
  583. if (!LinkWizard(&wd))
  584. {
  585. DeleteFile(lpszCmdLine);
  586. }
  587. }
  588. else
  589. {
  590. #define lpwd (&wd)
  591. TraceMsg(TF_ERROR, "%s", "APPWIZ ERORR: Bogus file name passed to NewLinkHere");
  592. TraceMsg(TF_ERROR, "%s", lpszCmdLine);
  593. #undef lpwd
  594. }
  595. }
  596. void WINAPI NewLinkHere(HWND hwndStub, HINSTANCE hAppInstance, LPSTR lpszCmdLine, int nCmdShow)
  597. {
  598. #ifdef UNICODE
  599. UINT iLen = lstrlenA(lpszCmdLine)+1;
  600. LPWSTR lpwszCmdLine;
  601. lpwszCmdLine = (LPWSTR)LocalAlloc(LPTR,iLen*SIZEOF(WCHAR));
  602. if (lpwszCmdLine)
  603. {
  604. MultiByteToWideChar(CP_ACP, 0,
  605. lpszCmdLine, -1,
  606. lpwszCmdLine, iLen);
  607. NewLinkHere_Common( hwndStub,
  608. hAppInstance,
  609. lpwszCmdLine,
  610. nCmdShow );
  611. LocalFree(lpwszCmdLine);
  612. }
  613. #else
  614. NewLinkHere_Common( hwndStub,
  615. hAppInstance,
  616. lpszCmdLine,
  617. nCmdShow );
  618. #endif
  619. }
  620. void WINAPI NewLinkHereW(HWND hwndStub, HINSTANCE hAppInstance, LPWSTR lpwszCmdLine, int nCmdShow)
  621. {
  622. #ifdef UNICODE
  623. NewLinkHere_Common( hwndStub,
  624. hAppInstance,
  625. lpwszCmdLine,
  626. nCmdShow );
  627. #else
  628. UINT iLen = WideCharToMultiByte(CP_ACP, 0,
  629. lpwszCmdLine, -1,
  630. NULL, 0, NULL, NULL)+1;
  631. LPSTR lpszCmdLine;
  632. lpszCmdLine = (LPSTR)LocalAlloc(LPTR,iLen);
  633. if (lpszCmdLine)
  634. {
  635. WideCharToMultiByte(CP_ACP, 0,
  636. lpwszCmdLine, -1,
  637. lpszCmdLine, iLen,
  638. NULL, NULL);
  639. NewLinkHere_Common( hwndStub,
  640. hAppInstance,
  641. lpszCmdLine,
  642. nCmdShow );
  643. LocalFree(lpszCmdLine);
  644. }
  645. #endif
  646. }
  647. //
  648. // Entry point called from PIFMGR.DLL. We'll only display the MS-DOS options
  649. // page for the specified hProps.
  650. //
  651. // NOTE: In this instance we want to LocalAlloc the wizard data since
  652. // we're being called from a 16-bit application (with limited stack).
  653. // Note that LPTR zero-initializes the block.
  654. //
  655. PIFWIZERR WINAPI AppWizard(HWND hwnd, HANDLE hProps, UINT dwAction)
  656. {
  657. LPWIZDATA lpwd = (LPWIZDATA)LocalAlloc(LPTR, sizeof(WIZDATA));
  658. PIFWIZERR err = PIFWIZERR_SUCCESS;
  659. if (!lpwd)
  660. {
  661. return(PIFWIZERR_OUTOFMEM);
  662. }
  663. lpwd->hProps = hProps;
  664. lpwd->hwnd = hwnd;
  665. switch (dwAction)
  666. {
  667. case WIZACTION_UICONFIGPROP:
  668. if (!MSDOSPropOnlyWizard(lpwd))
  669. {
  670. err = PIFWIZERR_USERCANCELED;
  671. }
  672. break;
  673. case WIZACTION_SILENTCONFIGPROP:
  674. err = ConfigRealModeOptions(lpwd, NULL, CRMOACTION_DEFAULT);
  675. break;
  676. case WIZACTION_CREATEDEFCLEANCFG:
  677. err = ConfigRealModeOptions(lpwd, NULL, CRMOACTION_CLEAN);
  678. break;
  679. default:
  680. err = PIFWIZERR_INVALIDPARAM;
  681. }
  682. LocalFree((LPVOID)lpwd);
  683. return(err);
  684. }
  685. //
  686. // Called directly by Cabinet
  687. //
  688. BOOL ConfigStartMenu(HWND hwnd, BOOL bDelete)
  689. {
  690. if (bDelete)
  691. {
  692. return(RemoveItemsDialog(hwnd));
  693. }
  694. else
  695. {
  696. WIZDATA wd;
  697. memset(&wd, 0, sizeof(wd));
  698. wd.hwnd = hwnd;
  699. wd.dwFlags |= WDFLAG_DONTOPENFLDR;
  700. return(LinkWizard(&wd));
  701. }
  702. }
  703. //
  704. // This is a generic function that all the app wizard sheets call
  705. // to do basic initialization.
  706. //
  707. LPWIZDATA InitWizSheet(HWND hDlg, LPARAM lParam, DWORD dwFlags)
  708. {
  709. LPPROPSHEETPAGE ppd = (LPPROPSHEETPAGE)lParam;
  710. LPWIZDATA lpwd = (LPWIZDATA)ppd->lParam;
  711. HWND hBmp = GetDlgItem(hDlg, IDC_WIZBMP);
  712. lpwd->hwnd = hDlg;
  713. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  714. SendMessage(hBmp, STM_SETIMAGE,
  715. IMAGE_BITMAP, (LPARAM)lpwd->hbmpWizard);
  716. return(lpwd);
  717. }
  718. void CleanUpWizData(LPWIZDATA lpwd)
  719. {
  720. //
  721. // Release any INewShortcutHook.
  722. //
  723. if (lpwd->pnshhk)
  724. {
  725. lpwd->pnshhk->lpVtbl->Release(lpwd->pnshhk);
  726. lpwd->pnshhk = NULL;
  727. }
  728. return;
  729. }
  730. HRESULT InstallOnTerminalServerWithUI(IN HWND hwnd, IN LPCWSTR lpApplicationName, // name of executable module
  731. IN LPCWSTR lpCommandLine, // command line string
  732. IN LPSECURITY_ATTRIBUTES lpProcessAttributes,
  733. IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
  734. IN BOOL bInheritHandles, // handle inheritance flag
  735. IN DWORD dwCreationFlags, // creation flags
  736. IN LPVOID lpEnvironment, // new environment block
  737. IN LPCWSTR lpCurrentDirectory, // current directory name
  738. IN LPSTARTUPINFOW lpStartupInfo,
  739. IN LPPROCESS_INFORMATION lpProcessInformation)
  740. {
  741. return InstallAppFromFloppyOrCDROMEx(hwnd, WDFLAG_AUTOTSINSTALLUI, lpApplicationName, lpCommandLine, lpProcessAttributes,
  742. lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
  743. lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
  744. }