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.

699 lines
19 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. //
  19. // (tedm) Header files for Setup
  20. //
  21. #include <setupapi.h>
  22. #include <syssetup.h>
  23. TCHAR const c_szPIF[] = TEXT(".pif");
  24. TCHAR const c_szLNK[] = TEXT(".lnk");
  25. #ifdef WX86
  26. BOOL
  27. IsWx86Enabled(
  28. VOID
  29. )
  30. //
  31. // Consults the registry to determine if Wx86 is enabled in the system
  32. // NOTE: this should be changed post SUR to call kernel32 which maintanes
  33. // this information, Instead of reading the registry each time.
  34. //
  35. {
  36. LONG Error;
  37. HKEY hKey;
  38. WCHAR ValueBuffer[MAX_PATH];
  39. DWORD ValueSize;
  40. DWORD dwType;
  41. Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  42. L"System\\CurrentControlSet\\Control\\Wx86",
  43. 0, KEY_READ,
  44. &hKey
  45. );
  46. if (Error != ERROR_SUCCESS) {
  47. return FALSE;
  48. }
  49. ValueSize = sizeof(ValueBuffer);
  50. Error = RegQueryValueExW(hKey,
  51. L"cmdline",
  52. NULL,
  53. &dwType,
  54. (LPBYTE)ValueBuffer,
  55. &ValueSize
  56. );
  57. RegCloseKey(hKey);
  58. return (Error == ERROR_SUCCESS &&
  59. dwType == REG_SZ &&
  60. ValueSize &&
  61. *ValueBuffer
  62. );
  63. }
  64. #endif
  65. const LPCTSTR g_szStartPages[] = { TEXT("remove"), TEXT("install"), TEXT("configurewindows") };
  66. int ParseStartParams(LPCTSTR pcszStart)
  67. {
  68. int iStartPage = 0;
  69. if (IsInRange(*pcszStart, TEXT('0'), TEXT('9')))
  70. return StrToInt(pcszStart);
  71. if (g_bRunOnNT5)
  72. {
  73. int i;
  74. for (i = 0; i < ARRAYSIZE(g_szStartPages); i++)
  75. {
  76. if (!StrCmpI(g_szStartPages[i], pcszStart))
  77. {
  78. iStartPage = i;
  79. break;
  80. }
  81. }
  82. }
  83. return iStartPage;
  84. }
  85. LONG CALLBACK CPlApplet(HWND hwnd, UINT Msg, LPARAM lParam1, LPARAM lParam2 )
  86. {
  87. UINT nStartPage = MAX_PAGES;
  88. // not currently used by chicago LPNEWCPLINFO lpNewCPlInfo;
  89. LPTSTR lpStartPage;
  90. switch (Msg)
  91. {
  92. case CPL_INIT:
  93. return TRUE;
  94. case CPL_GETCOUNT:
  95. return 1;
  96. case CPL_INQUIRE:
  97. #define lpCPlInfo ((LPCPLINFO)lParam2)
  98. lpCPlInfo->idIcon = IDI_CPLICON;
  99. lpCPlInfo->idName = IDS_NAME;
  100. lpCPlInfo->idInfo = IDS_INFO;
  101. lpCPlInfo->lData = 0;
  102. #undef lpCPlInfo
  103. break;
  104. case CPL_DBLCLK:
  105. OpenAppMgr(hwnd, 0);
  106. break;
  107. case CPL_STARTWPARMS:
  108. lpStartPage = (LPTSTR)lParam2;
  109. if (*lpStartPage)
  110. nStartPage = ParseStartParams(lpStartPage);
  111. //
  112. // Make sure that the requested starting page is less than the max page
  113. // for the selected applet.
  114. if (nStartPage >= MAX_PAGES) return FALSE;
  115. OpenAppMgr(hwnd, nStartPage);
  116. return TRUE; // return non-zero to indicate message handled
  117. default:
  118. return FALSE;
  119. }
  120. return TRUE;
  121. } // CPlApplet
  122. //
  123. // Adds a page to a property sheet.
  124. //
  125. void AddPage(LPPROPSHEETHEADER ppsh, UINT id, DLGPROC pfn, LPWIZDATA lpwd, DWORD dwPageFlags)
  126. {
  127. if (ppsh->nPages < MAX_PAGES)
  128. {
  129. PROPSHEETPAGE psp;
  130. psp.dwSize = sizeof(psp);
  131. psp.dwFlags = dwPageFlags;
  132. psp.hInstance = g_hinst;
  133. psp.pszTemplate = MAKEINTRESOURCE(id);
  134. psp.pfnDlgProc = pfn;
  135. psp.lParam = (LPARAM)lpwd;
  136. ppsh->phpage[ppsh->nPages] = CreatePropertySheetPage(&psp);
  137. if (ppsh->phpage[ppsh->nPages])
  138. ppsh->nPages++;
  139. }
  140. } // AddPage
  141. // This function disables auto-run during the add from floppy or CD wizard.
  142. // It is a subclass of the property sheet window.
  143. LRESULT CALLBACK WizParentWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
  144. UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
  145. {
  146. static UINT msgQueryCancelAutoPlay = 0;
  147. if (!msgQueryCancelAutoPlay)
  148. msgQueryCancelAutoPlay = RegisterWindowMessage(TEXT("QueryCancelAutoPlay"));
  149. if (uMsg == msgQueryCancelAutoPlay)
  150. {
  151. return TRUE; // Yes, cancel auto-play when wizard is running
  152. }
  153. else
  154. {
  155. return DefSubclassProc(hwnd, uMsg, wParam, lParam);
  156. }
  157. }
  158. // The following callback is specified when a wizard wants to disable auto-run.
  159. // The callback subclasses the wizard's window, to catch the QueryCancelAutoRun
  160. // message sent by the shell when it wants to auto-run a CD.
  161. int CALLBACK DisableAutoRunCallback(HWND hwnd, UINT uMsg, LPARAM lParam)
  162. {
  163. if (uMsg == PSCB_INITIALIZED)
  164. {
  165. SetWindowSubclass(hwnd, WizParentWindowProc, 0, 0);
  166. }
  167. return 0;
  168. }
  169. //
  170. // Common code used by the Link and Setup wizards to initialize the
  171. // property sheet header and wizard data.
  172. //
  173. void InitWizHeaders(LPPROPSHEETHEADER ppd,
  174. HPROPSHEETPAGE *rPages,
  175. LPWIZDATA lpwd, int iBmpID, DWORD dwFlags)
  176. {
  177. lpwd->hbmpWizard = LoadBitmap(g_hinst, MAKEINTRESOURCE(iBmpID));
  178. //PROPSHEETHEADER_V1_SIZE: needs to run on downlevel platform (NT4, Win95)
  179. ppd->dwSize = PROPSHEETHEADER_V1_SIZE;
  180. ppd->dwFlags = dwFlags;
  181. ppd->hwndParent = lpwd->hwnd;
  182. ppd->hInstance = g_hinst;
  183. ppd->pszCaption = NULL;
  184. ppd->nPages = 0;
  185. ppd->nStartPage = 0;
  186. ppd->phpage = rPages;
  187. if (lpwd->dwFlags & WDFLAG_NOAUTORUN)
  188. {
  189. ppd->dwFlags |= PSH_USECALLBACK;
  190. ppd->pfnCallback = DisableAutoRunCallback;
  191. }
  192. }
  193. //
  194. // Called when a wizard is dismissed. Cleans up any garbage left behind.
  195. //
  196. void FreeWizData(LPWIZDATA lpwd)
  197. {
  198. if (lpwd->hbmpWizard)
  199. {
  200. DeleteObject(lpwd->hbmpWizard);
  201. lpwd->hbmpWizard = NULL;
  202. }
  203. }
  204. typedef struct _WIZPAGE {
  205. int id;
  206. DLGPROC pfn;
  207. } WIZPAGE;
  208. //
  209. // Common code used by the Link Wizard and App Wizard (PIF
  210. // wizard).
  211. //
  212. BOOL DoWizard(LPWIZDATA lpwd, int iIDBitmap, const WIZPAGE *wp, int PageCount,
  213. DWORD dwWizardFlags, DWORD dwPageFlags)
  214. {
  215. HPROPSHEETPAGE rPages[MAX_PAGES];
  216. PROPSHEETHEADER psh;
  217. int i;
  218. HWND hwnd, hwndT;
  219. BOOL bResult = FALSE;
  220. BOOL bChangedIcon = FALSE;
  221. HICON hicoPrev;
  222. if (SUCCEEDED(CoInitialize(NULL)))
  223. {
  224. InitWizHeaders(&psh, rPages, lpwd, iIDBitmap, dwWizardFlags);
  225. for (i = 0; i < PageCount; i++)
  226. {
  227. AddPage(&psh, wp[i].id, wp[i].pfn, lpwd, dwPageFlags);
  228. }
  229. // Walk up the parent/owner chain until we find the master owner.
  230. //
  231. // We need to walk the parent chain because sometimes we are given
  232. // a child window as our lpwd->hwnd. And we need to walk the owner
  233. // chain in order to find the owner whose icon will be used for
  234. // Alt+Tab.
  235. //
  236. // GetParent() returns either the parent or owner. Normally this is
  237. // annoying, but we luck out and it's exactly what we want.
  238. hwnd = lpwd->hwnd;
  239. while ((hwndT = GetParent(hwnd)) != NULL)
  240. {
  241. hwnd = hwndT;
  242. }
  243. // If the master owner isn't visible we can futz his icon without
  244. // screwing up his appearance.
  245. if (!IsWindowVisible(hwnd))
  246. {
  247. HICON hicoNew = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_CPLICON));
  248. hicoPrev = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoNew);
  249. bChangedIcon = TRUE;
  250. }
  251. bResult = (BOOL)PropertySheet(&psh);
  252. FreeWizData(lpwd);
  253. // Clean up our icon now that we're done
  254. if (bChangedIcon)
  255. {
  256. // Put the old icon back
  257. HICON hicoNew = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoPrev);
  258. if (hicoNew)
  259. DestroyIcon(hicoNew);
  260. }
  261. CoUninitialize();
  262. }
  263. return bResult;
  264. }
  265. //
  266. //The same as DoWizard except that it returns FALSE only in case of an error.
  267. //Used by SetupWizard.
  268. //(DoWizard is buggy. In case of an error it may return either 0 or -1 and it
  269. // returns 0 when user hits "Cancel" button)
  270. //
  271. BOOL DoWizard2(LPWIZDATA lpwd, int iIDBitmap, const WIZPAGE *wp, int PageCount,
  272. DWORD dwWizardFlags, DWORD dwPageFlags)
  273. {
  274. HPROPSHEETPAGE rPages[MAX_PAGES];
  275. PROPSHEETHEADER psh;
  276. int i;
  277. HWND hwnd, hwndT;
  278. BOOL bResult = FALSE;
  279. BOOL bChangedIcon = FALSE;
  280. HICON hicoPrev;
  281. //
  282. //No support for modeless dialogs
  283. //
  284. ASSERT(!(dwWizardFlags & PSH_MODELESS));
  285. if(dwWizardFlags & PSH_MODELESS)
  286. {
  287. return FALSE;
  288. }
  289. if (SUCCEEDED(CoInitialize(NULL)))
  290. {
  291. InitWizHeaders(&psh, rPages, lpwd, iIDBitmap, dwWizardFlags);
  292. for (i = 0; i < PageCount; i++)
  293. {
  294. AddPage(&psh, wp[i].id, wp[i].pfn, lpwd, dwPageFlags);
  295. }
  296. // Walk up the parent/owner chain until we find the master owner.
  297. //
  298. // We need to walk the parent chain because sometimes we are given
  299. // a child window as our lpwd->hwnd. And we need to walk the owner
  300. // chain in order to find the owner whose icon will be used for
  301. // Alt+Tab.
  302. //
  303. // GetParent() returns either the parent or owner. Normally this is
  304. // annoying, but we luck out and it's exactly what we want.
  305. hwnd = lpwd->hwnd;
  306. while ((hwndT = GetParent(hwnd)) != NULL)
  307. {
  308. hwnd = hwndT;
  309. }
  310. // If the master owner isn't visible we can futz his icon without
  311. // screwing up his appearance.
  312. if (!IsWindowVisible(hwnd))
  313. {
  314. HICON hicoNew = LoadIcon(g_hinst, MAKEINTRESOURCE(IDI_CPLICON));
  315. hicoPrev = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoNew);
  316. bChangedIcon = TRUE;
  317. }
  318. bResult = (PropertySheet(&psh) != -1);
  319. FreeWizData(lpwd);
  320. // Clean up our icon now that we're done
  321. if (bChangedIcon)
  322. {
  323. // Put the old icon back
  324. HICON hicoNew = (HICON)SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicoPrev);
  325. if (hicoNew)
  326. DestroyIcon(hicoNew);
  327. }
  328. CoUninitialize();
  329. }
  330. return bResult;
  331. }
  332. //
  333. // Link Wizard
  334. //
  335. BOOL LinkWizard(LPWIZDATA lpwd)
  336. {
  337. BOOL fSuccess;
  338. static const WIZPAGE wp[] = {
  339. {DLG_BROWSE, BrowseDlgProc},
  340. {DLG_PICKFOLDER, PickFolderDlgProc},
  341. {DLG_GETTITLE, GetTitleDlgProc},
  342. {DLG_PICKICON, PickIconDlgProc} };
  343. // Don't set lpwd->hwnd to NULL!
  344. // We must create the link wizard with a parent or you end up with one
  345. // thread displaying two independent top-level windows and things get
  346. // really weird really fast.
  347. fSuccess = DoWizard(lpwd, IDB_SHORTCUTBMP, wp, ARRAYSIZE(wp),
  348. PSH_PROPTITLE | PSH_NOAPPLYNOW | PSH_WIZARD_LITE,
  349. PSP_DEFAULT | PSP_HIDEHEADER);
  350. return fSuccess;
  351. }
  352. BOOL SetupWizard(LPWIZDATA lpwd)
  353. {
  354. // This is what the user normally sees when using the Add/Remove Programs
  355. // control panel.
  356. static const WIZPAGE wp_normal[] = {
  357. {DLG_SETUP, SetupDlgProc},
  358. {DLG_SETUPBROWSE, SetupBrowseDlgProc},
  359. {DLG_CHGUSRFINISH_PREV, ChgusrFinishPrevDlgProc},
  360. {DLG_CHGUSRFINISH, ChgusrFinishDlgProc}
  361. };
  362. // This is the wizard that is used when the user double clicks on a setup
  363. // program and the shell uses us to enter Install Mode if Terminal Server
  364. // is installed.
  365. static const WIZPAGE wp_TSAutoInstall[] = {
  366. {DLG_CHGUSRFINISH_PREV, ChgusrFinishPrevDlgProc},
  367. {DLG_CHGUSRFINISH, ChgusrFinishDlgProc}
  368. };
  369. BOOL fResult;
  370. static const WIZPAGE * pwpToUse = wp_normal;
  371. DWORD dwPages = ARRAYSIZE(wp_normal);
  372. if (WDFLAG_AUTOTSINSTALLUI & lpwd->dwFlags)
  373. {
  374. pwpToUse = wp_TSAutoInstall;
  375. dwPages = ARRAYSIZE(wp_TSAutoInstall);
  376. }
  377. lpwd->dwFlags |= WDFLAG_SETUPWIZ;
  378. if (g_bRunOnNT5)
  379. {
  380. fResult = DoWizard2(lpwd, IDB_INSTALLBMP, pwpToUse, dwPages,
  381. PSH_PROPTITLE | PSH_NOAPPLYNOW | PSH_WIZARD_LITE,
  382. PSP_DEFAULT | PSP_HIDEHEADER);
  383. }
  384. else
  385. {
  386. fResult = DoWizard2(lpwd, IDB_LEGACYINSTALLBMP, pwpToUse, dwPages,
  387. PSH_PROPTITLE | PSH_NOAPPLYNOW | PSH_WIZARD,
  388. PSP_DEFAULT);
  389. }
  390. lpwd->dwFlags &= ~WDFLAG_SETUPWIZ;
  391. return(fResult);
  392. }
  393. STDAPI InstallAppFromFloppyOrCDROMEx(IN HWND hwnd, IN OPTIONAL DWORD dwAdditionalFlags,
  394. IN LPCWSTR lpApplicationName, // name of executable module
  395. IN LPCWSTR lpCommandLine, // command line string
  396. IN LPSECURITY_ATTRIBUTES lpProcessAttributes,
  397. IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
  398. IN BOOL bInheritHandles, // handle inheritance flag
  399. IN DWORD dwCreationFlags, // creation flags
  400. IN LPVOID lpEnvironment, // new environment block
  401. IN LPCWSTR lpCurrentDirectory, // current directory name
  402. IN LPSTARTUPINFOW lpStartupInfo,
  403. IN LPPROCESS_INFORMATION lpProcessInformation)
  404. {
  405. WIZDATA wd = {0};
  406. HRESULT hr = S_OK;
  407. BOOL bModeChanged = FALSE;
  408. wd.hwnd = hwnd;
  409. wd.dwFlags |= (WDFLAG_NOAUTORUN | dwAdditionalFlags);
  410. if (IsTerminalServicesRunning() && !IsUserAnAdmin())
  411. {
  412. ShellMessageBox(g_hinst, hwnd, MAKEINTRESOURCE(IDS_RESTRICTION),
  413. MAKEINTRESOURCE(IDS_NAME), MB_OK | MB_ICONEXCLAMATION);
  414. return S_FALSE;
  415. }
  416. if (WDFLAG_AUTOTSINSTALLUI & wd.dwFlags)
  417. {
  418. // Remember the previous "InstallMode"
  419. wd.bPrevMode = TermsrvAppInstallMode();
  420. // Set the "InstallMode"
  421. SetTermsrvAppInstallMode(TRUE);
  422. if (!CreateProcessW(lpApplicationName, (LPWSTR)lpCommandLine, lpProcessAttributes, lpThreadAttributes,
  423. bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo,
  424. lpProcessInformation))
  425. {
  426. SetTermsrvAppInstallMode(wd.bPrevMode);
  427. hr = E_FAIL;
  428. }
  429. bModeChanged = TRUE;
  430. }
  431. if (SUCCEEDED(hr) && !SetupWizard(&wd))
  432. {
  433. if(bModeChanged)
  434. {
  435. //
  436. //SetupWizard that suppose to return system to EXECUTE mode failed.
  437. //make sure that it does not remain in INSTALL mode.
  438. //
  439. SetTermsrvAppInstallMode(wd.bPrevMode);
  440. }
  441. hr = E_FAIL;
  442. }
  443. return hr;
  444. }
  445. STDAPI InstallAppFromFloppyOrCDROM(HWND hwnd)
  446. {
  447. return InstallAppFromFloppyOrCDROMEx(hwnd, 0, NULL, NULL, NULL, NULL, FALSE, 0, NULL, NULL, NULL, NULL);
  448. }
  449. //
  450. //
  451. // RUNDLL entry point to create a new link. An empty file has already been
  452. // created and is the only parameter passed in lpszCmdLine.
  453. //
  454. // hAppInstance is never used.
  455. void WINAPI NewLinkHere_Common(HWND hwnd, HINSTANCE hAppInstance, LPTSTR lpszCmdLine, int nCmdShow)
  456. {
  457. WIZDATA wd;
  458. TCHAR szFolder[MAX_PATH];
  459. memset(&wd, 0, sizeof(wd));
  460. wd.hwnd = hwnd;
  461. wd.dwFlags |= WDFLAG_LINKHEREWIZ | WDFLAG_DONTOPENFLDR;
  462. wd.lpszOriginalName = lpszCmdLine;
  463. lstrcpyn(szFolder, lpszCmdLine, ARRAYSIZE(szFolder));
  464. PathRemoveFileSpec(szFolder);
  465. wd.lpszFolder = szFolder;
  466. //
  467. // If the filename passed in is not valid then we'll just silently fail.
  468. //
  469. if (PathFileExists(lpszCmdLine))
  470. {
  471. if (!LinkWizard(&wd))
  472. {
  473. DeleteFile(lpszCmdLine);
  474. }
  475. }
  476. else
  477. {
  478. #define lpwd (&wd)
  479. TraceMsg(TF_ERROR, "%s", "APPWIZ ERORR: Bogus file name passed to NewLinkHere");
  480. TraceMsg(TF_ERROR, "%s", lpszCmdLine);
  481. #undef lpwd
  482. }
  483. }
  484. void WINAPI NewLinkHere(HWND hwndStub, HINSTANCE hAppInstance, LPSTR lpszCmdLine, int nCmdShow)
  485. {
  486. UINT iLen = lstrlenA(lpszCmdLine)+1;
  487. LPWSTR lpwszCmdLine;
  488. lpwszCmdLine = (LPWSTR)LocalAlloc(LPTR,iLen*SIZEOF(WCHAR));
  489. if (lpwszCmdLine)
  490. {
  491. MultiByteToWideChar(CP_ACP, 0,
  492. lpszCmdLine, -1,
  493. lpwszCmdLine, iLen);
  494. NewLinkHere_Common( hwndStub,
  495. hAppInstance,
  496. lpwszCmdLine,
  497. nCmdShow );
  498. LocalFree(lpwszCmdLine);
  499. }
  500. }
  501. void WINAPI NewLinkHereW(HWND hwndStub, HINSTANCE hAppInstance, LPWSTR lpwszCmdLine, int nCmdShow)
  502. {
  503. NewLinkHere_Common( hwndStub,
  504. hAppInstance,
  505. lpwszCmdLine,
  506. nCmdShow );
  507. }
  508. //
  509. // Called directly by Cabinet
  510. //
  511. BOOL ConfigStartMenu(HWND hwnd, BOOL bDelete)
  512. {
  513. if (bDelete)
  514. {
  515. return(RemoveItemsDialog(hwnd));
  516. }
  517. else
  518. {
  519. WIZDATA wd;
  520. memset(&wd, 0, sizeof(wd));
  521. wd.hwnd = hwnd;
  522. wd.dwFlags |= WDFLAG_DONTOPENFLDR;
  523. return(LinkWizard(&wd));
  524. }
  525. }
  526. //
  527. // This is a generic function that all the app wizard sheets call
  528. // to do basic initialization.
  529. //
  530. LPWIZDATA InitWizSheet(HWND hDlg, LPARAM lParam, DWORD dwFlags)
  531. {
  532. LPPROPSHEETPAGE ppd = (LPPROPSHEETPAGE)lParam;
  533. LPWIZDATA lpwd = (LPWIZDATA)ppd->lParam;
  534. HWND hBmp = GetDlgItem(hDlg, IDC_WIZBMP);
  535. lpwd->hwnd = hDlg;
  536. SetWindowLongPtr(hDlg, DWLP_USER, lParam);
  537. SendMessage(hBmp, STM_SETIMAGE,
  538. IMAGE_BITMAP, (LPARAM)lpwd->hbmpWizard);
  539. return(lpwd);
  540. }
  541. void CleanUpWizData(LPWIZDATA lpwd)
  542. {
  543. //
  544. // Release any INewShortcutHook.
  545. //
  546. if (lpwd->pnshhk)
  547. {
  548. lpwd->pnshhk->lpVtbl->Release(lpwd->pnshhk);
  549. lpwd->pnshhk = NULL;
  550. }
  551. return;
  552. }
  553. HRESULT InstallOnTerminalServerWithUI(IN HWND hwnd, IN LPCWSTR lpApplicationName, // name of executable module
  554. IN LPCWSTR lpCommandLine, // command line string
  555. IN LPSECURITY_ATTRIBUTES lpProcessAttributes,
  556. IN LPSECURITY_ATTRIBUTES lpThreadAttributes,
  557. IN BOOL bInheritHandles, // handle inheritance flag
  558. IN DWORD dwCreationFlags, // creation flags
  559. IN LPVOID lpEnvironment, // new environment block
  560. IN LPCWSTR lpCurrentDirectory, // current directory name
  561. IN LPSTARTUPINFOW lpStartupInfo,
  562. IN LPPROCESS_INFORMATION lpProcessInformation)
  563. {
  564. return InstallAppFromFloppyOrCDROMEx(hwnd, WDFLAG_AUTOTSINSTALLUI, lpApplicationName, lpCommandLine, lpProcessAttributes,
  565. lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment,
  566. lpCurrentDirectory, lpStartupInfo, lpProcessInformation);
  567. }