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.

642 lines
20 KiB

  1. #include "setupp.h"
  2. #pragma hdrstop
  3. #if 0 // This function appears to never be used.
  4. BOOL
  5. EnqueueFileCopies(
  6. IN HINF hInf,
  7. IN HSPFILEQ FileQ,
  8. IN PCWSTR Section,
  9. IN PCWSTR TargetRoot
  10. )
  11. {
  12. INFCONTEXT InfContext;
  13. BOOL LineExists;
  14. WCHAR System32Dir[MAX_PATH];
  15. PCWSTR SourceFilename,TargetFilename;
  16. BOOL b;
  17. GetSystemDirectory(System32Dir,MAX_PATH);
  18. LineExists = SetupFindFirstLine(hInf,Section,NULL,&InfContext);
  19. while(LineExists) {
  20. //
  21. // Fetch source and target filenames.
  22. //
  23. TargetFilename = pSetupGetField(&InfContext,1);
  24. if(!TargetFilename) {
  25. return(FALSE);
  26. }
  27. SourceFilename = pSetupGetField(&InfContext,2);
  28. if(!SourceFilename) {
  29. SourceFilename = TargetFilename;
  30. }
  31. //
  32. // Enqueue the file for copy.
  33. //
  34. b = SetupQueueCopy(
  35. FileQ,
  36. System32Dir,
  37. NULL,
  38. SourceFilename,
  39. NULL,
  40. NULL,
  41. TargetRoot,
  42. TargetFilename,
  43. BaseCopyStyle
  44. );
  45. if(!b) {
  46. return(FALSE);
  47. }
  48. LineExists = SetupFindNextLine(&InfContext,&InfContext);
  49. }
  50. return(TRUE);
  51. }
  52. #endif
  53. BOOL
  54. SideBySidePopulateCopyQueue(
  55. SIDE_BY_SIDE* Sxs,
  56. HSPFILEQ FileQ, OPTIONAL
  57. PCWSTR AssembliesRootSource OPTIONAL
  58. )
  59. {
  60. BOOL Success = FALSE;
  61. UINT SourceId = 0;
  62. WCHAR DiskNameBuffer[MAX_PATH];
  63. WCHAR PromptForSetupPath[MAX_PATH];
  64. WCHAR AssembliesRootDirectoryFound[MAX_PATH];
  65. DWORD cchAssembliesRootDirectoryFound = sizeof(AssembliesRootDirectoryFound);
  66. DWORD Err;
  67. WCHAR AssembliesRootDirectory[MAX_PATH];
  68. PCWSTR InfField = NULL;
  69. INFCONTEXT InfContext = {0};
  70. BOOL LineExists = FALSE;
  71. SXS_INSTALLW InstallData;
  72. SXS_INSTALL_REFERENCEW InstallReference;
  73. ASSERT(Sxs != NULL);
  74. //
  75. // we depend on these having been initialized, and we are not supposed to
  76. // be called in MiniSetup or OobeSetup
  77. //
  78. ASSERT(SourcePath[0] != 0);
  79. ASSERT(SyssetupInf != NULL);
  80. ASSERT(SyssetupInf != INVALID_HANDLE_VALUE);
  81. ASSERT(!MiniSetup);
  82. ASSERT(!OobeSetup);
  83. //
  84. // first, don't fail to give safe values, since we always try to cleanup
  85. //
  86. Sxs->Dll = NULL;
  87. Sxs->BeginAssemblyInstall = NULL;
  88. Sxs->EndAssemblyInstall = NULL;
  89. Sxs->InstallW = NULL;
  90. Sxs->Context = NULL;
  91. //
  92. // then commence with initialization that can fail
  93. //
  94. if (!(Sxs->Dll = LoadLibraryW(SXS_DLL_NAME_W))) {
  95. goto Exit;
  96. }
  97. if (!(Sxs->BeginAssemblyInstall = (PSXS_BEGIN_ASSEMBLY_INSTALL)GetProcAddress(Sxs->Dll, SXS_BEGIN_ASSEMBLY_INSTALL))) {
  98. goto Exit;
  99. }
  100. if (!(Sxs->EndAssemblyInstall = (PSXS_END_ASSEMBLY_INSTALL)GetProcAddress(Sxs->Dll, SXS_END_ASSEMBLY_INSTALL))) {
  101. goto Exit;
  102. }
  103. if (!(Sxs->InstallW = (PSXS_INSTALL_W)GetProcAddress(Sxs->Dll, SXS_INSTALL_W))) {
  104. goto Exit;
  105. }
  106. if (!Sxs->BeginAssemblyInstall(
  107. SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NOT_TRANSACTIONAL
  108. | SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_NO_VERIFY
  109. | SXS_BEGIN_ASSEMBLY_INSTALL_FLAG_REPLACE_EXISTING,
  110. (FileQ != NULL) ? SXS_INSTALLATION_FILE_COPY_CALLBACK_SETUP_COPY_QUEUE : NULL,
  111. FileQ, // callback context
  112. NULL, // impersonation callback
  113. NULL, // impersonation context
  114. &Sxs->Context
  115. )) {
  116. goto Exit;
  117. }
  118. //
  119. // Set up the reference data to indicate that all of these are OS-installed
  120. // assemblies.
  121. //
  122. ZeroMemory(&InstallReference, sizeof(InstallReference));
  123. InstallReference.cbSize = sizeof(InstallReference);
  124. InstallReference.dwFlags = 0;
  125. InstallReference.guidScheme = SXS_INSTALL_REFERENCE_SCHEME_OSINSTALL;
  126. //
  127. // Let's get the source disk name of this assembly - we'll need it to
  128. // pass around as the prompt.
  129. //
  130. if ( !SetupGetSourceFileLocation(
  131. SyssetupInf,
  132. NULL,
  133. L"shell32.dll",
  134. &SourceId,
  135. NULL,
  136. 0,
  137. NULL
  138. ) )
  139. goto Exit;
  140. if ( !SetupGetSourceInfo(
  141. SyssetupInf,
  142. SourceId,
  143. SRCINFO_DESCRIPTION,
  144. DiskNameBuffer,
  145. sizeof(DiskNameBuffer),
  146. NULL
  147. ) )
  148. goto Exit;
  149. if (AssembliesRootSource) {
  150. //
  151. // Set up the structure to call off to the installer
  152. //
  153. memset(&InstallData, 0, sizeof(InstallData));
  154. InstallData.cbSize = sizeof(InstallData);
  155. InstallData.dwFlags = SXS_INSTALL_FLAG_FROM_DIRECTORY |
  156. SXS_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE |
  157. SXS_INSTALL_FLAG_REFERENCE_VALID |
  158. SXS_INSTALL_FLAG_REFRESH_PROMPT_VALID |
  159. SXS_INSTALL_FLAG_INSTALL_COOKIE_VALID |
  160. SXS_INSTALL_FLAG_INSTALLED_BY_OSSETUP |
  161. SXS_INSTALL_FLAG_CODEBASE_URL_VALID;
  162. InstallData.lpReference = &InstallReference;
  163. InstallData.lpRefreshPrompt = DiskNameBuffer;
  164. InstallData.pvInstallCookie = Sxs->Context;
  165. InstallData.lpCodebaseURL = AssembliesRootSource;
  166. InstallData.lpManifestPath = AssembliesRootSource;
  167. if (!Sxs->InstallW(&InstallData)) {
  168. // abort call will be made in SideBySideFinish
  169. goto Exit;
  170. }
  171. } else {
  172. LineExists = SetupFindFirstLine(SyssetupInf, SXS_INF_ASSEMBLY_DIRECTORIES_SECTION_NAME_W, NULL, &InfContext);
  173. while(LineExists) {
  174. DWORD FileAttributes = 0;
  175. //
  176. // convention introduced specifically for side by side, so that
  177. // x86 files on ia64 might come from \i386\asms instead of \ia64\asms\i386,
  178. // depending on what dosnet.inf and syssetup.inf say:
  179. // a path that does not start with a slash is appended to \$win_nt$.~ls\processor;
  180. // a path that does start with a slash is appended to \$win_nt$.~ls
  181. //
  182. InfField = pSetupGetField(&InfContext, 0);
  183. if(InfField == NULL) {
  184. break;
  185. }
  186. // c:\$win_nt$.~ls
  187. lstrcpyn(AssembliesRootDirectory, SourcePath, MAX_PATH);
  188. if (InfField[0] == '\\' || InfField[0] == '/') {
  189. InfField += 1;
  190. } else {
  191. // c:\$win_nt$.~ls\i386
  192. if (!pSetupConcatenatePaths(AssembliesRootDirectory, PlatformName, MAX_PATH, NULL)) {
  193. goto Exit;
  194. }
  195. }
  196. // stash this away for a little bit
  197. lstrcpyn( PromptForSetupPath, AssembliesRootDirectory, MAX_PATH );
  198. //
  199. // For now, while "staging", we allow the directory to not exist, and to be
  200. // empty (emptiness is silently handled elsewhere by common code), but
  201. // comctl32 will be in an assembly, so assemblies will be mandatory
  202. // for the system to boot to Explorer.exe.
  203. //
  204. // 11/09/2000 (jonwis) If we can't find the assemblies root directory, prompt
  205. // for the installation media. This is ripped straight from the headlines
  206. // of crypto.c and cmdline.c.
  207. //
  208. for (;;) {
  209. Err = SetupPromptForDisk(
  210. MainWindowHandle, // Main window handle
  211. NULL, // Dialog title (defaulted)
  212. DiskNameBuffer, // Name of the disk to request
  213. PromptForSetupPath, // Full path of the asms root
  214. InfField, // We look to see if the dir is there
  215. NULL, // No tag file
  216. IDF_CHECKFIRST | IDF_NOSKIP | IDF_NODETAILS | IDF_NOBROWSE,
  217. AssembliesRootDirectoryFound, // What we'll use to install
  218. cchAssembliesRootDirectoryFound, // How long is that buffer?
  219. NULL
  220. );
  221. // See if what we got back from the prompt is success - if so, is the directory
  222. // really there? We might assume that it is if we get back _SUCCESS...
  223. if ( Err == DPROMPT_SUCCESS ) {
  224. FileAttributes = GetFileAttributes(AssembliesRootDirectoryFound);
  225. if ((FileAttributes != 0xFFFFFFFF) && (FileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
  226. // copy out the asms directory location that was found, and
  227. // stop looking.
  228. lstrcpyn(AssembliesRootDirectory, AssembliesRootDirectoryFound, MAX_PATH);
  229. break;
  230. }
  231. } else {
  232. break;
  233. }
  234. };
  235. // c:\$win_nt$.~ls\i386\asms
  236. if (!pSetupConcatenatePaths(AssembliesRootDirectory, InfField, MAX_PATH, NULL)) {
  237. goto Exit;
  238. }
  239. //
  240. // If we didn't get a success (ie: we broke out of the loop), fail the
  241. // installation. Heinous, but MarianT (setup dev) suggests this is the
  242. // best method.
  243. //
  244. if ( Err != DPROMPT_SUCCESS )
  245. goto Exit;
  246. //
  247. // Set up this structure to call off into SXS to do the installation
  248. // for us.
  249. //
  250. ZeroMemory(&InstallData, sizeof(InstallData));
  251. InstallData.cbSize = sizeof(InstallData);
  252. InstallData.dwFlags = SXS_INSTALL_FLAG_FROM_DIRECTORY |
  253. SXS_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE |
  254. SXS_INSTALL_FLAG_REFERENCE_VALID |
  255. SXS_INSTALL_FLAG_REFRESH_PROMPT_VALID |
  256. SXS_INSTALL_FLAG_INSTALL_COOKIE_VALID |
  257. SXS_INSTALL_FLAG_INSTALLED_BY_OSSETUP |
  258. SXS_INSTALL_FLAG_CODEBASE_URL_VALID;
  259. InstallData.lpManifestPath = AssembliesRootDirectory;
  260. InstallData.lpReference = &InstallReference;
  261. InstallData.lpRefreshPrompt = DiskNameBuffer;
  262. InstallData.pvInstallCookie = Sxs->Context;
  263. InstallData.lpCodebaseURL = SourcePath;
  264. if (!Sxs->InstallW( &InstallData )) {
  265. // abort call will be made in SideBySideFinish
  266. goto Exit;
  267. }
  268. LineExists = SetupFindNextLine(&InfContext, &InfContext);
  269. }
  270. }
  271. Success = TRUE;
  272. Exit:
  273. return Success;
  274. }
  275. BOOL
  276. SideBySideFinish(
  277. SIDE_BY_SIDE* Sxs,
  278. BOOL fSuccess
  279. )
  280. {
  281. #define FUNCTION L"SideBySideFinish"
  282. DWORD dwLastError = NO_ERROR;
  283. ASSERT(Sxs != NULL);
  284. //
  285. // failure to load the .dll or get entry points implies lack of success
  286. //
  287. ASSERT(Sxs->Dll != NULL || !fSuccess);
  288. ASSERT(Sxs->EndAssemblyInstall != NULL || !fSuccess);
  289. if (!fSuccess) {
  290. dwLastError = GetLastError();
  291. }
  292. if (Sxs->Context != NULL) {
  293. if (Sxs->EndAssemblyInstall != NULL) {
  294. if (!Sxs->EndAssemblyInstall(
  295. Sxs->Context,
  296. fSuccess ? SXS_END_ASSEMBLY_INSTALL_FLAG_COMMIT : SXS_END_ASSEMBLY_INSTALL_FLAG_ABORT,
  297. NULL // reserved out DWORD
  298. )) {
  299. if (fSuccess) {
  300. fSuccess = FALSE;
  301. dwLastError = GetLastError();
  302. }
  303. }
  304. }
  305. Sxs->Context = NULL;
  306. }
  307. if (Sxs->Dll != NULL) {
  308. if (!FreeLibrary(Sxs->Dll)) {
  309. if (fSuccess) {
  310. fSuccess = FALSE;
  311. dwLastError = GetLastError();
  312. }
  313. }
  314. Sxs->Dll = NULL;
  315. }
  316. if (!fSuccess) {
  317. SetLastError(dwLastError);
  318. }
  319. return fSuccess;
  320. #undef FUNCTION
  321. }
  322. BOOL
  323. SideBySideCreateSyssetupContext(
  324. VOID
  325. )
  326. {
  327. #define FUNCTION L"SideBySideCreateSyssetupContext"
  328. BOOL fSuccess = FALSE;
  329. const PPEB Peb = NtCurrentPeb();
  330. ACTCTXW CreateActCtxParams;
  331. HANDLE ActCtxHandle;
  332. ASSERT(Peb->ActivationContextData == NULL);
  333. ASSERT(Peb->ProcessAssemblyStorageMap == NULL);
  334. ASSERT(Peb->SystemAssemblyStorageMap == NULL);
  335. CreateActCtxParams.cbSize = sizeof(CreateActCtxParams);
  336. CreateActCtxParams.dwFlags = (ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_SET_PROCESS_DEFAULT);
  337. CreateActCtxParams.lpResourceName = SXS_MANIFEST_RESOURCE_ID;
  338. ASSERT(MyModuleFileName[0] != 0);
  339. CreateActCtxParams.lpSource = MyModuleFileName;
  340. //
  341. // The error value is INVALID_HANDLE_VALUE.
  342. // ACTCTX_FLAG_SET_PROCESS_DEFAULT has nothing to return upon success, so it returns NULL.
  343. // There is nothing to cleanup upon ACTCTX_FLAG_SET_PROCESS_DEFAULT success, the data
  344. // is referenced in the PEB, and lasts till process shutdown.
  345. //
  346. ActCtxHandle = CreateActCtxW(&CreateActCtxParams);
  347. if (ActCtxHandle == INVALID_HANDLE_VALUE) {
  348. fSuccess = FALSE;
  349. SetupDebugPrint1(L"SETUP: CreateActCtxW failed in " FUNCTION L", LastError is %d\n", GetLastError());
  350. goto Exit;
  351. }
  352. ASSERT(ActCtxHandle == NULL);
  353. fSuccess = TRUE;
  354. Exit:
  355. return fSuccess;
  356. #undef FUNCTION
  357. }
  358. BOOL
  359. CopySystemFiles(
  360. VOID
  361. )
  362. {
  363. BOOL b;
  364. HINF hInf;
  365. HSPFILEQ FileQ;
  366. PVOID Context;
  367. WCHAR Dir[MAX_PATH];
  368. DWORD ScanQueueResult;
  369. b = FALSE;
  370. //hInf = SetupOpenInfFile(L"filelist.inf",NULL,INF_STYLE_WIN4,NULL);
  371. hInf = SyssetupInf;
  372. if(hInf != INVALID_HANDLE_VALUE) {
  373. FileQ = SetupOpenFileQueue();
  374. if(FileQ != INVALID_HANDLE_VALUE) {
  375. b = SetupInstallFilesFromInfSection(
  376. SyssetupInf,
  377. NULL,
  378. FileQ,
  379. Win31Upgrade
  380. ? L"Files.Install.CleanInstall.Win31"
  381. : L"Files.Install.CleanInstall",
  382. NULL,
  383. BaseCopyStyle
  384. );
  385. //
  386. // Do the installation of class installers
  387. // We do this here because the installation of class intallers may involve
  388. // file copy. And in this case we can use the existing progress bar.
  389. //
  390. InstallPnpClassInstallers( MainWindowHandle,
  391. hInf,
  392. FileQ );
  393. #if 0
  394. //
  395. // This feature is going away, because we're going to
  396. // build the delete file list using rules
  397. //
  398. if(Win95Upgrade) {
  399. b = b && SetupQueueDeleteSectionW(
  400. FileQ,
  401. hInf,
  402. 0,
  403. L"Files.DeleteWin9x.System"
  404. );
  405. b = b && SetupQueueDeleteSectionW(
  406. FileQ,
  407. hInf,
  408. 0,
  409. L"Files.DeleteWin9x.Sysroot"
  410. );
  411. }
  412. #endif
  413. if(b) {
  414. b = FALSE;
  415. if(Context = InitSysSetupQueueCallbackEx(MainWindowHandle,
  416. INVALID_HANDLE_VALUE,0,0,NULL)) {
  417. if(!SetupScanFileQueue(
  418. FileQ,
  419. SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE,
  420. MainWindowHandle,
  421. NULL,
  422. NULL,
  423. &ScanQueueResult)) {
  424. //
  425. // SetupScanFileQueue should really never
  426. // fail when you don't ask it to call a
  427. // callback routine, but if it does, just
  428. // go ahead and commit the queue.
  429. //
  430. ScanQueueResult = 0;
  431. }
  432. if( ScanQueueResult != 1 ){
  433. b = SetupCommitFileQueue(MainWindowHandle,FileQ,SysSetupQueueCallback,Context);
  434. }
  435. TermSysSetupQueueCallback(Context);
  436. }
  437. }
  438. SetupCloseFileQueue(FileQ);
  439. }
  440. //SetupCloseInfFile(hInf);
  441. }
  442. return(b);
  443. }
  444. BOOL
  445. UpgradeSystemFiles(
  446. VOID
  447. )
  448. {
  449. BOOL b;
  450. HINF hInf;
  451. HSPFILEQ FileQ;
  452. PVOID Context;
  453. WCHAR Dir[MAX_PATH];
  454. DWORD ScanQueueResult;
  455. b = FALSE;
  456. //hInf = SetupOpenInfFile(L"filelist.inf",NULL,INF_STYLE_WIN4,NULL);
  457. hInf = SyssetupInf;
  458. if(hInf != INVALID_HANDLE_VALUE) {
  459. FileQ = SetupOpenFileQueue();
  460. if(FileQ != INVALID_HANDLE_VALUE) {
  461. b = SetupInstallFilesFromInfSection(
  462. SyssetupInf,
  463. NULL,
  464. FileQ,
  465. Win31Upgrade
  466. ? L"Files.Install.Upgrade.Win31"
  467. : L"Files.Install.Upgrade",
  468. NULL,
  469. BaseCopyStyle
  470. );
  471. //
  472. // Do the installation of class installers
  473. // We do this here because the installation of class intallers may involve
  474. // file copy. And in this case we can use the existing progress bar.
  475. //
  476. InstallPnpClassInstallers( MainWindowHandle,
  477. hInf,
  478. FileQ );
  479. if(b) {
  480. b = FALSE;
  481. if(Context = InitSysSetupQueueCallbackEx(MainWindowHandle,
  482. INVALID_HANDLE_VALUE,0,0,NULL)) {
  483. if(!SetupScanFileQueue(
  484. FileQ,
  485. SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE,
  486. MainWindowHandle,
  487. NULL,
  488. NULL,
  489. &ScanQueueResult)) {
  490. //
  491. // SetupScanFileQueue should really never
  492. // fail when you don't ask it to call a
  493. // callback routine, but if it does, just
  494. // go ahead and commit the queue.
  495. //
  496. ScanQueueResult = 0;
  497. }
  498. if( ScanQueueResult != 1 ){
  499. b = SetupCommitFileQueue(MainWindowHandle,FileQ,SysSetupQueueCallback,Context);
  500. }
  501. TermSysSetupQueueCallback(Context);
  502. }
  503. }
  504. SetupCloseFileQueue(FileQ);
  505. }
  506. //SetupCloseInfFile(hInf);
  507. }
  508. return(b);
  509. }
  510. VOID
  511. MarkFilesReadOnly(
  512. VOID
  513. )
  514. {
  515. WCHAR OldCurrentDir[MAX_PATH];
  516. WCHAR System32Dir[MAX_PATH];
  517. LPCTSTR SectionName;
  518. LONG LineCount;
  519. LONG ItemNo;
  520. INFCONTEXT InfContext;
  521. BOOL b;
  522. ASSERT( SyssetupInf != INVALID_HANDLE_VALUE );
  523. //
  524. // Set current directory to system32.
  525. // Preserve current directory to minimize side-effects.
  526. //
  527. if(!GetCurrentDirectory(MAX_PATH,OldCurrentDir)) {
  528. OldCurrentDir[0] = 0;
  529. }
  530. GetSystemDirectory(System32Dir,MAX_PATH);
  531. SetCurrentDirectory(System32Dir);
  532. //
  533. // Now go through the list of files.
  534. //
  535. SectionName = L"Files.MarkReadOnly";
  536. LineCount = SetupGetLineCount( SyssetupInf, SectionName );
  537. for( ItemNo=0; ItemNo<LineCount; ItemNo++ ) {
  538. if( SetupGetLineByIndex( SyssetupInf, SectionName, ItemNo, &InfContext )) {
  539. b = SetFileAttributes(
  540. pSetupGetField( &InfContext, 0 ),
  541. FILE_ATTRIBUTE_READONLY );
  542. if (b) {
  543. SetupDebugPrint1( L"SETUP: Marked file %ls read-only",
  544. pSetupGetField( &InfContext, 0 ) );
  545. } else {
  546. SetupDebugPrint1( L"SETUP: Could not mark file %ls read-only",
  547. pSetupGetField( &InfContext, 0 ) );
  548. }
  549. }
  550. }
  551. //
  552. // Reset current directory and return.
  553. //
  554. if(OldCurrentDir[0]) {
  555. SetCurrentDirectory(OldCurrentDir);
  556. }
  557. }