Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

8342 lines
241 KiB

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