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.

7646 lines
211 KiB

  1. #include "setupp.h"
  2. #include <passrec.h>
  3. #include <wow64reg.h>
  4. #pragma hdrstop
  5. //
  6. // These three functions are imported from setupasr.c, the module containing
  7. // the source for the Automatic System Recovery (ASR) functions.
  8. //
  9. // Returns TRUE if ASR is enabled. Otherwise, FALSE is returned.
  10. extern BOOL
  11. AsrIsEnabled(VOID);
  12. // Initializes ASR data. This is called iff the -asr switch is detected.
  13. extern VOID
  14. AsrInitialize(VOID);
  15. // Launches recovery applications specified in the asr state file.
  16. extern VOID
  17. AsrExecuteRecoveryApps(VOID);
  18. // Checks the system to see if we are running on the personal version of the
  19. // operating system.
  20. extern BOOL
  21. AsrpIsRunningOnPersonalSKU(VOID);
  22. //
  23. // Handle for watching changes to the user's profile directory and the current user hive.
  24. //
  25. PVOID WatchHandle;
  26. //
  27. // Handle to heap so we can periodically validate it.
  28. //
  29. #if DBG
  30. HANDLE g_hSysSetupHeap = NULL;
  31. #endif
  32. //
  33. // Product type: workstation, standalone server, dc server.
  34. //
  35. UINT ProductType;
  36. //
  37. // Set to TRUE if this is an ASR quick test
  38. //
  39. BOOL AsrQuickTest = FALSE;
  40. //
  41. // service pack dll module handle
  42. //
  43. HMODULE hModSvcPack;
  44. PSVCPACKCALLBACKROUTINE pSvcPackCallbackRoutine;
  45. //
  46. // Boolean value indicating whether this installation
  47. // originated with winnt/winnt32.
  48. // And, original source path, saved away for us by winnt/winnt32.
  49. //
  50. BOOL WinntBased;
  51. PCWSTR OriginalSourcePath;
  52. //
  53. // Boolean value indicating whether we're upgrading.
  54. //
  55. BOOL Upgrade;
  56. BOOL Win31Upgrade;
  57. BOOL Win95Upgrade;
  58. BOOL UninstallEnabled;
  59. //
  60. // Boolean value indicating whether we're in Setup or in appwiz.
  61. //
  62. BOOL IsSetup = FALSE;
  63. //
  64. // Boolean value indicating whether we're doing a subset of gui-mode setup.
  65. //
  66. BOOL MiniSetup = FALSE;
  67. //
  68. // Boolean value indicating whether we're doing a subset of gui-mode setup
  69. // AND we did PnP re-enumeration.
  70. //
  71. BOOL PnPReEnumeration = FALSE;
  72. //
  73. // Boolean value indicating whether we're doing a remote boot setup.
  74. //
  75. BOOL RemoteBootSetup = FALSE;
  76. //
  77. // During remote boot setup, BaseCopyStyle will be set to
  78. // SP_COPY_SOURCE_SIS_MASTER to indicate that single-instance
  79. // store links should be created instead of copying files.
  80. //
  81. ULONG BaseCopyStyle = 0;
  82. //
  83. // Support for SMS.
  84. //
  85. typedef DWORD (*SMSPROC) (char *, char*, char*, char*, char *, char *, char *, BOOL);
  86. HMODULE SMSHandle = NULL;
  87. SMSPROC InstallStatusMIF = NULL;
  88. //
  89. // Window handle of topmost setup window.
  90. //
  91. HWND SetupWindowHandle;
  92. HWND MainWindowHandle;
  93. HWND WizardHandle;
  94. //
  95. // Source path for installation.
  96. //
  97. WCHAR SourcePath[MAX_PATH];
  98. //
  99. // System setup inf.
  100. //
  101. HINF SyssetupInf;
  102. //
  103. // Save the unhandled exception filter so we can restore it when we're done.
  104. //
  105. LPTOP_LEVEL_EXCEPTION_FILTER SavedExceptionFilter = NULL;
  106. //
  107. // Unique Id for the main Setup thread. If any other thread has an unhandled
  108. // exception, we just log an error and try to keep going.
  109. //
  110. DWORD MainThreadId;
  111. //
  112. // The original locale we started setup under. If the locale changes during
  113. // gui-setup (via the IDD_REGIONAL_SETTINGS dialog), then new threads will
  114. // startup with the updated LCID, which may end up confusing any locale-centric
  115. // code. An example of this would be setupapi's string table implementation,
  116. // which does sorting by locale.
  117. //
  118. LCID OriginalInstallLocale;
  119. //
  120. // Flag indicating whether this is an unattended mode install/upgrade, and
  121. // if so, what mode to run in.
  122. // Also a flag indicating whether this is a preinstallation.
  123. // And a flag indicating whether we are supposed to allow rollback
  124. // once setup has been completed.
  125. // And a flag that tells us whether to skip the eula in the preinstall case.
  126. // And a flag that tells us whether any accessibility utilities are in use.
  127. //
  128. BOOL Unattended;
  129. UNATTENDMODE UnattendMode;
  130. BOOL Preinstall;
  131. BOOL AllowRollback;
  132. BOOL OemSkipEula;
  133. BOOL AccessibleSetup;
  134. BOOL Magnifier;
  135. BOOL ScreenReader;
  136. BOOL OnScreenKeyboard;
  137. BOOL EulaComplete = FALSE;
  138. //
  139. // Indicates whether we need to wait at the installation
  140. // end in unattended mode
  141. //
  142. BOOL UnattendWaitForReboot = FALSE;
  143. //
  144. // We can get into unattended mode in several ways, so we also check whether
  145. // the "/unattend" switch was explicitly specified.
  146. //
  147. BOOL UnattendSwitch;
  148. //
  149. // Flag indicating whether we should run OOBE after Setup completes. Note
  150. // that if it is FALSE, OOBE may still be run, based on other criteria.
  151. //
  152. BOOL ForceRunOobe;
  153. #ifdef PRERELEASE
  154. //
  155. // Test hooks
  156. //
  157. INT g_TestHook;
  158. #endif
  159. //
  160. // Flag indicating whether we are in a special mode for OEM's to use on the
  161. // factory floor.
  162. //
  163. BOOL ReferenceMachine;
  164. //
  165. // Flag indicating whether a volume was extended or not using
  166. // ExtendOemPartition
  167. //
  168. BOOL PartitionExtended = FALSE;
  169. //
  170. // Flag indicating if the eula was already shown during the textmode setup phase
  171. //
  172. BOOL TextmodeEula = FALSE;
  173. //
  174. // Flag indicating whether to skip missing files.
  175. //
  176. BOOL SkipMissingFiles;
  177. //
  178. // Catalog file to include (facilitates easy testing)
  179. //
  180. PWSTR IncludeCatalog;
  181. //
  182. // User command to execute, if any.
  183. //
  184. PWSTR UserExecuteCmd;
  185. //
  186. // String id of the string to be used for titles -- "Windows NT Setup"
  187. //
  188. UINT SetupTitleStringId;
  189. //
  190. // Strings used with date/timezone applet
  191. //
  192. PCWSTR DateTimeCpl = L"timedate.cpl";
  193. PCWSTR DateTimeParam = L"/firstboot";
  194. PCWSTR UnattendDateTimeParam = L"/z ";
  195. //
  196. // Registry Constants
  197. //
  198. #define REGSTR_PATH_SYSPREP _T("Software\\Microsoft\\Sysprep")
  199. #define REGSTR_VAL_SIDGENHISTORY _T("SidsGeneratedHistory")
  200. //
  201. // Global structure that contains information that will be used
  202. // by net setup. We pass a pointer to this structure when we call
  203. // NetSetupRequestWizardPages, then fill it in before we call into
  204. // the net setup wizard.
  205. //
  206. INTERNAL_SETUP_DATA InternalSetupData;
  207. //
  208. // In the initial install case, we time how long the wizard takes
  209. // to help randomize the sid we generate.
  210. //
  211. DWORD PreWizardTickCount;
  212. //
  213. // Global structure that contains callback routines and data needed by
  214. // the Setuplog routines.
  215. //
  216. SETUPLOG_CONTEXT SetuplogContext;
  217. //
  218. // Did we log an error during SfcInitProt()?
  219. //
  220. BOOL SfcErrorOccurred = FALSE;
  221. //
  222. // List of drivers that remote boot requires to be boot drivers.
  223. //
  224. const static PCWSTR RemoteBootDrivers[] = { L"mrxsmb", L"netbt", L"rdbss", L"tcpip", L"ipsec" };
  225. //
  226. // List of functions for the billboard background
  227. //
  228. typedef BOOL (CALLBACK* SETSTEP)(int);
  229. typedef HWND (CALLBACK* GETBBHWND)(void);
  230. typedef BOOL (WINAPI* INITBILLBOARD)(HWND , LPCTSTR, DWORD);
  231. typedef BOOL (WINAPI* TERMBILLBOARD)();
  232. HINSTANCE hinstBB = NULL;
  233. // End billboards
  234. VOID
  235. CallNetworkSetupBack(
  236. IN PCSTR ProcName
  237. );
  238. VOID
  239. RemoveMSKeyboardPtrPropSheet (
  240. VOID
  241. );
  242. VOID
  243. FixWordPadReg (
  244. VOID
  245. );
  246. VOID
  247. ProcessRegistryFiles(
  248. IN HWND Billboard
  249. );
  250. VOID
  251. SetStartTypeForRemoteBootDrivers(
  252. VOID
  253. );
  254. BOOL
  255. RunMigrationDlls (
  256. VOID
  257. );
  258. BOOL
  259. RunSetupPrograms(
  260. IN PVOID InfHandle,
  261. PWSTR SectionName
  262. );
  263. VOID
  264. GetUnattendRunOnceAndSetRegistry(
  265. VOID
  266. );
  267. VOID
  268. ExecuteUserCommand (
  269. HWND hProgress
  270. );
  271. BOOL
  272. MigrateExceptionPackages(
  273. IN HWND hProgress,
  274. IN DWORD StartAtPercent,
  275. IN DWORD StopAtPercent
  276. );
  277. VOID
  278. RemoveRestartability (
  279. HWND hProgress
  280. );
  281. PCTSTR
  282. pGenerateRandomPassword (
  283. VOID
  284. );
  285. DWORD GetProductFlavor();
  286. VOID
  287. CopyOemProgramFilesDir(
  288. VOID
  289. );
  290. VOID
  291. CopyOemDocumentsDir(
  292. VOID
  293. );
  294. BOOL
  295. UpdateServerProfileDirectory(
  296. VOID
  297. );
  298. VOID
  299. SendSMSMessage(
  300. IN UINT MessageId,
  301. IN BOOL Status
  302. )
  303. /*++
  304. Routine Description:
  305. If setup was initiated by SMS, then report our status.
  306. Arguments:
  307. MessageId - supplies the id for the message in the message table.
  308. Status - TRUE = "Success" or FALSE = "Failed"
  309. Return Value:
  310. None.
  311. --*/
  312. {
  313. PWSTR UnicodeBuffer;
  314. PSTR AnsiBuffer;
  315. if(InstallStatusMIF) {
  316. if( UnicodeBuffer = RetrieveAndFormatMessageV( NULL, MessageId, NULL )) {
  317. if(AnsiBuffer = pSetupUnicodeToAnsi (UnicodeBuffer)) {
  318. InstallStatusMIF(
  319. "setupinf",
  320. "Microsoft",
  321. "Windows NT",
  322. "5.0",
  323. "",
  324. "",
  325. AnsiBuffer,
  326. Status
  327. );
  328. MyFree (AnsiBuffer);
  329. }
  330. MyFree( UnicodeBuffer );
  331. }
  332. }
  333. }
  334. VOID
  335. BrandIE(
  336. )
  337. {
  338. if( Unattended && !Upgrade && !MiniSetup ) {
  339. typedef BOOL (*BRANDINTRAPROC) ( LPCSTR );
  340. typedef BOOL (*BRANDCLEANSTUBPROC) (HWND, HINSTANCE, LPCSTR, int);
  341. HMODULE IedkHandle = NULL;
  342. BRANDINTRAPROC BrandIntraProc;
  343. BRANDCLEANSTUBPROC BrandCleanStubProc;
  344. BOOL Success = TRUE;
  345. BOOL UseOemBrandingFile = FALSE;
  346. CHAR BrandingFileA[MAX_PATH];
  347. WCHAR OemBrandingFile[MAX_PATH];
  348. DWORD OemDirLen = 0;
  349. #define BUF_SIZE 4
  350. WCHAR Buf[BUF_SIZE];
  351. //
  352. // We need to call out to iedkcs32!BrandIntra.
  353. //
  354. // Load iedkcs32.dll, lookup BrandIntra and
  355. // call out to him.
  356. //
  357. if (GetPrivateProfileString(L"Branding", L"BrandIEUsingUnattended", L"",
  358. Buf, BUF_SIZE,
  359. AnswerFile)) {
  360. //Found the Branding section
  361. try {
  362. if( IedkHandle = LoadLibrary(L"IEDKCS32") ) {
  363. BrandCleanStubProc = (BRANDCLEANSTUBPROC) GetProcAddress(IedkHandle,"BrandCleanInstallStubs");
  364. BrandIntraProc = (BRANDINTRAPROC) GetProcAddress(IedkHandle,"BrandIntra");
  365. if( BrandCleanStubProc && BrandIntraProc ) {
  366. if (_wcsicmp(Buf, L"YES")) {
  367. //
  368. // Check whether the OEM supplies an IE branding file.
  369. //
  370. lstrcpy(OemBrandingFile,SourcePath);
  371. if (pSetupConcatenatePaths(OemBrandingFile,WINNT_OEM_DIR,MAX_PATH, &OemDirLen)) {
  372. OemBrandingFile[OemDirLen-1] = L'\\';
  373. if (GetPrivateProfileString(L"Branding", L"IEBrandingFile", L"",
  374. OemBrandingFile + OemDirLen,
  375. MAX_PATH - OemDirLen,
  376. AnswerFile)) {
  377. if (FileExists(OemBrandingFile, NULL))
  378. UseOemBrandingFile = TRUE;
  379. }
  380. } else {
  381. SetupDebugPrint( L"Setup: (non-critical error) Failed call pSetupConcatenatePaths\n" );
  382. }
  383. if (!UseOemBrandingFile) {
  384. Success = FALSE;
  385. SetupDebugPrint( L"Setup: (non-critical error) Could not find the OEM branding file for IE\n" );
  386. }
  387. }
  388. if (Success) {
  389. if (!WideCharToMultiByte(
  390. CP_ACP,
  391. 0,
  392. UseOemBrandingFile?OemBrandingFile:AnswerFile,
  393. -1,
  394. BrandingFileA,
  395. sizeof(BrandingFileA),
  396. NULL,
  397. NULL
  398. )) {
  399. Success = FALSE;
  400. SetupDebugPrint1( L"Setup: (non-critical error) Failed call WideCharToMultiByte (gle %u) \n", GetLastError() );
  401. } else {
  402. Success = BrandCleanStubProc( NULL, NULL, "", 0);
  403. if( !Success ) {
  404. SetupDebugPrint( L"Setup: (non-critical error) Failed call BrandCleanInstallStubs \n" );
  405. } else {
  406. Success = BrandIntraProc( BrandingFileA );
  407. if( !Success ) {
  408. SetupDebugPrint( L"Setup: (non-critical error) Failed call BrandIntra \n" );
  409. }
  410. }
  411. }
  412. }
  413. } else {
  414. Success = FALSE;
  415. SetupDebugPrint( L"Syssetup: (non-critical error) Failed GetProcAddress on BrandIntra or BrandCleanInstallStubs.\n" );
  416. }
  417. } else {
  418. Success = FALSE;
  419. SetupDebugPrint( L"Syssetup: (non-critical error) Failed load of iedkcs32.dll.\n" );
  420. }
  421. } except(EXCEPTION_EXECUTE_HANDLER) {
  422. Success = FALSE;
  423. SetupDebugPrint( L"Setup: Exception in iedkcs32!BrandIntra\n" );
  424. }
  425. if (IedkHandle)
  426. FreeLibrary(IedkHandle);
  427. if( !Success ) {
  428. //
  429. // We failed the call (for whatever reason). Log
  430. // this error.
  431. //
  432. SetuplogError(
  433. LogSevError,
  434. SETUPLOG_USE_MESSAGEID,
  435. MSG_BRAND_IE_FAILURE,
  436. NULL,NULL);
  437. }
  438. }
  439. }
  440. }
  441. VOID
  442. SpStartAccessibilityUtilities(
  443. IN HWND Billboard
  444. )
  445. /*++
  446. Routine Description:
  447. Installs and runs selected accessibility utilities.
  448. Arguments:
  449. Billboard - window handle of "Setup is Initializing" billboard.
  450. Returns:
  451. Boolean value indicating outcome.
  452. --*/
  453. {
  454. HINF hInf;
  455. HINF LayoutInf;
  456. HSPFILEQ FileQueue;
  457. PVOID QContext;
  458. BOOL b = TRUE;
  459. DWORD ScanQueueResult;
  460. //
  461. // Install text-to-speech engine and SAPI 5 for the screen reader.
  462. //
  463. FileQueue = SetupOpenFileQueue();
  464. b = b && (FileQueue != INVALID_HANDLE_VALUE);
  465. if(b) {
  466. hInf = SetupOpenInfFile(L"sapi5.inf",NULL,INF_STYLE_WIN4,NULL);
  467. if(hInf && (hInf != INVALID_HANDLE_VALUE)
  468. && (LayoutInf = InfCacheOpenLayoutInf(hInf))) {
  469. SetupInstallFilesFromInfSection(
  470. hInf,
  471. LayoutInf,
  472. FileQueue,
  473. L"DefaultInstall",
  474. SourcePath,
  475. SP_COPY_NEWER
  476. );
  477. SetupCloseInfFile(hInf);
  478. } else {
  479. b = FALSE;
  480. }
  481. }
  482. //
  483. // If enqueuing went OK, now perform the copying, renaming, and deleting.
  484. // Then perform the rest of the install process (registry stuff, etc).
  485. //
  486. if(b) {
  487. QContext = InitSysSetupQueueCallbackEx(
  488. Billboard,
  489. INVALID_HANDLE_VALUE,
  490. 0,0,NULL);
  491. if( QContext ) {
  492. if(!SetupScanFileQueue(
  493. FileQueue,
  494. SPQ_SCAN_FILE_VALIDITY | SPQ_SCAN_PRUNE_COPY_QUEUE,
  495. Billboard,
  496. NULL,
  497. NULL,
  498. &ScanQueueResult)) {
  499. //
  500. // SetupScanFileQueue should really never
  501. // fail when you don't ask it to call a
  502. // callback routine, but if it does, just
  503. // go ahead and commit the queue.
  504. //
  505. ScanQueueResult = 0;
  506. }
  507. if( ScanQueueResult != 1 ){
  508. b = SetupCommitFileQueue(
  509. Billboard,
  510. FileQueue,
  511. SysSetupQueueCallback,
  512. QContext
  513. );
  514. }
  515. TermSysSetupQueueCallback(QContext);
  516. }
  517. else {
  518. b = FALSE;
  519. }
  520. }
  521. if(b) {
  522. hInf = SetupOpenInfFile(L"sapi5.inf",NULL,INF_STYLE_WIN4,NULL);
  523. if(hInf && (hInf != INVALID_HANDLE_VALUE)) {
  524. SetupInstallFromInfSection(
  525. Billboard,
  526. hInf,
  527. L"DefaultInstall",
  528. SPINST_ALL ^ SPINST_FILES,
  529. NULL,
  530. NULL,
  531. 0,
  532. NULL,
  533. NULL,
  534. NULL,
  535. NULL
  536. );
  537. SetupCloseInfFile(hInf);
  538. } else {
  539. b = FALSE;
  540. }
  541. }
  542. //
  543. // Delete the file queue.
  544. //
  545. if(FileQueue != INVALID_HANDLE_VALUE) {
  546. SetupCloseFileQueue(FileQueue);
  547. }
  548. // END OF SAPI 5 INSTALLATION.
  549. if(Magnifier) {
  550. b = b && InvokeExternalApplication(L"magnify.exe", L"", NULL);
  551. }
  552. if(OnScreenKeyboard) {
  553. b = b && InvokeExternalApplication(L"osk.exe", L"", NULL);
  554. }
  555. if(!b) {
  556. SetuplogError(
  557. LogSevError,
  558. SETUPLOG_USE_MESSAGEID,
  559. MSG_LOG_ACCESSIBILITY_FAILED,
  560. NULL,NULL);
  561. }
  562. }
  563. VOID
  564. FatalError(
  565. IN UINT MessageId,
  566. ...
  567. )
  568. /*++
  569. Routine Description:
  570. Inform the user of an error which prevents Setup from continuing.
  571. The error is logged as a fatal error, and a message box is presented.
  572. Arguments:
  573. MessageId - supplies the id for the message in the message table.
  574. Additional agruments specify parameters to be inserted in the message.
  575. Return Value:
  576. DOES NOT RETURN.
  577. --*/
  578. {
  579. PWSTR Message;
  580. va_list arglist;
  581. HKEY hKey;
  582. DWORD RegData;
  583. va_start(arglist,MessageId);
  584. Message = SetuplogFormatMessageV(
  585. 0,
  586. SETUPLOG_USE_MESSAGEID,
  587. MessageId,
  588. &arglist);
  589. va_end(arglist);
  590. if(Message) {
  591. //
  592. // Log the error first.
  593. //
  594. SetuplogError(
  595. LogSevFatalError,Message,0,NULL,NULL);
  596. //
  597. // Now tell the user.
  598. //
  599. MessageBoxFromMessage(
  600. MainWindowHandle,
  601. MSG_FATAL_ERROR,
  602. NULL,
  603. IDS_FATALERROR,
  604. MB_ICONERROR | MB_OK | MB_SYSTEMMODAL,
  605. Message
  606. );
  607. } else {
  608. pSetupOutOfMemory(MainWindowHandle);
  609. }
  610. SetuplogError(
  611. LogSevInformation,
  612. SETUPLOG_USE_MESSAGEID,
  613. MSG_LOG_GUI_ABORTED,
  614. NULL,NULL);
  615. if ( SavedExceptionFilter ) {
  616. SetUnhandledExceptionFilter( SavedExceptionFilter );
  617. }
  618. TerminateSetupLog(&SetuplogContext);
  619. ViewSetupActionLog(MainWindowHandle, NULL, NULL);
  620. SendSMSMessage( MSG_SMS_FAIL, FALSE );
  621. if ( OobeSetup ) {
  622. //
  623. // Create registry entry that tell winlogon to shutdown for the OOBE case.
  624. // This doesn't work for MiniSetup, because winlogon always restarts in
  625. // that case.
  626. //
  627. RegCreateKeyEx(
  628. HKEY_LOCAL_MACHINE,
  629. L"System\\Setup",
  630. 0,
  631. NULL,
  632. REG_OPTION_NON_VOLATILE,
  633. KEY_SET_VALUE,
  634. NULL,
  635. &hKey,
  636. NULL
  637. );
  638. if ( hKey ) {
  639. RegData = ShutdownPowerOff;
  640. RegSetValueEx(
  641. hKey,
  642. L"SetupShutdownRequired",
  643. 0,
  644. REG_DWORD,
  645. (PVOID)&RegData,
  646. sizeof(RegData)
  647. );
  648. RegCloseKey(hKey);
  649. }
  650. }
  651. ExitProcess(1);
  652. }
  653. LONG
  654. WINAPI
  655. MyUnhandledExceptionFilter(
  656. IN struct _EXCEPTION_POINTERS *ExceptionInfo
  657. )
  658. /*++
  659. Routine Description:
  660. The routine deals with any unhandled exceptions in Setup. We log an error
  661. and kill the offending thread.
  662. Arguments:
  663. Same as UnhandledExceptionFilter.
  664. Return Value:
  665. Same as UnhandledExceptionFilter.
  666. --*/
  667. {
  668. UINT_PTR Param1, Param2;
  669. switch(ExceptionInfo->ExceptionRecord->NumberParameters) {
  670. case 1:
  671. Param1 = ExceptionInfo->ExceptionRecord->ExceptionInformation[0];
  672. Param2 = 0;
  673. break;
  674. case 2:
  675. Param1 = ExceptionInfo->ExceptionRecord->ExceptionInformation[0];
  676. Param2 = ExceptionInfo->ExceptionRecord->ExceptionInformation[1];
  677. break;
  678. default:
  679. Param1 = Param2 = 0;
  680. }
  681. SetupDebugPrint4( L"Setup: (critical error) Encountered an unhandled exception (%lx) at address %lx with the following parameters: %lx %lx.",
  682. ExceptionInfo->ExceptionRecord->ExceptionCode,
  683. ExceptionInfo->ExceptionRecord->ExceptionAddress,
  684. Param1,
  685. Param2
  686. );
  687. #ifdef NOT_FOR_NT5
  688. SetuplogError(
  689. LogSevError | SETUPLOG_SINGLE_MESSAGE,
  690. SETUPLOG_USE_MESSAGEID,
  691. MSG_LOG_UNHANDLED_EXCEPTION,
  692. ExceptionInfo->ExceptionRecord->ExceptionCode,
  693. ExceptionInfo->ExceptionRecord->ExceptionAddress,
  694. Param1,
  695. Param2,
  696. NULL,NULL);
  697. #else
  698. SetuplogError(
  699. LogSevError | SETUPLOG_SINGLE_MESSAGE,
  700. SETUPLOG_USE_MESSAGEID,
  701. MSG_LOG_UNHANDLED_EXCEPTION,
  702. ExceptionInfo->ExceptionRecord->ExceptionCode,
  703. ExceptionInfo->ExceptionRecord->ExceptionAddress,
  704. Param1,
  705. Param2,
  706. NULL,
  707. NULL
  708. );
  709. #endif
  710. #ifdef PRERELEASE
  711. //
  712. // If we're an internal build, then we want to debug this.
  713. //
  714. MessageBoxFromMessage (
  715. NULL,
  716. MSG_UNHANDLED_EXCEPTION,
  717. NULL,
  718. IDS_ERROR,
  719. MB_OK | MB_TASKMODAL | MB_ICONSTOP | MB_SETFOREGROUND,
  720. ExceptionInfo->ExceptionRecord->ExceptionCode,
  721. ExceptionInfo->ExceptionRecord->ExceptionAddress,
  722. Param1,
  723. Param2
  724. );
  725. return EXCEPTION_CONTINUE_EXECUTION;
  726. #endif
  727. //
  728. // If we're running under the debugger, then pass the exception to the
  729. // debugger. If the exception occurred in some thread other than the main
  730. // Setup thread, then kill the thread and hope that Setup can continue.
  731. // If the exception is in the main thread, then don't handle the exception,
  732. // and let Setup die.
  733. //
  734. if( GetCurrentThreadId() != MainThreadId &&
  735. !IsDebuggerPresent() ) {
  736. ExitThread( 0 );
  737. }
  738. return EXCEPTION_CONTINUE_SEARCH;
  739. }
  740. BOOL
  741. ProcessUniquenessValue(
  742. LPTSTR lpszDLLPath
  743. )
  744. {
  745. BOOL bRet = FALSE;
  746. //
  747. // Make sure we were passed something valid...
  748. //
  749. if ( lpszDLLPath && *lpszDLLPath )
  750. {
  751. LPWSTR pSrch;
  752. //
  753. // Look for the comma that separates the DLL and the entrypoint...
  754. //
  755. if ( pSrch = wcschr( lpszDLLPath, L',' ) )
  756. {
  757. CHAR szEntryPointA[MAX_PATH] = {0};
  758. // We found one, now NULL the string at the comma...
  759. //
  760. *(pSrch++) = L'\0';
  761. //
  762. // If there's still something after the comma, and we can convert it
  763. // into ANSI for GetProcAddress, then let's proceed...
  764. //
  765. if ( *pSrch &&
  766. ( 0 != WideCharToMultiByte( CP_ACP,
  767. 0,
  768. pSrch,
  769. -1,
  770. szEntryPointA,
  771. ARRAYSIZE(szEntryPointA),
  772. NULL,
  773. NULL ) ) )
  774. {
  775. HMODULE hModule = NULL;
  776. try
  777. {
  778. //
  779. // Load and call the entry point.
  780. //
  781. if ( hModule = LoadLibrary( lpszDLLPath ) )
  782. {
  783. FARPROC fpEntryPoint;
  784. if ( fpEntryPoint = GetProcAddress(hModule, szEntryPointA) )
  785. {
  786. //
  787. // Do it, ignoring any return value/errors
  788. //
  789. fpEntryPoint();
  790. //
  791. // We made it this far, consider this a success...
  792. //
  793. bRet = TRUE;
  794. }
  795. }
  796. }
  797. except(EXCEPTION_EXECUTE_HANDLER)
  798. {
  799. //
  800. // We don't do anything with the exception code...
  801. //
  802. }
  803. //
  804. // Free the library outside the try/except block in case the function faulted.
  805. //
  806. if ( hModule )
  807. {
  808. FreeLibrary( hModule );
  809. }
  810. }
  811. }
  812. }
  813. return bRet;
  814. }
  815. VOID
  816. ProcessUniquenessKey(
  817. BOOL fBeforeReseal
  818. )
  819. {
  820. HKEY hKey;
  821. TCHAR szRegPath[MAX_PATH] = {0};
  822. LPTSTR lpszBasePath = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\SysPrep\\");
  823. //
  824. // Build a path to the registry key we want to process...
  825. //
  826. lstrcpyn( szRegPath, lpszBasePath, ARRAYSIZE(szRegPath) );
  827. lstrcpyn( szRegPath + lstrlen(szRegPath),
  828. fBeforeReseal ? TEXT("SysprepBeforeExecute") : TEXT("SysprepAfterExecute"),
  829. ARRAYSIZE(szRegPath) - lstrlen(szRegPath) );
  830. //
  831. // We want to make sure an Administrator is doing this, so get KEY_ALL_ACCESS
  832. //
  833. if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  834. szRegPath,
  835. 0,
  836. KEY_ALL_ACCESS,
  837. &hKey ) )
  838. {
  839. DWORD dwValues = 0,
  840. dwMaxValueLen = 0,
  841. dwMaxValueNameLen = 0;
  842. //
  843. // Query the key to find out some information we care about...
  844. //
  845. if ( ( ERROR_SUCCESS == RegQueryInfoKey( hKey, // hKey
  846. NULL, // lpClass
  847. NULL, // lpcClass
  848. NULL, // lpReserved
  849. NULL, // lpcSubKeys
  850. NULL, // lpcMaxSubKeyLen
  851. NULL, // lpcMaxClassLen
  852. &dwValues, // lpcValues
  853. &dwMaxValueNameLen, // lpcMaxValueNameLen
  854. &dwMaxValueLen, // lpcMaxValueLen
  855. NULL, // lpcbSecurityDescriptor
  856. NULL ) ) && // lpftLastWriteTime
  857. ( dwValues > 0 ) &&
  858. ( dwMaxValueNameLen > 0) &&
  859. ( dwMaxValueLen > 0 ) )
  860. {
  861. //
  862. // Allocate buffers large enough to hold the data we want...
  863. //
  864. LPBYTE lpData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwMaxValueLen );
  865. LPTSTR lpValueName = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, ( dwMaxValueNameLen + 1 ) * sizeof(TCHAR) );
  866. //
  867. // Make sure we could allocate our buffers... otherwise bail out
  868. //
  869. if ( lpData && lpValueName )
  870. {
  871. DWORD dwIndex = 0;
  872. BOOL bContinue = TRUE;
  873. //
  874. // Enumerate through the key values and call the DLL entrypoints...
  875. //
  876. while ( bContinue )
  877. {
  878. DWORD dwType,
  879. cbData = dwMaxValueLen,
  880. dwValueNameLen = dwMaxValueNameLen + 1;
  881. bContinue = ( ERROR_SUCCESS == RegEnumValue( hKey,
  882. dwIndex++,
  883. lpValueName,
  884. &dwValueNameLen,
  885. NULL,
  886. &dwType,
  887. lpData,
  888. &cbData ) );
  889. //
  890. // Make sure we got some data of the correct format...
  891. //
  892. if ( bContinue && ( REG_SZ == dwType ) && ( cbData > 0 ) )
  893. {
  894. //
  895. // Now split up the string and call the entrypoints...
  896. //
  897. ProcessUniquenessValue( (LPTSTR) lpData );
  898. }
  899. }
  900. }
  901. //
  902. // Clean up any buffers we may have allocated...
  903. //
  904. if ( lpData )
  905. {
  906. HeapFree( GetProcessHeap(), 0, lpData );
  907. }
  908. if ( lpValueName )
  909. {
  910. HeapFree( GetProcessHeap(), 0, lpValueName );
  911. }
  912. }
  913. //
  914. // Close the key...
  915. //
  916. RegCloseKey( hKey );
  917. }
  918. }
  919. VOID
  920. RunExternalUniqueness(
  921. VOID
  922. )
  923. /*++
  924. ===============================================================================
  925. Routine Description:
  926. This routine will call out to any external dlls that will allow
  927. 3rd party apps to make their stuff unique.
  928. We'll look in 2 inf files:
  929. %windir%\inf\minioc.inf
  930. %systemroot%\sysprep\providers.inf
  931. In each of these files, we'll look in the [SysprepInitExecute] section
  932. for any entries. The entries must look like:
  933. dllname,entrypoint
  934. We'll load the dll and call into the entry point. Errors are ignored.
  935. Arguments:
  936. None.
  937. Return Value:
  938. TRUE if successful.
  939. FALSE if any errors encountered
  940. ===============================================================================
  941. --*/
  942. {
  943. WCHAR InfPath[MAX_PATH];
  944. PCWSTR DllName;
  945. PCWSTR EntryPointNameW;
  946. CHAR EntryPointNameA[MAX_PATH];
  947. HINF AnswerInf;
  948. HMODULE DllHandle;
  949. FARPROC MyProc;
  950. INFCONTEXT InfContext;
  951. DWORD i;
  952. PCWSTR SectionName = L"SysprepInitExecute";
  953. BOOL LineExists;
  954. DWORD Result;
  955. //
  956. // =================================
  957. // Minioc.inf
  958. // =================================
  959. //
  960. //
  961. // Build the path.
  962. //
  963. Result = GetWindowsDirectory( InfPath, MAX_PATH );
  964. if( Result == 0) {
  965. MYASSERT(FALSE);
  966. return;
  967. }
  968. lstrcat( InfPath, TEXT("\\inf\\minioc.inf") );
  969. //
  970. // See if he's got an entry
  971. // section.
  972. //
  973. AnswerInf = SetupOpenInfFile( InfPath, NULL, INF_STYLE_WIN4, NULL );
  974. if( AnswerInf == INVALID_HANDLE_VALUE ) {
  975. //
  976. // Try an old-style.
  977. //
  978. AnswerInf = SetupOpenInfFile( InfPath, NULL, INF_STYLE_OLDNT, NULL );
  979. }
  980. if( AnswerInf != INVALID_HANDLE_VALUE ) {
  981. //
  982. // Process each line in our section
  983. //
  984. LineExists = SetupFindFirstLine( AnswerInf, SectionName, NULL, &InfContext );
  985. while( LineExists ) {
  986. if( DllName = pSetupGetField(&InfContext, 1) ) {
  987. if( EntryPointNameW = pSetupGetField(&InfContext, 2) ) {
  988. DllHandle = NULL;
  989. //
  990. // Load and call the entry point.
  991. //
  992. try {
  993. if( DllHandle = LoadLibrary(DllName) ) {
  994. //
  995. // No Unicode version of GetProcAddress(). Convert string to ANSI.
  996. //
  997. i = WideCharToMultiByte(CP_ACP,0,EntryPointNameW,-1,EntryPointNameA,MAX_PATH,NULL,NULL);
  998. if( MyProc = GetProcAddress(DllHandle, EntryPointNameA) ) {
  999. //
  1000. // Do it, ignoring any return value/errors
  1001. //
  1002. MyProc();
  1003. }
  1004. }
  1005. } except(EXCEPTION_EXECUTE_HANDLER) {
  1006. }
  1007. if( DllHandle ) {
  1008. FreeLibrary( DllHandle );
  1009. }
  1010. }
  1011. }
  1012. LineExists = SetupFindNextLine(&InfContext,&InfContext);
  1013. }
  1014. SetupCloseInfFile( AnswerInf );
  1015. }
  1016. //
  1017. // =================================
  1018. // Provider.inf
  1019. // =================================
  1020. //
  1021. ProcessUniquenessKey( FALSE );
  1022. }
  1023. #ifdef _X86_
  1024. VOID
  1025. CleanUpHardDriveTags (
  1026. VOID
  1027. )
  1028. {
  1029. WCHAR path[MAX_PATH];
  1030. WCHAR rootPath[4] = TEXT("*:\\");
  1031. UINT i;
  1032. BYTE bitPosition;
  1033. DWORD drives;
  1034. UINT type;
  1035. lstrcpy(path, L"*:\\");
  1036. lstrcat(path, WINNT_WIN95UPG_DRVLTR_W);
  1037. drives = GetLogicalDrives ();
  1038. for (bitPosition = 0; bitPosition < 26; bitPosition++) {
  1039. if (drives & (1 << bitPosition)) {
  1040. *rootPath = bitPosition + L'A';
  1041. type = GetDriveType (rootPath);
  1042. if (type == DRIVE_FIXED) {
  1043. *path = *rootPath;
  1044. DeleteFile (path);
  1045. }
  1046. }
  1047. }
  1048. }
  1049. #endif
  1050. HRESULT
  1051. WaitForSamService()
  1052. /*++
  1053. Routine Description:
  1054. This procedure waits for the SAM service to start and to complete
  1055. all its initialization.
  1056. Arguments:
  1057. Return Value:
  1058. Notes:
  1059. acosma 10/12/2001 - code borrowed from winlogon. Waiting for 20 seconds just like winlogon.
  1060. --*/
  1061. {
  1062. NTSTATUS Status;
  1063. DWORD WaitStatus;
  1064. UNICODE_STRING EventName;
  1065. HANDLE EventHandle;
  1066. OBJECT_ATTRIBUTES EventAttributes;
  1067. HRESULT Hr;
  1068. //
  1069. // open SAM event
  1070. //
  1071. RtlInitUnicodeString( &EventName, L"\\SAM_SERVICE_STARTED");
  1072. InitializeObjectAttributes( &EventAttributes, &EventName, 0, 0, NULL );
  1073. Status = NtOpenEvent( &EventHandle,
  1074. SYNCHRONIZE|EVENT_MODIFY_STATE,
  1075. &EventAttributes );
  1076. if ( !NT_SUCCESS(Status))
  1077. {
  1078. if( Status == STATUS_OBJECT_NAME_NOT_FOUND )
  1079. {
  1080. //
  1081. // SAM hasn't created this event yet, let us create it now.
  1082. // SAM opens this event to set it.
  1083. //
  1084. Status = NtCreateEvent(
  1085. &EventHandle,
  1086. SYNCHRONIZE|EVENT_MODIFY_STATE,
  1087. &EventAttributes,
  1088. NotificationEvent,
  1089. FALSE // The event is initially not signaled
  1090. );
  1091. if( Status == STATUS_OBJECT_NAME_EXISTS ||
  1092. Status == STATUS_OBJECT_NAME_COLLISION )
  1093. {
  1094. //
  1095. // second change, if the SAM created the event before we
  1096. // do.
  1097. //
  1098. Status = NtOpenEvent( &EventHandle,
  1099. SYNCHRONIZE|EVENT_MODIFY_STATE,
  1100. &EventAttributes );
  1101. }
  1102. }
  1103. if ( !NT_SUCCESS(Status))
  1104. {
  1105. //
  1106. // could not make the event handle
  1107. //
  1108. return( Status );
  1109. }
  1110. }
  1111. WaitStatus = WaitForSingleObject( EventHandle,
  1112. 300*1000 ); // 5 minutes
  1113. if ( WaitStatus == WAIT_OBJECT_0 )
  1114. {
  1115. Hr = S_OK;
  1116. }
  1117. else
  1118. {
  1119. Hr = WaitStatus;
  1120. }
  1121. (VOID) NtClose( EventHandle );
  1122. return Hr;
  1123. }
  1124. #define UPDATE_KEYS L"UpdateKeys"
  1125. #define KEY_UPDATE_NEEDED 0
  1126. #define KEY_UPDATE_FAIL 1
  1127. #define KEY_UPDATE_SUCCESS 2
  1128. #define KEY_UPDATE_MAX 2
  1129. VOID
  1130. UpdateSecurityKeys(
  1131. )
  1132. /*+++
  1133. This function calls an API that generates new security keys for machines
  1134. that have been cloned. If the API fails, it is a fatal error. Whether it
  1135. succeeds or not, we record the result in the registry so that we don't
  1136. try again if the machine is restarted.
  1137. --*/
  1138. {
  1139. DWORD Status;
  1140. HKEY hKey = NULL;
  1141. DWORD dwType;
  1142. LONG RegData = KEY_UPDATE_NEEDED;
  1143. DWORD cbData;
  1144. SetupDebugPrint(L"Updating keys ...");
  1145. RegCreateKeyEx(
  1146. HKEY_LOCAL_MACHINE,
  1147. L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\OOBE",
  1148. 0,
  1149. NULL,
  1150. REG_OPTION_NON_VOLATILE,
  1151. KEY_READ | KEY_WRITE,
  1152. NULL,
  1153. &hKey,
  1154. NULL
  1155. );
  1156. if ( hKey ) {
  1157. cbData = sizeof(RegData);
  1158. Status = RegQueryValueEx(
  1159. hKey,
  1160. UPDATE_KEYS,
  1161. NULL,
  1162. &dwType,
  1163. (PVOID)&RegData,
  1164. &cbData
  1165. );
  1166. if ( Status != ERROR_SUCCESS ||
  1167. dwType != REG_DWORD ||
  1168. RegData > KEY_UPDATE_MAX
  1169. ) {
  1170. RegData = KEY_UPDATE_NEEDED;
  1171. }
  1172. }
  1173. switch (RegData) {
  1174. case KEY_UPDATE_NEEDED:
  1175. #if 1
  1176. Status = CryptResetMachineCredentials( 0 );
  1177. #else
  1178. // To test the failure case:
  1179. Status = ERROR_OUT_OF_PAPER;
  1180. #endif
  1181. if ( Status != ERROR_SUCCESS ) {
  1182. SetupDebugPrint1(L"... failed. Error = %d", Status);
  1183. MYASSERT( Status );
  1184. RegData = KEY_UPDATE_FAIL;
  1185. } else {
  1186. SetupDebugPrint(L"... succeeded.");
  1187. RegData = KEY_UPDATE_SUCCESS;
  1188. }
  1189. if ( hKey ) {
  1190. Status = RegSetValueEx(
  1191. hKey,
  1192. UPDATE_KEYS,
  1193. 0,
  1194. REG_DWORD,
  1195. (PVOID)&RegData,
  1196. sizeof(RegData)
  1197. );
  1198. MYASSERT( Status == ERROR_SUCCESS);
  1199. }
  1200. break;
  1201. case KEY_UPDATE_FAIL:
  1202. SetupDebugPrint(L"... not needed (previously failed).");
  1203. break;
  1204. case KEY_UPDATE_SUCCESS:
  1205. SetupDebugPrint(L"... not needed (previously succeeded).");
  1206. break;
  1207. default:
  1208. MYASSERT(0);
  1209. }
  1210. if (hKey) {
  1211. RegCloseKey(hKey);
  1212. }
  1213. // Note: FatalError() doesn't return.
  1214. if ( RegData == KEY_UPDATE_FAIL ) {
  1215. FatalError( MSG_LOG_CANT_SET_SECURITY, 0, 0 );
  1216. }
  1217. }
  1218. #ifdef _OCM
  1219. PVOID
  1220. #else
  1221. VOID
  1222. #endif
  1223. CommonInitialization(
  1224. VOID
  1225. )
  1226. /*++
  1227. Routine Description:
  1228. Initialize GUI Setup. This is common to upgrades and initial installs.
  1229. In this phase, we perform initialization tasks such as creating the
  1230. main background window, initializing the action log (into which we will
  1231. store error and other info), and fetch setup parameters from the
  1232. response file.
  1233. We also install the NT catalog file(s) and load system infs.
  1234. Note that any errors that occur during this phase are fatal.
  1235. NOTE: IF YOU ADD CODE TO THIS FUNCTION THAT REQUIRES A SERVICE TO RUN MAKE
  1236. SURE THAT IT IS NOT EXECUTED IN OOBE MODE. OOBE DELAYS THE STARTING OF
  1237. SERVICES UNTIL THE MACHINE NAME HAS BEEN CHANGED, SO WAITING FOR A
  1238. SERVICE TO START DURING INITIALIZATION WILL CAUSE A DEADLOCK.
  1239. Arguments:
  1240. None.
  1241. Return Value:
  1242. #ifdef _OCM
  1243. OC Manager context handle.
  1244. #else
  1245. None.
  1246. #endif
  1247. --*/
  1248. {
  1249. #define MyAnswerBufLen (2*MAX_PATH)
  1250. WCHAR MyAnswerFile[MyAnswerBufLen];
  1251. WCHAR MyAnswer[MyAnswerBufLen];
  1252. DWORD rc,wowretval, Err;
  1253. BOOL b;
  1254. HWND Billboard;
  1255. HCURSOR hCursor;
  1256. WCHAR Path[MAX_PATH];
  1257. PWSTR Cmd;
  1258. PWSTR Args;
  1259. WCHAR PathBuffer[4*MAX_PATH];
  1260. PWSTR PreInstallProfilesDir;
  1261. int i;
  1262. HANDLE h;
  1263. WCHAR CmdLine[MAX_PATH];
  1264. #ifdef _OCM
  1265. PVOID OcManagerContext;
  1266. #endif
  1267. TCHAR paramBuffer[MAX_PATH];
  1268. TCHAR profilePath[MAX_PATH];
  1269. DWORD Size;
  1270. //
  1271. // Get handle to heap so we can periodically validate it.
  1272. //
  1273. #if DBG
  1274. g_hSysSetupHeap = GetProcessHeap();
  1275. #endif
  1276. //
  1277. // Hack to make mini setup restartable.
  1278. //
  1279. if( MiniSetup ) {
  1280. HKEY hKeySetup;
  1281. // OOBE will set its own restartability.
  1282. //
  1283. if (! OobeSetup)
  1284. {
  1285. BEGIN_SECTION(L"Making mini setup restartable");
  1286. //
  1287. // Reset the SetupType entry to 1. We'll clear
  1288. // it at the end of gui-mode.
  1289. //
  1290. rc = (DWORD)RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1291. L"System\\Setup",
  1292. 0,
  1293. KEY_SET_VALUE | KEY_QUERY_VALUE,
  1294. &hKeySetup );
  1295. if(rc == NO_ERROR) {
  1296. //
  1297. // Set HKLM\System\Setup\SetupType Key to SETUPTYPE_NOREBOOT
  1298. //
  1299. rc = 1;
  1300. RegSetValueEx( hKeySetup,
  1301. TEXT( "SetupType" ),
  1302. 0,
  1303. REG_DWORD,
  1304. (CONST BYTE *)&rc,
  1305. sizeof(DWORD));
  1306. RegCloseKey(hKeySetup);
  1307. }
  1308. END_SECTION(L"Making mini setup restartable");
  1309. }
  1310. }
  1311. //
  1312. // Initialize the action log. This is where we log any errors or other
  1313. // info we think might be useful to the user.
  1314. //
  1315. BEGIN_SECTION(L"Initializing action log");
  1316. InitializeSetupLog(&SetuplogContext);
  1317. MainThreadId = GetCurrentThreadId();
  1318. OriginalInstallLocale = GetThreadLocale();
  1319. SavedExceptionFilter = SetUnhandledExceptionFilter( MyUnhandledExceptionFilter );
  1320. END_SECTION(L"Initializing action log");
  1321. Win95Upgrade = (SpSetupLoadParameter(pwWin95Upgrade,
  1322. paramBuffer,
  1323. sizeof(paramBuffer) / sizeof(paramBuffer[0])) &&
  1324. !lstrcmpi(paramBuffer, pwYes));
  1325. Upgrade = (SpSetupLoadParameter(pwNtUpgrade,
  1326. paramBuffer,
  1327. sizeof(paramBuffer) / sizeof(paramBuffer[0])) &&
  1328. !lstrcmpi(paramBuffer, pwYes));
  1329. #ifdef _X86_
  1330. if(Win95Upgrade){
  1331. UninstallEnabled = (SpSetupLoadParameter(pwBackupImage,
  1332. paramBuffer,
  1333. sizeof(paramBuffer) / sizeof(paramBuffer[0])) &&
  1334. 0xffffffff != GetFileAttributes(paramBuffer));
  1335. }
  1336. #endif
  1337. if (UninstallEnabled) {
  1338. //
  1339. // Put the boot.ini timeout to 30 seconds (or whatever the answer
  1340. // file says it should be), so that if setup fails, the user can
  1341. // clearly see the Cancel Setup option in the boot menu. The
  1342. // timeout gets set back to 5 seconds during PNP detection, so
  1343. // that PNP hung device logic still works.
  1344. //
  1345. RestoreBootTimeout();
  1346. }
  1347. if (!OobeSetup)
  1348. {
  1349. if(Win95Upgrade || !Upgrade){
  1350. Size = ARRAYSIZE(profilePath);
  1351. if(GetAllUsersProfileDirectory(profilePath, &Size)) {
  1352. DeleteOnRestartOfGUIMode(profilePath);
  1353. }
  1354. else{
  1355. SetupDebugPrint(TEXT("Cannot get All Users profile path."));
  1356. }
  1357. Size = ARRAYSIZE(profilePath);
  1358. if(GetDefaultUserProfileDirectory(profilePath, &Size)) {
  1359. DeleteOnRestartOfGUIMode(profilePath);
  1360. }
  1361. else{
  1362. SetupDebugPrint(TEXT("Cannot get Default User profile path."));
  1363. }
  1364. }
  1365. }
  1366. //
  1367. // Create the main setup background window. We need to know which product
  1368. // we are for the "Initializing" dialog.
  1369. //
  1370. SpSetProductTypeFromParameters();
  1371. #ifdef PRERELEASE
  1372. {
  1373. //
  1374. // Initialize test hook failure point (internal use only, for testing restartability)
  1375. //
  1376. WCHAR buffer[32];
  1377. //
  1378. // This next function call is just to ensure the global AnswerFile value is filled in.
  1379. // Since this is temp code, we call GetPrivateProfileString knowing some of the
  1380. // implementation of SpSetupLoadParameter.
  1381. //
  1382. SpSetupLoadParameter(pwWin95Upgrade,buffer,sizeof(buffer)/sizeof(WCHAR));
  1383. // Get the test hook that we want to fail on
  1384. g_TestHook = GetPrivateProfileInt (L"TestHooks", L"BugCheckPoint", 0, AnswerFile);
  1385. }
  1386. #endif
  1387. TESTHOOK(501);
  1388. if( !OobeSetup ) {
  1389. WCHAR p[16];
  1390. BEGIN_SECTION(L"Creating setup background window");
  1391. MainWindowHandle = CreateSetupWindow();
  1392. // Need to know this to calc the remaining time correct.
  1393. Win95Upgrade = (SpSetupLoadParameter(pwWin95Upgrade,p,sizeof(p)/sizeof(WCHAR)) && !lstrcmpi(p,pwYes));
  1394. // Now the billboard window is up. set the first estimate.
  1395. RemainingTime = CalcTimeRemaining(Phase_Initialize);
  1396. SetRemainingTime(RemainingTime);
  1397. Billboard = DisplayBillboard(MainWindowHandle,MSG_INITIALIZING);
  1398. hCursor = SetCursor( LoadCursor( NULL, IDC_WAIT ) );
  1399. END_SECTION(L"Creating setup background window");
  1400. }
  1401. //
  1402. // Update security keys for syspreped systems. See RAID 432224.
  1403. //
  1404. if ( MiniSetup ) {
  1405. HRESULT hrSamStatus;
  1406. HKEY hKey = NULL;
  1407. DWORD dwValue,
  1408. dwSize = sizeof(dwValue);
  1409. //
  1410. // Before calling UpdateSecurityKeys make sure that LSA is properly initialized.
  1411. //
  1412. if ( S_OK != (hrSamStatus = WaitForSamService()) ) {
  1413. SetuplogError(LogSevError,
  1414. TEXT("SAM initialization has timed out or failed. (rc=%1!x!)."),
  1415. 0,
  1416. hrSamStatus,
  1417. NULL,
  1418. NULL
  1419. );
  1420. }
  1421. // Determine if we have regenerated the SIDS without calling the UpdateSecurityKeys
  1422. //
  1423. if ( (RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGSTR_PATH_SYSPREP, 0, KEY_ALL_ACCESS, &hKey ) == NO_ERROR) &&
  1424. (RegQueryValueEx(hKey, REGSTR_VAL_SIDGENHISTORY, NULL, NULL, (LPBYTE)&dwValue, &dwSize) == ERROR_SUCCESS) &&
  1425. (dwValue == 1)
  1426. )
  1427. {
  1428. // We've regenerated SIDS without calling UpdateSecurityKeys, lets do it now
  1429. //
  1430. UpdateSecurityKeys();
  1431. RegDeleteValue(hKey,REGSTR_VAL_SIDGENHISTORY);
  1432. }
  1433. // Close the key that we opened
  1434. //
  1435. if ( hKey )
  1436. {
  1437. RegCloseKey(hKey);
  1438. }
  1439. }
  1440. //
  1441. // Support for SMS.
  1442. //
  1443. if( !MiniSetup ) {
  1444. try {
  1445. BEGIN_SECTION(L"Initializing SMS support");
  1446. if( SMSHandle = LoadLibrary( TEXT("ISMIF32")) ) {
  1447. if( InstallStatusMIF = (SMSPROC)GetProcAddress(SMSHandle,"InstallStatusMIF")) {
  1448. SetupDebugPrint( L"Setup: GetProcAddress on ISMIF32 succeeded." );
  1449. } else {
  1450. SetupDebugPrint( L"Setup: (non-critical error): Failed GetProcAddress on ISMIF32." );
  1451. }
  1452. } else {
  1453. SetupDebugPrint( L"Setup: (non-critical error): Failed load of ismif32.dll." );
  1454. }
  1455. END_SECTION(L"Initializing SMS support");
  1456. } except(EXCEPTION_EXECUTE_HANDLER) {
  1457. SetupDebugPrint( L"Setup: Exception in ISMIF32." );
  1458. END_SECTION(L"Initializing SMS support");
  1459. }
  1460. }
  1461. //
  1462. // Are we in safe mode?
  1463. //
  1464. // BUGBUG: OOBE shouldn't start in safe mode
  1465. //
  1466. #ifdef NOT_FOR_NT5
  1467. {
  1468. DWORD d;
  1469. HKEY hkey;
  1470. d = RegOpenKeyEx(HKEY_LOCAL_MACHINE,L"System\\CurrentControlSet\\Control\\SafeBoot\\Option",0,KEY_READ,&hkey);
  1471. if(d == NO_ERROR) {
  1472. RegCloseKey(hkey);
  1473. SetuplogError(
  1474. LogSevError,
  1475. L"Setup is running in safe-mode. This is not supported.\r\n",
  1476. 0,NULL,NULL);
  1477. }
  1478. }
  1479. #endif
  1480. //
  1481. // Prevent power management from kicking in.
  1482. //
  1483. BEGIN_SECTION(L"Shutting down power management");
  1484. SetThreadExecutionState(
  1485. ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
  1486. END_SECTION(L"Shutting down power management");
  1487. //
  1488. // Fetch our parameters. Note that this also takes care of initializing
  1489. // uniqueness stuff, so later initialization of preinstall and unattend mode
  1490. // don't ever have to know anything about the uniqueness stuff -- it's
  1491. // totally transparent to them.
  1492. //
  1493. if (MiniSetup) {
  1494. DWORD Err;
  1495. //
  1496. // Initialize unattended operation now. In the case of MiniSetup,
  1497. // we actually determine if we're unattended during UnattendInitialize.
  1498. // We make that determination based on whether or not there's an
  1499. // unattend file.
  1500. //
  1501. BEGIN_SECTION(L"Initialize unattended operation (mini-setup only)");
  1502. UnattendInitialize();
  1503. END_SECTION(L"Initialize unattended operation (mini-setup only)");
  1504. //
  1505. // Check to see if our unattend file specifies a test root certificate
  1506. // to be installed via a "TestCert" entry.
  1507. //
  1508. BEGIN_SECTION(L"Checking for test root certificate (mini-setup only)");
  1509. GetSystemDirectory(MyAnswerFile, MAX_PATH);
  1510. pSetupConcatenatePaths(MyAnswerFile, WINNT_GUI_FILE, MAX_PATH, NULL);
  1511. if(GetPrivateProfileString(WINNT_UNATTENDED,
  1512. WINNT_U_TESTCERT,
  1513. pwNull,
  1514. MyAnswer,
  1515. MyAnswerBufLen,
  1516. MyAnswerFile)) {
  1517. Err = SetupAddOrRemoveTestCertificate(MyAnswer, INVALID_HANDLE_VALUE);
  1518. if(Err != NO_ERROR) {
  1519. SetupDebugPrint2( L"SETUP: SetupAddOrRemoveTestCertificate(%ls) failed. Error = %d \n", MyAnswer, Err );
  1520. SetuplogError(LogSevError,
  1521. SETUPLOG_USE_MESSAGEID,
  1522. MSG_LOG_SYSSETUP_CERT_NOT_INSTALLED,
  1523. MyAnswer,
  1524. Err,
  1525. NULL,
  1526. SETUPLOG_USE_MESSAGEID,
  1527. Err,
  1528. NULL,
  1529. NULL
  1530. );
  1531. KillBillboard(Billboard);
  1532. FatalError(MSG_LOG_BAD_UNATTEND_PARAM, WINNT_U_TESTCERT, WINNT_UNATTENDED);
  1533. }
  1534. }
  1535. END_SECTION(L"Checking for test root certificate (mini-setup only)");
  1536. BEGIN_SECTION(L"Reinstalling SLP files");
  1537. GetDllCacheFolder(MyAnswer, MyAnswerBufLen);
  1538. pSetupConcatenatePaths(MyAnswer,L"OEMBIOS.CAT",MyAnswerBufLen,NULL);
  1539. if ( FileExists(MyAnswer, NULL) )
  1540. {
  1541. SetupInstallCatalog(MyAnswer);
  1542. }
  1543. END_SECTION(L"Reinstalling SLP files");
  1544. PnpSeed = GetSeed();
  1545. pSetupSetGlobalFlags(pSetupGetGlobalFlags()&~PSPGF_NO_VERIFY_INF);
  1546. BEGIN_SECTION(L"Initializing code signing policies");
  1547. InitializeCodeSigningPolicies(TRUE);
  1548. END_SECTION(L"Initializing code signing policies");
  1549. } else {
  1550. //
  1551. // Load up all the parameters. Note that this also initializes the
  1552. // unattend engine.
  1553. //
  1554. BEGIN_SECTION(L"Processing parameters from sif");
  1555. if( !SpSetupProcessParameters(&Billboard) ) {
  1556. KillBillboard(Billboard);
  1557. FatalError(MSG_LOG_LEGACYINTERFACE,0,0);
  1558. }
  1559. END_SECTION(L"Processing parameters from sif");
  1560. }
  1561. //
  1562. // see if we need to prop flag to supress driver prompts
  1563. // this puts setupapi into full headless mode
  1564. //
  1565. if (UnattendMode == UAM_FULLUNATTENDED) {
  1566. pSetupSetNoDriverPrompts(TRUE);
  1567. }
  1568. //
  1569. // load the service pack dll if it is present
  1570. //
  1571. if( !MiniSetup ) {
  1572. BEGIN_SECTION(L"Loading service pack (phase 1)");
  1573. hModSvcPack = MyLoadLibraryWithSignatureCheck( SVCPACK_DLL_NAME );
  1574. if (hModSvcPack) {
  1575. pSvcPackCallbackRoutine = (PSVCPACKCALLBACKROUTINE)GetProcAddress( hModSvcPack, SVCPACK_CALLBACK_NAME );
  1576. } else {
  1577. DWORD LastError = GetLastError();
  1578. if (LastError != ERROR_FILE_NOT_FOUND && LastError != ERROR_PATH_NOT_FOUND) {
  1579. SetuplogError(LogSevWarning,
  1580. SETUPLOG_USE_MESSAGEID,
  1581. MSG_LOG_SVCPACK_DLL_LOAD_FAILED,
  1582. LastError, NULL,NULL
  1583. );
  1584. }
  1585. }
  1586. CALL_SERVICE_PACK( SVCPACK_PHASE_1, 0, 0, 0 );
  1587. END_SECTION(L"Loading service pack (phase 1)");
  1588. }
  1589. #ifdef _X86_
  1590. //
  1591. // Win9x upgrade: do pre-migration work
  1592. //
  1593. if (Win95Upgrade && ! OobeSetup) {
  1594. BEGIN_SECTION(L"Win9x premigration (Win9x only)");
  1595. PreWin9xMigration();
  1596. END_SECTION(L"Win9x premigration (Win9x only)");
  1597. }
  1598. //
  1599. // Clean up drvlettr tag files from drvlettr mapping.
  1600. //
  1601. if( !MiniSetup ) {
  1602. BEGIN_SECTION(L"Cleaning up hard drive tags");
  1603. CleanUpHardDriveTags ();
  1604. END_SECTION(L"Cleaning up hard drive tags");
  1605. }
  1606. #endif
  1607. TESTHOOK(518);
  1608. //
  1609. // Initialize preinstallation.
  1610. //
  1611. if( !MiniSetup ) {
  1612. BEGIN_SECTION(L"Initializing OEM preinstall");
  1613. InitializePreinstall();
  1614. END_SECTION(L"Initializing OEM preinstall");
  1615. } else {
  1616. //
  1617. // MiniSetup case...
  1618. //
  1619. //
  1620. // Find out what platform we're on. This will initalize
  1621. // PlatformName.
  1622. //
  1623. SetUpProcessorNaming();
  1624. }
  1625. if( MiniSetup ) {
  1626. //
  1627. // MiniSetup case
  1628. //
  1629. DWORD CMP_WaitNoPendingInstallEvents (IN DWORD dwTimeout);
  1630. DWORD rc, Type, dword;
  1631. HKEY hKey;
  1632. WCHAR Data[MAX_PATH];
  1633. ULONG Size = MAX_PATH;
  1634. //
  1635. // Mini-setup is _never_ an upgrade...
  1636. //
  1637. MYASSERT(!Upgrade);
  1638. if( ProductType == PRODUCT_WORKSTATION) {
  1639. if( GetProductFlavor() == 4) {
  1640. SetupTitleStringId = IDS_TITLE_INSTALL_P;
  1641. }
  1642. else {
  1643. SetupTitleStringId = IDS_TITLE_INSTALL_W;
  1644. }
  1645. }
  1646. else
  1647. {
  1648. SetupTitleStringId = IDS_TITLE_INSTALL_S;
  1649. }
  1650. if(Unattended) {
  1651. //
  1652. // Initialize preinstallation.
  1653. //
  1654. UnattendMode = UAM_DEFAULTHIDE;
  1655. BEGIN_SECTION(L"Initializing OEM preinstall (mini-setup only)");
  1656. InitializePreinstall();
  1657. END_SECTION(L"Initializing OEM preinstall (mini-setup only)");
  1658. }
  1659. // OOBE will have already completed PnP at this point.
  1660. //
  1661. if (! OobeSetup)
  1662. {
  1663. //
  1664. // Let the network component do some cleanup before we start the
  1665. // pnp stuff
  1666. BEGIN_SECTION(L"Initial network setup cleanup (mini-setup only)");
  1667. CallNetworkSetupBack("DoInitialCleanup");
  1668. END_SECTION(L"Initial network setup cleanup (mini-setup only)");
  1669. }
  1670. BEGIN_SECTION(L"Opening syssetup.inf (mini-setup only)");
  1671. SyssetupInf = SetupOpenInfFile(L"syssetup.inf",NULL,INF_STYLE_WIN4,NULL);
  1672. END_SECTION(L"Opening syssetup.inf (mini-setup only)");
  1673. if(SyssetupInf == INVALID_HANDLE_VALUE) {
  1674. KillBillboard(Billboard);
  1675. FatalError(MSG_LOG_SYSINFBAD,L"syssetup.inf",0,0);
  1676. }
  1677. //
  1678. // Now go off and do the unattended locale stuff. We need
  1679. // to see if the user sent us any source path before we call
  1680. // out to intl.cpl because he'll want to copy some files.
  1681. // If there are no files, there's no need to even call
  1682. // intl.cpl
  1683. //
  1684. BEGIN_SECTION(L"Unattended locale initialization (mini-setup only)");
  1685. //
  1686. // Pickup the answer file.
  1687. //
  1688. GetSystemDirectory(MyAnswerFile,MAX_PATH);
  1689. pSetupConcatenatePaths(MyAnswerFile,WINNT_GUI_FILE,MAX_PATH,NULL);
  1690. if( GetPrivateProfileString( TEXT("Unattended"),
  1691. TEXT("InstallFilesPath"),
  1692. pwNull,
  1693. MyAnswer,
  1694. MyAnswerBufLen,
  1695. MyAnswerFile ) ) {
  1696. if( lstrcmp( pwNull, MyAnswer ) ) {
  1697. //
  1698. // He sent us a source path. We need to go ahead
  1699. // and set SourcePath and LegacySourcePath here
  1700. // because we'll be calling out to intl.cpl again
  1701. // during the regional settings page. So we might
  1702. // as well do the forward work here.
  1703. //
  1704. lstrcpy( LegacySourcePath, MyAnswer );
  1705. //
  1706. // And this is good enough for MiniSetup. We shouldn't
  1707. // ever need SourcePath, but set it just to make sure.
  1708. //
  1709. lstrcpy( SourcePath, MyAnswer );
  1710. wsprintf(
  1711. CmdLine,
  1712. L"/f:\"%s\" /s:\"%s\"",
  1713. MyAnswerFile,
  1714. LegacySourcePath
  1715. );
  1716. InvokeControlPanelApplet(L"intl.cpl",L"",0,CmdLine);
  1717. }
  1718. } else {
  1719. //
  1720. // Set the strings from the registry.
  1721. //
  1722. //
  1723. // Open HKLM\Software\Microsoft\Windows\CurrentVersion\Setup
  1724. //
  1725. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1726. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup"),
  1727. 0,
  1728. KEY_ALL_ACCESS,
  1729. &hKey );
  1730. if(rc == NO_ERROR) {
  1731. //
  1732. // Retrieve the original value.
  1733. //
  1734. rc = RegQueryValueEx(hKey,
  1735. TEXT("SourcePath"),
  1736. NULL,
  1737. &Type,
  1738. (LPBYTE)&Data,
  1739. &Size);
  1740. if( rc == ERROR_SUCCESS ) {
  1741. //
  1742. // Got it. Write it into SfcDisable.
  1743. //
  1744. lstrcpy( SourcePath, Data );
  1745. lstrcpy( LegacySourcePath, SourcePath );
  1746. pSetupConcatenatePaths( LegacySourcePath, PlatformName, MAX_PATH, NULL );
  1747. }
  1748. RegCloseKey(hKey);
  1749. }
  1750. }
  1751. END_SECTION(L"Unattended local initialization (mini-setup only)");
  1752. //
  1753. // Now give the PnP engine time to finish before we
  1754. // start the wizard. Only do this if we're NOT doing
  1755. // a -PnP though. The only way to do that is to look
  1756. // at the registry. We can tell if that's been
  1757. // requested by checking the value in:
  1758. // HKLM\SYSTEM\SETUP\MiniSetupDoPnP.
  1759. //
  1760. BEGIN_SECTION(L"Waiting for PnP engine to finish");
  1761. rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1762. L"SYSTEM\\SETUP",
  1763. 0,
  1764. KEY_READ,
  1765. &hKey );
  1766. if( rc == NO_ERROR ) {
  1767. Size = sizeof(DWORD);
  1768. rc = RegQueryValueEx( hKey,
  1769. L"MiniSetupDoPnP",
  1770. NULL,
  1771. &Type,
  1772. (LPBYTE)&dword,
  1773. &Size );
  1774. if( (rc == NO_ERROR) && (dword == 1) ) {
  1775. PnPReEnumeration = TRUE;
  1776. } else {
  1777. //
  1778. // Wait.
  1779. //
  1780. CMP_WaitNoPendingInstallEvents ( INFINITE );
  1781. //
  1782. // Update PnP drivers if specified from answerfile.
  1783. //
  1784. if ( GetPrivateProfileString( TEXT("Unattended"),
  1785. TEXT("UpdateInstalledDrivers"),
  1786. pwNull,
  1787. MyAnswer,
  1788. MyAnswerBufLen,
  1789. MyAnswerFile ) )
  1790. {
  1791. if ( 0 == _wcsicmp( TEXT("YES"), MyAnswer ) ) {
  1792. BEGIN_SECTION(L"Updating PnP Drivers");
  1793. UpdatePnpDeviceDrivers();
  1794. END_SECTION(L"Updating PnP Drivers");
  1795. }
  1796. }
  1797. }
  1798. }
  1799. END_SECTION(L"Waiting for PnP engine to finish");
  1800. } else { // !MiniSetup
  1801. //
  1802. // fix problem with IntelliType Manager conflict.
  1803. //
  1804. RemoveMSKeyboardPtrPropSheet ();
  1805. //
  1806. // Fix Wordpad registry entry.
  1807. //
  1808. FixWordPadReg ();
  1809. if(Unattended) {
  1810. BEGIN_SECTION(L"Invoking external app (unattended only)");
  1811. //
  1812. // Set the current dir to %windir% -- to be consistent with
  1813. // UserExecuteCmd
  1814. //
  1815. GetWindowsDirectory(PathBuffer,MAX_PATH);
  1816. SetCurrentDirectory(PathBuffer);
  1817. //
  1818. // The program to execute is in 2 parts: DetachedProgram and Arguments.
  1819. //
  1820. if(Cmd = UnattendFetchString(UAE_PROGRAM)) {
  1821. if(Cmd[0]) {
  1822. Args = UnattendFetchString(UAE_ARGUMENT);
  1823. ExpandEnvironmentStrings(Cmd,PathBuffer,MAX_PATH);
  1824. ExpandEnvironmentStrings(Args ? Args : L"",PathBuffer+MAX_PATH,3*MAX_PATH);
  1825. if(!InvokeExternalApplication(PathBuffer,PathBuffer+MAX_PATH,NULL)) {
  1826. SetuplogError(
  1827. LogSevError,
  1828. SETUPLOG_USE_MESSAGEID,
  1829. MSG_LOG_DETACHED_PROGRAM_FAILED,
  1830. PathBuffer,
  1831. NULL,NULL);
  1832. }
  1833. if(Args) {
  1834. MyFree(Args);
  1835. }
  1836. }
  1837. MyFree(Cmd);
  1838. }
  1839. END_SECTION(L"Invoking external app (unattended only)");
  1840. }
  1841. if(!Upgrade) {
  1842. //
  1843. // See if the user wants the profiles in a custom
  1844. // location.
  1845. //
  1846. if (Unattended && UnattendAnswerTable[UAE_PROFILESDIR].Answer.String) {
  1847. if (!SetProfilesDirInRegistry(UnattendAnswerTable[UAE_PROFILESDIR].Answer.String)) {
  1848. b = FALSE;
  1849. }
  1850. }
  1851. //
  1852. // In preinstall scenarios the OEM might "preload" the Default Users
  1853. // or All Users profile with links. Currently the Profiles or Documents and Settings
  1854. // directory is created in Winlogon as services.exe need to use it.
  1855. //
  1856. // We have a changed behavior with Whistler. If the OEM wants to overlay a Profiles directory on the system
  1857. // then he needs to postfix it with $$. This is also true in the cases where he needs to provide a $$rename.txt.
  1858. // That way winlogon will always create a true folder without .Windows appended. We then just come here and overlay
  1859. //
  1860. //
  1861. if(Preinstall) {
  1862. PSID AdminSid = NULL;
  1863. WCHAR AdminAccountName[MAX_PATH];
  1864. DWORD dwsize;
  1865. BEGIN_SECTION(L"Initialize user profiles (preinstall)");
  1866. PreInstallProfilesDir = PathBuffer;
  1867. if (Unattended && UnattendAnswerTable[UAE_PROFILESDIR].Answer.String) {
  1868. lstrcpy( Path, UnattendAnswerTable[UAE_PROFILESDIR].Answer.String );
  1869. } else {
  1870. dwsize = MAX_PATH;
  1871. GetProfilesDirectory( Path, &dwsize );
  1872. }
  1873. lstrcpy( PreInstallProfilesDir, Path );
  1874. lstrcat( PreInstallProfilesDir, L"$$" );
  1875. //
  1876. // Recreate it from scratch.
  1877. //
  1878. ProcessRegistryFiles( Billboard );
  1879. InitializeProfiles( TRUE );
  1880. //
  1881. // Since the Profiles directory maybe (actually is) already created by Winlogon
  1882. // we now just special case the "Documents and Settings$$" directory and merge it after InitializeProfiles.
  1883. // This is hacky but will save the people who do a winnt.exe based PreInstall. They just
  1884. // need to change their first directive to be a rename to the Profiles folder postfixed with a "$$".
  1885. // WE will notice this special directory and do a merge with the current Profiles directory.
  1886. //
  1887. if(FileExists(PreInstallProfilesDir,NULL)) {
  1888. if( (Err = TreeCopy(PreInstallProfilesDir,Path)) == NO_ERROR ){
  1889. Delnode( PreInstallProfilesDir);
  1890. }else {
  1891. SetuplogError(LogSevWarning,
  1892. L"Setup (PreInstall) Failed to tree copy Profiles Dir %1 to %2 (TreeCopy failed %1!u!)\r\n",
  1893. 0, PreInstallProfilesDir, Path, Err, NULL,NULL
  1894. );
  1895. }
  1896. }
  1897. END_SECTION(L"Initialize user profiles (preinstall)");
  1898. }
  1899. }
  1900. if( !Preinstall ) {
  1901. //
  1902. // Create/upgrade the registry
  1903. //
  1904. BEGIN_SECTION(L"Create/upgrade registry");
  1905. ProcessRegistryFiles(Billboard);
  1906. END_SECTION(L"Create/upgrade registry");
  1907. //
  1908. // Initialize user profiles
  1909. //
  1910. BEGIN_SECTION(L"Initializing user profiles");
  1911. InitializeProfiles(TRUE);
  1912. END_SECTION(L"Initializing user profiles");
  1913. }
  1914. //
  1915. // Set fonts directory to system + read only. This causes
  1916. // explorer to treat the directory specially and allows the font
  1917. // folder to work.
  1918. //
  1919. GetWindowsDirectory(Path,MAX_PATH);
  1920. pSetupConcatenatePaths(Path,L"FONTS",MAX_PATH,NULL);
  1921. SetFileAttributes(Path,FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM);
  1922. //
  1923. // Copy some files.
  1924. //
  1925. if(!Upgrade) {
  1926. BEGIN_SECTION(L"Copying System Files");
  1927. if(!CopySystemFiles()) {
  1928. b = FALSE;
  1929. }
  1930. END_SECTION(L"Copying System Files");
  1931. } else {
  1932. BEGIN_SECTION(L"Upgrading System Files");
  1933. if(!UpgradeSystemFiles()) {
  1934. b = FALSE;
  1935. }
  1936. END_SECTION(L"Upgrading System Files");
  1937. }
  1938. //
  1939. // Install default language group
  1940. //
  1941. BEGIN_SECTION(L"Initializing regional settings");
  1942. pSetupInitRegionalSettings(Billboard);
  1943. END_SECTION(L"Initializing regional settings");
  1944. wsprintf(
  1945. CmdLine,
  1946. L"/f:\"%s\" /s:\"%s\"",
  1947. AnswerFile,
  1948. LegacySourcePath
  1949. );
  1950. InvokeControlPanelApplet(L"intl.cpl",L"",0,CmdLine);
  1951. //
  1952. // If upgrade, start watching for changes to the user's
  1953. // profile directory and the current user hive. These changes will
  1954. // be propagated to the userdifr hive.
  1955. // Need to be after InitializeProfiles so that Getspecialfolder is
  1956. // pointing correctly.
  1957. //
  1958. if(Upgrade) {
  1959. DWORD reRet;
  1960. MYASSERT( !OobeSetup );
  1961. reRet = WatchStart(&WatchHandle);
  1962. if(reRet != NO_ERROR) {
  1963. WatchHandle = NULL;
  1964. }
  1965. } else {
  1966. WatchHandle = NULL;
  1967. }
  1968. //
  1969. // Start any requested accessibility utilities
  1970. //
  1971. SpStartAccessibilityUtilities(Billboard);
  1972. //
  1973. // Let the network component do some cleanup before we start the pnp stuff
  1974. //
  1975. BEGIN_SECTION(L"Network setup initial cleanup");
  1976. CallNetworkSetupBack("DoInitialCleanup");
  1977. END_SECTION(L"Network setup initial cleanup");
  1978. //
  1979. // Do self registration of some components that may be needed during
  1980. // setup. This includes initialization of darwin.
  1981. //
  1982. BEGIN_SECTION(L"Registering Phase 1 Dlls");
  1983. RegisterOleControls(MainWindowHandle,SyssetupInf,NULL,0,0,L"RegistrationPhase1");
  1984. END_SECTION(L"Registering Phase 1 Dlls");
  1985. // Call the Compatibility infs. ProcessCompatibilityInfs in turn calls
  1986. // DoInstallComponentInfs with the unattend inf and section
  1987. if( Upgrade )
  1988. {
  1989. BEGIN_SECTION(L"Processing compatibility infs (upgrade)");
  1990. ProcessCompatibilityInfs( Billboard, INVALID_HANDLE_VALUE, 0 );
  1991. END_SECTION(L"Processing compatibility infs (upgrade)");
  1992. }
  1993. } // else !MiniSetup
  1994. TESTHOOK(519);
  1995. //
  1996. // We need to see if the user wants us to extend our partition.
  1997. // We'll do it here in case the user gave us a partition that's
  1998. // just big enough to fit on (i.e. we'd run out of disk space
  1999. // later in gui-mode. Some OEM will want this).
  2000. //
  2001. // Besides that, there isn't enough stuff in this function yet...
  2002. //
  2003. GetSystemDirectory(MyAnswerFile,MAX_PATH);
  2004. pSetupConcatenatePaths(MyAnswerFile,WINNT_GUI_FILE,MAX_PATH,NULL);
  2005. if( GetPrivateProfileString( TEXT("Unattended"),
  2006. TEXT("ExtendOemPartition"),
  2007. pwNull,
  2008. MyAnswer,
  2009. MyAnswerBufLen,
  2010. MyAnswerFile ) ) {
  2011. if( lstrcmp( pwNull, MyAnswer ) ) {
  2012. //
  2013. // Yep, he wants us to do it. Go extend
  2014. // the partition we installed on.
  2015. //
  2016. rc = wcstoul( MyAnswer, NULL, 10 );
  2017. if( rc > 0 ) {
  2018. //
  2019. // 1 means size it maximally, any other non-0
  2020. // number means extend by that many MB
  2021. //
  2022. BEGIN_SECTION(L"Extending partition");
  2023. ExtendPartition( MyAnswerFile[0], (rc == 1) ? 0 : rc );
  2024. END_SECTION(L"Extending partition");
  2025. }
  2026. }
  2027. }
  2028. if (!OobeSetup)
  2029. {
  2030. // OOBE will initialize external modules later.
  2031. //
  2032. // If OOBE is running, services.exe is waiting for OOBE to signal it
  2033. // before initializing the Services Control Manager. (This allows OOBE
  2034. // to perform actions like change the computer name without affecting
  2035. // services that rely on those actions.) If initialization of an
  2036. // external object waits for the SCM to start the system will deadlock.
  2037. //
  2038. InitializeExternalModules(
  2039. TRUE,
  2040. &OcManagerContext
  2041. );
  2042. TESTHOOK(520);
  2043. }
  2044. if( !OobeSetup ) {
  2045. KillBillboard(Billboard);
  2046. SetCursor( hCursor );
  2047. }
  2048. #ifdef _OCM
  2049. return(OcManagerContext);
  2050. #endif
  2051. }
  2052. VOID
  2053. InitializeExternalModules(
  2054. BOOL DoSetupStuff,
  2055. PVOID* pOcManagerContext // optional
  2056. )
  2057. {
  2058. PVOID OcManagerContext;
  2059. pSetupWaitForScmInitialization();
  2060. if (DoSetupStuff)
  2061. {
  2062. if (MiniSetup)
  2063. {
  2064. RunExternalUniqueness();
  2065. }
  2066. OcManagerContext = FireUpOcManager();
  2067. if (NULL != pOcManagerContext)
  2068. {
  2069. *pOcManagerContext = OcManagerContext;
  2070. }
  2071. }
  2072. }
  2073. VOID
  2074. SetDefaultPowerScheme(
  2075. VOID
  2076. )
  2077. /*++
  2078. Routine Description:
  2079. Arguments:
  2080. None.
  2081. Return Value:
  2082. None.
  2083. --*/
  2084. {
  2085. #define AnswerBufLen (4*MAX_PATH)
  2086. WCHAR AnswerFile[AnswerBufLen];
  2087. WCHAR Answer[AnswerBufLen];
  2088. SYSTEM_POWER_CAPABILITIES SysPwrCapabilities;
  2089. BOOLEAN Enable;
  2090. NTSTATUS Error;
  2091. //
  2092. // Figure out what the appropriate power scheme is and set it.
  2093. //
  2094. if (ProductType != PRODUCT_WORKSTATION) {
  2095. //
  2096. // Set to Always on (Servers)
  2097. //
  2098. SetupDebugPrint(L"Power scheme: server.");
  2099. if (!SetActivePwrScheme(3, NULL, NULL)) {
  2100. SetupDebugPrint1(L"SetActivePwrScheme failed. Error = %d", GetLastError());
  2101. } else {
  2102. SetupDebugPrint(L"SetActivePwrScheme succeeded.");
  2103. }
  2104. } else if (IsLaptop()) {
  2105. //
  2106. // Set to Portable (Laptop)
  2107. //
  2108. SetupDebugPrint(L"Power scheme: laptop.");
  2109. if (!SetActivePwrScheme(1, NULL, NULL)) {
  2110. SetupDebugPrint1(L"SetActivePwrScheme failed. Error = %d", GetLastError());
  2111. } else {
  2112. SetupDebugPrint(L"SetActivePwrScheme succeeded.");
  2113. }
  2114. } else {
  2115. //
  2116. // Set to Home/Office (Desktop)
  2117. //
  2118. SetupDebugPrint(L"Power scheme: desktop.");
  2119. if (!SetActivePwrScheme(0, NULL, NULL)) {
  2120. SetupDebugPrint1(L"SetActivePwrScheme failed. Error = %d", GetLastError());
  2121. } else {
  2122. SetupDebugPrint(L"SetActivePwrScheme succeeded.");
  2123. }
  2124. }
  2125. //
  2126. // Now take care of any hibernation settings the user may be asking us
  2127. // to apply via the unattend file.
  2128. //
  2129. //
  2130. // Pickup the answer file.
  2131. //
  2132. GetSystemDirectory(AnswerFile,MAX_PATH);
  2133. pSetupConcatenatePaths(AnswerFile,WINNT_GUI_FILE,MAX_PATH,NULL);
  2134. //
  2135. // Is Hibernation specified?
  2136. //
  2137. if( GetPrivateProfileString( WINNT_UNATTENDED,
  2138. TEXT("Hibernation"),
  2139. pwNull,
  2140. Answer,
  2141. AnswerBufLen,
  2142. AnswerFile ) ) {
  2143. if( _wcsicmp( L"NO", Answer ) == 0 ) {
  2144. REGVALITEM RegistryItem[1];
  2145. DWORD RegErr, d = 1;
  2146. // Request the privilege to create a pagefile. Oddly enough this is needed
  2147. // to disable hibernation.
  2148. //
  2149. pSetupEnablePrivilege(SE_CREATE_PAGEFILE_NAME, TRUE);
  2150. //
  2151. // It is set to No. Go ahead and disable hibernation.
  2152. //
  2153. Enable = FALSE;
  2154. Error = NtPowerInformation ( SystemReserveHiberFile,
  2155. &Enable,
  2156. sizeof (Enable),
  2157. NULL,
  2158. 0 );
  2159. if (!NT_SUCCESS(Error)) {
  2160. SetuplogError(LogSevWarning,
  2161. L"Setup failed to disable hibernation as specified by the answer file (NtPowerInformation failed %1!u!)\r\n",
  2162. 0, Error, NULL,NULL
  2163. );
  2164. return;
  2165. }
  2166. RegistryItem[0].Data = &d;
  2167. RegistryItem[0].Size = sizeof(d);
  2168. RegistryItem[0].Type = REG_DWORD;
  2169. RegistryItem[0].Name = L"HibernationPreviouslyEnabled";
  2170. RegErr = SetGroupOfValues(
  2171. HKEY_LOCAL_MACHINE,
  2172. L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
  2173. RegistryItem,
  2174. 1
  2175. );
  2176. if(RegErr != NO_ERROR){
  2177. SetuplogError(LogSevWarning,
  2178. L"Setup failed to disable hibernation as specified by the answer file (SetGroupOfValues failed %1!u!)\r\n",
  2179. 0, RegErr, NULL,NULL
  2180. );
  2181. }
  2182. }
  2183. }
  2184. }
  2185. VOID
  2186. SetupAddAlternateComputerName(
  2187. PWSTR AltComputerName
  2188. )
  2189. /*++
  2190. Routine Description:
  2191. This function adds an alternate compture name on the specified transport.
  2192. Arguments:
  2193. Transport - Transport to add the computer name on.
  2194. AltComputerName - Alternate computer name to add
  2195. EmulatedDomain - Emulated Domain to add computer name on
  2196. Return Value:
  2197. None.
  2198. TransportName - type browdeb dn to get a list of transports.
  2199. programatically, copy GetBrowserTransportList into here.
  2200. Once I get the list, find the first one that contains "Netbt_tcpip"
  2201. and use that string.
  2202. EmulatedDomain, just leave it null
  2203. --*/
  2204. {
  2205. #include <ntddbrow.h>
  2206. #define LDM_PACKET_SIZE (sizeof(LMDR_REQUEST_PACKET)+(LM20_CNLEN+1)*sizeof(WCHAR))
  2207. HANDLE BrowserHandle;
  2208. UNICODE_STRING DeviceName;
  2209. IO_STATUS_BLOCK IoStatusBlock;
  2210. OBJECT_ATTRIBUTES ObjectAttributes;
  2211. NTSTATUS Status;
  2212. PLMDR_REQUEST_PACKET RequestPacket = NULL;
  2213. LPBYTE Where;
  2214. PLMDR_TRANSPORT_LIST TransportList = NULL,
  2215. TransportEntry = NULL;
  2216. extern NET_API_STATUS
  2217. BrDgReceiverIoControl(
  2218. IN HANDLE FileHandle,
  2219. IN ULONG DgReceiverControlCode,
  2220. IN PLMDR_REQUEST_PACKET Drp,
  2221. IN ULONG DrpSize,
  2222. IN PVOID SecondBuffer OPTIONAL,
  2223. IN ULONG SecondBufferLength,
  2224. OUT PULONG Information OPTIONAL
  2225. );
  2226. extern NET_API_STATUS
  2227. DeviceControlGetInfo(
  2228. IN HANDLE FileHandle,
  2229. IN ULONG DeviceControlCode,
  2230. IN PVOID RequestPacket,
  2231. IN ULONG RequestPacketLength,
  2232. OUT LPVOID *OutputBuffer,
  2233. IN ULONG PreferedMaximumLength,
  2234. IN ULONG BufferHintSize,
  2235. OUT PULONG Information OPTIONAL
  2236. );
  2237. //
  2238. // Open a browser handle.
  2239. //
  2240. RtlInitUnicodeString( &DeviceName, DD_BROWSER_DEVICE_NAME_U);
  2241. InitializeObjectAttributes( &ObjectAttributes,
  2242. &DeviceName,
  2243. OBJ_CASE_INSENSITIVE,
  2244. NULL,
  2245. NULL );
  2246. Status = NtOpenFile( &BrowserHandle,
  2247. SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
  2248. &ObjectAttributes,
  2249. &IoStatusBlock,
  2250. FILE_SHARE_READ | FILE_SHARE_WRITE,
  2251. FILE_SYNCHRONOUS_IO_NONALERT );
  2252. if( NT_SUCCESS(Status) ) {
  2253. RequestPacket = MyMalloc( LDM_PACKET_SIZE );
  2254. if( !RequestPacket ) {
  2255. NtClose( BrowserHandle );
  2256. return;
  2257. }
  2258. ZeroMemory( RequestPacket, LDM_PACKET_SIZE );
  2259. //
  2260. // Get a transport name.
  2261. //
  2262. RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION_DOM;
  2263. RequestPacket->Type = EnumerateXports;
  2264. RtlInitUnicodeString(&RequestPacket->TransportName, NULL);
  2265. RtlInitUnicodeString(&RequestPacket->EmulatedDomainName, NULL);
  2266. Status = DeviceControlGetInfo( BrowserHandle,
  2267. IOCTL_LMDR_ENUMERATE_TRANSPORTS,
  2268. RequestPacket,
  2269. LDM_PACKET_SIZE,
  2270. (PVOID *)&TransportList,
  2271. 0xffffffff,
  2272. 4096,
  2273. NULL );
  2274. if( NT_SUCCESS(Status) ) {
  2275. //
  2276. // Nuke the transport name in the request packet just to be safe.
  2277. //
  2278. RequestPacket->TransportName.Buffer = NULL;
  2279. //
  2280. // Now figure out which entry in the transport list is the
  2281. // one we want.
  2282. //
  2283. TransportEntry = TransportList;
  2284. while( TransportEntry != NULL ) {
  2285. _wcslwr( TransportEntry->TransportName );
  2286. if( wcsstr(TransportEntry->TransportName, L"netbt_tcpip") ) {
  2287. //
  2288. // Got it.
  2289. //
  2290. RequestPacket->TransportName.Buffer = TransportEntry->TransportName;
  2291. RequestPacket->TransportName.Length = (USHORT)TransportEntry->TransportNameLength;
  2292. break;
  2293. }
  2294. //
  2295. // Look at the next entry.
  2296. //
  2297. if (TransportEntry->NextEntryOffset == 0) {
  2298. TransportEntry = NULL;
  2299. } else {
  2300. TransportEntry = (PLMDR_TRANSPORT_LIST)((PCHAR)TransportEntry+TransportEntry->NextEntryOffset);
  2301. }
  2302. }
  2303. if( RequestPacket->TransportName.Buffer ) {
  2304. //
  2305. // Prepare a packet to send him.
  2306. //
  2307. RequestPacket->Version = LMDR_REQUEST_PACKET_VERSION;
  2308. RtlInitUnicodeString(&RequestPacket->EmulatedDomainName, NULL);
  2309. RequestPacket->Parameters.AddDelName.Type = AlternateComputerName;
  2310. RequestPacket->Parameters.AddDelName.DgReceiverNameLength = min( wcslen(AltComputerName)*sizeof(WCHAR),
  2311. LM20_CNLEN*sizeof(WCHAR));
  2312. wcsncpy(RequestPacket->Parameters.AddDelName.Name, AltComputerName,LM20_CNLEN+1);
  2313. RequestPacket->Parameters.AddDelName.Name[LM20_CNLEN] = (WCHAR)L'\0';
  2314. Where = ((LPBYTE)(RequestPacket->Parameters.AddDelName.Name)) +
  2315. RequestPacket->Parameters.AddDelName.DgReceiverNameLength +
  2316. sizeof(WCHAR);
  2317. Status = BrDgReceiverIoControl( BrowserHandle,
  2318. IOCTL_LMDR_ADD_NAME_DOM,
  2319. RequestPacket,
  2320. (DWORD)(Where - (LPBYTE)RequestPacket),
  2321. NULL,
  2322. 0,
  2323. NULL );
  2324. }
  2325. }
  2326. MyFree( RequestPacket );
  2327. NtClose( BrowserHandle );
  2328. }
  2329. }
  2330. BOOL
  2331. RestoreBootTimeout(
  2332. VOID
  2333. )
  2334. {
  2335. WCHAR AnswerFile[MAX_PATH];
  2336. WCHAR Answer[50];
  2337. DWORD Val;
  2338. //
  2339. // Pickup the answer file.
  2340. //
  2341. GetSystemDirectory(AnswerFile,MAX_PATH);
  2342. pSetupConcatenatePaths(AnswerFile,WINNT_GUI_FILE,MAX_PATH,NULL);
  2343. //
  2344. // Is boot timeout specified?
  2345. //
  2346. if( GetPrivateProfileString( TEXT("SetupData"),
  2347. WINNT_S_OSLOADTIMEOUT,
  2348. pwNull,
  2349. Answer,
  2350. sizeof(Answer)/sizeof(TCHAR),
  2351. AnswerFile ) ) {
  2352. if( lstrcmp( pwNull, Answer ) ) {
  2353. //
  2354. // We got an answer. If it's valid, then set it.
  2355. //
  2356. Val = wcstoul(Answer,NULL,10);
  2357. } else {
  2358. Val = 30;
  2359. }
  2360. } else {
  2361. Val = 30;
  2362. }
  2363. return ChangeBootTimeout(Val);
  2364. }
  2365. VOID
  2366. PrepareForNetSetup(
  2367. VOID
  2368. )
  2369. /*++
  2370. Routine Description:
  2371. Arguments:
  2372. None.
  2373. Return Value:
  2374. None.
  2375. --*/
  2376. {
  2377. BOOL b = TRUE;
  2378. //
  2379. // Create Windows NT software key entry
  2380. //
  2381. // if(!MiniSetup && !CreateWindowsNtSoftwareEntry(TRUE)) {
  2382. // b = FALSE;
  2383. // }
  2384. //
  2385. // Create InstallDate value entry in Windows NT software key.
  2386. // This has to happen after the Date/Time wizard page was executed, when the user can
  2387. // no longer go back to that page.
  2388. //
  2389. if(!CreateInstallDateEntry()) {
  2390. b = FALSE;
  2391. }
  2392. if(!SetProductIdInRegistry()) {
  2393. b = FALSE;
  2394. }
  2395. if(!StoreNameOrgInRegistry( NameOrgName, NameOrgOrg )) {
  2396. b = FALSE;
  2397. }
  2398. if(!MiniSetup && !SetEnabledProcessorCount()) {
  2399. b = FALSE;
  2400. }
  2401. if( (!MiniSetup && !SetAccountsDomainSid(0,Win32ComputerName)) ||
  2402. (!SetComputerNameEx(ComputerNamePhysicalDnsHostname, ComputerName)) ) {
  2403. //
  2404. // Set account domain sid, as well as the computer name.
  2405. // Also create the sam event that SAM will use to signal us
  2406. // when it's finished initializing.
  2407. // Any failures here are fatal.
  2408. //
  2409. FatalError(MSG_LOG_SECURITY_CATASTROPHE,0,0);
  2410. }
  2411. if( !RestoreBootTimeout() ){
  2412. SetupDebugPrint( L"Setup: (non-critical error) Failed to restore boot timeout values\n" );
  2413. }
  2414. #ifndef _WIN64
  2415. //
  2416. // Install netdde
  2417. //
  2418. if(!InstallNetDDE()) {
  2419. b = FALSE;
  2420. }
  2421. #endif
  2422. SetUpDataBlock();
  2423. //
  2424. // In the case of MiniSetup, we're about to go into the
  2425. // networking wizard pages. Remember though that lots of
  2426. // our default components have already been installed. This
  2427. // means that they won't be re-installed, which means the
  2428. // related services won't be started. Network setup isn't
  2429. // smart enough to check to see if these services are started
  2430. // before proceeding (which results in his failure). To get
  2431. // around that, we'll start the services right here.
  2432. //
  2433. // Currently, here's what we need to start:
  2434. // tcpip
  2435. // dhcp
  2436. // dnscache
  2437. // Netman
  2438. // lmhosts
  2439. // LanmanWorkstation
  2440. //
  2441. if( MiniSetup ) {
  2442. SetupStartService( L"tcpip", FALSE );
  2443. SetupStartService( L"dhcp", FALSE );
  2444. SetupStartService( L"dnscache", FALSE );
  2445. SetupStartService( L"Netman", FALSE );
  2446. SetupStartService( L"lmhosts", FALSE );
  2447. SetupStartService( L"LanmanWorkstation", TRUE );
  2448. //
  2449. // HACK: fix up the computername before we go off and
  2450. // try and join a domain.
  2451. //
  2452. SetupAddAlternateComputerName( ComputerName );
  2453. }
  2454. if(!b) {
  2455. SetuplogError(
  2456. LogSevError,
  2457. SETUPLOG_USE_MESSAGEID,
  2458. MSG_LOG_PREPARE_NET_FAILED,
  2459. NULL,NULL);
  2460. }
  2461. }
  2462. VOID
  2463. PrepareForNetUpgrade(
  2464. VOID
  2465. )
  2466. {
  2467. BOOL b = TRUE;
  2468. if( !RestoreBootTimeout() ){
  2469. SetupDebugPrint( L"Setup: (non-critical error) Failed to restore boot timeout values\n" );
  2470. }
  2471. // if(!CreateWindowsNtSoftwareEntry(TRUE)) {
  2472. // b = FALSE;
  2473. // }
  2474. //
  2475. // Create InstallDate value entry in Windows NT software key.
  2476. // This has to happen after the Date/Time wizard page was executed, when the user can
  2477. // no longer go back to that page.
  2478. //
  2479. if(!CreateInstallDateEntry()) {
  2480. b = FALSE;
  2481. }
  2482. if(!SetEnabledProcessorCount()) {
  2483. b = FALSE;
  2484. }
  2485. SetUpDataBlock();
  2486. if(!b) {
  2487. SetuplogError(
  2488. LogSevError,
  2489. SETUPLOG_USE_MESSAGEID,
  2490. MSG_LOG_PREPARE_NET_FAILED,
  2491. NULL,NULL);
  2492. }
  2493. }
  2494. VOID
  2495. ProcessShellUnattendSettings(
  2496. VOID
  2497. )
  2498. {
  2499. WCHAR PathBuffer[MAX_PATH];
  2500. if (GetSystemDirectory(PathBuffer,MAX_PATH) == 0) {
  2501. MYASSERT(FALSE);
  2502. return;
  2503. }
  2504. pSetupConcatenatePaths(PathBuffer, WINNT_GUI_FILE, MAX_PATH, NULL);
  2505. SetupShellSettings(PathBuffer, TEXT("Shell"));
  2506. }
  2507. BOOL
  2508. SetupShellSettings(
  2509. LPWSTR lpszUnattend,
  2510. LPWSTR lpszSection
  2511. )
  2512. {
  2513. BOOL bRet = TRUE;
  2514. DWORD dwError;
  2515. WCHAR Answer[MAX_PATH];
  2516. // Check the "DefaultStartPanelOff" key to see if the user wants to have the
  2517. // start panel off by default
  2518. if( GetPrivateProfileString( lpszSection,
  2519. TEXT("DefaultStartPanelOff"),
  2520. pwNull,
  2521. Answer,
  2522. MAX_PATH,
  2523. lpszUnattend) ) {
  2524. if ( ( lstrcmpi( pwYes, Answer ) == 0 ) || ( lstrcmpi( pwNo, Answer ) == 0 ) ) {
  2525. HKEY hkStartPanel;
  2526. if ( RegCreateKey( HKEY_LOCAL_MACHINE,
  2527. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\StartMenu\\StartPanel"),
  2528. &hkStartPanel ) == ERROR_SUCCESS ) {
  2529. DWORD dwData;
  2530. if ( lstrcmpi( pwYes, Answer ) == 0 )
  2531. {
  2532. dwData = 1;
  2533. }
  2534. else
  2535. {
  2536. dwData = 0;
  2537. }
  2538. dwError = RegSetValueEx( hkStartPanel,
  2539. TEXT("DefaultStartPanelOff"),
  2540. 0,
  2541. REG_DWORD,
  2542. (BYTE*)&dwData,
  2543. sizeof(dwData) );
  2544. if (dwError != ERROR_SUCCESS)
  2545. {
  2546. bRet = FALSE;
  2547. SetuplogError(LogSevWarning,
  2548. L"SETUP: ProcessShellUnattendSettings() failed to set DefaultStartPanelOff reg value!\r\n",
  2549. 0, NULL, NULL);
  2550. }
  2551. RegCloseKey( hkStartPanel );
  2552. }
  2553. else
  2554. {
  2555. bRet = FALSE;
  2556. SetuplogError(LogSevWarning,
  2557. L"SETUP: ProcessShellUnattendSettings() failed in to create StartPanel reg key!\r\n",
  2558. 0, NULL, NULL);
  2559. }
  2560. }
  2561. }
  2562. // Check the "DefaultThemesOff" key to see if the user wants to not apply themes by default
  2563. if( GetPrivateProfileString( lpszSection,
  2564. TEXT("DefaultThemesOff"),
  2565. pwNull,
  2566. Answer,
  2567. MAX_PATH,
  2568. lpszUnattend) ) {
  2569. if ( ( lstrcmpi( pwYes, Answer ) == 0 ) || ( lstrcmpi( pwNo, Answer ) == 0 ) ) {
  2570. HKEY hkThemes;
  2571. if ( RegCreateKey( HKEY_LOCAL_MACHINE,
  2572. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes"),
  2573. &hkThemes ) == ERROR_SUCCESS ) {
  2574. BOOL bYes;
  2575. if ( lstrcmpi( pwYes, Answer ) == 0)
  2576. {
  2577. bYes = TRUE;
  2578. }
  2579. else
  2580. {
  2581. bYes = FALSE;
  2582. }
  2583. dwError = RegSetValueEx( hkThemes,
  2584. TEXT("NoThemeInstall"),
  2585. 0,
  2586. REG_SZ,
  2587. (BYTE*)(bYes ? TEXT("TRUE") : TEXT("FALSE")), // needs to be reg_sz "TRUE" or "FALSE" string
  2588. bYes ? sizeof(TEXT("TRUE")) : sizeof(TEXT("FALSE")) );
  2589. if (dwError != ERROR_SUCCESS)
  2590. {
  2591. bRet = FALSE;
  2592. SetuplogError(LogSevWarning,
  2593. L"SETUP: ProcessShellUnattendSettings() failed to set NoThemeInstall reg value!\r\n",
  2594. 0, NULL, NULL);
  2595. }
  2596. RegCloseKey( hkThemes );
  2597. }
  2598. else
  2599. {
  2600. bRet = FALSE;
  2601. SetuplogError(LogSevWarning,
  2602. L"SETUP: ProcessShellUnattendSettings() failed in to create Themes key!\r\n",
  2603. 0, NULL, NULL);
  2604. }
  2605. }
  2606. }
  2607. // See if the user has specified a "CustomInstalledTheme" which we will apply by default to all users
  2608. if( GetPrivateProfileString( lpszSection,
  2609. TEXT("CustomDefaultThemeFile"),
  2610. pwNull,
  2611. Answer,
  2612. MAX_PATH,
  2613. lpszUnattend) ) {
  2614. if ( lstrcmpi( pwNull, Answer ) != 0 ) {
  2615. HKEY hkThemes;
  2616. if ( RegCreateKey( HKEY_LOCAL_MACHINE,
  2617. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes"),
  2618. &hkThemes ) == ERROR_SUCCESS ) {
  2619. dwError = RegSetValueEx( hkThemes,
  2620. TEXT("CustomInstallTheme"),
  2621. 0,
  2622. REG_EXPAND_SZ,
  2623. (BYTE*)Answer,
  2624. (lstrlen(Answer) + 1) * sizeof(TCHAR));
  2625. if (dwError != ERROR_SUCCESS)
  2626. {
  2627. bRet = FALSE;
  2628. SetuplogError(LogSevWarning,
  2629. L"SETUP: ProcessShellUnattendSettings() failed to set CustomInstallTheme reg value!\r\n",
  2630. 0, NULL, NULL);
  2631. }
  2632. RegCloseKey( hkThemes );
  2633. }
  2634. else
  2635. {
  2636. bRet = FALSE;
  2637. SetuplogError(LogSevWarning,
  2638. L"SETUP: ProcessShellUnattendSettings() failed in to create Themes key!\r\n",
  2639. 0, NULL, NULL);
  2640. }
  2641. }
  2642. }
  2643. return bRet;
  2644. }
  2645. VOID
  2646. ConfigureSetup(
  2647. IN HWND hProgress,
  2648. IN ULONG StartAtPercent,
  2649. IN ULONG StopAtPercent
  2650. )
  2651. {
  2652. #define AnswerBufLen (4*MAX_PATH)
  2653. UINT GaugeRange;
  2654. BOOL b;
  2655. DWORD dwSize;
  2656. WCHAR TempString[MAX_PATH];
  2657. WCHAR adminName[MAX_USERNAME+1];
  2658. WCHAR AnswerFile[AnswerBufLen];
  2659. WCHAR Answer[AnswerBufLen];
  2660. OSVERSIONINFOEXW osvi;
  2661. BOOL fPersonalSKU = FALSE;
  2662. //
  2663. // Determine if we are installing Personal SKU
  2664. //
  2665. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
  2666. GetVersionEx((OSVERSIONINFOW*)&osvi);
  2667. fPersonalSKU = ( osvi.wProductType == VER_NT_WORKSTATION && (osvi.wSuiteMask & VER_SUITE_PERSONAL));
  2668. //
  2669. // Initialize the progress indicator control.
  2670. //
  2671. if( !OobeSetup ) {
  2672. GaugeRange = (17*100/(StopAtPercent-StartAtPercent));
  2673. SendMessage(hProgress, WMX_PROGRESSTICKS, 17, 0);
  2674. SendMessage(hProgress,PBM_SETRANGE,0,MAKELPARAM(0,GaugeRange));
  2675. SendMessage(hProgress,PBM_SETPOS,GaugeRange*StartAtPercent/100,0);
  2676. SendMessage(hProgress,PBM_SETSTEP,1,0);
  2677. }
  2678. MYASSERT(!Upgrade);
  2679. b = TRUE;
  2680. if(!MiniSetup ) {
  2681. //
  2682. // Create config.nt/autoexec.nt.
  2683. //
  2684. if( !ConfigureMsDosSubsystem() ) {
  2685. SetupDebugPrint( L"SETUP: ConfigureMsDosSubsystem failed" );
  2686. b = FALSE;
  2687. }
  2688. //
  2689. // Make the appropriate entries for wow.
  2690. //
  2691. SendMessage(hProgress,PBM_STEPIT,0,0);
  2692. if( !MakeWowEntry() ) {
  2693. SetupDebugPrint( L"SETUP: MakeWowEntry failed" );
  2694. b = FALSE;
  2695. }
  2696. SendMessage(hProgress,PBM_STEPIT,0,0);
  2697. CallSceConfigureServices();
  2698. //
  2699. // Enable and start the spooler.
  2700. //
  2701. SendMessage(hProgress,PBM_STEPIT,0,0);
  2702. if( !MyChangeServiceStart(szSpooler,SERVICE_AUTO_START) ) {
  2703. SetupDebugPrint( L"SETUP: MyChangeServiceStart failed" );
  2704. b = FALSE;
  2705. }
  2706. if( !StartSpooler() ) {
  2707. SetupDebugPrint( L"SETUP: StartSpooler failed" );
  2708. b = FALSE;
  2709. }
  2710. //
  2711. // Set up program groups.
  2712. //
  2713. SendMessage(hProgress,PBM_STEPIT,0,0);
  2714. if(!CreateStartMenuItems(SyssetupInf)) {
  2715. SetupDebugPrint( L"SETUP: CreateStartMenuItems failed" );
  2716. b = FALSE;
  2717. }
  2718. //
  2719. // Change some service start values.
  2720. //
  2721. SendMessage(hProgress,PBM_STEPIT,0,0);
  2722. if(!MyChangeServiceStart(L"EventLog",SERVICE_AUTO_START)) {
  2723. SetupDebugPrint( L"SETUP: MyChangeServiceStart(EventLog) failed" );
  2724. b = FALSE;
  2725. }
  2726. if(!MyChangeServiceStart(L"ClipSrv",SERVICE_DEMAND_START)) {
  2727. SetupDebugPrint( L"SETUP: MyChangeServiceStart(ClipSrv) failed" );
  2728. b = FALSE;
  2729. }
  2730. if(!MyChangeServiceStart(L"NetDDE",SERVICE_DEMAND_START)) {
  2731. SetupDebugPrint( L"SETUP: MyChangeServiceStart(NetDDE) failed" );
  2732. b = FALSE;
  2733. }
  2734. if(!MyChangeServiceStart(L"NetDDEdsdm",SERVICE_DEMAND_START)) {
  2735. SetupDebugPrint( L"SETUP: MyChangeServiceStart(NetDDEdsdm) failed" );
  2736. b = FALSE;
  2737. }
  2738. // Moved Admin Password code to wizard
  2739. SendMessage(hProgress,PBM_STEPIT,0,0);
  2740. }
  2741. //
  2742. // For OobeSetup, OOBE has just run and manage new account creation
  2743. //
  2744. if ( fPersonalSKU && !OobeSetup )
  2745. {
  2746. WCHAR OwnerName[MAX_USERNAME+1];
  2747. NTSTATUS OwnerCreated = STATUS_UNSUCCESSFUL;
  2748. WCHAR PathBuffer[MAX_PATH];
  2749. if (LoadString(MyModuleHandle,IDS_OWNER,OwnerName,MAX_USERNAME+1))
  2750. {
  2751. OwnerCreated = CreateLocalAdminAccount(OwnerName,TEXT(""),NULL);
  2752. if(OwnerCreated){
  2753. DeleteOnRestartOfGUIMode(OwnerName);
  2754. }
  2755. SetupDebugPrint2(
  2756. L"SETUP: CreateLocalAdminAccount %s NTSTATUS(%d)",
  2757. OwnerName,
  2758. OwnerCreated
  2759. );
  2760. }
  2761. else
  2762. {
  2763. SetupDebugPrint( L"SETUP: Failed LoadString on IDS_OWNER" );
  2764. }
  2765. if (GetSystemDirectory(PathBuffer, MAX_PATH))
  2766. {
  2767. pSetupConcatenatePaths(
  2768. PathBuffer,
  2769. TEXT("oobe\\oobeinfo.ini"),
  2770. MAX_PATH,
  2771. NULL
  2772. );
  2773. WritePrivateProfileString(
  2774. TEXT("Options"),
  2775. TEXT("RemoveOwner"),
  2776. (OwnerCreated == STATUS_SUCCESS) ? TEXT("1") : TEXT("0"),
  2777. PathBuffer
  2778. );
  2779. }
  2780. }
  2781. //
  2782. // Don't bother with the Autologon stuff if the user provided an encrypted password in the unattend file
  2783. //
  2784. if( !fPersonalSKU || Win95Upgrade ){
  2785. if( !EncryptedAdminPasswordSet ){
  2786. if (Unattended && UnattendAnswerTable[UAE_AUTOLOGON].Answer.String &&
  2787. lstrcmpi(UnattendAnswerTable[UAE_AUTOLOGON].Answer.String,pwYes)==0) {
  2788. if (fPersonalSKU) {
  2789. if (!LoadString(MyModuleHandle,IDS_OWNER,adminName,MAX_USERNAME+1)) {
  2790. b = FALSE;
  2791. }
  2792. } else {
  2793. GetAdminAccountName( adminName );
  2794. }
  2795. if (b && !SetAutoAdminLogonInRegistry(adminName,AdminPassword)) {
  2796. SetupDebugPrint( L"SETUP: SetAutoAdminLogonInRegistry failed" );
  2797. b = FALSE;
  2798. }
  2799. }
  2800. }
  2801. }
  2802. #ifdef DOLOCALUSER
  2803. if(CreateUserAccount) {
  2804. if(!CreateLocalUserAccount(UserName,UserPassword,NULL)) {
  2805. SetupDebugPrint( L"SETUP: CreateLocalUserAccount failed" );
  2806. b = FALSE;
  2807. }
  2808. else {
  2809. DeleteOnRestartOfGUIMode(UserName);
  2810. }
  2811. }
  2812. #endif
  2813. //
  2814. // Set temp/tmp variables.
  2815. //
  2816. if(!MiniSetup){
  2817. SendMessage(hProgress,PBM_STEPIT,0,0);
  2818. lstrcpy(TempString,L"%SystemRoot%\\TEMP");
  2819. SetEnvironmentVariableInRegistry(L"TEMP",TempString,TRUE);
  2820. SetEnvironmentVariableInRegistry(L"TMP",TempString,TRUE);
  2821. #ifdef _X86_
  2822. //
  2823. // Set NPX emulation state.
  2824. //
  2825. if( !SetNpxEmulationState() ) {
  2826. SetupDebugPrint( L"SETUP: SetNpxEmulationState failed" );
  2827. b = FALSE;
  2828. }
  2829. #endif // def _X86_
  2830. BEGIN_SECTION(L"Loading service pack (phase 4)");
  2831. CALL_SERVICE_PACK( SVCPACK_PHASE_4, 0, 0, 0 );
  2832. END_SECTION(L"Loading service pack (phase 4)");
  2833. }
  2834. //
  2835. // Call the network setup back to handle Internet Server issues.
  2836. //
  2837. BEGIN_SECTION(L"Network setup handling Internet Server issues");
  2838. SendMessage(hProgress,PBM_STEPIT,0,0);
  2839. CallNetworkSetupBack(NETSETUPINSTALLSOFTWAREPROCNAME);
  2840. if (!MiniSetup && RemoteBootSetup) {
  2841. SetStartTypeForRemoteBootDrivers();
  2842. }
  2843. END_SECTION(L"Network setup handling Internet Server issues");
  2844. //
  2845. // Stamp build number
  2846. //
  2847. if( !MiniSetup ) {
  2848. SendMessage(hProgress,PBM_STEPIT,0,0);
  2849. StampBuildNumber();
  2850. //
  2851. // Set some misc stuff in win.ini
  2852. //
  2853. if( !WinIniAlter1() ) {
  2854. SetupDebugPrint( L"SETUP: WinIniAlter1 failed" );
  2855. b = FALSE;
  2856. }
  2857. //
  2858. // Fonts.
  2859. //
  2860. SendMessage(hProgress,PBM_STEPIT,0,0);
  2861. pSetupMarkHiddenFonts();
  2862. //
  2863. // Set up pagefile and crashdump.
  2864. //
  2865. BEGIN_SECTION(L"Setting up virtual memory");
  2866. SendMessage(hProgress,PBM_STEPIT,0,0);
  2867. if( !SetUpVirtualMemory() ) {
  2868. SetupDebugPrint( L"SETUP: SetUpVirtualMemory failed" );
  2869. b = FALSE;
  2870. }
  2871. END_SECTION(L"Setting up virtual memory");
  2872. if( !SetShutdownVariables() ) {
  2873. SetupDebugPrint( L"SETUP: SetShutdownVariables failed" );
  2874. b = FALSE;
  2875. }
  2876. //
  2877. // run any programs
  2878. //
  2879. BEGIN_SECTION(L"Processing [RunPrograms] section");
  2880. RunSetupPrograms(SyssetupInf,L"RunPrograms");
  2881. END_SECTION(L"Processing [RunPrograms] section");
  2882. //
  2883. //Brand IE for clean unattended installs.
  2884. //This should be called before the default user hive is saved.
  2885. //
  2886. BrandIE();
  2887. } else {
  2888. //
  2889. // See if it's okay to reset the pagefile for the MiniSetup case.
  2890. //
  2891. GetSystemDirectory(AnswerFile,MAX_PATH);
  2892. pSetupConcatenatePaths(AnswerFile,WINNT_GUI_FILE,MAX_PATH,NULL);
  2893. GetPrivateProfileString( TEXT("Unattended"),
  2894. TEXT("KeepPageFile"),
  2895. pwNull,
  2896. Answer,
  2897. AnswerBufLen,
  2898. AnswerFile );
  2899. if( !lstrcmp( pwNull, Answer ) ) {
  2900. if( !SetUpVirtualMemory() ) {
  2901. SetupDebugPrint( L"SETUP: SetUpVirtualMemory failed" );
  2902. b = FALSE;
  2903. }
  2904. }
  2905. }
  2906. //
  2907. // Set the default power scheme. Note that this must be done before saving
  2908. // the userdef hive.
  2909. //
  2910. if( !OobeSetup ) {
  2911. SendMessage(hProgress,PBM_STEPIT,0,0);
  2912. }
  2913. SetDefaultPowerScheme();
  2914. //
  2915. // There's nothing specific to preinstall about cmdlines.txt.
  2916. // In retail cases the file simply won't exit. Calling this in
  2917. // all cases simplifies things for some people out there.
  2918. //
  2919. // We need to do this here so that if the user has commands
  2920. // that populate the user's hive, they'll get pushed down
  2921. // into default hive.
  2922. //
  2923. if(!ExecutePreinstallCommands()) {
  2924. SetupDebugPrint( L"ExecutePreinstallCommands() failed" );
  2925. }
  2926. //
  2927. // Save off the userdef hive. Don't change the ordering here
  2928. // unless you know what you're doing!
  2929. //
  2930. if( !MiniSetup ) {
  2931. BEGIN_SECTION(L"Saving hives");
  2932. dwSize = MAX_PATH;
  2933. SendMessage(hProgress,PBM_STEPIT,0,0);
  2934. if (GetDefaultUserProfileDirectory(TempString, &dwSize)) {
  2935. pSetupConcatenatePaths(TempString,L"\\NTUSER.DAT",MAX_PATH,NULL);
  2936. if(!SaveHive(HKEY_USERS,L".DEFAULT",TempString,REG_STANDARD_FORMAT)) { // standard format as it can be used for roaming
  2937. SetupDebugPrint( L"SETUP: SaveHive failed" );
  2938. b = FALSE;
  2939. }
  2940. SetFileAttributes (TempString, FILE_ATTRIBUTE_HIDDEN);
  2941. } else {
  2942. SetupDebugPrint( L"SETUP: GetDefaultUserProfileDirectory failed" );
  2943. b = FALSE;
  2944. }
  2945. END_SECTION(L"Saving hives");
  2946. } else {
  2947. BEGIN_SECTION(L"Fixing up hives");
  2948. //
  2949. // This is the MiniSetup case. We're going to surgically
  2950. // place some values from the default hive into all the
  2951. // user profiles.
  2952. //
  2953. FixupUserHives();
  2954. END_SECTION(L"Fixing up hives");
  2955. }
  2956. //
  2957. // Set wallpaper and screen saver.
  2958. //
  2959. if( !MiniSetup ) {
  2960. SendMessage(hProgress,PBM_STEPIT,0,0);
  2961. if( !SetDefaultWallpaper() ) {
  2962. SetupDebugPrint( L"SETUP: SetDefaultWallpaper failed" );
  2963. b = FALSE;
  2964. }
  2965. if( !SetLogonScreensaver() ) {
  2966. SetupDebugPrint( L"SETUP: SetLogonScreensaver failed" );
  2967. b = FALSE;
  2968. }
  2969. BEGIN_SECTION(L"Copying optional directories");
  2970. if( !CopyOptionalDirectories() ) {
  2971. SetupDebugPrint( L"SETUP: CopyOptionalDirectories failed" );
  2972. b = FALSE;
  2973. }
  2974. END_SECTION(L"Copying optional directories");
  2975. SendMessage(hProgress,PBM_STEPIT,0,0);
  2976. if(!b) {
  2977. SetuplogError(
  2978. LogSevError,
  2979. SETUPLOG_USE_MESSAGEID,
  2980. MSG_LOG_FINISH_SETUP_FAILED,
  2981. NULL,NULL);
  2982. }
  2983. }
  2984. }
  2985. VOID
  2986. ConfigureUpgrade(
  2987. IN HWND hProgress,
  2988. IN ULONG StartAtPercent,
  2989. IN ULONG StopAtPercent
  2990. )
  2991. {
  2992. UINT GaugeRange;
  2993. BOOL b;
  2994. DWORD dwSize;
  2995. WCHAR TempString[MAX_PATH];
  2996. DWORD DontCare;
  2997. DWORD VolumeFreeSpaceMB[26];
  2998. DWORD TType, TLength, ret;
  2999. PWSTR TData;
  3000. //
  3001. // Initialize the progress indicator control.
  3002. //
  3003. GaugeRange = (12*100/(StopAtPercent-StartAtPercent));
  3004. SendMessage(hProgress, WMX_PROGRESSTICKS, 12, 0);
  3005. SendMessage(hProgress,PBM_SETRANGE,0,MAKELPARAM(0,GaugeRange));
  3006. SendMessage(hProgress,PBM_SETPOS,GaugeRange*StartAtPercent/100,0);
  3007. SendMessage(hProgress,PBM_SETSTEP,1,0);
  3008. MYASSERT(Upgrade);
  3009. b = TRUE;
  3010. //
  3011. // Create config.sys/autoexec.bat/msdos.sys/io.sys, if they
  3012. // don't already exist
  3013. //
  3014. SendMessage(hProgress,PBM_STEPIT,0,0);
  3015. if(!ConfigureMsDosSubsystem()) {
  3016. SetupDebugPrint( L"SETUP: ConfigureMsDosSubsystem failed" );
  3017. b = FALSE;
  3018. }
  3019. if(!FixQuotaEntries()) {
  3020. SetupDebugPrint( L"SETUP: FixQuotaEntries failed" );
  3021. b = FALSE;
  3022. }
  3023. if(!InstallOrUpgradeFonts()) {
  3024. SetupDebugPrint( L"SETUP: InstallOrUpgradeFonts failed" );
  3025. b = FALSE;
  3026. }
  3027. pSetupMarkHiddenFonts();
  3028. //
  3029. // Restore the page file information saved during textmode setup.
  3030. // Ignore any error, since there is nothing that the user can do.
  3031. //
  3032. SendMessage(hProgress,PBM_STEPIT,0,0);
  3033. SetUpVirtualMemory();
  3034. if(!SetShutdownVariables()) {
  3035. SetupDebugPrint( L"SETUP: SetShutdownVariables failed" );
  3036. b = FALSE;
  3037. }
  3038. //
  3039. // Get list of free space available on each hard drive. We don't care
  3040. // about this, but it has the side effect of deleting all pagefiles,
  3041. // which we do want to do.
  3042. //
  3043. SendMessage(hProgress,PBM_STEPIT,0,0);
  3044. BuildVolumeFreeSpaceList(VolumeFreeSpaceMB);
  3045. //
  3046. // Upgrade program groups.
  3047. //
  3048. SendMessage(hProgress,PBM_STEPIT,0,0);
  3049. if(!UpgradeStartMenuItems(SyssetupInf)) {
  3050. SetupDebugPrint( L"SETUP: UpgradeStartMenuItems failed" );
  3051. b = FALSE;
  3052. }
  3053. SendMessage(hProgress,PBM_STEPIT,0,0);
  3054. if(!MyChangeServiceStart(szSpooler,SERVICE_AUTO_START)) {
  3055. SetupDebugPrint( L"SETUP: MyChangeServiceStart failed" );
  3056. b = FALSE;
  3057. }
  3058. SetUpDataBlock();
  3059. DontCare = UpgradePrinters();
  3060. if(DontCare != NO_ERROR) {
  3061. SetupDebugPrint( L"SETUP: UpgradePrinters failed" );
  3062. b = FALSE;
  3063. }
  3064. SendMessage(hProgress,PBM_STEPIT,0,0);
  3065. if( !UpdateServicesDependencies(SyssetupInf) ) {
  3066. SetupDebugPrint( L"SETUP: UpdateServicesDependencies failed" );
  3067. b = FALSE;
  3068. }
  3069. //
  3070. // Set temp/tmp variables for upgrades.
  3071. //
  3072. SendMessage(hProgress,PBM_STEPIT,0,0);
  3073. // Look for Environment variable TEMP (we assume that TEMP and TMP appear together)
  3074. // Will not be present on NT4 upgrades
  3075. ret = QueryValueInHKLM( L"System\\CurrentControlSet\\Control\\Session Manager\\Environment",
  3076. L"TEMP",
  3077. &TType,
  3078. (PVOID)&TData,
  3079. &TLength);
  3080. if( ret != NO_ERROR ){ //only when the TEMP variable is not defined (<=NT4 upgrades)
  3081. lstrcpy(TempString,L"%SystemDrive%\\TEMP"); // On NT4 use %SystemDrive%
  3082. SetEnvironmentVariableInRegistry(L"TEMP",TempString,TRUE);
  3083. SetEnvironmentVariableInRegistry(L"TMP",TempString,TRUE);
  3084. }
  3085. #ifdef _X86_
  3086. //
  3087. // Set NPX emulation state.
  3088. //
  3089. if(!SetNpxEmulationState()) {
  3090. SetupDebugPrint( L"SETUP: SetNpxEmulationState failed" );
  3091. b = FALSE;
  3092. }
  3093. #endif // def _X86_
  3094. SendMessage(hProgress,PBM_STEPIT,0,0);
  3095. if(!SetProductIdInRegistry()) {
  3096. SetupDebugPrint( L"SETUP: SetProductIdInRegistry failed" );
  3097. b = FALSE;
  3098. }
  3099. if( !MiniSetup ) {
  3100. BEGIN_SECTION(L"Loading service pack (phase 4)");
  3101. CALL_SERVICE_PACK( SVCPACK_PHASE_4, 0, 0, 0 );
  3102. END_SECTION(L"Loading service pack (phase 4)");
  3103. }
  3104. CallNetworkSetupBack(NETSETUPINSTALLSOFTWAREPROCNAME);
  3105. if (RemoteBootSetup) {
  3106. SetStartTypeForRemoteBootDrivers();
  3107. }
  3108. //
  3109. // Stamp build number
  3110. //
  3111. SendMessage(hProgress,PBM_STEPIT,0,0);
  3112. StampBuildNumber();
  3113. //
  3114. // UpgradeRegistrySecurity();
  3115. //
  3116. //
  3117. // Set the default power scheme. Note that this must be done before saving
  3118. // the userdef hive.
  3119. //
  3120. SendMessage(hProgress,PBM_STEPIT,0,0);
  3121. SetDefaultPowerScheme();
  3122. //
  3123. // Save off the userdef hive. Don't change the ordering here
  3124. // unless you know what you're doing!
  3125. //
  3126. SendMessage(hProgress,PBM_STEPIT,0,0);
  3127. dwSize = MAX_PATH;
  3128. if (GetDefaultUserProfileDirectory(TempString, &dwSize)) {
  3129. pSetupConcatenatePaths(TempString,L"\\NTUSER.DAT",MAX_PATH,NULL);
  3130. if(!SaveHive(HKEY_USERS,L".DEFAULT",TempString,REG_STANDARD_FORMAT)) { // standard format as it can be used for roaming
  3131. SetupDebugPrint( L"SETUP: SaveHive failed" );
  3132. b = FALSE;
  3133. }
  3134. SetFileAttributes (TempString, FILE_ATTRIBUTE_HIDDEN);
  3135. } else {
  3136. SetupDebugPrint( L"SETUP: GetDefaultUserProfileDirectory failed" );
  3137. b = FALSE;
  3138. }
  3139. SendMessage(hProgress,PBM_STEPIT,0,0);
  3140. if(!CopyOptionalDirectories()) {
  3141. SetupDebugPrint( L"SETUP: CopyOptionalDirectories failed" );
  3142. b = FALSE;
  3143. }
  3144. if(!b) {
  3145. SetuplogError(
  3146. LogSevError,
  3147. SETUPLOG_USE_MESSAGEID,
  3148. MSG_LOG_FINISH_SETUP_FAILED,
  3149. NULL,NULL);
  3150. }
  3151. }
  3152. VOID
  3153. ConfigureCommon(
  3154. IN HWND hProgress,
  3155. IN ULONG StartAtPercent,
  3156. IN ULONG StopAtPercent
  3157. )
  3158. {
  3159. UINT GaugeRange;
  3160. int i;
  3161. //
  3162. // Initialize the progress indicator control.
  3163. //
  3164. if( !OobeSetup ) {
  3165. GaugeRange = (5*100/(StopAtPercent-StartAtPercent));
  3166. SendMessage(hProgress, WMX_PROGRESSTICKS, 5, 0);
  3167. SendMessage(hProgress,PBM_SETRANGE,0,MAKELPARAM(0,GaugeRange));
  3168. SendMessage(hProgress,PBM_SETPOS,GaugeRange*StartAtPercent/100,0);
  3169. SendMessage(hProgress,PBM_SETSTEP,1,0);
  3170. }
  3171. //
  3172. // Install extra code pages on servers
  3173. //
  3174. if( !MiniSetup ) {
  3175. SendMessage(hProgress,PBM_STEPIT,0,0);
  3176. //
  3177. // Process the [Shell] Section of the unattend file
  3178. //
  3179. ProcessShellUnattendSettings();
  3180. if( !(ProductType == PRODUCT_WORKSTATION) ) {
  3181. InstallServerNLSFiles(MainWindowHandle);
  3182. }
  3183. //
  3184. // Do the SCE GenerateTemplate stuff
  3185. //
  3186. SendMessage(hProgress,PBM_STEPIT,0,0);
  3187. BEGIN_SECTION(L"Generating security templates");
  3188. CallSceGenerateTemplate();
  3189. END_SECTION(L"Generating security templates");
  3190. //
  3191. // Try a call out to DcPromoSaveDcStateForUpgrade()...
  3192. //
  3193. if( ISDC(ProductType) && Upgrade ) {
  3194. typedef DWORD (*DCPROC) ( LPCWSTR );
  3195. HMODULE DCPromoHandle;
  3196. DCPROC MyProc;
  3197. DWORD Result;
  3198. BOOL Success = TRUE;
  3199. //
  3200. // We need to call out to dcpromo!DcPromoSaveDcStateForUpgrade.
  3201. // Load dcpromo.dll, lookup DcPromoSaveDcStateForUpgrade and
  3202. // call out to him.
  3203. //
  3204. try {
  3205. if( DCPromoHandle = LoadLibrary(L"DCPROMO") ) {
  3206. if( MyProc = (DCPROC)GetProcAddress(DCPromoHandle,"DcPromoSaveDcStateForUpgrade")) {
  3207. Result = MyProc( NULL );
  3208. if( Result != ERROR_SUCCESS ) {
  3209. Success = FALSE;
  3210. SetupDebugPrint1( L"Setup: (non-critical error) Failed call DcPromoSaveDcStateForUpgrade (%lx.\n", Result );
  3211. }
  3212. } else {
  3213. Success = FALSE;
  3214. SetupDebugPrint( L"Syssetup: (non-critical error) Failed GetProcAddress on DcPromoSaveDcStateForUpgrade.\n" );
  3215. }
  3216. } else {
  3217. Success = FALSE;
  3218. SetupDebugPrint( L"Syssetup: (non-critical error) Failed load of dcpromo.dll.\n" );
  3219. }
  3220. } except(EXCEPTION_EXECUTE_HANDLER) {
  3221. Success = FALSE;
  3222. SetupDebugPrint( L"Setup: Exception in dcpromo!DcPromoSaveDcStateForUpgrade\n" );
  3223. }
  3224. if( !Success ) {
  3225. //
  3226. // We failed the call (for whatever reason). Treat
  3227. // this as a fatal error.
  3228. //
  3229. FatalError( MSG_DCPROMO_FAILURE, 0, 0 );
  3230. }
  3231. }
  3232. //
  3233. // Fix up permissions/attributes on some files.
  3234. //
  3235. pSetInstallAttributes();
  3236. //
  3237. // Set the read-only attribute on some files.
  3238. //
  3239. SendMessage(hProgress,PBM_STEPIT,0,0);
  3240. MarkFilesReadOnly();
  3241. }
  3242. //
  3243. // Fix up the legacy install source.
  3244. //
  3245. if( !OobeSetup ) {
  3246. SendMessage(hProgress,PBM_STEPIT,0,0);
  3247. }
  3248. CreateWindowsNtSoftwareEntry(FALSE);
  3249. //
  3250. // Now put the GuiRunOnce section into the registry.
  3251. //
  3252. if( !OobeSetup ) {
  3253. SendMessage(hProgress,PBM_STEPIT,0,0);
  3254. }
  3255. GetUnattendRunOnceAndSetRegistry();
  3256. }
  3257. VOID
  3258. SFCCheck(
  3259. IN HWND hProgress,
  3260. IN ULONG StartAtPercent,
  3261. IN ULONG StopAtPercent
  3262. )
  3263. /*++
  3264. Routine Description:
  3265. This routine calls into WFP (WFP == SFC) to scan all files on the system to
  3266. ensure that the files are all valid. The routine also populates the WFP
  3267. "dllcache", which is a local store of files on the system.
  3268. Arguments:
  3269. hProgress - progress window for updating a gas guage "tick count".
  3270. StartAtPercent - where to start on the gas guage
  3271. StopAtPercent - Where to stop on the gas guage
  3272. Return Value:
  3273. None.
  3274. --*/
  3275. {
  3276. PPROTECT_FILE_ENTRY Files;
  3277. ULONG FileCount;
  3278. DWORD GaugeRange;
  3279. WCHAR AnswerFile[AnswerBufLen];
  3280. WCHAR Answer[AnswerBufLen];
  3281. DWORD d;
  3282. DWORD l;
  3283. HKEY hKey;
  3284. DWORD Size;
  3285. DWORD Type;
  3286. //
  3287. // determine how big to make the dllcache by looking at the
  3288. // SFCQuota unattend value, otherwise use the below default.
  3289. //
  3290. #if 0
  3291. d = (ProductType == PRODUCT_WORKSTATION)
  3292. ? SFC_QUOTA_DEFAULT
  3293. : 0xffffffff;
  3294. #else
  3295. d = 0xffffffff;
  3296. #endif
  3297. //
  3298. // SFCQuota unattend value?
  3299. //
  3300. GetSystemDirectory(AnswerFile,MAX_PATH);
  3301. pSetupConcatenatePaths(AnswerFile,WINNT_GUI_FILE,MAX_PATH,NULL);
  3302. if( GetPrivateProfileString( TEXT("SystemFileProtection"),
  3303. TEXT("SFCQuota"),
  3304. pwNull,
  3305. Answer,
  3306. AnswerBufLen,
  3307. AnswerFile ) ) {
  3308. if( lstrcmp( pwNull, Answer ) ) {
  3309. //
  3310. // We got an answer. If it's valid, then set it.
  3311. //
  3312. d = wcstoul(Answer,NULL,16);
  3313. }
  3314. }
  3315. //
  3316. // Get the total file count
  3317. //
  3318. if (SfcGetFiles( &Files, &FileCount ) == STATUS_SUCCESS) {
  3319. //
  3320. // Initialize the progress indicator control.
  3321. //
  3322. GaugeRange = ((FileCount)*100/(StopAtPercent-StartAtPercent));
  3323. SendMessage(hProgress, WMX_PROGRESSTICKS, FileCount, 0);
  3324. SendMessage( hProgress, PBM_SETRANGE, 0, MAKELPARAM(0,GaugeRange) );
  3325. SendMessage( hProgress, PBM_SETPOS, GaugeRange*StartAtPercent/100, 0 );
  3326. SendMessage( hProgress, PBM_SETSTEP, 1, 0 );
  3327. //
  3328. // check the files
  3329. //
  3330. SfcInitProt(
  3331. SFC_REGISTRY_OVERRIDE,
  3332. SFC_DISABLE_SETUP,
  3333. SFC_SCAN_ALWAYS,
  3334. d,
  3335. hProgress,
  3336. SourcePath,
  3337. EnumPtrSfcIgnoreFiles.Start
  3338. );
  3339. }
  3340. //
  3341. // Free our list of files that Sfc scan should ignore.
  3342. //
  3343. if (EnumPtrSfcIgnoreFiles.Start) {
  3344. MultiSzFree(&EnumPtrSfcIgnoreFiles);
  3345. }
  3346. // also set the "allowprotectedrenames" registry key so that the next boot
  3347. // after gui-mode setup allows any pending rename operations to occur.
  3348. // We do this for performance reasons -- if we aren't looking at the rename
  3349. // operations, it speeds up boot time. We can do this for the gui-setup
  3350. // case because we trust the copy operations occuring during gui-setup.
  3351. //
  3352. // Open the key
  3353. //
  3354. l = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  3355. TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager"),
  3356. 0,
  3357. KEY_ALL_ACCESS,
  3358. &hKey );
  3359. if(l == NO_ERROR) {
  3360. d = 1;
  3361. //
  3362. // Write AllowProtectedRenames.
  3363. //
  3364. l = RegSetValueEx(hKey,
  3365. TEXT("AllowProtectedRenames"),
  3366. 0,
  3367. REG_DWORD,
  3368. (CONST BYTE *)&d,
  3369. sizeof(DWORD) );
  3370. RegCloseKey(hKey);
  3371. }
  3372. }
  3373. VOID
  3374. ExecuteUserCommand (
  3375. HWND hProgress
  3376. )
  3377. {
  3378. WCHAR PathBuffer[4*MAX_PATH];
  3379. DWORD d;
  3380. DWORD Result;
  3381. //
  3382. // Execute user-specified command, if any.
  3383. //
  3384. if (hProgress) {
  3385. SendMessage(hProgress,PBM_STEPIT,0,0);
  3386. }
  3387. if(UserExecuteCmd) {
  3388. //
  3389. // Set current directory to %windir%
  3390. //
  3391. Result = GetWindowsDirectory(PathBuffer,sizeof(PathBuffer)/sizeof(PathBuffer[0]));
  3392. if( Result == 0) {
  3393. MYASSERT(FALSE);
  3394. return;
  3395. }
  3396. SetCurrentDirectory(PathBuffer);
  3397. ExpandEnvironmentStrings(
  3398. UserExecuteCmd,
  3399. PathBuffer,
  3400. sizeof(PathBuffer)/sizeof(PathBuffer[0])
  3401. );
  3402. InvokeExternalApplication(NULL,PathBuffer,(PDWORD)&d);
  3403. }
  3404. }
  3405. BOOL
  3406. CALLBACK
  3407. pExceptionPackageInstallationCallback(
  3408. IN const PSETUP_OS_COMPONENT_DATA SetupOsComponentData,
  3409. IN const PSETUP_OS_EXCEPTION_DATA SetupOsExceptionData,
  3410. IN OUT DWORD_PTR Context
  3411. )
  3412. /*++
  3413. Routine Description:
  3414. This callback routine creates a child process to register the specified
  3415. exception package on the system.
  3416. Arguments:
  3417. SetupOsComponentData - specifies component ID information
  3418. SetupOsExceptionData - specifies component migration information
  3419. Context - context pointer from calling function
  3420. Return Value:
  3421. TRUE indicates that the exception package was successfully applied.
  3422. --*/
  3423. {
  3424. PEXCEPTION_MIGRATION_CONTEXT EMC = (PEXCEPTION_MIGRATION_CONTEXT) Context;
  3425. DWORD RetVal;
  3426. WCHAR Cmdline[MAX_PATH*2];
  3427. PWSTR GuidString;
  3428. #define COMPONENT_PACKAGE_TIMEOUT 60*1000*10 //ten minutes
  3429. StringFromIID( &SetupOsComponentData->ComponentGuid, &GuidString);
  3430. SetupDebugPrint5( L"Exception Package #%d\r\nComponent Data\r\n\tName: %ws\r\n\tGuid: %ws\r\n\tVersionMajor: %d\r\n\tVersionMinor: %d",
  3431. EMC->Count,
  3432. SetupOsComponentData->FriendlyName,
  3433. GuidString,
  3434. SetupOsComponentData->VersionMajor,
  3435. SetupOsComponentData->VersionMinor);
  3436. SetupDebugPrint2( L"ExceptionData\n\tInf: %ws\n\tCatalog: %ws",
  3437. SetupOsExceptionData->ExceptionInfName,
  3438. SetupOsExceptionData->CatalogFileName);
  3439. EMC->Count += 1;
  3440. //
  3441. // make sure the signature of the inf validates against the supplied catalog before
  3442. // installing the package.
  3443. //
  3444. RetVal = pSetupVerifyFile(
  3445. NULL,
  3446. SetupOsExceptionData->CatalogFileName,
  3447. NULL,
  3448. 0,
  3449. pSetupGetFileTitle(SetupOsExceptionData->ExceptionInfName),
  3450. SetupOsExceptionData->ExceptionInfName,
  3451. NULL,
  3452. NULL,
  3453. FALSE,
  3454. NULL,
  3455. NULL,
  3456. NULL
  3457. );
  3458. if (RetVal == ERROR_SUCCESS) {
  3459. //
  3460. // Build the cmdline to install the package.
  3461. //
  3462. wsprintf( Cmdline,
  3463. L"%ws,DefaultInstall,1,N",
  3464. SetupOsExceptionData->ExceptionInfName);
  3465. //
  3466. // By specifying the last param as non-NULL, we will wait forever for this
  3467. // package to finish installing
  3468. //
  3469. InvokeExternalApplicationEx( L"RUNDLL32 advpack.dll,LaunchINFSection",
  3470. Cmdline,
  3471. &RetVal,
  3472. COMPONENT_PACKAGE_TIMEOUT,
  3473. FALSE);
  3474. }
  3475. if (EMC->hWndProgress) {
  3476. SendMessage(EMC->hWndProgress,PBM_STEPIT,0,0);
  3477. }
  3478. if (RetVal == ERROR_SUCCESS) {
  3479. SetuplogError(
  3480. LogSevInformation,
  3481. SETUPLOG_USE_MESSAGEID,
  3482. MSG_APPLY_EXCEPTION_PACKAGE,
  3483. SetupOsComponentData->FriendlyName,
  3484. SetupOsComponentData->VersionMajor,
  3485. SetupOsComponentData->VersionMinor,
  3486. NULL,NULL);
  3487. } else {
  3488. SetuplogError(
  3489. LogSevError,
  3490. SETUPLOG_USE_MESSAGEID,
  3491. MSG_APPLY_EXCEPTION_PACKAGE_FAILURE,
  3492. SetupOsComponentData->FriendlyName,
  3493. SetupOsComponentData->VersionMajor,
  3494. SetupOsComponentData->VersionMinor,
  3495. NULL,NULL);
  3496. EMC->AnyComponentFailed = TRUE;
  3497. }
  3498. CoTaskMemFree( GuidString );
  3499. //
  3500. // if we hit a failure installing exception packages, we
  3501. // continue onto the next package but we remember that this failed
  3502. // in our context structure.
  3503. //
  3504. return(TRUE);
  3505. }
  3506. BOOL
  3507. CALLBACK
  3508. pExceptionPackageDeleteCallback(
  3509. IN const PSETUP_OS_COMPONENT_DATA SetupOsComponentData,
  3510. IN const PSETUP_OS_EXCEPTION_DATA SetupOsExceptionData,
  3511. IN OUT DWORD_PTR Context
  3512. )
  3513. /*++
  3514. Routine Description:
  3515. Callback routine to remove "bad packages" from the system.
  3516. The callback looks in syssetup.inf's [OsComponentPackagesToRemove]
  3517. section for the current GUID. If it finds an entry for the GUID,
  3518. it does a version check against the version in the syssetup.inf.
  3519. If the version in syssetup.inf is newer, the exception package
  3520. associated with that GUID is removed. The version in syssetup.inf
  3521. is a DWORD expressed as:
  3522. hiword == VersionMajor
  3523. loword == VersionMinor
  3524. Arguments:
  3525. SetupOsComponentData - specifies component ID information
  3526. SetupOsExceptionData - specifies component migration information
  3527. Context - context pointer from calling function
  3528. Return Value:
  3529. Always TRUE.
  3530. --*/
  3531. {
  3532. INFCONTEXT InfContext;
  3533. PWSTR GuidString;
  3534. DWORD VersionInInf, InstalledVersion;
  3535. UNREFERENCED_PARAMETER(Context);
  3536. StringFromIID( &SetupOsComponentData->ComponentGuid, &GuidString);
  3537. //
  3538. // see if we find the component in the syssetup inf.
  3539. //
  3540. if (SetupFindFirstLine( SyssetupInf,
  3541. L"OsComponentPackagesToRemove",
  3542. GuidString,
  3543. &InfContext)) {
  3544. //
  3545. // we found it, now see if it is an older version
  3546. //
  3547. if (SetupGetIntField( &InfContext, 1, &VersionInInf)) {
  3548. InstalledVersion = MAKELONG(SetupOsComponentData->VersionMinor,
  3549. SetupOsComponentData->VersionMajor );
  3550. if (VersionInInf >= InstalledVersion) {
  3551. //
  3552. // it's an obsoleted version, so just remove it.
  3553. //
  3554. SetupUnRegisterOsComponent(&SetupOsComponentData->ComponentGuid);
  3555. }
  3556. }
  3557. }
  3558. CoTaskMemFree( GuidString );
  3559. return(TRUE);
  3560. }
  3561. BOOL
  3562. MigrateExceptionPackages(
  3563. HWND hProgress,
  3564. DWORD StartAtPercent,
  3565. DWORD StopAtPercent
  3566. )
  3567. /*++
  3568. Routine Description:
  3569. This routine enumerates the registered exception packages on the system.
  3570. For each package on the system, a child process is started to install
  3571. the package.
  3572. Arguments:
  3573. hProgress - progress window for updating a gas guage "tick count".
  3574. StartAtPercent - indicates what % to start the gas guage at
  3575. StopAtPercent - indicates what % to end the gas guage at
  3576. Return Value:
  3577. TRUE indicates that all exception packages were successfully applied.
  3578. --*/
  3579. {
  3580. DWORD i;
  3581. DWORD GaugeRange;
  3582. DWORD NumberOfPackages;
  3583. EXCEPTION_MIGRATION_CONTEXT EMC;
  3584. HINF hInf;
  3585. WCHAR AnswerFile[MAX_PATH];
  3586. if (SyssetupInf == INVALID_HANDLE_VALUE) {
  3587. //
  3588. // we're not running in GUI-mode setup, so open a handle to the
  3589. // syssetup.inf for the program
  3590. //
  3591. SyssetupInf = SetupOpenInfFile (L"syssetup.inf",NULL,INF_STYLE_WIN4,NULL);
  3592. }
  3593. //
  3594. // If the answer file tells us not to migrate exception packages,
  3595. // then don't do it.
  3596. //
  3597. GetSystemDirectory(AnswerFile, MAX_PATH);
  3598. pSetupConcatenatePaths(AnswerFile,WINNT_GUI_FILE,MAX_PATH,NULL);
  3599. if (GetPrivateProfileInt(
  3600. TEXT("Data"),
  3601. TEXT("IgnoreExceptionPackages"),
  3602. 0,
  3603. AnswerFile) == 1) {
  3604. return(TRUE);
  3605. }
  3606. //
  3607. // The very first thing we do is prune any known bad exceptions from
  3608. // the list. Just continue if this fails.
  3609. //
  3610. SetupEnumerateRegisteredOsComponents(
  3611. pExceptionPackageDeleteCallback,
  3612. (DWORD_PTR)NULL );
  3613. //
  3614. // now see how many components there are so we can scale the gas guage
  3615. //
  3616. if (!SetupQueryRegisteredOsComponentsOrder(&NumberOfPackages, NULL)) {
  3617. SetuplogError(
  3618. LogSevError,
  3619. SETUPLOG_USE_MESSAGEID,
  3620. MSG_ENUM_EXCEPTION_PACKAGE_FAILURE,
  3621. NULL,NULL);
  3622. return(FALSE);
  3623. }
  3624. //
  3625. // If there are no packages, we're done!
  3626. //
  3627. if (NumberOfPackages == 0) {
  3628. return (TRUE);
  3629. }
  3630. if (hProgress) {
  3631. GaugeRange = (NumberOfPackages*100/(StopAtPercent-StartAtPercent));
  3632. SendMessage(hProgress, WMX_PROGRESSTICKS, NumberOfPackages, 0);
  3633. SendMessage(hProgress,PBM_SETRANGE,0,MAKELPARAM(0,GaugeRange));
  3634. SendMessage(hProgress,PBM_SETPOS,GaugeRange*StartAtPercent/100,0);
  3635. SendMessage(hProgress,PBM_SETSTEP,1,0);
  3636. }
  3637. EMC.hWndProgress = hProgress;
  3638. EMC.Count = 0;
  3639. EMC.AnyComponentFailed = FALSE;
  3640. //
  3641. // now enumerate the packages, installing each of them in turn.
  3642. //
  3643. if (!SetupEnumerateRegisteredOsComponents( pExceptionPackageInstallationCallback ,
  3644. (DWORD_PTR)&EMC)) {
  3645. SetuplogError(
  3646. LogSevError,
  3647. SETUPLOG_USE_MESSAGEID,
  3648. MSG_ENUM_EXCEPTION_PACKAGE_FAILURE,
  3649. NULL,NULL);
  3650. return(FALSE);
  3651. }
  3652. return (TRUE);
  3653. }
  3654. VOID
  3655. RemoveRestartability (
  3656. HWND hProgress
  3657. )
  3658. {
  3659. //
  3660. // If install partition was extended then make sure
  3661. // we clean up any stale volume(s)
  3662. //
  3663. if (PartitionExtended) {
  3664. DWORD ErrorCode = RemoveStaleVolumes();
  3665. if (ErrorCode != ERROR_SUCCESS) {
  3666. //
  3667. // TDB : Log the error code
  3668. //
  3669. }
  3670. }
  3671. //
  3672. // Note the order of the following operations.
  3673. // If the order were changed, there is a small window where if the system
  3674. // were to be rebooted, setup would not restart, but the SKU stuff would
  3675. // be inconsistent, causing a licensing bugcheck.
  3676. //
  3677. if (hProgress) {
  3678. SendMessage(hProgress,PBM_STEPIT,0,0);
  3679. }
  3680. SetUpEvaluationSKUStuff();
  3681. //
  3682. // Indicate that setup is no longer in progress.
  3683. // Do this before creating repair info! Also do it before
  3684. // removing restart stuff. This way we will always either restart setup
  3685. // or be able to log in.
  3686. //
  3687. if (hProgress) {
  3688. SendMessage(hProgress,PBM_STEPIT,0,0);
  3689. }
  3690. ResetSetupInProgress();
  3691. RemoveRestartStuff();
  3692. }
  3693. BOOL Activationrequired(VOID);
  3694. // Setup types defined in winlogon\setup.h
  3695. #define SETUPTYPE_NOREBOOT 2
  3696. BOOL
  3697. PrepareForOOBE(
  3698. )
  3699. {
  3700. DWORD l;
  3701. DWORD d;
  3702. HKEY hKeySetup;
  3703. TCHAR Value[MAX_PATH];
  3704. PWSTR SpecifiedDomain = NULL;
  3705. NETSETUP_JOIN_STATUS JoinStatus;
  3706. BOOL DoIntroOnly = FALSE;
  3707. BOOL AutoActivate = FALSE;
  3708. BOOL RunOOBE = TRUE;
  3709. WCHAR Path[MAX_PATH];
  3710. if((SyssetupInf != INVALID_HANDLE_VALUE) && !Activationrequired())
  3711. {
  3712. // If we are a select SKU
  3713. if (SetupInstallFromInfSection(NULL,
  3714. SyssetupInf,
  3715. L"DEL_ACTIVATE",
  3716. SPINST_PROFILEITEMS , //SPINST_ALL,
  3717. NULL,
  3718. NULL,
  3719. 0,
  3720. NULL,
  3721. NULL,
  3722. NULL,
  3723. NULL) != 0)
  3724. {
  3725. // Success
  3726. SetupDebugPrint( L"Setup: (Information) activation icons removed\n" );
  3727. }
  3728. else
  3729. {
  3730. // Failure
  3731. SetupDebugPrint( L"Setup: (Information) could not remove hte activation icons\n" );
  3732. }
  3733. }
  3734. if (AsrIsEnabled()) {
  3735. //
  3736. // We don't want to run the OOBE intro after an ASR restore
  3737. //
  3738. return TRUE;
  3739. }
  3740. if (ReferenceMachine) {
  3741. //
  3742. // We don't want to run OOBE if we're setting up a reference machine.
  3743. //
  3744. return TRUE;
  3745. }
  3746. if (ProductType != PRODUCT_WORKSTATION)
  3747. {
  3748. // Don't run OOBE.
  3749. RunOOBE = FALSE;
  3750. // Only run Autoactivation if not DTC and unattended and AutoActivate=Yes
  3751. if (UnattendSwitch)
  3752. {
  3753. // if not DTC
  3754. if (GetProductFlavor() != 3)
  3755. {
  3756. // Check for AutoActivate=Yes
  3757. GetSystemDirectory(Path,MAX_PATH);
  3758. pSetupConcatenatePaths(Path,WINNT_GUI_FILE,MAX_PATH,NULL);
  3759. if( GetPrivateProfileString( TEXT("Unattended"),
  3760. TEXT("AutoActivate"),
  3761. pwNull,
  3762. Value,
  3763. sizeof(Value)/sizeof(TCHAR),
  3764. Path ) )
  3765. {
  3766. SetupDebugPrint( L"Setup: (Information) found AutoAvtivate in unattend file\n" );
  3767. AutoActivate = (lstrcmpi(Value,pwYes) == 0);
  3768. }
  3769. }
  3770. }
  3771. }
  3772. if (!RunOOBE && !AutoActivate)
  3773. {
  3774. return TRUE;
  3775. }
  3776. // Now we either run OOBE (RunOOBE==TRUE) or we AutoActivate (AutoActivate == TRUE) or both
  3777. //
  3778. // Open HKLM\System\Setup
  3779. //
  3780. l = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  3781. TEXT("SYSTEM\\Setup"),
  3782. 0,
  3783. KEY_ALL_ACCESS,
  3784. &hKeySetup );
  3785. if(l != NO_ERROR)
  3786. {
  3787. SetLastError(l);
  3788. SetupDebugPrint1(
  3789. L"SETUP: PrepareForOOBE() failed to open Setup key. Error = %d",
  3790. l );
  3791. return FALSE;
  3792. }
  3793. //
  3794. // Set HKLM\System\Setup\SetupType Key to SETUPTYPE_NOREBOOT
  3795. //
  3796. d = SETUPTYPE_NOREBOOT;
  3797. l = RegSetValueEx(hKeySetup,
  3798. TEXT("SetupType"),
  3799. 0,
  3800. REG_DWORD,
  3801. (CONST BYTE *)&d,
  3802. sizeof(DWORD));
  3803. if(l != NO_ERROR)
  3804. {
  3805. RegCloseKey(hKeySetup);
  3806. SetLastError(l);
  3807. SetupDebugPrint1(
  3808. L"SETUP: PrepareForOOBE() failed to set SetupType. Error = %d",
  3809. l );
  3810. return FALSE;
  3811. }
  3812. if (RunOOBE)
  3813. {
  3814. // Set the registry to run OOBE
  3815. //
  3816. //
  3817. // Set HKLM\System\Setup\OobeInProgress to (DWORD) 1
  3818. //
  3819. d = 1;
  3820. l = RegSetValueEx(hKeySetup,
  3821. REGSTR_VALUE_OOBEINPROGRESS,
  3822. 0,
  3823. REG_DWORD,
  3824. (CONST BYTE *)&d,
  3825. sizeof(DWORD));
  3826. if(l != NO_ERROR)
  3827. {
  3828. RegCloseKey(hKeySetup);
  3829. SetLastError(l);
  3830. SetupDebugPrint2(
  3831. L"SETUP: PrepareForOOBE() failed to set %ws. Error = %d",
  3832. REGSTR_VALUE_OOBEINPROGRESS,
  3833. l );
  3834. return FALSE;
  3835. }
  3836. //
  3837. // Modify the HKLM\System\Setup\CmdLine key to run MSOOBE
  3838. //
  3839. ExpandEnvironmentStrings(
  3840. TEXT("%SystemRoot%\\System32\\oobe\\msoobe.exe /f /retail"),
  3841. Value,
  3842. sizeof(Value)/sizeof(Value[0])
  3843. );
  3844. }
  3845. else
  3846. {
  3847. // Set the registry to run Autoactivation
  3848. //
  3849. //
  3850. // Modify the HKLM\System\Setup\CmdLine key to run Autoactivation
  3851. //
  3852. ExpandEnvironmentStrings(
  3853. TEXT("%SystemRoot%\\System32\\oobe\\oobebaln.exe /s"),
  3854. Value,
  3855. sizeof(Value)/sizeof(Value[0])
  3856. );
  3857. }
  3858. l = RegSetValueEx(hKeySetup,
  3859. TEXT("CmdLine"),
  3860. 0,
  3861. REG_MULTI_SZ,
  3862. (CONST BYTE *)Value,
  3863. (lstrlen( Value ) + 1) * sizeof(TCHAR));
  3864. if(l != NO_ERROR)
  3865. {
  3866. RegCloseKey(hKeySetup);
  3867. SetLastError(l);
  3868. SetupDebugPrint1(
  3869. L"SETUP: PrepareForOOBE() failed to set CmdLine. Error = %d",
  3870. l );
  3871. return FALSE;
  3872. }
  3873. RegCloseKey(hKeySetup);
  3874. //
  3875. // OOBE should do nothing but show the introductory animation if we're
  3876. // unattended, or in a domain, unless a special unattend key is set to
  3877. // force normal retail OOBE to run.
  3878. // Note that we check whether the user explicity specifed the "/unattend"
  3879. // switch.
  3880. //
  3881. if ( UnattendSwitch ) {
  3882. DoIntroOnly = TRUE;
  3883. } else {
  3884. l = NetGetJoinInformation( NULL,
  3885. &SpecifiedDomain,
  3886. &JoinStatus );
  3887. if ( SpecifiedDomain ) {
  3888. NetApiBufferFree( SpecifiedDomain );
  3889. }
  3890. if ( l == NO_ERROR && JoinStatus == NetSetupDomainName ) {
  3891. DoIntroOnly = TRUE;
  3892. }
  3893. }
  3894. if ( DoIntroOnly && !ForceRunOobe ) {
  3895. ExpandEnvironmentStrings(
  3896. TEXT("%SystemRoot%\\System32\\oobe\\oobeinfo.ini"),
  3897. Value,
  3898. sizeof(Value)/sizeof(Value[0])
  3899. );
  3900. WritePrivateProfileString(
  3901. TEXT("Options"),
  3902. TEXT("IntroOnly"),
  3903. TEXT("1"),
  3904. Value
  3905. );
  3906. }
  3907. return (TRUE);
  3908. }
  3909. BOOL
  3910. WINAPI
  3911. PrepareForAudit(
  3912. )
  3913. {
  3914. HKEY hKey;
  3915. TCHAR szFileName[MAX_PATH + 32] = TEXT("");
  3916. BOOL bRet = TRUE;
  3917. SetupDebugPrint( L"SETUP: PrepareForAudit");
  3918. // We need the path to factory.exe.
  3919. //
  3920. if ( ( ExpandEnvironmentStrings(TEXT("%SystemDrive%\\sysprep\\factory.exe"), szFileName, sizeof(szFileName) / sizeof(TCHAR)) == 0 ) ||
  3921. ( szFileName[0] == TEXT('\0') ) ||
  3922. ( GetFileAttributes(szFileName) == 0xFFFFFFFF ) )
  3923. {
  3924. // If this fails, there is nothing we can really do.
  3925. //
  3926. SetupDebugPrint1( L"SETUP: PrepareForAudit, Factory.exe not found at: %s",szFileName);
  3927. return FALSE;
  3928. }
  3929. // Now make sure we are also setup as a setup program to run before we log on.
  3930. //
  3931. if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\Setup"), 0, KEY_ALL_ACCESS, &hKey ) == ERROR_SUCCESS )
  3932. {
  3933. DWORD dwVal;
  3934. //
  3935. // Setup the control flags for the SETUP key
  3936. // The Setting used are:
  3937. // CmdLine = c:\sysprep\factory.exe -setup
  3938. // SetupType = 2 (No reboot)
  3939. // SystemSetupInProgress = 0 (no service restrictions)... assuming this is already cleared by setup.
  3940. // MiniSetupInProgress = 0 (Not doing a mini setup)
  3941. // FactoryPreInstallInProgress = 1 (Delay pnp driver installs)
  3942. // AuditInProgress = 1 (general key to determine if the OEM is auditing the machine)
  3943. //
  3944. // Cleanup setting Audit/Factory does not need and does not reset
  3945. ResetSetupInProgress();
  3946. RegDeleteValue(hKey,L"MiniSetupInProgress");
  3947. RegDeleteValue(hKey,REGSTR_VALUE_OOBEINPROGRESS);
  3948. // Now set the values which Audit/Factory needs
  3949. lstrcat(szFileName, TEXT(" -setup"));
  3950. if ( RegSetValueEx(hKey, TEXT("CmdLine"), 0, REG_SZ, (CONST LPBYTE) szFileName, (lstrlen(szFileName) + 1) * sizeof(TCHAR)) != ERROR_SUCCESS )
  3951. bRet = FALSE;
  3952. dwVal = SETUPTYPE_NOREBOOT;
  3953. if ( RegSetValueEx(hKey, TEXT("SetupType"), 0, REG_DWORD, (CONST LPBYTE) &dwVal, sizeof(DWORD)) != ERROR_SUCCESS )
  3954. bRet = FALSE;
  3955. dwVal = 1;
  3956. if ( RegSetValueEx(hKey, TEXT("FactoryPreInstallInProgress"), 0, REG_DWORD, (CONST LPBYTE) &dwVal, sizeof(DWORD)) != ERROR_SUCCESS )
  3957. bRet = FALSE;
  3958. dwVal = 1;
  3959. if ( RegSetValueEx(hKey, TEXT("AuditInProgress"), 0, REG_DWORD, (CONST LPBYTE) &dwVal, sizeof(DWORD)) != ERROR_SUCCESS )
  3960. bRet = FALSE;
  3961. RegCloseKey(hKey);
  3962. }
  3963. else
  3964. bRet = FALSE;
  3965. return bRet;
  3966. }
  3967. VOID
  3968. RemoveFiles(
  3969. IN HWND hProgress
  3970. )
  3971. {
  3972. #define AnswerBufLen (4*MAX_PATH)
  3973. #define WINNT_GUI_FILE_PNF L"$winnt$.pnf"
  3974. WCHAR PathBuffer[AnswerBufLen];
  3975. WCHAR Answer[AnswerBufLen];
  3976. DWORD Result;
  3977. DWORD Status;
  3978. //
  3979. // Initialize the progress indicator control.
  3980. //
  3981. SendMessage(hProgress,PBM_SETRANGE,0,MAKELPARAM(0,6));
  3982. SendMessage(hProgress,PBM_SETPOS,0,0);
  3983. SendMessage(hProgress,PBM_SETSTEP,1,0);
  3984. //
  3985. // Restoring the path saved in textmode on upgrades
  3986. //
  3987. SendMessage(hProgress,PBM_STEPIT,0,0);
  3988. if( Upgrade )
  3989. RestoreOldPathVariable();
  3990. if(!MiniSetup) {
  3991. SendMessage(hProgress,PBM_STEPIT,0,0);
  3992. SendMessage(hProgress,PBM_STEPIT,0,0);
  3993. #ifdef _X86_
  3994. //
  3995. // Win95 migration file removal
  3996. //
  3997. if( Win95Upgrade ) {
  3998. Win95MigrationFileRemoval();
  3999. }
  4000. RemoveFiles_X86(SyssetupInf);
  4001. //
  4002. // remove downloaded files in %windir%\winnt32
  4003. //
  4004. Result = GetWindowsDirectory(PathBuffer,MAX_PATH);
  4005. if (Result == 0) {
  4006. MYASSERT(FALSE);
  4007. return;
  4008. }
  4009. pSetupConcatenatePaths(PathBuffer,TEXT("WINNT32"),MAX_PATH,NULL);
  4010. Delnode(PathBuffer);
  4011. //
  4012. // Prepare to run OOBE after reboot
  4013. //
  4014. if( !PrepareForOOBE() ) {
  4015. SetuplogError(
  4016. LogSevError,
  4017. SETUPLOG_USE_MESSAGEID,
  4018. MSG_LOG_CANT_RUN_OOBE,
  4019. GetLastError(),
  4020. NULL,NULL);
  4021. }
  4022. #endif
  4023. if( Upgrade ) {
  4024. //
  4025. //If we upgraded from NT4-SP4, remove the files/registration
  4026. //for sp4 uninstall. If we upgraded from NT4-SPx where x<4,
  4027. //we don't need to remove anything from the registry.
  4028. //
  4029. Result = GetWindowsDirectory(PathBuffer,MAX_PATH);
  4030. if (Result == 0) {
  4031. MYASSERT(FALSE);
  4032. return;
  4033. }
  4034. pSetupConcatenatePaths(PathBuffer, L"$ntservicepackuninstall$",MAX_PATH,NULL);
  4035. Delnode(PathBuffer);
  4036. RegDeleteKey(HKEY_LOCAL_MACHINE,
  4037. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Windows NT 4.0 Service Pack 4"));
  4038. RegDeleteKey(HKEY_LOCAL_MACHINE,
  4039. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Windows NT 4.0 Service Pack 5"));
  4040. RegDeleteKey(HKEY_LOCAL_MACHINE,
  4041. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Windows NT 4.0 Service Pack 6"));
  4042. // We should not have to do this.
  4043. // Ther servick pack team needs to remember to put the correct key at
  4044. // Software\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix
  4045. RegDeleteKey(HKEY_LOCAL_MACHINE,
  4046. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Windows 2000 Service Pack 1"));
  4047. RegDeleteKey(HKEY_LOCAL_MACHINE,
  4048. TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Windows 2000 Service Pack 2"));
  4049. //Remove the files/registry keys for all the hotfixes.
  4050. // It also implements a generic way to removing Service Pack uninstall entries
  4051. //
  4052. RemoveHotfixData();
  4053. } else {
  4054. //
  4055. // Setup for audit mode if this is a reference machine.
  4056. //
  4057. if ( ReferenceMachine )
  4058. PrepareForAudit();
  4059. }
  4060. DuCleanup ();
  4061. DuInstallEndGuiSetupDrivers ();
  4062. SendMessage(hProgress,PBM_STEPIT,0,0);
  4063. DeleteLocalSource();
  4064. } else {
  4065. SendMessage(hProgress,PBM_STEPIT,0,0);
  4066. SendMessage(hProgress,PBM_STEPIT,0,0);
  4067. SendMessage(hProgress,PBM_STEPIT,0,0);
  4068. }
  4069. //
  4070. // At this point, the net stuff is done. Re-read the product type
  4071. // which might have been changed by them (such as changing PDC/BDC).
  4072. //
  4073. ProductType = InternalSetupData.ProductType;
  4074. //
  4075. // Call the net guys back once again to let them do any final
  4076. // processing, such as BDC replication.
  4077. //
  4078. CallNetworkSetupBack(NETSETUPFINISHINSTALLPROCNAME);
  4079. //
  4080. // If the computer name was a non-RFC name or if it was truncated
  4081. // to make a valid netbios name, put a warning in the log file.
  4082. //
  4083. if (IsNameNonRfc)
  4084. SetuplogError(
  4085. LogSevWarning,
  4086. SETUPLOG_USE_MESSAGEID,
  4087. MSG_LOG_DNS_NON_RFC_NAME,
  4088. ComputerName,
  4089. NULL,NULL);
  4090. if (IsNameTruncated)
  4091. SetuplogError(
  4092. LogSevWarning,
  4093. SETUPLOG_USE_MESSAGEID,
  4094. MSG_LOG_DNS_NAME_TRUNCATED,
  4095. ComputerName,
  4096. Win32ComputerName,
  4097. NULL,NULL);
  4098. //
  4099. // Delete the PNF to take care of security issue with passwords
  4100. // Do this before we save the current system hives so that the
  4101. // delayed delete works
  4102. //
  4103. GetSystemDirectory(PathBuffer,MAX_PATH);
  4104. pSetupConcatenatePaths(PathBuffer,WINNT_GUI_FILE_PNF,MAX_PATH,NULL);
  4105. MoveFileEx( PathBuffer, NULL, MOVEFILE_DELAY_UNTIL_REBOOT );
  4106. //
  4107. // Delete the SAM.sav hive file as we no longer need it. Textmode setup
  4108. // creates this file only in upgrades as a backup. We will try to delete it in any case
  4109. // as this file can be used by hackers for offline attacks.
  4110. //
  4111. GetSystemDirectory(PathBuffer,MAX_PATH);
  4112. pSetupConcatenatePaths(PathBuffer, L"config\\sam.sav", MAX_PATH, NULL);
  4113. DeleteFile( PathBuffer );
  4114. //
  4115. // Setup the Crash Recovery stuff. This is implemented as RTL APIS
  4116. // Call them now to setup the tracking file etc. as we are past the
  4117. // restartable phase of GUI mode and don't run the risk of having it
  4118. // enabled for GUI mode itself. Crash Recovery tracks boot and shutdown and in
  4119. // the event of failures in either it will by default pick the right advanced
  4120. // boot option.
  4121. //
  4122. BEGIN_SECTION( L"Setting up Crash Recovery" );
  4123. SetupCrashRecovery();
  4124. END_SECTION( L"Setting up Crash Recovery" );
  4125. //
  4126. // Save and replace the system hives.
  4127. // This is necessary in order to remove fragmentation and compact the
  4128. // system hives. Remember that any type of writes to the registry
  4129. // after this point won't be reflected on next boot.
  4130. //
  4131. SendMessage(hProgress,PBM_STEPIT,0,0);
  4132. if( !MiniSetup ) {
  4133. SaveAndReplaceSystemHives();
  4134. }
  4135. SendMessage(hProgress,PBM_STEPIT,0,0);
  4136. //
  4137. // Delete the \sysprep directory.
  4138. //
  4139. if( MiniSetup ) {
  4140. HANDLE hEventLog = NULL;
  4141. Result = GetWindowsDirectory( PathBuffer, MAX_PATH );
  4142. if (Result == 0) {
  4143. MYASSERT(FALSE);
  4144. return;
  4145. }
  4146. PathBuffer[3] = 0;
  4147. pSetupConcatenatePaths( PathBuffer, TEXT("sysprep"), MAX_PATH, NULL );
  4148. Delnode( PathBuffer );
  4149. //
  4150. // Delete the setupcl.exe so session manager won't start us for each
  4151. // session (TS client, user switching).
  4152. //
  4153. Result = GetSystemDirectory( PathBuffer, MAX_PATH );
  4154. if (Result == 0) {
  4155. MYASSERT(FALSE);
  4156. return;
  4157. }
  4158. pSetupConcatenatePaths( PathBuffer, TEXT("setupcl.exe"), MAX_PATH, NULL );
  4159. SetFileAttributes(PathBuffer, FILE_ATTRIBUTE_NORMAL);
  4160. DeleteFile(PathBuffer);
  4161. //
  4162. // Clear the Event logs.
  4163. //
  4164. hEventLog = OpenEventLog( NULL, TEXT("System") );
  4165. if (hEventLog) {
  4166. ClearEventLog( hEventLog, NULL );
  4167. CloseEventLog( hEventLog );
  4168. }
  4169. hEventLog = OpenEventLog( NULL, TEXT("Application") );
  4170. if (hEventLog) {
  4171. ClearEventLog( hEventLog, NULL );
  4172. CloseEventLog( hEventLog );
  4173. }
  4174. hEventLog = OpenEventLog( NULL, TEXT("Security") );
  4175. if (hEventLog) {
  4176. ClearEventLog( hEventLog, NULL );
  4177. CloseEventLog( hEventLog );
  4178. }
  4179. }
  4180. //
  4181. // Delete certain keys out of the unattend file:
  4182. // - AdminPassword
  4183. // - DomainAdminPassword
  4184. // - UserPassword
  4185. // - DefaultPassword
  4186. // - ProductId
  4187. // - ProductKey
  4188. //
  4189. Result = GetSystemDirectory(PathBuffer,MAX_PATH);
  4190. if (Result == 0) {
  4191. MYASSERT(FALSE);
  4192. return;
  4193. }
  4194. pSetupConcatenatePaths(PathBuffer,WINNT_GUI_FILE,MAX_PATH,NULL);
  4195. if(Unattended) {
  4196. // AdminPassword
  4197. if( GetPrivateProfileString( WINNT_GUIUNATTENDED,
  4198. TEXT("AdminPassword"),
  4199. pwNull,
  4200. Answer,
  4201. AnswerBufLen,
  4202. PathBuffer ) ) {
  4203. if( lstrcmp( pwNull, Answer ) ) {
  4204. WritePrivateProfileString( WINNT_GUIUNATTENDED,
  4205. TEXT("AdminPassword"),
  4206. pwNull,
  4207. PathBuffer );
  4208. }
  4209. }
  4210. // DomainAdminPassword
  4211. if( GetPrivateProfileString( TEXT("Identification"),
  4212. TEXT("DomainAdminPassword"),
  4213. pwNull,
  4214. Answer,
  4215. AnswerBufLen,
  4216. PathBuffer ) ) {
  4217. if( lstrcmp( pwNull, Answer ) ) {
  4218. WritePrivateProfileString( TEXT("Identification"),
  4219. TEXT("DomainAdminPassword"),
  4220. pwNull,
  4221. PathBuffer );
  4222. }
  4223. }
  4224. // UserPassword
  4225. if( GetPrivateProfileString( TEXT("Win9xUpg.UserOptions"),
  4226. TEXT("UserPassword"),
  4227. pwNull,
  4228. Answer,
  4229. AnswerBufLen,
  4230. PathBuffer ) ) {
  4231. if( lstrcmp( pwNull, Answer ) ) {
  4232. WritePrivateProfileString( TEXT("Win9xUpg"),
  4233. TEXT("UserPassword"),
  4234. pwNull,
  4235. PathBuffer );
  4236. }
  4237. }
  4238. // DefaultPassword
  4239. if( GetPrivateProfileString( TEXT("Win9xUpg.UserOptions"),
  4240. TEXT("DefaultPassword"),
  4241. pwNull,
  4242. Answer,
  4243. AnswerBufLen,
  4244. PathBuffer ) ) {
  4245. if( lstrcmp( pwNull, Answer ) ) {
  4246. WritePrivateProfileString( TEXT("Win9xUpg"),
  4247. TEXT("DefaultPassword"),
  4248. pwNull,
  4249. PathBuffer );
  4250. }
  4251. }
  4252. }
  4253. // ProductId
  4254. if( GetPrivateProfileString( pwUserData,
  4255. pwProdId,
  4256. pwNull,
  4257. Answer,
  4258. AnswerBufLen,
  4259. PathBuffer ) ) {
  4260. if( lstrcmp( pwNull, Answer ) ) {
  4261. WritePrivateProfileString( pwUserData,
  4262. pwProdId,
  4263. pwNull,
  4264. PathBuffer );
  4265. }
  4266. }
  4267. // ProductKey
  4268. if( GetPrivateProfileString( pwUserData,
  4269. pwProductKey,
  4270. pwNull,
  4271. Answer,
  4272. AnswerBufLen,
  4273. PathBuffer ) ) {
  4274. if( lstrcmp( pwNull, Answer ) ) {
  4275. WritePrivateProfileString( pwUserData,
  4276. pwProductKey,
  4277. pwNull,
  4278. PathBuffer );
  4279. }
  4280. }
  4281. //
  4282. // Sysprep disables system restore, so we need to re-enable it now that
  4283. // we're done.
  4284. //
  4285. if ( MiniSetup ) {
  4286. HINSTANCE hSrClient = LoadLibrary(L"srclient.dll");
  4287. if (hSrClient) {
  4288. DWORD (WINAPI *pEnableSrEx)(LPCWSTR, BOOL) = (DWORD (WINAPI *)(LPCWSTR, BOOL))GetProcAddress(hSrClient, "EnableSREx");
  4289. if (pEnableSrEx) {
  4290. Status = pEnableSrEx( NULL , TRUE); // TRUE - synchronous call. Wait for SR to finish enabling.
  4291. if ( Status != ERROR_SUCCESS ) {
  4292. SetupDebugPrint1( L"SETUP: EnableSREx(NULL, TRUE) failed. Error = %d", Status);
  4293. }
  4294. } else {
  4295. SetupDebugPrint1( L"SETUP: Unable to find EnableSREx in srclient.dll. Error = %d", GetLastError());
  4296. }
  4297. FreeLibrary(hSrClient);
  4298. } else {
  4299. SetupDebugPrint1( L"SETUP: Unable to load srclient.dll. Error = %d", GetLastError());
  4300. }
  4301. }
  4302. }
  4303. VOID
  4304. SetStartTypeForRemoteBootDrivers(
  4305. VOID
  4306. )
  4307. /*++
  4308. Routine Description:
  4309. This routine is called at the end of remote boot setup to change the
  4310. start type for certain drivers to BOOT_START.
  4311. Arguments:
  4312. None.
  4313. Returns:
  4314. None.
  4315. --*/
  4316. {
  4317. DWORD i;
  4318. BOOL b;
  4319. WCHAR imagePath[sizeof("System32\\DRIVERS\\xxxxxxxx.sys")];
  4320. //
  4321. // Loop through the list of boot drivers. We call MyChangeServiceConfig
  4322. // directly instead of MyChangeServiceStart so that we can specify
  4323. // an image path, which prevents the service controller from rejecting
  4324. // the change (because it expects the current image path to start
  4325. // with \SystemRoot which it doesn't).
  4326. //
  4327. for ( i = 0; i < (sizeof(RemoteBootDrivers) / sizeof(RemoteBootDrivers[0])); i++ ) {
  4328. wsprintf(imagePath, L"System32\\DRIVERS\\%ws.sys", RemoteBootDrivers[i]);
  4329. b = MyChangeServiceConfig(
  4330. RemoteBootDrivers[i],
  4331. SERVICE_NO_CHANGE,
  4332. SERVICE_BOOT_START,
  4333. SERVICE_NO_CHANGE,
  4334. imagePath,
  4335. NULL,
  4336. NULL,
  4337. NULL,
  4338. NULL,
  4339. NULL
  4340. );
  4341. }
  4342. }
  4343. VOID
  4344. CallNetworkSetupBack(
  4345. IN PCSTR ProcName
  4346. )
  4347. {
  4348. HMODULE NetSetupModule;
  4349. NETSETUPINSTALLSOFTWAREPROC NetProc;
  4350. DWORD d;
  4351. BOOL b;
  4352. if(NetSetupModule = LoadLibrary(L"NETSHELL")) {
  4353. if(NetProc = (NETSETUPINSTALLSOFTWAREPROC)GetProcAddress(NetSetupModule,ProcName)) {
  4354. SetUpDataBlock();
  4355. NetProc(MainWindowHandle,&InternalSetupData);
  4356. }
  4357. //
  4358. // We don't free the library because it might create threads
  4359. // that are hanging around.
  4360. //
  4361. }
  4362. }
  4363. VOID
  4364. SetUpDataBlock(
  4365. VOID
  4366. )
  4367. /*++
  4368. Routine Description:
  4369. This routine sets up the internal setup data block structure that
  4370. we use to communicate information to the network setup wizard.
  4371. Note that we passed a pointer to this structure when we fetched
  4372. the net setup wizard pages but at that point the structure was completely
  4373. uninitialized.
  4374. Arguments:
  4375. None.
  4376. Returns:
  4377. None.
  4378. --*/
  4379. {
  4380. PWSTR p;
  4381. WCHAR str[1024];
  4382. InternalSetupData.dwSizeOf = sizeof(INTERNAL_SETUP_DATA);
  4383. //
  4384. // Set the mode: custom, laptop, minimal, typical
  4385. //
  4386. InternalSetupData.SetupMode = SetupMode;
  4387. //
  4388. // Set the product type: workstation, dc, etc.
  4389. //
  4390. InternalSetupData.ProductType = ProductType;
  4391. //
  4392. // Set the operation flags.
  4393. //
  4394. if(Win31Upgrade) {
  4395. InternalSetupData.OperationFlags |= SETUPOPER_WIN31UPGRADE;
  4396. }
  4397. if(Win95Upgrade) {
  4398. InternalSetupData.OperationFlags |= SETUPOPER_WIN95UPGRADE;
  4399. }
  4400. if(Upgrade) {
  4401. InternalSetupData.OperationFlags |= SETUPOPER_NTUPGRADE;
  4402. }
  4403. if(Unattended) {
  4404. InternalSetupData.OperationFlags |= SETUPOPER_BATCH;
  4405. InternalSetupData.UnattendFile = AnswerFile;
  4406. if(Preinstall) {
  4407. InternalSetupData.OperationFlags |= SETUPOPER_PREINSTALL;
  4408. }
  4409. }
  4410. if(MiniSetup) {
  4411. //
  4412. // Pretend we've got access to all the files.
  4413. //
  4414. InternalSetupData.OperationFlags |= SETUPOPER_ALLPLATFORM_AVAIL;
  4415. // Let people know we are in MiniSetup
  4416. InternalSetupData.OperationFlags |= SETUPOPER_MINISETUP;
  4417. }
  4418. //
  4419. // Tell the net guys the source path.
  4420. //
  4421. InternalSetupData.SourcePath = SourcePath;
  4422. InternalSetupData.LegacySourcePath = LegacySourcePath;
  4423. //
  4424. // If we are installing from CD then assume all platforms
  4425. // are available.
  4426. //
  4427. if(SourcePath[0] && (SourcePath[1] == L':') && (SourcePath[2] == L'\\')) {
  4428. lstrcpyn(str,SourcePath,4);
  4429. if(GetDriveType(str) == DRIVE_CDROM) {
  4430. InternalSetupData.OperationFlags |= SETUPOPER_ALLPLATFORM_AVAIL;
  4431. }
  4432. }
  4433. //
  4434. // Tell the net guys the wizard title they should use.
  4435. //
  4436. if(!InternalSetupData.WizardTitle) {
  4437. p = NULL;
  4438. if(LoadString(MyModuleHandle,SetupTitleStringId,str,sizeof(str)/sizeof(str[0]))) {
  4439. p = pSetupDuplicateString(str);
  4440. }
  4441. InternalSetupData.WizardTitle = p ? p : L"";
  4442. }
  4443. //
  4444. // Reset the two call-specific data fields.
  4445. //
  4446. InternalSetupData.CallSpecificData1 = InternalSetupData.CallSpecificData2 = 0;
  4447. // Set the billboard call back function if we have a billboard
  4448. InternalSetupData.ShowHideWizardPage = ShowHideWizardPage;
  4449. InternalSetupData.BillboardProgressCallback = Billboard_Progress_Callback;
  4450. InternalSetupData.BillBoardSetProgressText= Billboard_Set_Progress_Text;
  4451. }
  4452. VOID
  4453. SetFinishItemAttributes(
  4454. IN HWND hdlg,
  4455. IN int BitmapControl,
  4456. IN HANDLE hBitmap,
  4457. IN int TextControl,
  4458. IN LONG Weight
  4459. )
  4460. {
  4461. HWND hBitmapControl, hTxt;
  4462. HFONT Font;
  4463. LOGFONT LogFont;
  4464. if( OobeSetup ) {
  4465. return;
  4466. }
  4467. hBitmapControl = GetDlgItem(hdlg, BitmapControl);
  4468. SendMessage (hBitmapControl, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitmap);
  4469. ShowWindow (hBitmapControl, SW_SHOW);
  4470. if((Font = (HFONT)SendDlgItemMessage(hdlg,TextControl,WM_GETFONT,0,0))
  4471. && GetObject(Font,sizeof(LOGFONT),&LogFont)) {
  4472. LogFont.lfWeight = Weight;
  4473. if(Font = CreateFontIndirect(&LogFont)) {
  4474. SendDlgItemMessage (hdlg, TextControl, WM_SETFONT, (WPARAM)Font,
  4475. MAKELPARAM(TRUE,0));
  4476. }
  4477. }
  4478. }
  4479. DWORD
  4480. FinishThread(
  4481. PFINISH_THREAD_PARAMS Context
  4482. )
  4483. {
  4484. HANDLE hArrow, hCheck;
  4485. HWND hProgress;
  4486. DWORD DontCare;
  4487. NTSTATUS Status;
  4488. SYSTEM_REGISTRY_QUOTA_INFORMATION srqi;
  4489. ULONG RegistryQuota = 0;
  4490. WCHAR str[1024];
  4491. BEGIN_SECTION(L"FinishThread");
  4492. SetThreadLocale(OriginalInstallLocale);
  4493. //
  4494. // Initialize stuff.
  4495. //
  4496. if( !OobeSetup ) {
  4497. hArrow = LoadImage (MyModuleHandle, MAKEINTRESOURCE(IDB_ARROW), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  4498. hCheck = LoadImage (MyModuleHandle, MAKEINTRESOURCE(IDB_CHECK), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS);
  4499. hProgress = GetDlgItem(Context->hdlg, IDC_PROGRESS1);
  4500. }
  4501. if( !MiniSetup ) {
  4502. pSetupEnablePrivilege(SE_INCREASE_QUOTA_NAME,TRUE);
  4503. Status = NtQuerySystemInformation(SystemRegistryQuotaInformation,
  4504. &srqi, sizeof(srqi), NULL);
  4505. if(NT_SUCCESS(Status)) {
  4506. RegistryQuota = srqi.RegistryQuotaAllowed;
  4507. srqi.RegistryQuotaAllowed *= 2;
  4508. SetupDebugPrint2(L"SETUP: Changing registry quota from %d to %d...",
  4509. RegistryQuota, srqi.RegistryQuotaAllowed);
  4510. Status = NtSetSystemInformation(SystemRegistryQuotaInformation,
  4511. &srqi, sizeof(srqi));
  4512. if (NT_SUCCESS(Status)) {
  4513. SetupDebugPrint(L"SETUP: ... succeeded");
  4514. } else {
  4515. SetupDebugPrint(L"SETUP: ... failed");
  4516. }
  4517. }
  4518. }
  4519. //
  4520. // Copying files
  4521. //
  4522. if( !OobeSetup ) {
  4523. SetFinishItemAttributes (Context->hdlg, IDC_COPY_BMP, hArrow, IDC_COPY_TXT, FW_BOLD);
  4524. if(!LoadString(MyModuleHandle, IDS_BB_COPY_TXT, str, SIZECHARS(str)))
  4525. {
  4526. *str = L'\0';
  4527. }
  4528. SendMessage(GetParent(Context->hdlg),WMX_SETPROGRESSTEXT,0,(LPARAM)str);
  4529. }
  4530. MYASSERT(Context->OcManagerContext);
  4531. BEGIN_SECTION(L"Terminating the OC manager");
  4532. KillOcManager(Context->OcManagerContext);
  4533. END_SECTION(L"Terminating the OC manager");
  4534. if( !MiniSetup ) {
  4535. BEGIN_SECTION(L"Loading service pack (phase 3)");
  4536. CALL_SERVICE_PACK( SVCPACK_PHASE_3, 0, 0, 0 );
  4537. END_SECTION(L"Loading service pack (phase 3)");
  4538. BEGIN_SECTION(L"Installing Component Infs");
  4539. DoInstallComponentInfs(MainWindowHandle, Context->hdlg, WM_MY_PROGRESS, SyssetupInf, L"Infs.Always" );
  4540. END_SECTION(L"Installing Component Infs");
  4541. }
  4542. if( !OobeSetup ) {
  4543. SetFinishItemAttributes (Context->hdlg, IDC_COPY_BMP, hCheck, IDC_COPY_TXT, FW_NORMAL);
  4544. }
  4545. //
  4546. // Configuring your computer
  4547. //
  4548. if( !OobeSetup ) {
  4549. SetFinishItemAttributes (Context->hdlg, IDC_CONFIGURE_BMP, hArrow, IDC_CONFIGURE_TXT, FW_BOLD);
  4550. if(!LoadString(MyModuleHandle, IDS_BB_CONFIGURE, str, SIZECHARS(str)))
  4551. {
  4552. *str = L'\0';
  4553. }
  4554. SendMessage(GetParent(Context->hdlg),WMX_SETPROGRESSTEXT,0,(LPARAM)str);
  4555. }
  4556. if( !MiniSetup ) {
  4557. RemainingTime = CalcTimeRemaining(Phase_Inf_Registration);
  4558. SetRemainingTime(RemainingTime);
  4559. BEGIN_SECTION(L"Processing RegSvr Sections");
  4560. RegisterOleControls(Context->hdlg,SyssetupInf,hProgress,0,40,L"RegistrationPhase2");
  4561. END_SECTION(L"Processing RegSvr Sections");
  4562. }
  4563. RemainingTime = CalcTimeRemaining(Phase_RunOnce_Registration);
  4564. SetRemainingTime(RemainingTime);
  4565. BEGIN_SECTION(L"DoRunonce");
  4566. DoRunonce();
  4567. END_SECTION(L"DoRunonce");
  4568. if(Upgrade) {
  4569. BEGIN_SECTION(L"Configuring Upgrade");
  4570. ConfigureUpgrade(hProgress,40,70);
  4571. END_SECTION(L"Configuring Upgrade");
  4572. } else {
  4573. BEGIN_SECTION(L"Configuring Setup");
  4574. ConfigureSetup(hProgress,40,70);
  4575. END_SECTION(L"Configuring Setup");
  4576. }
  4577. RemainingTime = CalcTimeRemaining(Phase_SecurityTempates);
  4578. SetRemainingTime(RemainingTime);
  4579. BEGIN_SECTION(L"Configuring Common");
  4580. ConfigureCommon(hProgress,70,100);
  4581. END_SECTION(L"Configuring Common");
  4582. if( !MiniSetup ) {
  4583. if(WatchHandle) {
  4584. if(WatchStop(WatchHandle) == NO_ERROR) {
  4585. MakeUserdifr(WatchHandle);
  4586. }
  4587. WatchFree(WatchHandle);
  4588. }
  4589. }
  4590. //
  4591. // tell umpnpmgr to stop installing any more devices, if it was already doing so
  4592. //
  4593. if( (!MiniSetup) || (MiniSetup && PnPReEnumeration) ) {
  4594. PnpStopServerSideInstall();
  4595. }
  4596. if (!OobeSetup)
  4597. {
  4598. SetFinishItemAttributes (Context->hdlg, IDC_CONFIGURE_BMP, hCheck, IDC_CONFIGURE_TXT, FW_NORMAL);
  4599. }
  4600. #ifdef _X86_
  4601. //
  4602. // Do Win95 migration, if necessary.
  4603. //
  4604. // !!ATTENTION!!
  4605. //
  4606. // This code must run at the end of GUI mode, but before registry ACLs are applied and also
  4607. // before temporary files are deleted. Every NT component must be in place before migration
  4608. // occurs in order for the migrated users to receive all NT-specific settings.
  4609. //
  4610. if (Win95Upgrade) {
  4611. RemainingTime = CalcTimeRemaining(Phase_Win9xMigration);
  4612. SetRemainingTime(RemainingTime);
  4613. BEGIN_SECTION(L"Migrating Win9x settings");
  4614. SetBBStep(5);
  4615. SetFinishItemAttributes (Context->hdlg, IDC_UPGRADE_BMP, hArrow, IDC_UPGRADE_TXT, FW_BOLD);
  4616. if(!LoadString(MyModuleHandle, IDS_BB_UPGRADE, str, SIZECHARS(str)))
  4617. {
  4618. *str = L'\0';
  4619. }
  4620. SendMessage(GetParent(Context->hdlg),WMX_SETPROGRESSTEXT,0,(LPARAM)str);
  4621. if (!MigrateWin95Settings (hProgress, AnswerFile)) {
  4622. //
  4623. // User's machine is unstable. Fail setup, so that uninstall must kick in.
  4624. //
  4625. WCHAR skipFile[MAX_PATH];
  4626. BOOL ok = FALSE;
  4627. if (GetWindowsDirectory (skipFile, MAX_PATH)) {
  4628. pSetupConcatenatePaths (skipFile, TEXT("nofail"), MAX_PATH, NULL);
  4629. if (GetFileAttributes (skipFile) != 0xFFFFFFFF) {
  4630. ok = TRUE;
  4631. }
  4632. }
  4633. if (!ok) {
  4634. FatalError (MSG_LOG_MIGRATION_FAILED,0,0);
  4635. }
  4636. }
  4637. SetFinishItemAttributes (Context->hdlg, IDC_UPGRADE_BMP, hCheck, IDC_UPGRADE_TXT, FW_NORMAL);
  4638. END_SECTION(L"Migrating Win9x settings");
  4639. }
  4640. #endif // def _X86_
  4641. SetFinishItemAttributes (Context->hdlg, IDC_SAVE_BMP, hArrow, IDC_SAVE_TXT, FW_BOLD);
  4642. //
  4643. // The last things to set up. Make it quick -- the gas guage may be at 100% at this point.
  4644. //
  4645. if( !MiniSetup ) {
  4646. ExecuteUserCommand (NULL);
  4647. InitializeCodeSigningPolicies (FALSE); // NOTE: don't bother stepping the progress--this is really quick!
  4648. SetBBStep(5);
  4649. //
  4650. // Saving your configuration
  4651. //
  4652. if(!LoadString(MyModuleHandle, IDS_BB_SAVE, str, SIZECHARS(str)))
  4653. {
  4654. *str = L'\0';
  4655. }
  4656. SendMessage(GetParent(Context->hdlg),WMX_SETPROGRESSTEXT,0,(LPARAM)str);
  4657. //
  4658. // Fix the security on <All Users\Application Data\Microsoft\Windows NT>
  4659. //
  4660. BEGIN_SECTION(L"Fix the security on <All Users\\Application Data\\Microsoft\\Windows NT>");
  4661. InvokeExternalApplication(L"shmgrate.exe", L"Fix-HTML-Help", 0);
  4662. END_SECTION(L"Fix the security on <All Users\\Application Data\\Microsoft\\Windows NT>");
  4663. //
  4664. // Do any exception package installation at this point
  4665. //
  4666. BEGIN_SECTION(L"Migrating exception packages");
  4667. MigrateExceptionPackages(hProgress, 0, 10 );
  4668. END_SECTION(L"Migrating exception packages");
  4669. //
  4670. // Run any nt migration dlls.
  4671. //
  4672. if (Upgrade) {
  4673. RunMigrationDlls ();
  4674. }
  4675. //
  4676. // Scan the system dirs to validate all protected dlls
  4677. //
  4678. RemainingTime = CalcTimeRemaining(Phase_SFC);
  4679. SetRemainingTime(RemainingTime);
  4680. BEGIN_SECTION(L"Running SFC");
  4681. SFCCheck(hProgress,10,70);
  4682. END_SECTION(L"Running SFC");
  4683. #ifdef PRERELEASE
  4684. if (SfcErrorOccurred) {
  4685. //
  4686. // Hack out the fatal error so we can get the build out.
  4687. //
  4688. // FatalError(MSG_LOG_SFC_FAILED,0,0);
  4689. }
  4690. #endif
  4691. } else {
  4692. //
  4693. // We're in MiniSetup, which means 3 things:
  4694. // 1. If the OEM desires it, they can request a change of kernel+HAL
  4695. // we have to do this at the end, due to the way we upgrade HAL
  4696. // doing this sooner can cause other installs to crash
  4697. //
  4698. // 2. SFC has been run on this machine and the files have been
  4699. // inventoried.
  4700. // 3. We're very concerned with execution time here.
  4701. //
  4702. // Given the last two items, we're just going to re-enable SFC
  4703. // as it was before the user ran sysprep.
  4704. //
  4705. // 1 and 3 are contradictory, however 1 shouldn't take too long
  4706. // and will be used in rare cases
  4707. //
  4708. DWORD d;
  4709. DWORD l;
  4710. HKEY hKey;
  4711. DWORD Size;
  4712. DWORD Type;
  4713. //
  4714. // We want to see if the OEM wants MiniSetup to choose a different kernel+HAL
  4715. // this has to be done after all other installation
  4716. // due to the special way we update the kernel+HAL+dependent files
  4717. //
  4718. BEGIN_SECTION(L"Updating HAL (mini-setup)");
  4719. PnpUpdateHAL();
  4720. END_SECTION(L"Updating HAL (mini-setup)");
  4721. }
  4722. //
  4723. // Only copy these folders if OEMPreinstall=yes, and it's not Mini-Setup
  4724. //
  4725. if (Preinstall && !MiniSetup) {
  4726. //
  4727. // Recursively move custom OEM \\Temp\\$PROGS directories to %Program Files%
  4728. //
  4729. BEGIN_SECTION(L"TreeCopy $OEM\\$PROGS");
  4730. CopyOemProgramFilesDir();
  4731. END_SECTION(L"TreeCopy $OEM\\$PROGS");
  4732. //
  4733. // Recursively move custom OEM \\Temp\\$DOCS directories to %Documents and Settings%
  4734. //
  4735. BEGIN_SECTION(L"TreeCopy $OEM\\$DOCS");
  4736. CopyOemDocumentsDir();
  4737. END_SECTION(L"TreeCopy $OEM\\$DOCS");
  4738. }
  4739. //
  4740. // Call User Profile code to copy the SystemProfile under system32\config\systemprofile
  4741. //
  4742. if( !CopySystemProfile(Upgrade ? FALSE : TRUE) ){
  4743. //Log the error and move on.
  4744. SetuplogError(LogSevError,
  4745. L"Setup failed to migrate the SystemProfile (CopySystemProfile failed %1!u!)\r\n",
  4746. 0, GetLastError(), NULL,NULL
  4747. );
  4748. }
  4749. // Only do this in MiniSetup. OOBE is calling this at a different time. Real setup does not need this.
  4750. if (MiniSetup && !OobeSetup)
  4751. {
  4752. RunOEMExtraTasks();
  4753. }
  4754. // Clean up CurrentProductId which should only be used during gui-mode.
  4755. DeleteCurrentProductIdInRegistry();
  4756. // Simulate OOBE's functionality of copying the default profile directory to all user profiles.
  4757. // Only do this for MiniSetup and Server skus (server doesn't use OOBE).
  4758. //
  4759. if ( MiniSetup && !OobeSetup && (ProductType != PRODUCT_WORKSTATION) )
  4760. {
  4761. if ( !UpdateServerProfileDirectory() )
  4762. {
  4763. SetuplogError(LogSevError,
  4764. L"Setup failed to update user(s) profiles. (UpdateServerProfileDirectory failed %1!u!)\r\n",
  4765. 0, GetLastError(), NULL,NULL
  4766. );
  4767. }
  4768. }
  4769. //
  4770. // FROM THIS POINT ON DO NOTHING THAT IS CRITICAL TO THE OPERATION
  4771. // OF THE SYSTEM. OPERATIONS AFTER THIS POINT ARE NOT PROTECTED BY
  4772. // RESTARTABILITY.
  4773. //
  4774. RemoveRestartability (NULL);
  4775. //
  4776. // Update the install date time for shell's application install feature
  4777. //
  4778. CreateInstallDateEntry();
  4779. //
  4780. // Save repair info.
  4781. //
  4782. if(!MiniSetup) {
  4783. RemainingTime = CalcTimeRemaining(Phase_SaveRepair);
  4784. SetRemainingTime(RemainingTime);
  4785. BEGIN_SECTION(L"Saving repair info");
  4786. SaveRepairInfo( hProgress, 70, 100 );
  4787. END_SECTION(L"Saving repair info");
  4788. }
  4789. SetFinishItemAttributes (Context->hdlg, IDC_SAVE_BMP, hCheck, IDC_SAVE_TXT, FW_NORMAL);
  4790. //
  4791. // Removing any temporary files used
  4792. //
  4793. RemainingTime = CalcTimeRemaining(Phase_RemoveTempFiles);
  4794. SetRemainingTime(RemainingTime);
  4795. BEGIN_SECTION(L"Removing Temporary Files");
  4796. if( !OobeSetup ) {
  4797. SetFinishItemAttributes (Context->hdlg, IDC_REMOVE_BMP, hArrow, IDC_REMOVE_TXT, FW_BOLD);
  4798. if(!LoadString(MyModuleHandle, IDS_BB_REMOVE, str, SIZECHARS(str)))
  4799. {
  4800. *str = L'\0';
  4801. }
  4802. SendMessage(GetParent(Context->hdlg),WMX_SETPROGRESSTEXT,0,(LPARAM)str);
  4803. }
  4804. //
  4805. // This call does more than just remove files. It also commits the hives and takes care of admin password stuff etc.
  4806. //
  4807. RemoveFiles(hProgress);
  4808. if( !OobeSetup ) {
  4809. SetFinishItemAttributes (Context->hdlg, IDC_REMOVE_BMP, hCheck, IDC_REMOVE_TXT, FW_NORMAL);
  4810. }
  4811. END_SECTION(L"Removing Temporary Files");
  4812. //
  4813. // Log Any failure for SceSetupRootSecurity.
  4814. //
  4815. if( !MiniSetup ) {
  4816. if (bSceSetupRootSecurityComplete == TRUE) {
  4817. SetupDebugPrint(L"SETUP: CallSceSetupRootSecurity completed");
  4818. }
  4819. else {
  4820. SetuplogError( LogSevError, SETUPLOG_USE_MESSAGEID, MSG_LOG_SCE_SETUPROOT_ERROR, L"%windir%", NULL, NULL);
  4821. if( SceSetupRootSecurityThreadHandle){
  4822. TerminateThread( SceSetupRootSecurityThreadHandle, STATUS_TIMEOUT);
  4823. CloseHandle( SceSetupRootSecurityThreadHandle);
  4824. }
  4825. }
  4826. }
  4827. //
  4828. // Clean up
  4829. //
  4830. if( !MiniSetup ) {
  4831. if(NT_SUCCESS(Status)) {
  4832. SetupDebugPrint2(L"SETUP: Changing registry quota from %d to %d...",
  4833. srqi.RegistryQuotaAllowed, RegistryQuota);
  4834. srqi.RegistryQuotaAllowed = RegistryQuota;
  4835. Status = NtSetSystemInformation(SystemRegistryQuotaInformation,
  4836. &srqi, sizeof(srqi));
  4837. if (NT_SUCCESS(Status)) {
  4838. SetupDebugPrint(L"SETUP: ... succeeded");
  4839. } else {
  4840. SetupDebugPrint(L"SETUP: ... failed");
  4841. }
  4842. }
  4843. //
  4844. // Now save information about the upgrade/clean install
  4845. // into the eventlog.
  4846. //
  4847. SaveInstallInfoIntoEventLog();
  4848. }
  4849. if( !OobeSetup ) {
  4850. PostMessage(Context->hdlg,WMX_TERMINATE,0,0);
  4851. DeleteObject(hArrow);
  4852. DeleteObject(hCheck);
  4853. }
  4854. END_SECTION(L"FinishThread");
  4855. return 0;
  4856. }
  4857. VOID
  4858. ShutdownSetup(
  4859. VOID
  4860. )
  4861. {
  4862. int i;
  4863. if (SyssetupInf) SetupCloseInfFile(SyssetupInf);
  4864. //
  4865. // Inform the user if there were errors, and optionally view the log.
  4866. //
  4867. SetuplogError(
  4868. LogSevInformation,
  4869. SETUPLOG_USE_MESSAGEID,
  4870. MSG_LOG_GUI_END,
  4871. NULL,NULL);
  4872. if ( SavedExceptionFilter ) {
  4873. SetUnhandledExceptionFilter( SavedExceptionFilter );
  4874. }
  4875. TerminateSetupLog(&SetuplogContext);
  4876. if(SetuplogContext.WorstError >= LogSevWarning || !IsErrorLogEmpty()) {
  4877. SendSMSMessage( MSG_SMS_MINORERRORS, TRUE );
  4878. #ifdef PRERELEASE
  4879. if(!Unattended) {
  4880. i = MessageBoxFromMessage(
  4881. MainWindowHandle,
  4882. MSG_SETUP_HAD_ERRORS,
  4883. NULL,
  4884. SetupTitleStringId,
  4885. MB_SYSTEMMODAL | MB_YESNO | MB_ICONASTERISK | MB_SETFOREGROUND,
  4886. SETUPLOG_ERROR_FILENAME
  4887. );
  4888. if(i == IDYES) {
  4889. ViewSetupActionLog (MainWindowHandle, NULL, NULL);
  4890. }
  4891. }
  4892. #endif
  4893. } else {
  4894. SendSMSMessage( MSG_SMS_SUCCEED, TRUE );
  4895. }
  4896. //
  4897. // Note : In unattend mode only wait for reboot if
  4898. // specifically asked for using the "WaitForReboot"
  4899. // key
  4900. //
  4901. if(Unattended && UnattendWaitForReboot) {
  4902. //
  4903. // Count down to reboot
  4904. //
  4905. DialogBoxParam(
  4906. MyModuleHandle,
  4907. MAKEINTRESOURCE(IDD_DONE_SUCCESS),
  4908. MainWindowHandle,
  4909. DoneDlgProc,
  4910. SetuplogContext.WorstError >= LogSevError ? MSG_SETUP_DONE_GENERIC
  4911. : (Upgrade ? MSG_UPGRADE_DONE_SUCCESS : MSG_SETUP_DONE_SUCCESS)
  4912. );
  4913. }
  4914. //
  4915. // do some wow64 syncing stuffs.
  4916. //
  4917. #ifdef _WIN64
  4918. Wow64SyncCLSID();
  4919. #endif
  4920. //
  4921. // Done. Post a quit message to our background bitmap thread so it goes
  4922. // away.
  4923. //
  4924. if (SetupWindowHandle)
  4925. {
  4926. // Cannot use DestroyWindow, since the window was created by a different thread.
  4927. SendMessage(SetupWindowHandle, WM_EXIT_SETUPWINDOW, 0, 0);
  4928. }
  4929. if (SetupWindowThreadHandle)
  4930. {
  4931. // Just make sure the thread finishes before continue.
  4932. WaitForSingleObject(SetupWindowThreadHandle, INFINITE);
  4933. CloseHandle(SetupWindowThreadHandle);
  4934. }
  4935. ASSERT_HEAP_IS_VALID();
  4936. }
  4937. VOID
  4938. InstallWindowsNt(
  4939. int argc,
  4940. char *argv[]
  4941. )
  4942. /*++
  4943. Routine Description:
  4944. Main entry point for syssetup.dll. Responsible for installing
  4945. NT on system by calling the required components in the proper
  4946. order.
  4947. Arguments:
  4948. argc/argv
  4949. Returns:
  4950. none
  4951. --*/
  4952. {
  4953. int i;
  4954. BOOL ValidOption = FALSE;
  4955. #ifdef _OCM
  4956. PVOID OcManagerContext;
  4957. #endif
  4958. //
  4959. // Indicate that we're running in Setup, not in appwiz.
  4960. // Nothing should come before this!
  4961. //
  4962. IsSetup = TRUE;
  4963. BEGIN_SECTION(L"Installing Windows NT");
  4964. #if 1 // NOTE: Can be turned off before we ship if we don't find use for this. Give a 2 second window!
  4965. // If debugger is not already attached to the process and we have the user pressing the Shift+F10 key,
  4966. // launch just cmd.exe to help debug.
  4967. //
  4968. // MessageBox(NULL, L"Hit Shift-F10 Now.", L"Launch Command Window", MB_OK);
  4969. Sleep(2000) ; // Hack: give user 2 seconds to press Shift+F10. Else we could go by too fast!
  4970. if (!IsDebuggerPresent()) {
  4971. SHORT wTemp;
  4972. DWORD dwTemp ;
  4973. wTemp = GetAsyncKeyState(VK_SHIFT) ;
  4974. if (wTemp & 0x8000) { // See if the user is holding down the Shift key or held it before
  4975. wTemp = GetAsyncKeyState(VK_F10) ;
  4976. if (wTemp & 0x8000) { // See if the user is holding down the F10 key also or held it before?
  4977. // InvokeExternalApplication(L"ntsd", L" -d setup -newsetup", NULL) ; // if kd is enabled, we can do this
  4978. // InvokeExternalApplication(L"ntsd", L"setup -newsetup", NULL) ; // in no kd, case launch under ntsd locally
  4979. InvokeExternalApplication(L"cmd", L"", &dwTemp) ;
  4980. return;
  4981. }
  4982. }
  4983. }
  4984. #endif
  4985. // Calc. the time estimates
  4986. SetTimeEstimates();
  4987. BEGIN_SECTION(L"Initialization");
  4988. //
  4989. // Tell SetupAPI not to bother backing up files and not to verify
  4990. // that any INFs are digitally signed.
  4991. //
  4992. pSetupSetGlobalFlags(pSetupGetGlobalFlags()|PSPGF_NO_BACKUP|PSPGF_NO_VERIFY_INF);
  4993. //
  4994. // Scan Command Line for -mini or -asr flags
  4995. //
  4996. // -mini enables gui-mode setup but with
  4997. // only a minimal subset of his functionality. We're going
  4998. // to display a few wizard pages and that's about it.
  4999. //
  5000. // -asr causes the Automated System Recovery (ASR) code to run.
  5001. //
  5002. // -asrquicktest bypasses all of Setup/PnP, and jumps to the
  5003. // ASR disk recofiguration and recovery app code.
  5004. //
  5005. for(i = 0; i < argc; i++) {
  5006. if(argv[i][0] == '-') {
  5007. if(!_strcmpi(argv[i],"-newsetup")) {
  5008. ValidOption = TRUE;
  5009. }
  5010. if(!_strcmpi(argv[i],"-mini")) {
  5011. MiniSetup = TRUE;
  5012. ValidOption = TRUE;
  5013. }
  5014. if(!_strcmpi(argv[i], "-asr")) {
  5015. AsrInitialize();
  5016. ValidOption = TRUE;
  5017. }
  5018. if(!_strcmpi(argv[i], "-asrquicktest")) {
  5019. AsrQuickTest = TRUE;
  5020. ValidOption = TRUE;
  5021. AsrInitialize();
  5022. }
  5023. }
  5024. }
  5025. if( ValidOption == FALSE ){
  5026. WCHAR TitleBuffer[1024], MessageBuffer[1024];
  5027. LoadString(MyModuleHandle, IDS_WINNT_SETUP , TitleBuffer, SIZECHARS(TitleBuffer));
  5028. LoadString(MyModuleHandle, IDS_MAINTOBS_MSG1 , MessageBuffer, SIZECHARS(MessageBuffer));
  5029. MessageBox(NULL, MessageBuffer, TitleBuffer, MB_ICONINFORMATION | MB_OK);
  5030. return;
  5031. }
  5032. // Check if we are in SafeMode ....
  5033. // If so cause a popup and return.
  5034. if( IsSafeMode() ){
  5035. WCHAR TitleBuffer[1024], MessageBuffer[1024];
  5036. LoadString(MyModuleHandle, IDS_WINNT_SETUP , TitleBuffer, SIZECHARS(TitleBuffer));
  5037. LoadString(MyModuleHandle, IDS_SAFEMODENOTALLOWED , MessageBuffer, SIZECHARS(MessageBuffer));
  5038. MessageBox(NULL, MessageBuffer, TitleBuffer, MB_ICONINFORMATION | MB_OK);
  5039. return;
  5040. }
  5041. //
  5042. // If we're running ASR quick tests, jump directly to the recovery code
  5043. //
  5044. if (AsrQuickTest) {
  5045. #if DBG
  5046. g_hSysSetupHeap = GetProcessHeap();
  5047. #endif
  5048. goto Recovery;
  5049. }
  5050. //
  5051. // super bad hack becase pnp, atapi, and cdrom driver are always broken
  5052. // we open a handle to the first cdrom drive so the drive doesn't get removed
  5053. //
  5054. {
  5055. NTSTATUS Status;
  5056. OBJECT_ATTRIBUTES ObjectAttributes;
  5057. UNICODE_STRING UnicodeString;
  5058. HANDLE Handle;
  5059. IO_STATUS_BLOCK StatusBlock;
  5060. RtlInitUnicodeString(&UnicodeString,L"\\Device\\CdRom0");
  5061. InitializeObjectAttributes(
  5062. &ObjectAttributes,
  5063. &UnicodeString,
  5064. OBJ_CASE_INSENSITIVE,
  5065. NULL,
  5066. NULL
  5067. );
  5068. SetErrorMode(SEM_FAILCRITICALERRORS);
  5069. Status = NtCreateFile(
  5070. &Handle,
  5071. FILE_READ_ATTRIBUTES,
  5072. &ObjectAttributes,
  5073. &StatusBlock,
  5074. NULL,
  5075. FILE_ATTRIBUTE_NORMAL,
  5076. FILE_SHARE_READ | FILE_SHARE_WRITE,
  5077. FILE_OPEN,
  5078. 0,
  5079. NULL,
  5080. 0
  5081. );
  5082. if (!NT_SUCCESS(Status)) {
  5083. SetupDebugPrint1( L"Setup: Could not open the cdrom for hack, ec=0x%08x\n", Status );
  5084. }
  5085. }
  5086. //
  5087. // Initialization phase. Common to initial install and upgrade.
  5088. //
  5089. BEGIN_SECTION(L"Common Initialiazation");
  5090. #ifdef _OCM
  5091. OcManagerContext =
  5092. #endif
  5093. CommonInitialization();
  5094. END_SECTION(L"Common Initialiazation");
  5095. if(Upgrade || MiniSetup) {
  5096. InitializePidVariables();
  5097. TESTHOOK(521);
  5098. } else {
  5099. if(!InitializePidVariables()) {
  5100. FatalError(MSG_SETUP_CANT_READ_PID,0,0);
  5101. }
  5102. //
  5103. // Do the wizard. Time how long it takes, to later help further randomize
  5104. // the account domain sid we're going to generate later.
  5105. //
  5106. PreWizardTickCount = GetTickCount();
  5107. }
  5108. //
  5109. // Disable the PM engine from powering down the machine
  5110. // while the wizard is going.
  5111. //
  5112. SetThreadExecutionState( ES_SYSTEM_REQUIRED |
  5113. ES_DISPLAY_REQUIRED |
  5114. ES_CONTINUOUS );
  5115. SetUpDataBlock();
  5116. InternalSetupData.CallSpecificData1 = 0;
  5117. //
  5118. // Create Windows NT software key entry on both upgrade and clean install
  5119. //
  5120. if(Upgrade || !MiniSetup ) {
  5121. CreateWindowsNtSoftwareEntry(TRUE);
  5122. }
  5123. END_SECTION(L"Initialization");
  5124. BEGIN_SECTION(L"Wizard");
  5125. #ifdef _OCM
  5126. MYASSERT(OcManagerContext);
  5127. Wizard(OcManagerContext);
  5128. //
  5129. // this call was moved to CopyFilesDlgProc as an optimization
  5130. //
  5131. //KillOcManager(OcManagerContext);
  5132. #else
  5133. Wizard();
  5134. #endif
  5135. END_SECTION(L"Wizard");
  5136. Recovery:
  5137. BEGIN_SECTION(L"Recovery");
  5138. if (AsrIsEnabled()) {
  5139. AsrExecuteRecoveryApps();
  5140. }
  5141. END_SECTION(L"Recovery");
  5142. BEGIN_SECTION(L"Shutdown");
  5143. ShutdownSetup();
  5144. END_SECTION(L"Shutdown");
  5145. RemoveAllPendingOperationsOnRestartOfGUIMode();
  5146. if (hinstBB)
  5147. {
  5148. FreeLibrary(hinstBB);
  5149. hinstBB = NULL;
  5150. }
  5151. LogPidValues();
  5152. END_SECTION(L"Installing Windows NT");
  5153. }
  5154. VOID
  5155. RemoveMSKeyboardPtrPropSheet (
  5156. VOID
  5157. )
  5158. /*++
  5159. Routine Description:
  5160. Fixes problem with IntelliType Manager under NT 4.0 by disabling it.
  5161. Arguments:
  5162. None.
  5163. Returns:
  5164. None.
  5165. --*/
  5166. {
  5167. HKEY hkeyDir; // handle of the key containing the directories
  5168. TCHAR szKbdCpPath[MAX_PATH]; // buffer for the fully-qualified path to INI file
  5169. LONG lRet; // return value from RegQueryValueEx
  5170. DWORD dwDataType; // data-type returned from call to RegQueryValueEx
  5171. DWORD BufferSize;
  5172. PCWSTR sz_off = L"OFF";
  5173. //
  5174. // open the key that contains the directories of all the software for all the MS Input Devices
  5175. //
  5176. RegOpenKey ( HKEY_CURRENT_USER,
  5177. L"Control Panel\\Microsoft Input Devices\\Directories", &hkeyDir );
  5178. //
  5179. // get the path to the MS Keyboard software
  5180. //
  5181. BufferSize = sizeof (szKbdCpPath);
  5182. lRet = RegQueryValueEx ( hkeyDir, L"Keyboard", 0, &dwDataType,
  5183. (LPBYTE)szKbdCpPath, &BufferSize);
  5184. //
  5185. // close the directories key now
  5186. //
  5187. RegCloseKey ( hkeyDir );
  5188. // check if we were able to get the directory of the keyboard software; if not, then
  5189. // there may be no keyboard software installed or at least we don't know where
  5190. // to find it; if we got it OK, then use it
  5191. if ( lRet == ERROR_SUCCESS) {
  5192. //
  5193. // we have the path to the INI file, so build the fully qualified path to the INI file
  5194. //
  5195. lstrcat ( szKbdCpPath, L"\\KBDCP.INI" );
  5196. //
  5197. // remove the KBDPTR32.DLL entry from the list of 32-bit property sheet DLLs now,
  5198. // because we don't want it loading on Windows NT 4.0 or later
  5199. WritePrivateProfileString ( L"Property Sheets 32", L"KBDPTR32.DLL",
  5200. NULL, szKbdCpPath );
  5201. lRet = RegOpenKey (HKEY_CURRENT_USER,
  5202. L"Control Panel\\Microsoft Input Devices\\WindowsPointer",
  5203. &hkeyDir);
  5204. if (lRet == ERROR_SUCCESS) {
  5205. RegSetValueEx (
  5206. hkeyDir,
  5207. L"MouseKey",
  5208. 0,
  5209. REG_SZ,
  5210. (LPBYTE)sz_off,
  5211. (lstrlen(sz_off)+1) * sizeof(WCHAR)
  5212. );
  5213. RegCloseKey (hkeyDir);
  5214. }
  5215. }
  5216. }
  5217. VOID
  5218. FixWordPadReg (
  5219. VOID
  5220. )
  5221. /*++
  5222. Routine Description:
  5223. Fixes problem with registry entry that associates .doc files with WordPad.
  5224. Arguments:
  5225. None.
  5226. Returns:
  5227. None.
  5228. --*/
  5229. {
  5230. PCWSTR SearchString = L"WordPad.Document";
  5231. PCWSTR ReplaceString = L"WordPad.Document.1";
  5232. LONG Ret;
  5233. HKEY Key;
  5234. DWORD Type;
  5235. BYTE Data[MAX_PATH];
  5236. DWORD Size = MAX_PATH;
  5237. Ret = RegOpenKeyEx (
  5238. HKEY_CLASSES_ROOT,
  5239. L".doc",
  5240. 0,
  5241. KEY_ALL_ACCESS,
  5242. &Key
  5243. );
  5244. if (Ret != ERROR_SUCCESS) {
  5245. return;
  5246. }
  5247. Ret = RegQueryValueEx (
  5248. Key,
  5249. L"",
  5250. NULL,
  5251. &Type,
  5252. Data,
  5253. &Size
  5254. );
  5255. if (Ret != ERROR_SUCCESS ||
  5256. lstrcmp ((PCWSTR)Data, SearchString)) {
  5257. return;
  5258. }
  5259. RegSetValueEx (
  5260. Key,
  5261. L"",
  5262. 0,
  5263. Type,
  5264. (PBYTE)ReplaceString,
  5265. (lstrlen (ReplaceString) + 1) * sizeof (WCHAR)
  5266. );
  5267. }
  5268. VOID
  5269. ProcessRegistryFiles(
  5270. IN HWND Billboard
  5271. )
  5272. /*++
  5273. Routine Description:
  5274. This function processes all the inf files listed in the section
  5275. [RegistryInfs] of syssetup.inf.
  5276. The infs listed in this section will populate/upgrade the DEFAULT
  5277. hive and HKEY_CLASSES_ROOT.
  5278. Note that any errors that occur during this phase are fatal.
  5279. Arguments:
  5280. Billboard - Handle to the billboard displayed when this function was called
  5281. If an error occurs, tyhe function will kill the billboard.
  5282. Return Value:
  5283. None.
  5284. This function will not return if an error occurs.
  5285. --*/
  5286. {
  5287. ULONG LineCount;
  5288. ULONG LineNo;
  5289. PCWSTR RegSectionName = L"RegistryInfs";
  5290. PCWSTR InfName;
  5291. HINF InfHandle;
  5292. INFCONTEXT InfContext;
  5293. BOOL b;
  5294. //
  5295. // Get the number of lines in the section. The section may be empty
  5296. // or non-existant; this is not an error condition.
  5297. //
  5298. LineCount = (UINT)SetupGetLineCount(SyssetupInf,RegSectionName);
  5299. if((LONG)LineCount > 0) {
  5300. for(LineNo=0; LineNo<LineCount; LineNo++) {
  5301. if(SetupGetLineByIndex(SyssetupInf,RegSectionName,LineNo,&InfContext) &&
  5302. ((InfName = pSetupGetField(&InfContext,1)) != NULL) ) {
  5303. //
  5304. // Now load the registry (win95-style!) infs.
  5305. //
  5306. //
  5307. InfHandle = SetupOpenInfFile(InfName,NULL,INF_STYLE_WIN4,NULL);
  5308. if(InfHandle == INVALID_HANDLE_VALUE) {
  5309. KillBillboard(Billboard);
  5310. FatalError(MSG_LOG_SYSINFBAD,InfName,0,0);
  5311. }
  5312. //
  5313. // Process the inf just opened
  5314. //
  5315. b = SetupInstallFromInfSection( NULL, // Window,
  5316. InfHandle,
  5317. (Upgrade)? L"Upgrade" : L"CleanInstall",
  5318. SPINST_ALL & ~SPINST_FILES,
  5319. NULL,
  5320. NULL,
  5321. 0,
  5322. NULL,
  5323. NULL,
  5324. NULL,
  5325. NULL
  5326. );
  5327. if(!b) {
  5328. KillBillboard(Billboard);
  5329. FatalError(MSG_LOG_SYSINFBAD,InfName,0,0);
  5330. }
  5331. }
  5332. }
  5333. }
  5334. }
  5335. UCHAR
  5336. QueryDriveLetter(
  5337. IN ULONG Signature,
  5338. IN LONGLONG Offset
  5339. )
  5340. {
  5341. PDRIVE_LAYOUT_INFORMATION layout;
  5342. UCHAR c;
  5343. WCHAR name[80], result[80], num[10];
  5344. DWORD i, j;
  5345. HANDLE h;
  5346. BOOL b;
  5347. DWORD bytes;
  5348. PARTITION_INFORMATION partInfo;
  5349. layout = LocalAlloc(0, 4096);
  5350. if (!layout) {
  5351. return 0;
  5352. }
  5353. for (c = 'C'; c <= 'Z'; c++) {
  5354. name[0] = c;
  5355. name[1] = ':';
  5356. name[2] = 0;
  5357. if (QueryDosDevice(name, result, 80) < 17) {
  5358. continue;
  5359. }
  5360. j = 0;
  5361. for (i = 16; result[i]; i++) {
  5362. if (result[i] == '\\') {
  5363. break;
  5364. }
  5365. num[j++] = result[i];
  5366. }
  5367. num[j] = 0;
  5368. wsprintf(name, L"\\\\.\\PhysicalDrive%s", num);
  5369. h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  5370. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  5371. INVALID_HANDLE_VALUE);
  5372. if (h == INVALID_HANDLE_VALUE) {
  5373. continue;
  5374. }
  5375. b = DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_LAYOUT, NULL, 0, layout,
  5376. 4096, &bytes, NULL);
  5377. CloseHandle(h);
  5378. if (!b) {
  5379. continue;
  5380. }
  5381. if (layout->Signature != Signature) {
  5382. continue;
  5383. }
  5384. wsprintf(name, L"\\\\.\\%c:", c);
  5385. h = CreateFile(name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  5386. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
  5387. INVALID_HANDLE_VALUE);
  5388. if (h == INVALID_HANDLE_VALUE) {
  5389. continue;
  5390. }
  5391. b = DeviceIoControl(h, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0,
  5392. &partInfo, sizeof(partInfo), &bytes, NULL);
  5393. CloseHandle(h);
  5394. if (!b) {
  5395. continue;
  5396. }
  5397. if (partInfo.StartingOffset.QuadPart == Offset) {
  5398. break;
  5399. }
  5400. }
  5401. LocalFree(layout);
  5402. return (c <= 'Z') ? c : 0;
  5403. }
  5404. MIGDLLINIT MigDllInitProc;
  5405. MIGDLLSHUTDOWN MigDllShutdownProc;
  5406. MIGDLLCLOSEW MigDllCloseProc;
  5407. MIGDLLOPENW MigDllOpenProc;
  5408. MIGDLLFREELIST MigDllFreeListProc;
  5409. MIGDLLENUMNEXTW MigDllEnumNextProc;
  5410. MIGDLLENUMFIRSTW MigDllEnumFirstProc;
  5411. MIGDLLADDDLLTOLISTW MigDllAddDllToListProc;
  5412. MIGDLLCREATELIST MigDllCreateListProc;
  5413. MIGDLLINITIALIZEDSTW MigDllInitializeDstProc;
  5414. MIGDLLAPPLYSYSTEMSETTINGSW MigDllApplySystemSettingsProc;
  5415. BOOL
  5416. LoadMigLibEntryPoints (
  5417. HANDLE Library
  5418. )
  5419. {
  5420. MigDllInitProc = (MIGDLLINIT) GetProcAddress (Library, "MigDllInit");
  5421. MigDllShutdownProc = (MIGDLLSHUTDOWN) GetProcAddress (Library, "MigDllShutdown");
  5422. MigDllCloseProc = (MIGDLLCLOSEW) GetProcAddress (Library, "MigDllCloseW");
  5423. MigDllOpenProc = (MIGDLLOPENW) GetProcAddress (Library, "MigDllOpenW");
  5424. MigDllFreeListProc = (MIGDLLFREELIST) GetProcAddress (Library, "MigDllFreeList");
  5425. MigDllEnumNextProc = (MIGDLLENUMNEXTW) GetProcAddress (Library, "MigDllEnumNextW");
  5426. MigDllEnumFirstProc = (MIGDLLENUMFIRSTW) GetProcAddress (Library, "MigDllEnumFirstW");
  5427. MigDllAddDllToListProc = (MIGDLLADDDLLTOLISTW) GetProcAddress (Library, "MigDllAddDllToListW");
  5428. MigDllCreateListProc = (MIGDLLCREATELIST) GetProcAddress (Library, "MigDllCreateList");
  5429. MigDllInitializeDstProc = (MIGDLLINITIALIZEDSTW) GetProcAddress (Library, "MigDllInitializeDstW");
  5430. MigDllApplySystemSettingsProc = (MIGDLLAPPLYSYSTEMSETTINGSW) GetProcAddress (Library, "MigDllApplySystemSettingsW");
  5431. if (!MigDllInitProc ||
  5432. !MigDllShutdownProc ||
  5433. !MigDllCloseProc ||
  5434. !MigDllOpenProc ||
  5435. !MigDllFreeListProc ||
  5436. !MigDllEnumNextProc ||
  5437. !MigDllEnumFirstProc ||
  5438. !MigDllAddDllToListProc ||
  5439. !MigDllCreateListProc ||
  5440. !MigDllInitializeDstProc ||
  5441. !MigDllApplySystemSettingsProc
  5442. ) {
  5443. return FALSE;
  5444. }
  5445. return TRUE;
  5446. }
  5447. BOOL
  5448. CallMigDllEntryPoints (
  5449. PMIGDLLENUM Enum
  5450. )
  5451. {
  5452. MIGRATIONDLL dll;
  5453. LONG rc;
  5454. if (!MigDllOpenProc (&dll, Enum->Properties->DllPath, APPLYMODE, FALSE, SOURCEOS_WINNT)) {
  5455. return FALSE;
  5456. }
  5457. __try {
  5458. rc = ERROR_SUCCESS;
  5459. if (!MigDllInitializeDstProc (
  5460. &dll,
  5461. Enum->Properties->WorkingDirectory,
  5462. SourcePath,
  5463. NULL,
  5464. 0
  5465. )) {
  5466. rc = GetLastError ();
  5467. }
  5468. if (rc != ERROR_SUCCESS) {
  5469. return FALSE;
  5470. }
  5471. if (!MigDllApplySystemSettingsProc (
  5472. &dll,
  5473. Enum->Properties->WorkingDirectory,
  5474. NULL,
  5475. NULL,
  5476. 0
  5477. )) {
  5478. rc = GetLastError ();
  5479. }
  5480. if (rc != ERROR_SUCCESS) {
  5481. return FALSE;
  5482. }
  5483. }
  5484. __finally {
  5485. MigDllCloseProc (&dll);
  5486. }
  5487. return TRUE;
  5488. }
  5489. BOOL
  5490. RunMigrationDlls (
  5491. VOID
  5492. )
  5493. {
  5494. WCHAR libraryPath[MAX_PATH];
  5495. HANDLE libHandle = NULL;
  5496. DLLLIST list = NULL;
  5497. MIGDLLENUM e;
  5498. WCHAR DllInfPath[MAX_PATH];
  5499. WCHAR DllPath[MAX_PATH];
  5500. HINF inf;
  5501. INFCONTEXT ic;
  5502. MIGRATIONDLL dll;
  5503. //
  5504. // Build handle to library and load.
  5505. //
  5506. GetSystemDirectory (libraryPath, MAX_PATH);
  5507. pSetupConcatenatePaths (libraryPath, TEXT("miglibnt.dll"), MAX_PATH, NULL);
  5508. libHandle = LoadLibrary (libraryPath);
  5509. if (!libHandle || libHandle == INVALID_HANDLE_VALUE) {
  5510. return TRUE;
  5511. }
  5512. __try {
  5513. if (!LoadMigLibEntryPoints (libHandle)) {
  5514. __leave;
  5515. }
  5516. if (!MigDllInitProc ()) {
  5517. __leave;
  5518. }
  5519. list = MigDllCreateListProc ();
  5520. if (!list) {
  5521. __leave;
  5522. }
  5523. //
  5524. // Read in list of dlls.
  5525. //
  5526. GetWindowsDirectory (DllInfPath, MAX_PATH);
  5527. pSetupConcatenatePaths (DllInfPath, TEXT("Setup\\dlls.inf"), MAX_PATH, NULL);
  5528. inf = SetupOpenInfFile (DllInfPath, NULL, INF_STYLE_WIN4, NULL);
  5529. if (!inf || inf == INVALID_HANDLE_VALUE) {
  5530. __leave;
  5531. }
  5532. if (SetupFindFirstLine (inf, TEXT("DllsToLoad"), NULL, &ic)) {
  5533. do {
  5534. if (SetupGetStringField (&ic, 1, DllPath, MAX_PATH,NULL)) {
  5535. if (MigDllOpenProc (&dll, DllPath, APPLYMODE, FALSE, SOURCEOS_WINNT)) {
  5536. MigDllAddDllToListProc (list, &dll);
  5537. MigDllCloseProc (&dll);
  5538. }
  5539. }
  5540. } while (SetupFindNextLine (&ic, &ic));
  5541. }
  5542. //
  5543. // Enumerate all migration dlls we ran on the winnt32 side and run
  5544. // their syssetup side entry points.
  5545. //
  5546. if (MigDllEnumFirstProc (&e, list)) {
  5547. do {
  5548. CallMigDllEntryPoints (&e);
  5549. } while (MigDllEnumNextProc (&e));
  5550. }
  5551. }
  5552. __finally {
  5553. if (list) {
  5554. MigDllFreeListProc (list);
  5555. }
  5556. if (libHandle && libHandle != INVALID_HANDLE_VALUE) {
  5557. if( MigDllShutdownProc) {
  5558. MigDllShutdownProc ();
  5559. }
  5560. FreeLibrary (libHandle);
  5561. }
  5562. }
  5563. return TRUE;
  5564. }
  5565. BOOL
  5566. RunSetupPrograms(
  5567. IN PVOID InfHandle,
  5568. PWSTR SectionName
  5569. )
  5570. /*++
  5571. Routine Description:
  5572. This routine executes the commands listed on [RunPrograms] section in the syssetup inf file.
  5573. Each line is interpreted as a single command.
  5574. Arguments:
  5575. None.
  5576. Return Value:
  5577. Boolean value indicating outcome.
  5578. --*/
  5579. {
  5580. WCHAR OldCurrentDir[MAX_PATH];
  5581. WCHAR System32Dir[MAX_PATH];
  5582. LONG LineCount,LineNo;
  5583. PCWSTR CommandLine;
  5584. DWORD DontCare;
  5585. BOOL AnyError;
  5586. INFCONTEXT InfContext;
  5587. //
  5588. // Set current directory to system32.
  5589. // Preserve current directory to minimize side-effects.
  5590. //
  5591. if(!GetCurrentDirectory(MAX_PATH,OldCurrentDir)) {
  5592. OldCurrentDir[0] = 0;
  5593. }
  5594. GetSystemDirectory(System32Dir,MAX_PATH);
  5595. SetCurrentDirectory(System32Dir);
  5596. //
  5597. // Get the number of lines in the section that contains the commands to
  5598. // be executed. The section may be empty or non-existant; this is not
  5599. // an error condition. In that case LineCount may be -1 or 0.
  5600. //
  5601. AnyError = FALSE;
  5602. LineCount = SetupGetLineCount(InfHandle,SectionName);
  5603. for(LineNo=0; LineNo<LineCount; LineNo++) {
  5604. if(SetupGetLineByIndex(InfHandle,SectionName,(DWORD)LineNo,&InfContext)
  5605. && (CommandLine = pSetupGetField(&InfContext,1))) {
  5606. if(!InvokeExternalApplication(NULL,CommandLine,&DontCare)) {
  5607. AnyError = TRUE;
  5608. SetupDebugPrint1(L"SETUP: Unable to execute the command: %ls", CommandLine);
  5609. }
  5610. } else {
  5611. //
  5612. // Strange case, inf is messed up
  5613. //
  5614. AnyError = TRUE;
  5615. SetupDebugPrint(L"SETUP: Syssetup.inf is corrupt");
  5616. }
  5617. }
  5618. //
  5619. // Reset current directory and return.
  5620. //
  5621. if(OldCurrentDir[0]) {
  5622. SetCurrentDirectory(OldCurrentDir);
  5623. }
  5624. if(AnyError) {
  5625. SetuplogError(
  5626. LogSevError,
  5627. SETUPLOG_USE_MESSAGEID,
  5628. MSG_LOG_PROGRAM_FAIL,
  5629. SectionName,
  5630. NULL,NULL);
  5631. }
  5632. return(!AnyError);
  5633. }
  5634. VOID
  5635. GetUnattendRunOnceAndSetRegistry(
  5636. VOID
  5637. )
  5638. {
  5639. HINF AnswerInf;
  5640. WCHAR AnswerFile[MAX_PATH];
  5641. WCHAR Buf[128];
  5642. BOOL AnyError;
  5643. INFCONTEXT InfContext;
  5644. LONG LineCount,LineNo;
  5645. PCWSTR SectionName = pwGuiRunOnce;
  5646. PCWSTR CommandLine;
  5647. HKEY hKey;
  5648. GetSystemDirectory(AnswerFile,MAX_PATH);
  5649. pSetupConcatenatePaths(AnswerFile,WINNT_GUI_FILE,MAX_PATH,NULL);
  5650. AnswerInf = SetupOpenInfFile(AnswerFile,NULL,INF_STYLE_OLDNT,NULL);
  5651. if(AnswerInf == INVALID_HANDLE_VALUE) {
  5652. return;
  5653. }
  5654. if (RegOpenKey( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce", &hKey ) != ERROR_SUCCESS) {
  5655. SetupCloseInfFile( AnswerInf );
  5656. return;
  5657. }
  5658. AnyError = FALSE;
  5659. LineCount = SetupGetLineCount(AnswerInf,SectionName);
  5660. for(LineNo=0; LineNo<LineCount; LineNo++) {
  5661. if(SetupGetLineByIndex(AnswerInf,SectionName,(DWORD)LineNo,&InfContext)
  5662. && (CommandLine = pSetupGetField(&InfContext,1)))
  5663. {
  5664. swprintf( Buf, L"%ws%d", SectionName, LineNo );
  5665. if (RegSetValueEx( hKey, Buf, 0, REG_EXPAND_SZ, (LPBYTE)CommandLine, (wcslen(CommandLine)+1)*sizeof(WCHAR) ) != ERROR_SUCCESS) {
  5666. AnyError = TRUE;
  5667. }
  5668. } else {
  5669. //
  5670. // Strange case, inf is messed up
  5671. //
  5672. AnyError = TRUE;
  5673. }
  5674. }
  5675. RegCloseKey( hKey );
  5676. SetupCloseInfFile( AnswerInf );
  5677. return;
  5678. }
  5679. // This function returns the product flavor as a DWORD.
  5680. // NOTE: The value has to be the same as the *_PRODUCTTYPE in winnt32.h
  5681. DWORD GetProductFlavor()
  5682. {
  5683. DWORD ProductFlavor = 0; // Default Professional
  5684. OSVERSIONINFOEX osvi;
  5685. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  5686. GetVersionEx((OSVERSIONINFO*)&osvi);
  5687. if (osvi.wProductType == VER_NT_WORKSTATION)
  5688. {
  5689. if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
  5690. {
  5691. ProductFlavor = 4; // Personal
  5692. }
  5693. }
  5694. else
  5695. {
  5696. ProductFlavor = 1; // In the server case assume normal server
  5697. if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
  5698. {
  5699. ProductFlavor = 3; // Datacenter
  5700. }
  5701. else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
  5702. {
  5703. ProductFlavor = 2; // Advanced server
  5704. }
  5705. }
  5706. return ProductFlavor;
  5707. }
  5708. void PrepareBillBoard(HWND hwnd)
  5709. {
  5710. TCHAR szPath[MAX_PATH];
  5711. TCHAR *p;
  5712. WNDCLASS wndclass;
  5713. INITBILLBOARD pinitbb;
  5714. hinstBB = LoadLibrary(TEXT("winntbbu.dll"));
  5715. if (hinstBB)
  5716. {
  5717. *szPath = 0;
  5718. if (GetModuleFileName (MyModuleHandle, szPath, MAX_PATH))
  5719. {
  5720. if(p = wcsrchr(szPath,L'\\'))
  5721. {
  5722. *p = 0;
  5723. }
  5724. }
  5725. pinitbb = (INITBILLBOARD)GetProcAddress(hinstBB, "InitBillBoard");
  5726. if (pinitbb)
  5727. {
  5728. (*pinitbb)(hwnd, szPath, GetProductFlavor());
  5729. SetBBStep(4);
  5730. }
  5731. }
  5732. }
  5733. void TerminateBillBoard()
  5734. {
  5735. TERMBILLBOARD pTermBillBoard;
  5736. if (hinstBB)
  5737. {
  5738. if (pTermBillBoard = (TERMBILLBOARD)GetProcAddress(hinstBB, "TermBillBoard"))
  5739. pTermBillBoard ();
  5740. }
  5741. }
  5742. HWND GetBBhwnd()
  5743. {
  5744. GETBBHWND pgetbbhwnd;
  5745. static HWND retHWND = NULL;
  5746. if (retHWND == NULL)
  5747. {
  5748. if (hinstBB)
  5749. {
  5750. if (pgetbbhwnd = (GETBBHWND )GetProcAddress(hinstBB, "GetBBHwnd"))
  5751. retHWND = pgetbbhwnd();
  5752. }
  5753. }
  5754. return retHWND;
  5755. }
  5756. void SetBBStep(int iStep)
  5757. {
  5758. static SETSTEP psetstep = NULL;
  5759. if (psetstep == NULL)
  5760. {
  5761. if (hinstBB)
  5762. {
  5763. psetstep = (SETSTEP )GetProcAddress(hinstBB, "SetStep");
  5764. }
  5765. }
  5766. if (psetstep)
  5767. psetstep(iStep);
  5768. }
  5769. VOID
  5770. CenterWindowRelativeToWindow(
  5771. HWND hwndtocenter,
  5772. HWND hwndcenteron,
  5773. BOOL bWizard
  5774. )
  5775. /*++
  5776. Routine Description:
  5777. Centers a dialog hwndtocenter on Windows hwndcenteron.
  5778. if bWizard and the height of the hwndcenteron is 480 or less
  5779. align windows to the right edge of the hwndcenteron.
  5780. In all other cases center both ways.
  5781. Arguments:
  5782. hwndtocenter - window handle of dialog to center
  5783. hwndcenteron - window handle to center dialog on
  5784. bWizard - in low res, align dialog with the right
  5785. edge of hwndcenteron
  5786. Return Value:
  5787. None.
  5788. --*/
  5789. {
  5790. RECT rcFrame,
  5791. rcWindow;
  5792. LONG x,
  5793. y,
  5794. w,
  5795. h;
  5796. POINT point;
  5797. HWND Parent;
  5798. UINT uiHeight = 0;
  5799. GetWindowRect(GetDesktopWindow(), &rcWindow);
  5800. uiHeight = rcWindow.bottom - rcWindow.top;
  5801. if (hwndcenteron == NULL)
  5802. Parent = GetDesktopWindow();
  5803. else
  5804. Parent = hwndcenteron;
  5805. point.x = point.y = 0;
  5806. ClientToScreen(Parent,&point);
  5807. GetWindowRect(hwndtocenter,&rcWindow);
  5808. GetClientRect(Parent,&rcFrame);
  5809. w = rcWindow.right - rcWindow.left + 1;
  5810. h = rcWindow.bottom - rcWindow.top + 1;
  5811. y = point.y + ((rcFrame.bottom - rcFrame.top + 1 - h) / 2);
  5812. // Anything but the wizard can stay centered horizontally.
  5813. // or if we don't have a billboard (hwndcenteron == NULL)
  5814. // or if the height of the desktop is more then 480
  5815. // just center
  5816. if (!bWizard || (hwndcenteron == NULL) || (uiHeight > 480))
  5817. {
  5818. x = point.x + ((rcFrame.right - rcFrame.left + 1 - w) / 2);
  5819. }
  5820. else
  5821. {
  5822. RECT rcParentWindow;
  5823. GetWindowRect(Parent, &rcParentWindow);
  5824. x = point.x + rcParentWindow.right - rcParentWindow.left + 1 - w;
  5825. }
  5826. MoveWindow(hwndtocenter,x,y,w,h,FALSE);
  5827. }
  5828. VOID
  5829. CopyOemProgramFilesDir(
  5830. VOID
  5831. )
  5832. /*++
  5833. Routine Description:
  5834. Tree copies the $OEM$\\$PROGS to %Program Files% folder.
  5835. Arguments:
  5836. None.
  5837. Return Value:
  5838. None.
  5839. --*/
  5840. {
  5841. WCHAR OemDir[MAX_PATH];
  5842. WCHAR ProgramFilesDir[MAX_PATH];
  5843. DWORD Error = NO_ERROR;
  5844. //
  5845. // Build the target Program Files folder path
  5846. //
  5847. ExpandEnvironmentStrings(L"%ProgramFiles%",ProgramFilesDir,MAX_PATH);
  5848. //
  5849. // SourcePath should be initialized to $win_nt$.~ls
  5850. //
  5851. lstrcpy(OemDir,SourcePath);
  5852. pSetupConcatenatePaths(OemDir,WINNT_OEM_DIR,MAX_PATH,NULL);
  5853. pSetupConcatenatePaths(OemDir,WINNT_OEM_FILES_PROGRAMFILES,MAX_PATH,NULL);
  5854. Error = TreeCopy(OemDir,ProgramFilesDir);
  5855. if (!NT_SUCCESS(Error)) {
  5856. SetuplogError(LogSevWarning,
  5857. L"Setup failed to TreeCopy %2 to %3 (TreeCopy failed %1!u!)\r\n",
  5858. 0, Error, OemDir, ProgramFilesDir, Error, NULL,NULL
  5859. );
  5860. return;
  5861. }
  5862. }
  5863. VOID
  5864. CopyOemDocumentsDir(
  5865. VOID
  5866. )
  5867. /*++
  5868. Routine Description:
  5869. Tree copies the $OEM$\\$DOCS to %Document and Settings% folder.
  5870. Arguments:
  5871. None.
  5872. Return Value:
  5873. None.
  5874. --*/
  5875. {
  5876. WCHAR OemDir[MAX_PATH];
  5877. WCHAR DocumentsAndSettingsDir[MAX_PATH];
  5878. DWORD Error = NO_ERROR, dwSize = MAX_PATH;
  5879. //
  5880. // Make sure we can get the Documents and Settings folder
  5881. //
  5882. if (GetProfilesDirectory(DocumentsAndSettingsDir,&dwSize))
  5883. {
  5884. //
  5885. // SourcePath should be initialized to $win_nt$.~ls
  5886. //
  5887. lstrcpy(OemDir,SourcePath);
  5888. pSetupConcatenatePaths(OemDir,WINNT_OEM_DIR,MAX_PATH,NULL);
  5889. pSetupConcatenatePaths(OemDir,WINNT_OEM_FILES_DOCUMENTS,MAX_PATH,NULL);
  5890. Error = TreeCopy(OemDir,DocumentsAndSettingsDir);
  5891. if (!NT_SUCCESS(Error)) {
  5892. SetuplogError(LogSevWarning,
  5893. L"Setup failed to TreeCopy %2 to %3 (TreeCopy failed %1!u!)\r\n",
  5894. 0, Error, OemDir, DocumentsAndSettingsDir, NULL,NULL
  5895. );
  5896. return;
  5897. }
  5898. }
  5899. else {
  5900. SetuplogError(LogSevWarning,
  5901. L"SETUP: GetProfilesDirectory() failed in function CopyOemDocumentsDir()\r\n",
  5902. 0, NULL, NULL
  5903. );
  5904. }
  5905. }
  5906. BOOL
  5907. SystemMyGetUserProfileDirectory(
  5908. IN LPWSTR szUser, // a user account name
  5909. OUT LPWSTR szUserProfileDir, // buffer to receive null terminate string
  5910. IN OUT LPDWORD pcchSize // input the buffer size in TCHAR, including terminating NULL
  5911. )
  5912. /*++
  5913. Routine Description:
  5914. This function does what the SDK function GetUserProfileDirectory does,
  5915. except that it accepts a user account name instead of handle to a user
  5916. token.
  5917. Return Value:
  5918. TRUE - Success
  5919. FALSE - Failure
  5920. Note:
  5921. This function is copy from msobcomm\misc.cpp exactly. We may want
  5922. to put is to common\util.cpp.
  5923. --*/
  5924. {
  5925. PSID pSid = NULL;
  5926. DWORD cbSid = 0;
  5927. LPWSTR szDomainName = NULL;
  5928. DWORD cbDomainName = 0;
  5929. SID_NAME_USE eUse = SidTypeUser;
  5930. BOOL bRet;
  5931. bRet = LookupAccountName(NULL,
  5932. szUser,
  5933. NULL,
  5934. &cbSid,
  5935. NULL,
  5936. &cbDomainName,
  5937. &eUse);
  5938. if (!bRet && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  5939. {
  5940. pSid = (PSID) LocalAlloc(LPTR, cbSid);
  5941. szDomainName = (LPWSTR) LocalAlloc(LPTR, cbDomainName * sizeof(TCHAR));
  5942. if (pSid && szDomainName)
  5943. {
  5944. bRet = LookupAccountName(NULL,
  5945. szUser,
  5946. pSid,
  5947. &cbSid,
  5948. szDomainName,
  5949. &cbDomainName,
  5950. &eUse);
  5951. }
  5952. }
  5953. if (bRet && SidTypeUser == eUse)
  5954. {
  5955. bRet = GetUserProfileDirFromSid(pSid, szUserProfileDir, pcchSize);
  5956. if (!bRet)
  5957. {
  5958. SetuplogError(LogSevWarning,
  5959. L"Setup failed to GetUserProfileDirFromSid. (GetUserProfileDirFromSid failed %1!u!)\r\n",
  5960. 0, GetLastError(), NULL,NULL
  5961. );
  5962. }
  5963. }
  5964. else
  5965. {
  5966. if (SidTypeUser == eUse)
  5967. {
  5968. SetuplogError(LogSevWarning,
  5969. L"LookupAccountName %1 (%2!u!)\r\n",
  5970. 0, szUser, GetLastError(),NULL,NULL
  5971. );
  5972. }
  5973. }
  5974. if (pSid)
  5975. {
  5976. LocalFree(pSid);
  5977. pSid = NULL;
  5978. }
  5979. if (szDomainName)
  5980. {
  5981. LocalFree(szDomainName);
  5982. szDomainName = NULL;
  5983. }
  5984. return bRet;
  5985. }
  5986. BOOL
  5987. SystemResetRegistryKey(
  5988. IN HKEY Rootkey,
  5989. IN PCWSTR Subkey,
  5990. IN PCWSTR Delkey
  5991. )
  5992. /*++
  5993. Routine Description:
  5994. Reset a registry key by deleting the key and all subvalues
  5995. then recreate the key
  5996. Arguments:
  5997. Return Value:
  5998. --*/
  5999. {
  6000. HKEY hkey;
  6001. HKEY nkey;
  6002. DWORD rc;
  6003. BOOL AnyErrors;
  6004. DWORD disp;
  6005. AnyErrors = FALSE;
  6006. rc = RegCreateKeyEx(Rootkey, Subkey, 0L, NULL,
  6007. REG_OPTION_BACKUP_RESTORE,
  6008. KEY_CREATE_SUB_KEY, NULL, &hkey, NULL);
  6009. if ( rc == NO_ERROR )
  6010. {
  6011. rc = SHDeleteKey(hkey, Delkey);
  6012. if( (rc != NO_ERROR) && (rc != ERROR_FILE_NOT_FOUND) )
  6013. {
  6014. AnyErrors = TRUE;
  6015. }
  6016. else
  6017. {
  6018. rc = RegCreateKeyEx(hkey, Delkey, 0L, NULL,
  6019. REG_OPTION_NON_VOLATILE,
  6020. KEY_ALL_ACCESS, NULL, &nkey, &disp);
  6021. if ( rc != NO_ERROR )
  6022. {
  6023. AnyErrors = TRUE;
  6024. }
  6025. else
  6026. {
  6027. RegCloseKey(nkey);
  6028. }
  6029. }
  6030. RegCloseKey(hkey);
  6031. }
  6032. else
  6033. {
  6034. AnyErrors = TRUE;
  6035. }
  6036. return (!AnyErrors);
  6037. }
  6038. BOOL
  6039. SystemUpdateUserProfileDirectory(
  6040. IN LPTSTR szSrcUser
  6041. )
  6042. {
  6043. #define DUMMY_HIVE_NAME L"$$DEFAULT_USER$$"
  6044. #define ACTIVE_SETUP_KEY DUMMY_HIVE_NAME L"\\SOFTWARE\\Microsoft\\Active Setup"
  6045. #define ACTIVE_SETUP_SUBKEY L"Installed Components"
  6046. BOOL bRet = FALSE;
  6047. WCHAR szSrcProfileDir[MAX_PATH];
  6048. DWORD cchSrcProfileDir = MAX_PATH;
  6049. WCHAR szDestProfileDir[MAX_PATH];
  6050. DWORD cchDestProfileDir = MAX_PATH;
  6051. WCHAR szDefaultUserHivePath[MAX_PATH];
  6052. HKEY hHiveKey = NULL;
  6053. DWORD rc;
  6054. if (!SystemMyGetUserProfileDirectory(szSrcUser, szSrcProfileDir, &cchSrcProfileDir))
  6055. {
  6056. SetuplogError(LogSevWarning,
  6057. L"Setup failed to get user profile directory. (SystemMyGetUserProfileDirectory failed %1!u!)\r\n",
  6058. 0, GetLastError(), NULL,NULL
  6059. );
  6060. goto cleanup;
  6061. }
  6062. if (!GetDefaultUserProfileDirectory(szDestProfileDir, &cchDestProfileDir))
  6063. {
  6064. SetuplogError(LogSevWarning,
  6065. L"Setup failed to get default user profile directory. (GetDefaultUserProfileDirectory failed %1!u!)\r\n",
  6066. 0, GetLastError(), NULL,NULL
  6067. );
  6068. goto cleanup;
  6069. }
  6070. if (!CopyProfileDirectory(
  6071. szSrcProfileDir,
  6072. szDestProfileDir,
  6073. CPD_FORCECOPY | CPD_SYNCHRONIZE | CPD_NOERRORUI | CPD_IGNORECOPYERRORS))
  6074. {
  6075. SetuplogError(LogSevWarning,
  6076. L"Setup failed to CopyProfileDirectory. (CopyProfileDirectory failed %1!u!)\r\n",
  6077. 0, GetLastError(), NULL,NULL
  6078. );
  6079. goto cleanup;
  6080. }
  6081. //
  6082. // Fix default user hive
  6083. //
  6084. pSetupEnablePrivilege(SE_RESTORE_NAME, TRUE);
  6085. lstrcpyn(szDefaultUserHivePath, szDestProfileDir, ARRAYSIZE(szDefaultUserHivePath));
  6086. pSetupConcatenatePaths(
  6087. szDefaultUserHivePath,
  6088. L"NTUSER.DAT",
  6089. ARRAYSIZE(szDefaultUserHivePath),
  6090. NULL);
  6091. rc = RegLoadKey(
  6092. HKEY_USERS,
  6093. DUMMY_HIVE_NAME,
  6094. szDefaultUserHivePath);
  6095. if (rc != ERROR_SUCCESS)
  6096. {
  6097. SetuplogError(LogSevWarning,
  6098. L"Setup failed to load Default User hive. (RegLoadKey failed %1!u!)\r\n",
  6099. 0, rc, NULL,NULL
  6100. );
  6101. goto cleanup;
  6102. }
  6103. //
  6104. // The active setup component install keys of the cloned profile contains
  6105. // the version checking information. Remove the keys so that components will
  6106. // run per-user initialization code properly.
  6107. //
  6108. if (!SystemResetRegistryKey(
  6109. HKEY_USERS,
  6110. ACTIVE_SETUP_KEY,
  6111. ACTIVE_SETUP_SUBKEY))
  6112. {
  6113. SetuplogError(LogSevWarning,
  6114. L"Setup failed to load Default User hive. (SystemResetRegistryKey failed)\r\n",
  6115. 0, NULL,NULL
  6116. );
  6117. }
  6118. RegUnLoadKey(
  6119. HKEY_USERS,
  6120. DUMMY_HIVE_NAME
  6121. );
  6122. bRet = TRUE;
  6123. cleanup:
  6124. return bRet;
  6125. }
  6126. BOOL
  6127. UpdateServerProfileDirectory(
  6128. VOID
  6129. )
  6130. /*++
  6131. Routine Description:
  6132. Copy the customized user profile (administrator) to all user profiles.
  6133. Arguments:
  6134. None.
  6135. Return Value:
  6136. Boolean.
  6137. --*/
  6138. {
  6139. BOOL bRet = FALSE;
  6140. WCHAR szTemplateUser[MAX_PATH];
  6141. BEGIN_SECTION(L"Updating Server Profile Directories");
  6142. if(LoadString(MyModuleHandle,
  6143. IDS_ADMINISTRATOR,
  6144. szTemplateUser,
  6145. MAX_PATH) != 0)
  6146. {
  6147. if ( !(bRet = SystemUpdateUserProfileDirectory(szTemplateUser)) )
  6148. {
  6149. SetuplogError(LogSevWarning,
  6150. L"Setup failed to update server profile directory.\r\n",
  6151. 0, NULL, NULL,NULL
  6152. );
  6153. }
  6154. }
  6155. END_SECTION(L"Updating Server Profile Directories");
  6156. return bRet;
  6157. }
  6158. BOOL
  6159. OpkCheckVersion(
  6160. DWORD dwMajorVersion,
  6161. DWORD dwQFEVersion
  6162. )
  6163. /*++
  6164. Routine Description:
  6165. Checks whether OPK tool with specified version numbers is allowed to run on this OS.
  6166. Arguments:
  6167. DWORD dwMajorVersion - Major version number for tool.
  6168. DWORD dwQFEVersion - QFE version number for tool.
  6169. Return Value:
  6170. TRUE - Tool is allowed to run on this OS.
  6171. FALSE - Tool is not allowed to run on this OS.
  6172. --*/
  6173. {
  6174. BOOL bRet = TRUE,
  6175. bXP = FALSE; // Variable is TRUE if this is 2600 XP build. It is set below.
  6176. HKEY hKey = NULL;
  6177. LPTSTR lpszRegPath = _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\SysPrep");
  6178. if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  6179. lpszRegPath,
  6180. 0,
  6181. KEY_QUERY_VALUE,
  6182. &hKey ) )
  6183. {
  6184. DWORD dwType = 0,
  6185. cbBuildNumber = 0;
  6186. LPTSTR lpszBuildNumber = NULL;
  6187. if ( 2600 == dwMajorVersion )
  6188. {
  6189. bXP = TRUE;
  6190. }
  6191. //
  6192. // Read the minimum allowed build number from the registry:
  6193. //
  6194. // 1. Get the size of the data in the registry
  6195. // 2. Allocate a buffer
  6196. // 3. Read the data.
  6197. //
  6198. if ( ( ERROR_SUCCESS == RegQueryValueEx( hKey,
  6199. bXP ? _T("XPMinVersion") : _T("NETMinVersion"),
  6200. NULL,
  6201. &dwType,
  6202. NULL,
  6203. &cbBuildNumber ) ) &&
  6204. ( cbBuildNumber > 0 ) &&
  6205. ( lpszBuildNumber = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, cbBuildNumber ) ) &&
  6206. ( ERROR_SUCCESS == RegQueryValueEx( hKey,
  6207. bXP ? _T("XPMinVersion") : _T("NETMinVersion"),
  6208. NULL,
  6209. &dwType,
  6210. (LPBYTE) lpszBuildNumber,
  6211. &cbBuildNumber ) ) &&
  6212. ( REG_SZ == dwType ) )
  6213. {
  6214. LPTSTR lpTemp = NULL;
  6215. DWORD dwMinMajorVersion = 0,
  6216. dwMinQFEVersion = 0;
  6217. //
  6218. // Parse the string that we got from the registry into major version and QFE version.
  6219. //
  6220. if ( lpTemp = _tcsstr( lpszBuildNumber, _T(".") ) )
  6221. {
  6222. *lpTemp = _T('\0');
  6223. // Get the Major version of the build number
  6224. //
  6225. dwMinMajorVersion = _tstoi( lpszBuildNumber );
  6226. // Advance past the NULL separator that we added.
  6227. //
  6228. lpTemp++;
  6229. dwMinQFEVersion = _tstoi( lpTemp );
  6230. //
  6231. // Now make sure we are allowed to run
  6232. //
  6233. if ( dwMajorVersion < dwMinMajorVersion )
  6234. {
  6235. //
  6236. // If major version is less than minimum allowed major version don't let it run.
  6237. //
  6238. bRet = FALSE;
  6239. }
  6240. else if ( dwMajorVersion == dwMinMajorVersion )
  6241. {
  6242. //
  6243. // If major version is equal to the minimum allowed major version then check at the QFE field.
  6244. //
  6245. if ( dwQFEVersion < dwMinQFEVersion )
  6246. {
  6247. bRet = FALSE;
  6248. }
  6249. }
  6250. }
  6251. }
  6252. if ( lpszBuildNumber )
  6253. {
  6254. HeapFree( GetProcessHeap(), 0, lpszBuildNumber );
  6255. }
  6256. RegCloseKey( hKey );
  6257. }
  6258. return bRet;
  6259. }