Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5393 lines
149 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #if defined(_X86_) //NEC98 I970721
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <winbase.h>
  7. #include <n98boot.h>
  8. #endif // PC98
  9. #include <pencrypt.h>
  10. #include <winsta.h>
  11. #include <ntverp.h>
  12. #include <undo.h>
  13. #include "errorrep.h"
  14. #include "faulth.h"
  15. void PrepareBillBoard(HWND hwnd);
  16. void TerminateBillBoard();
  17. void CreateMainWindow();
  18. UINT GetMediaProductBuildNumber (VOID);
  19. void CopyExtraBVTDirs();
  20. HWND BackgroundWnd2 = NULL;
  21. //
  22. // Misc globals.
  23. //
  24. HINSTANCE hInst;
  25. DWORD TlsIndex;
  26. //
  27. // Upgrade information block
  28. //
  29. WINNT32_PLUGIN_INIT_INFORMATION_BLOCK info;
  30. #ifdef _X86_
  31. PWINNT32_PLUGIN_SETAUTOBOOT_ROUTINE W95SetAutoBootFlag;
  32. WINNT32_WIN9XUPG_INIT_INFORMATION_BLOCK Win9xInfo;
  33. #endif
  34. //
  35. // This is the title of the application. It changes dynamically depending on
  36. // whether we're on server or workstation, etc.
  37. //
  38. UINT AppTitleStringId = IDS_APPTITLE;
  39. //
  40. // Flag indicating whether we are initiating an MSI-install.
  41. //
  42. BOOL RunFromMSI = FALSE;
  43. //
  44. // Flag indicating whether we are initiating an Typical install
  45. // Initialize to Typical install.
  46. DWORD dwSetupFlags = UPG_FLAG_TYPICAL;
  47. //
  48. // Flag indicating whether we are initiating an upgrade.
  49. //
  50. BOOL Upgrade = TRUE;
  51. //
  52. // Flag to say if we need to write the AcpiHAL value to the winnt.sif file
  53. //
  54. BOOL WriteAcpiHalValue = FALSE;
  55. //
  56. // What should we write as the value for the AcpiHalValue
  57. //
  58. BOOL AcpiHalValue = FALSE;
  59. //
  60. // Flag indicating whether we're installing/upgrading to NT Server
  61. //
  62. BOOL Server;
  63. //
  64. // Flag to indicate if we are running BVT's
  65. //
  66. BOOL RunningBVTs = FALSE;
  67. //
  68. // When running BVT's, what baudrate should we set the debugger to?
  69. //
  70. LONG lDebugBaudRate = 115200;
  71. //
  72. // When running BVT's, what comport should we set the debugger to?
  73. //
  74. LONG lDebugComPort = 0;
  75. //
  76. // When running BVT's, should we copy the symbols locally?
  77. //
  78. BOOL CopySymbols = TRUE;
  79. //
  80. // Flag to indicate if we are running ASR tests
  81. //
  82. DWORD AsrQuickTest = 0;
  83. //
  84. // Flags for product type and flavor for upgrade modules
  85. //
  86. PRODUCTTYPE UpgradeProductType = UNKNOWN;
  87. UINT ProductFlavor = UNKNOWN_PRODUCTTYPE;
  88. //
  89. // Global flag indicating whether the entire overall program operation
  90. // was successful. Also a flag indicating whether to shut down automatically
  91. // when the wizard is done in the non-unattended case.
  92. //
  93. BOOL GlobalResult = FALSE;
  94. BOOL AutomaticallyShutDown = TRUE;
  95. //
  96. // Global OS version info.
  97. //
  98. OSVERSIONINFO OsVersion;
  99. DWORD OsVersionNumber = 0;
  100. //
  101. // Flags indicating how we were run and whether to create
  102. // a local source.
  103. //
  104. BOOL RunFromCD;
  105. BOOL MakeLocalSource;
  106. BOOL UserSpecifiedMakeLocalSource = FALSE;
  107. BOOL NoLs = FALSE;
  108. TCHAR UserSpecifiedLocalSourceDrive;
  109. //
  110. // the default for MLS is CD1 only
  111. //
  112. DWORD MLSDiskID = 1;
  113. //
  114. // advanced install options
  115. //
  116. BOOL ChoosePartition = TRUE;
  117. BOOL UseSignatures = TRUE;
  118. TCHAR InstallDir[MAX_PATH];
  119. //
  120. // SMS support
  121. //
  122. typedef DWORD (*SMSPROC) (char *, char*, char*, char*, char *, char *, char *, BOOL);
  123. PSTR LastMessage = NULL;
  124. #if defined(REMOTE_BOOT)
  125. //
  126. // Flag indicating whether we're running on a remote boot client.
  127. //
  128. BOOL RemoteBoot;
  129. //
  130. // Path to the machine directory for a remote boot client.
  131. //
  132. TCHAR MachineDirectory[MAX_PATH];
  133. #endif // defined(REMOTE_BOOT)
  134. //
  135. // Flags indicating which Accessibility utilities to use
  136. //
  137. BOOL AccessibleMagnifier;
  138. BOOL AccessibleKeyboard;
  139. BOOL AccessibleVoice;
  140. BOOL AccessibleReader;
  141. //
  142. // Build number we're upgrading from
  143. //
  144. DWORD BuildNumber = 0;
  145. //
  146. // Are any of the Accesssibility utilities enabled?
  147. //
  148. BOOL AccessibleSetup;
  149. //
  150. // Name of unattended script file to be used for Accessible Setup
  151. //
  152. TCHAR AccessibleScriptFile[MAX_PATH] = TEXT("setupacc.txt");
  153. //
  154. // Flags and values relating to unattended operation.
  155. //
  156. BOOL UnattendedOperation;
  157. BOOL UnattendSwitchSpecified = FALSE;
  158. PTSTR UnattendedScriptFile;
  159. UINT UnattendedShutdownTimeout;
  160. BOOL BatchMode;
  161. //
  162. // Source paths and count of paths.
  163. //
  164. TCHAR SourcePaths[MAX_SOURCE_COUNT][MAX_PATH];
  165. UINT SourceCount;
  166. //
  167. // source paths to current architecture's files
  168. //
  169. TCHAR NativeSourcePaths[MAX_SOURCE_COUNT][MAX_PATH];
  170. TCHAR *UserSpecifiedOEMShare = NULL;
  171. //
  172. // Local source information.
  173. //
  174. TCHAR LocalSourceDrive;
  175. DWORD LocalSourceDriveOffset;
  176. TCHAR LocalSourceDirectory[MAX_PATH];
  177. TCHAR LocalSourceWithPlatform[MAX_PATH];
  178. TCHAR LocalBootDirectory[MAX_PATH];
  179. #ifdef _X86_
  180. TCHAR LocalBackupDirectory[MAX_PATH];
  181. TCHAR FirstFloppyDriveLetter;
  182. #endif
  183. LONGLONG LocalSourceSpaceRequired;
  184. LONGLONG WinDirSpaceFor9x = 0l;
  185. BOOL BlockOnNotEnoughSpace = TRUE;
  186. UINT UpgRequiredMb;
  187. UINT UpgAvailableMb;
  188. BOOL UpginfsUpdated = FALSE;
  189. //
  190. // Optional directory stuff.
  191. //
  192. UINT OptionalDirectoryCount;
  193. TCHAR OptionalDirectories[MAX_OPTIONALDIRS][MAX_PATH];
  194. UINT OptionalDirectoryFlags[MAX_OPTIONALDIRS];
  195. //
  196. // Name of INF. Constructed so we don't have to realloc anything.
  197. // Note the default.
  198. // Also, handles to dosnet.inf and txtsetup.sif.
  199. //
  200. TCHAR InfName[] = TEXT("DOSNET.INF");
  201. PVOID MainInf;
  202. TCHAR FullInfName[MAX_PATH];
  203. PVOID TxtsetupSif;
  204. PVOID NtcompatInf;
  205. //
  206. // Array of drive letters for all system partitions.
  207. // Note that on x86 there will always be exactly one.
  208. // The list is 0-terminated.
  209. //
  210. TCHAR SystemPartitionDriveLetters[27];
  211. TCHAR SystemPartitionDriveLetter;
  212. #ifdef UNICODE
  213. UINT SystemPartitionCount;
  214. PWSTR* SystemPartitionNtNames;
  215. PWSTR SystemPartitionNtName;
  216. #else
  217. //
  218. // if running on Win9x, there may be a LocalSourcePath passed as parameter
  219. //
  220. PCSTR g_LocalSourcePath;
  221. #endif
  222. //
  223. // UDF stuff
  224. //
  225. LPCTSTR UniquenessId;
  226. LPCTSTR UniquenessDatabaseFile;
  227. //
  228. // Variables relating to the multi string of options that are passed
  229. // to plugin DLLs (Like Win9xUpg)
  230. //
  231. LPTSTR UpgradeOptions;
  232. DWORD UpgradeOptionsLength;
  233. DWORD UpgradeOptionsSize;
  234. //
  235. // Compliance related variables
  236. //
  237. BOOL NoCompliance = FALSE;
  238. //
  239. // Variables to hold messages concerning reason that the upgrade cannot be completed.
  240. //
  241. #define MSG_UPGRADE_OK 0
  242. #define MSG_LAST_REASON 0
  243. #define FAILREASON(x) MSG_##x,
  244. DWORD UpgradeFailureMessages[] = {
  245. UPGRADEFAILURES /*,*/ MSG_UPGRADE_INIT_ERROR
  246. };
  247. #undef FAILREASON
  248. UINT UpgradeFailureReason = 0;
  249. TCHAR UpgradeSourcePath[MAX_PATH];
  250. //
  251. // Internal override to version checking. Useful for making quick
  252. // privates for foreign language versions.
  253. //
  254. BOOL SkipLocaleCheck = FALSE;
  255. //
  256. // override for the win9x virus scanner check.
  257. //
  258. BOOL SkipVirusScannerCheck = FALSE;
  259. BOOL UseBIOSToBoot = FALSE;
  260. //
  261. // Preinstall stuff
  262. //
  263. BOOL OemPreinstall;
  264. #ifdef _X86_
  265. POEM_BOOT_FILE OemBootFiles;
  266. #endif
  267. //
  268. // Miscellaneous other command line parameters.
  269. //
  270. LPCTSTR CmdToExecuteAtEndOfGui;
  271. BOOL AutoSkipMissingFiles;
  272. BOOL HideWinDir;
  273. TCHAR ProductId[64] = TEXT("\0");
  274. UINT PIDDays = 0;
  275. LPTSTR g_EncryptedPID = NULL;
  276. BOOL g_bDeferPIDValidation = FALSE;
  277. //
  278. // Flag indicating that the user cancelled.
  279. // Handle for mutex used to guarantee that only one error dialog
  280. // is on the screen at once.
  281. //
  282. BOOL Cancelled;
  283. HANDLE UiMutex;
  284. //
  285. // Flag indicating user is aborting. This flag suppresses the final screen in
  286. // cancel mode. I.E. The unsuccssessful completion page.
  287. // win9xupg ReportOnly mode.
  288. //
  289. BOOL Aborted;
  290. //
  291. // Floppy-related stuff.
  292. // Defined, but not used for ARC based machines.
  293. //
  294. BOOL MakeBootMedia = TRUE;
  295. BOOL Floppyless = TRUE;
  296. //
  297. // Upgrade extension DLL.
  298. //
  299. UPGRADE_SUPPORT UpgradeSupport;
  300. //
  301. // Only check to see if we can upgrade or not.
  302. //
  303. BOOL CheckUpgradeOnly;
  304. BOOL CheckUpgradeOnlyQ;
  305. //
  306. // Specifies that winnt32 runs as an "Upgrade Advisor"
  307. // and not all installation files are available
  308. //
  309. BOOL UpgradeAdvisorMode;
  310. //
  311. // Build the command console.
  312. //
  313. BOOL BuildCmdcons;
  314. //
  315. // Are we doing the PID encyption?
  316. //
  317. BOOL PIDEncryption = FALSE;
  318. BOOL g_Quiet = FALSE;
  319. #define WINNT_U_ENCRYPT TEXT("ENCRYPT")
  320. #ifdef RUN_SYSPARSE
  321. // Remove this before RTM.
  322. // Be default run sysparse
  323. BOOL NoSysparse = FALSE;
  324. PROCESS_INFORMATION piSysparse = { NULL, NULL, 0, 0};
  325. LRESULT SysParseDlgProc( IN HWND hdlg, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam);
  326. HWND GetBBhwnd();
  327. #endif
  328. //
  329. // Log Functions
  330. //
  331. SETUPOPENLOG fnSetupOpenLog = NULL;
  332. SETUPLOGERROR fnSetupLogError = NULL;
  333. SETUPCLOSELOG fnSetupCloseLog = NULL;
  334. //
  335. // Unsupported driver list
  336. // This list contains the information about the unsupported drivers that needs
  337. // to be migrated on a clean install or upgrade.
  338. //
  339. // PUNSUPORTED_DRIVER_INFO UnsupportedDriverList = NULL;
  340. //
  341. // When Winnt32.exe is launched over a network, these two parameters have valid
  342. // values and need to be taken into consideration before displaying any dialog box
  343. //
  344. HWND Winnt32Dlg = NULL;
  345. HANDLE WinNT32StubEvent = NULL;
  346. HINSTANCE hinstBB = NULL;
  347. //
  348. // Definition for dynamically-loaded InitiateSystemShutdownEx API
  349. //
  350. typedef
  351. (WINAPI *PFNINITIATESYSTEMSHUTDOWNEX)(LPTSTR,
  352. LPTSTR,
  353. DWORD,
  354. BOOL,
  355. BOOL,
  356. DWORD);
  357. //
  358. // Routines from Setupapi.dll
  359. //
  360. BOOL
  361. (*SetupapiCabinetRoutine)(
  362. IN LPCTSTR CabinetFile,
  363. IN DWORD Flags,
  364. IN PSP_FILE_CALLBACK MsgHandler,
  365. IN PVOID Context
  366. );
  367. DWORD
  368. (*SetupapiDecompressOrCopyFile)(
  369. IN PCTSTR SourceFileName,
  370. OUT PCTSTR TargetFileName,
  371. OUT PUINT CompressionType OPTIONAL
  372. );
  373. HINF
  374. (*SetupapiOpenInfFile)(
  375. IN LPCTSTR FileName,
  376. IN LPCTSTR InfClass, OPTIONAL
  377. IN DWORD InfStyle,
  378. OUT PUINT ErrorLine OPTIONAL
  379. );
  380. VOID
  381. (*SetupapiCloseInfFile)(
  382. IN HINF InfHandle
  383. );
  384. BOOL
  385. (*SetupapiFindFirstLine)(
  386. IN HINF InfHandle,
  387. IN PCTSTR Section,
  388. IN PCTSTR Key, OPTIONAL
  389. OUT PINFCONTEXT Context
  390. );
  391. BOOL
  392. (*SetupapiFindNextLine)(
  393. IN PINFCONTEXT Context1,
  394. OUT PINFCONTEXT Context2
  395. );
  396. BOOL
  397. (*SetupapiFindNextMatchLine)(
  398. IN PINFCONTEXT Context1,
  399. IN PCTSTR Key,
  400. OUT PINFCONTEXT Context2
  401. );
  402. LONG
  403. (*SetupapiGetLineCount)(
  404. IN HINF InfHandle,
  405. IN LPCTSTR Section
  406. );
  407. DWORD
  408. (*SetupapiGetFieldCount)(
  409. IN PINFCONTEXT Context
  410. );
  411. BOOL
  412. (*SetupapiGetStringField)(
  413. IN PINFCONTEXT Context,
  414. DWORD FieldIndex,
  415. PTSTR ReturnBuffer,
  416. DWORD ReturnBufferSize,
  417. PDWORD RequiredSize
  418. );
  419. BOOL
  420. (*SetupapiGetLineByIndex)(
  421. IN HINF InfHandle,
  422. IN LPCTSTR Section,
  423. IN DWORD Index,
  424. OUT PINFCONTEXT Context
  425. );
  426. HSPFILEQ
  427. (*SetupapiOpenFileQueue) (
  428. VOID
  429. );
  430. BOOL
  431. (*SetupapiCloseFileQueue) (
  432. IN HSPFILEQ QueueHandle
  433. );
  434. BOOL
  435. (*SetupapiQueueCopy) (
  436. IN HSPFILEQ QueueHandle,
  437. IN PCTSTR SourceRootPath, OPTIONAL
  438. IN PCTSTR SourcePath, OPTIONAL
  439. IN PCTSTR SourceFilename,
  440. IN PCTSTR SourceDescription, OPTIONAL
  441. IN PCTSTR SourceTagfile, OPTIONAL
  442. IN PCTSTR TargetDirectory,
  443. IN PCTSTR TargetFilename, OPTIONAL
  444. IN DWORD CopyStyle
  445. );
  446. BOOL
  447. (*SetupapiCommitFileQueue) (
  448. IN HWND Owner, OPTIONAL
  449. IN HSPFILEQ QueueHandle,
  450. IN PSP_FILE_CALLBACK_W MsgHandler,
  451. IN PVOID Context
  452. );
  453. UINT
  454. (*SetupapiDefaultQueueCallback) (
  455. IN PVOID Context,
  456. IN UINT Notification,
  457. IN UINT_PTR Param1,
  458. IN UINT_PTR Param2
  459. );
  460. PVOID
  461. (*SetupapiInitDefaultQueueCallback) (
  462. HWND OwnerWindow
  463. );
  464. VOID
  465. (*SetupapiTermDefaultQueueCallback) (
  466. PVOID Context
  467. );
  468. BOOL
  469. (*SetupapiGetSourceFileLocation) (
  470. HINF InfHandle, // handle of an INF file
  471. PINFCONTEXT InfContext, // optional, context of an INF file
  472. PCTSTR FileName, // optional, source file to locate
  473. PUINT SourceId, // receives the source media ID
  474. PTSTR ReturnBuffer, // optional, receives the location
  475. DWORD ReturnBufferSize, // size of the supplied buffer
  476. PDWORD RequiredSize // optional, buffer size needed
  477. );
  478. //
  479. //srclient.dll (SystemRestore) functions
  480. //
  481. DWORD
  482. (*SRClientDisableSR) (
  483. LPCWSTR pszDrive
  484. );
  485. //
  486. // NEC98 Specific local function
  487. //
  488. VOID
  489. DeleteNEC98DriveAssignFlag(
  490. VOID
  491. );
  492. BOOLEAN
  493. AdjustPrivilege(
  494. PWSTR Privilege
  495. );
  496. VOID
  497. LocateFirstFloppyDrive(
  498. VOID
  499. );
  500. VOID
  501. W95SetABFwFresh(
  502. int bBootDrvLtr
  503. );
  504. BOOL
  505. NEC98CheckDMI(
  506. VOID
  507. );
  508. VOID
  509. DisableSystemRestore( void );
  510. //
  511. //
  512. //
  513. BOOL
  514. GetArgsFromUnattendFile(
  515. VOID
  516. )
  517. /*++
  518. Routine Description:
  519. This routine read relevent arguments from any specified unattended file.
  520. Specifically we are concerned here with oem preinstall stuff and whether
  521. to upgrade.
  522. Arguments:
  523. None.
  524. Return Value:
  525. Boolean value indicating whether the unattend file the user specified is
  526. valid. If not, the user will have been told about why.
  527. If the user specified no unattend file on the command line, then the
  528. return value is TRUE.
  529. --*/
  530. {
  531. DWORD d;
  532. TCHAR Buffer[2*MAX_PATH];
  533. BOOL b = TRUE;
  534. PVOID InfHandle;
  535. LPCTSTR p;
  536. BOOL userDDU = FALSE;
  537. #ifdef _X86_
  538. POEM_BOOT_FILE FileStruct,Previous;
  539. #endif
  540. if(UnattendedScriptFile) {
  541. d = GetFileAttributes(UnattendedScriptFile);
  542. if(d == (DWORD)(-1)) {
  543. MessageBoxFromMessage(
  544. NULL,
  545. MSG_UNATTEND_FILE_INVALID,
  546. FALSE,
  547. AppTitleStringId,
  548. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  549. UnattendedScriptFile
  550. );
  551. return(FALSE);
  552. }
  553. //
  554. // Before we do much else, we should make sure the user has given
  555. // us a valid answer file. We can't check everything, but a quick
  556. // and dirty sanity check would be to go ahead and call LoadInfFile
  557. // and see what he says about it.
  558. //
  559. switch(LoadInfFile(UnattendedScriptFile,FALSE,&InfHandle)) {
  560. case NO_ERROR:
  561. break;
  562. case ERROR_NOT_ENOUGH_MEMORY:
  563. MessageBoxFromMessage(
  564. NULL,
  565. MSG_OUT_OF_MEMORY,
  566. FALSE,
  567. AppTitleStringId,
  568. MB_OK | MB_ICONERROR | MB_TASKMODAL
  569. );
  570. return(FALSE);
  571. break;
  572. default:
  573. MessageBoxFromMessage(
  574. NULL,
  575. MSG_UNATTEND_FILE_INVALID,
  576. FALSE,
  577. AppTitleStringId,
  578. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  579. UnattendedScriptFile
  580. );
  581. return(FALSE);
  582. break;
  583. }
  584. //
  585. // Check upgrade.
  586. //
  587. // In previous versions of NT the default was not to upgrade if
  588. // the value wasn't present at all. In addition there was an upgrade
  589. // type of "single" which meant to upgrade only if there was only one
  590. // NT build on the machine.
  591. //
  592. // We preserve the original default behavior but don't bother with
  593. // dealing with the "single" semantics -- just accept "single" as
  594. // a synonym for "yes".
  595. //
  596. GetPrivateProfileString(
  597. WINNT_UNATTENDED,
  598. ISNT() ? WINNT_U_NTUPGRADE : WINNT_U_WIN95UPGRADE,
  599. WINNT_A_NO,
  600. Buffer,
  601. sizeof(Buffer)/sizeof(TCHAR),
  602. UnattendedScriptFile
  603. );
  604. Upgrade = ((lstrcmpi(Buffer,WINNT_A_YES) == 0) || (lstrcmpi(Buffer,TEXT("single")) == 0));
  605. #if defined(REMOTE_BOOT)
  606. //
  607. // Remote boot machines MUST upgrade.
  608. //
  609. if (RemoteBoot) {
  610. Upgrade = TRUE;
  611. }
  612. #endif // defined(REMOTE_BOOT)
  613. GetPrivateProfileString(
  614. WINNT_UNATTENDED,
  615. WINNT_OEMPREINSTALL,
  616. WINNT_A_NO,
  617. Buffer,
  618. sizeof(Buffer)/sizeof(TCHAR),
  619. UnattendedScriptFile
  620. );
  621. if(!lstrcmpi(Buffer,WINNT_A_YES)) {
  622. OemPreinstall = TRUE;
  623. //
  624. // Add oem system directory to the list of optional directories.
  625. //
  626. // The user may have specified a different location for the $OEM$
  627. // directory, so we need to look in the unattend file for that.
  628. //
  629. GetPrivateProfileString(
  630. WINNT_UNATTENDED,
  631. WINNT_OEM_DIRLOCATION,
  632. WINNT_A_NO,
  633. Buffer,
  634. sizeof(Buffer)/sizeof(TCHAR),
  635. UnattendedScriptFile
  636. );
  637. if( lstrcmpi( Buffer, WINNT_A_NO ) ) {
  638. //
  639. // make sure the location ends with "\$oem$". If it
  640. // doesn't, then append it ourselves.
  641. //
  642. _tcsupr( Buffer );
  643. if( !_tcsstr(Buffer, TEXT("$OEM$")) ) {
  644. ConcatenatePaths( Buffer, TEXT("$OEM$"), MAX_PATH );
  645. }
  646. UserSpecifiedOEMShare = DupString( Buffer );
  647. RememberOptionalDir( UserSpecifiedOEMShare, OPTDIR_OEMSYS );
  648. } else {
  649. RememberOptionalDir(WINNT_OEM_DIR,OPTDIR_OEMSYS | OPTDIR_ADDSRCARCH);
  650. }
  651. if (!IsArc()) {
  652. #ifdef _X86_
  653. //
  654. // Remember all oem boot files and then unload the inf.
  655. //
  656. Previous = NULL;
  657. for(d=0; b && (p=InfGetFieldByIndex(InfHandle,WINNT_OEMBOOTFILES,d,0)); d++) {
  658. if(FileStruct = MALLOC(sizeof(OEM_BOOT_FILE))) {
  659. FileStruct->Next = NULL;
  660. if(FileStruct->Filename = DupString(p)) {
  661. if(Previous) {
  662. Previous->Next = FileStruct;
  663. } else {
  664. OemBootFiles = FileStruct;
  665. }
  666. Previous = FileStruct;
  667. } else {
  668. b = FALSE;
  669. }
  670. } else {
  671. b = FALSE;
  672. }
  673. }
  674. if(!b) {
  675. MessageBoxFromMessage(
  676. NULL,
  677. MSG_OUT_OF_MEMORY,
  678. FALSE,
  679. AppTitleStringId,
  680. MB_OK | MB_ICONERROR | MB_TASKMODAL
  681. );
  682. }
  683. #endif // _X86_
  684. } // if (!IsArc())
  685. }
  686. GetPrivateProfileString(
  687. WINNT_USERDATA,
  688. WINNT_US_PRODUCTID,
  689. WINNT_A_NO,
  690. Buffer,
  691. sizeof(Buffer)/sizeof(TCHAR),
  692. UnattendedScriptFile
  693. );
  694. if( lstrcmpi( Buffer, WINNT_A_NO ) == 0 )
  695. {
  696. GetPrivateProfileString(
  697. WINNT_USERDATA,
  698. WINNT_US_PRODUCTKEY,
  699. WINNT_A_NO,
  700. Buffer,
  701. sizeof(Buffer)/sizeof(TCHAR),
  702. UnattendedScriptFile
  703. );
  704. }
  705. // Buffer contains the Product ID or WINNT_A_NO if none in the unattend file
  706. // Is the PID encrypted?
  707. // We would only need to check for the exact length, but since we can defer
  708. // the decryption of an encrypted PID until GUI mode, 2 time the length should be saver
  709. if (lstrlen(Buffer) > (4 + MAX_PID30_EDIT*5)*2)
  710. {
  711. LPTSTR szDecryptedPID = NULL;
  712. HRESULT hr = ValidateEncryptedPID(Buffer, &szDecryptedPID);
  713. DebugLog (Winnt32LogInformation, TEXT("ValidateEncryptedPID returned: <hr=0x%1!lx!>"), 0, hr);
  714. if (FAILED(hr) || (hr == S_OK))
  715. {
  716. // if FAILED(hr) assume Crypto is not installed correct.
  717. // If we encrypted the data, but the encrypted data did not contain valid data
  718. // the function does not return a FAILED(hr) and does not return S_OK;
  719. // It returns 0x01 to 0x04, depending on what failure.
  720. // In the case we get a failure from Crypto ( it returns FAILED(hr))
  721. // we want to defer the checking of the PID until GUI mode
  722. // for that we need to save the encrypted PID
  723. // First assume we defer PID validation.
  724. g_bDeferPIDValidation = TRUE;
  725. g_EncryptedPID = GlobalAlloc(GPTR, (lstrlen(Buffer) + 1) *sizeof(TCHAR));
  726. if (g_EncryptedPID)
  727. {
  728. // Save the decrypted PID we need to write it to winnt.sif
  729. lstrcpy(g_EncryptedPID, Buffer);
  730. }
  731. // Only if the PID could be decrypted and falls in to the time interval
  732. // do we save the decrypted PID.
  733. if (hr == S_OK)
  734. {
  735. lstrcpyn(ProductId, szDecryptedPID, sizeof(ProductId)/sizeof(TCHAR));
  736. g_bDeferPIDValidation = FALSE;
  737. }
  738. }
  739. // else we could encrypt the data, but something is wrong
  740. //
  741. if (szDecryptedPID)
  742. {
  743. GlobalFree(szDecryptedPID);
  744. }
  745. }
  746. else if (lstrcmpi(Buffer, WINNT_A_NO))
  747. {
  748. lstrcpyn(ProductId, Buffer, sizeof(ProductId)/sizeof(TCHAR));
  749. }
  750. else
  751. {
  752. *ProductId = TEXT('\0');
  753. }
  754. GetPrivateProfileString(
  755. WINNT_UNATTENDED,
  756. TEXT("FileSystem"),
  757. TEXT(""),
  758. Buffer,
  759. sizeof(Buffer)/sizeof(TCHAR),
  760. UnattendedScriptFile
  761. );
  762. ForceNTFSConversion = !lstrcmpi(Buffer, TEXT("ConvertNTFS"));
  763. if (!g_DynUpdtStatus->Disabled && !g_DynUpdtStatus->DynamicUpdatesSource[0]) {
  764. //
  765. // will Setup do the Dynamic Updates step at all?
  766. //
  767. if (GetPrivateProfileString(
  768. WINNT_UNATTENDED,
  769. WINNT_U_DYNAMICUPDATESDISABLE,
  770. TEXT(""),
  771. Buffer,
  772. sizeof(Buffer)/sizeof(TCHAR),
  773. UnattendedScriptFile
  774. )
  775. #ifdef PRERELEASE
  776. || GetPrivateProfileString(
  777. WINNT_UNATTENDED,
  778. TEXT("disabledynamicupdates"),
  779. TEXT(""),
  780. Buffer,
  781. sizeof(Buffer)/sizeof(TCHAR),
  782. UnattendedScriptFile
  783. )
  784. #endif
  785. ) {
  786. userDDU = TRUE;
  787. if( !lstrcmpi( Buffer, WINNT_A_YES ) ) {
  788. g_DynUpdtStatus->Disabled = TRUE;
  789. }
  790. }
  791. }
  792. if (!g_DynUpdtStatus->Disabled && !g_DynUpdtStatus->DynamicUpdatesSource[0]) {
  793. //
  794. // get location of previously downloaded files (if any)
  795. //
  796. if (GetPrivateProfileString(
  797. WINNT_UNATTENDED,
  798. WINNT_U_DYNAMICUPDATESHARE,
  799. TEXT(""),
  800. g_DynUpdtStatus->DynamicUpdatesSource,
  801. sizeof(g_DynUpdtStatus->DynamicUpdatesSource) / sizeof(TCHAR),
  802. UnattendedScriptFile
  803. )) {
  804. RemoveTrailingWack (g_DynUpdtStatus->DynamicUpdatesSource);
  805. if (DoesDirectoryExist (g_DynUpdtStatus->DynamicUpdatesSource)) {
  806. g_DynUpdtStatus->UserSpecifiedUpdates = TRUE;
  807. } else {
  808. b = FALSE;
  809. }
  810. } else {
  811. if (!userDDU) {
  812. g_DynUpdtStatus->Disabled = TRUE;
  813. }
  814. }
  815. }
  816. UnloadInfFile(InfHandle);
  817. }
  818. return(b);
  819. }
  820. BOOL
  821. ParseArguments(
  822. VOID
  823. )
  824. /*++
  825. Routine Description:
  826. Parse arguments passed to the program. Perform syntactic validation
  827. and fill in defaults where necessary.
  828. Valid arguments:
  829. /batch suppress message boxes
  830. /cmd:command_line command to execute at end of gui setup
  831. /copydir:dirname tree copy directory from source into %systemroot%
  832. Note that this supports ".." syntax to backtrack
  833. one directory
  834. /copysource:dirname copy directory for use as source
  835. /debug[level][:filename] maintain debug log at level, defaults to warning level 2
  836. and file c:\winnt32.log
  837. /DynamicUpdatesDisable disable dynamic setup
  838. /s:source specify source
  839. /syspart:letter force a drive to be considered the system partition
  840. /tempdrive:letter manually specify drive for local source
  841. /udf:id[,file] uniqueness id and optional udf
  842. /unattend[num][:file] unattended mode with optional countdown
  843. and unattend file. (The countdown is ignored
  844. on Win95.) 'Unattended' is also accepted.
  845. /nodownload not documented; on Win9x installs over the net,
  846. do NOT download program files to a temporary directory and restart
  847. from there. Effective in winnt32.exe only; here it's ignored
  848. /local not documented; used by winnt32.exe only; ignored in winnt32a|u.dll
  849. /# introduces undoc'ed/internal switches. Handed off
  850. to internal switch handler in internal.c.
  851. /restart specified when winnt32.exe was restarted as a result
  852. of updating one of the underlying modules; internal only
  853. /nosysparse suppress running sysparse.
  854. /E:"PID:days" To encrypt the PID and add a delta of days,
  855. needs to have /Unattend:file specified.
  856. Arguments:
  857. None. Arguments are retreived via GetCommandLine().
  858. Return Value:
  859. None.
  860. --*/
  861. {
  862. LPTSTR Arg;
  863. LPTSTR BadParam = NULL;
  864. LPTSTR Colon;
  865. LPTSTR p;
  866. BOOL Valid;
  867. LPCTSTR DebugFileLog;
  868. LONG DebugLevel;
  869. BOOL b;
  870. unsigned u;
  871. int argc;
  872. LPTSTR *argv;
  873. DWORD d;
  874. WIN32_FIND_DATA fd;
  875. DWORD attr;
  876. argv = CommandLineToArgv(&argc);
  877. //
  878. // Skip program name. We should always get back argc as at least 1,
  879. // but be robust anyway.
  880. //
  881. if(argc) {
  882. argc--;
  883. argv++;
  884. }
  885. DebugFileLog = NULL;
  886. DebugLevel = 0;
  887. Valid = TRUE;
  888. while(argc--) {
  889. Arg = *argv++;
  890. if((*Arg == TEXT('/')) || (*Arg == TEXT('-'))) {
  891. switch(_totupper(Arg[1])) {
  892. case TEXT('B'):
  893. if(!_tcsnicmp(Arg+1,TEXT("batch"),5)) {
  894. BatchMode = TRUE;
  895. } else {
  896. Valid = FALSE;
  897. }
  898. break;
  899. case TEXT('C'):
  900. if(!_tcsnicmp(Arg+1,TEXT("copydir:"),8)) {
  901. if(Arg[9]) {
  902. RememberOptionalDir(Arg+9, OPTDIR_PLATFORM_SPECIFIC_FIRST);
  903. } else {
  904. Valid = FALSE;
  905. }
  906. } else if(!_tcsnicmp(Arg+1,TEXT("copysource:"),11)) {
  907. if(Arg[12]) {
  908. TCHAR TempString[MAX_PATH];
  909. RememberOptionalDir(Arg+12, OPTDIR_TEMPONLY| OPTDIR_ADDSRCARCH);
  910. #ifdef _IA64_
  911. //
  912. // Add the i386\<optional dir> folder if it exists. This helps in the lang folder case where
  913. // we advocate in the network install case to explicitly specify /copysource:lang
  914. lstrcpy( TempString, TEXT("..\\I386\\"));
  915. lstrcat( TempString, Arg+12 );
  916. //Also check if an I386 equivalent WOW directory exists
  917. AddCopydirIfExists( TempString, OPTDIR_TEMPONLY | OPTDIR_PLATFORM_INDEP );
  918. #endif
  919. } else {
  920. Valid = FALSE;
  921. }
  922. } else if(!_tcsnicmp(Arg+1,TEXT("cmd:"),4)) {
  923. if(CmdToExecuteAtEndOfGui) {
  924. Valid = FALSE;
  925. } else {
  926. CmdToExecuteAtEndOfGui = Arg+5;
  927. }
  928. } else if(!_tcsnicmp(Arg+1,TEXT("checkupgradeonly"),16)) {
  929. CheckUpgradeOnly = TRUE;
  930. UnattendedOperation = TRUE;
  931. //
  932. // Tell the win9X upgrade dll to generate a
  933. // report.
  934. //
  935. InternalProcessCmdLineArg( TEXT("/#U:ReportOnly") );
  936. InternalProcessCmdLineArg( TEXT("/#U:PR") );
  937. //
  938. // See if the user wants this to run *really*
  939. // quietly...
  940. //
  941. if(!_tcsnicmp(Arg+1,TEXT("checkupgradeonlyq"),17)) {
  942. //
  943. // Yep. Tell everyone to go through quietly...
  944. //
  945. CheckUpgradeOnlyQ = TRUE;
  946. InternalProcessCmdLineArg( TEXT("/#U:CheckUpgradeOnlyQ") );
  947. }
  948. } else if(!_tcsnicmp(Arg+1,TEXT("cmdcons"),4)) {
  949. BuildCmdcons = TRUE;
  950. NoCompliance = TRUE; // disable the compliance checking
  951. } else {
  952. Valid = FALSE;
  953. }
  954. break;
  955. case TEXT('D'):
  956. if (_tcsicmp(Arg+1,WINNT_U_DYNAMICUPDATESDISABLE) == 0
  957. #ifdef PRERELEASE
  958. || _tcsicmp(Arg+1,TEXT("disabledynamicupdates")) == 0
  959. #endif
  960. ) {
  961. g_DynUpdtStatus->Disabled = TRUE;
  962. break;
  963. }
  964. if (!_tcsnicmp (Arg + 1, WINNT_U_DYNAMICUPDATESHARE, sizeof (WINNT_U_DYNAMICUPDATESHARE_A) - 1) &&
  965. Arg[sizeof (WINNT_U_DYNAMICUPDATESHARE_A)] == TEXT(':')) {
  966. //
  967. // Updated files specified on the command line
  968. //
  969. if (g_DynUpdtStatus->DynamicUpdatesSource[0]) {
  970. Valid = FALSE;
  971. break;
  972. }
  973. _tcsncpy (
  974. g_DynUpdtStatus->DynamicUpdatesSource,
  975. Arg + 1 + sizeof (WINNT_U_DYNAMICUPDATESHARE_A),
  976. MAX_PATH
  977. );
  978. RemoveTrailingWack (g_DynUpdtStatus->DynamicUpdatesSource);
  979. if (DoesDirectoryExist (g_DynUpdtStatus->DynamicUpdatesSource)) {
  980. g_DynUpdtStatus->UserSpecifiedUpdates = TRUE;
  981. } else {
  982. Valid = FALSE;
  983. }
  984. break;
  985. }
  986. if (!_tcsnicmp (Arg + 1, WINNT_U_DYNAMICUPDATESPREPARE, sizeof (WINNT_U_DYNAMICUPDATESPREPARE_A) - 1) &&
  987. Arg[sizeof (WINNT_U_DYNAMICUPDATESPREPARE_A)] == TEXT(':')) {
  988. if (g_DynUpdtStatus->DynamicUpdatesSource[0]) {
  989. Valid = FALSE;
  990. break;
  991. }
  992. _tcsncpy (
  993. g_DynUpdtStatus->DynamicUpdatesSource,
  994. Arg + 1 + sizeof (WINNT_U_DYNAMICUPDATESPREPARE_A),
  995. MAX_PATH
  996. );
  997. RemoveTrailingWack (g_DynUpdtStatus->DynamicUpdatesSource);
  998. g_DynUpdtStatus->PrepareWinnt32 = TRUE;
  999. if (DoesDirectoryExist (g_DynUpdtStatus->DynamicUpdatesSource)) {
  1000. g_DynUpdtStatus->UserSpecifiedUpdates = TRUE;
  1001. } else {
  1002. Valid = FALSE;
  1003. }
  1004. break;
  1005. }
  1006. if(DebugFileLog || _tcsnicmp(Arg+1,TEXT("debug"),5)) {
  1007. Valid = FALSE;
  1008. break;
  1009. }
  1010. DebugLevel = _tcstol(Arg+6,&Colon,10);
  1011. if((DebugLevel == -1) || (*Colon && (*Colon != TEXT(':')))) {
  1012. Valid = FALSE;
  1013. break;
  1014. }
  1015. if(Colon == Arg+6) {
  1016. //
  1017. // No debug level specified, use default
  1018. //
  1019. DebugLevel = Winnt32LogInformation;
  1020. }
  1021. if(*Colon) {
  1022. //
  1023. // Log file name was specified.
  1024. //
  1025. Colon++;
  1026. if(*Colon) {
  1027. DebugFileLog = Colon;
  1028. } else {
  1029. Valid = FALSE;
  1030. break;
  1031. }
  1032. }
  1033. break;
  1034. case TEXT('E'):
  1035. //
  1036. // Take care of headless parameters.
  1037. //
  1038. if( !_tcsnicmp(Arg+1,WINNT_U_HEADLESS_REDIRECT,_tcslen(WINNT_U_HEADLESS_REDIRECT)) ) {
  1039. if( Arg[_tcslen(WINNT_U_HEADLESS_REDIRECT)+2] ) {
  1040. _tcscpy( HeadlessSelection, Arg+(_tcslen(WINNT_U_HEADLESS_REDIRECT)+2) );
  1041. Valid = TRUE;
  1042. } else {
  1043. Valid = FALSE;
  1044. }
  1045. } else if( !_tcsnicmp(Arg+1,WINNT_U_HEADLESS_REDIRECTBAUDRATE,_tcslen(WINNT_U_HEADLESS_REDIRECTBAUDRATE)) ) {
  1046. if( Arg[_tcslen(WINNT_U_HEADLESS_REDIRECTBAUDRATE)+2] ) {
  1047. HeadlessBaudRate = _tcstoul(Arg+(_tcslen(WINNT_U_HEADLESS_REDIRECTBAUDRATE)+2),NULL,10);
  1048. } else {
  1049. Valid = FALSE;
  1050. }
  1051. }
  1052. else if ( _tcsnicmp(Arg+1,WINNT_U_ENCRYPT,_tcslen(WINNT_U_ENCRYPT)) == 0 )
  1053. {
  1054. LPTSTR pTmp;
  1055. pTmp = &Arg[lstrlen(WINNT_U_ENCRYPT)+1];
  1056. Valid = FALSE;
  1057. // Make sure we have /Encrypt:
  1058. if (*pTmp == TEXT(':'))
  1059. {
  1060. pTmp++;
  1061. while (*pTmp && (*pTmp != TEXT(':')))
  1062. {
  1063. pTmp = CharNext(pTmp);
  1064. }
  1065. if (*pTmp == TEXT(':'))
  1066. {
  1067. *pTmp = TEXT('\0');
  1068. ++pTmp;
  1069. PIDDays = _tcstoul(pTmp, NULL, 10);
  1070. Valid = ((PIDDays >= 5) && (PIDDays <= 60));
  1071. }
  1072. // Save the product ID.
  1073. lstrcpyn(ProductId, &Arg[lstrlen(WINNT_U_ENCRYPT)+2], sizeof(ProductId)/sizeof(TCHAR));
  1074. PIDEncryption = TRUE;
  1075. }
  1076. }
  1077. break;
  1078. case TEXT('L'):
  1079. if (_tcsicmp (Arg+1, TEXT("local"))) {
  1080. Valid = FALSE;
  1081. }
  1082. break;
  1083. case TEXT('M'):
  1084. //
  1085. // Alternate source for missing files
  1086. //
  1087. if(Arg[2] == TEXT(':')) {
  1088. if (!DoesDirectoryExist (Arg+3)) {
  1089. Valid = FALSE;
  1090. break;
  1091. }
  1092. _tcscpy(AlternateSourcePath, Arg+3);
  1093. //
  1094. // If the user is using the /M switch, he's got privates
  1095. // that he wants to use. It's possible that some of these
  1096. // privates will be in the driver cab, inwhich case, he'd
  1097. // have to make a copy of the cab with his private. Unreasonable.
  1098. // We can get around this by simply copying all the files
  1099. // from the user-specified private directory (/M<foobar>)
  1100. // into the local source. textmode and guimode will look
  1101. // for files before extractifi ming them from the CAB. All we
  1102. // need to do here is add the user's directory to the master
  1103. // copy list.
  1104. //
  1105. RememberOptionalDir(AlternateSourcePath,OPTDIR_OVERLAY);
  1106. //
  1107. // If we're using privates, go ahead and copy the
  1108. // source local.
  1109. //
  1110. MakeLocalSource = TRUE;
  1111. UserSpecifiedMakeLocalSource = TRUE;
  1112. } else if( !_tcsnicmp( Arg+1, TEXT("MakeLocalSource"), 15)) {
  1113. //
  1114. // check if there are any options for this switch
  1115. //
  1116. if (Arg[16] && Arg[16] != TEXT(':')) {
  1117. Valid = FALSE;
  1118. break;
  1119. }
  1120. MakeLocalSource = TRUE;
  1121. UserSpecifiedMakeLocalSource = TRUE;
  1122. if (!Arg[16]) {
  1123. break;
  1124. }
  1125. if (!Arg[17]) {
  1126. //
  1127. // add this for W2K backwards compatibility
  1128. //
  1129. break;
  1130. }
  1131. if (!_tcsicmp (Arg + 17, TEXT("all"))) {
  1132. //
  1133. // copy ALL CDs
  1134. //
  1135. MLSDiskID = 0;
  1136. } else {
  1137. DWORD chars;
  1138. if (!_stscanf (Arg + 17, TEXT("%u%n"), &MLSDiskID, &chars) || Arg[17 + chars] != 0) {
  1139. Valid = FALSE;
  1140. }
  1141. }
  1142. } else {
  1143. Valid = FALSE;
  1144. }
  1145. break;
  1146. case TEXT('N'):
  1147. //
  1148. // Possibly a /noreboot or /nosysparse?
  1149. //
  1150. if( !_tcsicmp( Arg+1, TEXT("noreboot")) ) {
  1151. AutomaticallyShutDown = FALSE;
  1152. }
  1153. #ifdef RUN_SYSPARSE
  1154. else if( !_tcsicmp( Arg+1, TEXT("nosysparse"))) {
  1155. NoSysparse = TRUE;
  1156. }
  1157. #endif
  1158. else if( _tcsicmp( Arg+1, TEXT("nodownload"))) {
  1159. Valid = FALSE;
  1160. }
  1161. break;
  1162. case TEXT('Q'):
  1163. g_Quiet = TRUE;
  1164. break;
  1165. case TEXT('R'):
  1166. if (!_tcsnicmp (Arg + 1, TEXT("Restart"), 7)) {
  1167. g_DynUpdtStatus->Winnt32Restarted = TRUE;
  1168. if (Arg[8] == TEXT(':')) {
  1169. lstrcpy (g_DynUpdtStatus->RestartAnswerFile, Arg + 9);
  1170. } else if (Arg[8]) {
  1171. Valid = FALSE;
  1172. }
  1173. } else {
  1174. Valid = FALSE;
  1175. }
  1176. break;
  1177. case TEXT('S'):
  1178. if((Arg[2] == TEXT(':')) && Arg[3]) {
  1179. //
  1180. // Ignore extraneous sources
  1181. //
  1182. if(SourceCount < MAX_SOURCE_COUNT) {
  1183. if (GetFullPathName (
  1184. Arg+3,
  1185. sizeof(NativeSourcePaths[SourceCount])/sizeof(TCHAR),
  1186. NativeSourcePaths[SourceCount],
  1187. NULL
  1188. )) {
  1189. SourceCount++;
  1190. } else {
  1191. Valid = FALSE;
  1192. }
  1193. }
  1194. } else {
  1195. if(!_tcsnicmp(Arg+1,TEXT("syspart:"),8)
  1196. && Arg[9]
  1197. && (_totupper(Arg[9]) >= TEXT('A'))
  1198. && (_totupper(Arg[9]) <= TEXT('Z'))
  1199. && !ForcedSystemPartition) {
  1200. #ifdef _X86_
  1201. if (IsNEC98()){
  1202. if (!IsValidDrive(Arg[9])){
  1203. Valid = FALSE;
  1204. break;
  1205. }
  1206. }
  1207. #endif
  1208. ForcedSystemPartition = (TCHAR)_totupper(Arg[9]);
  1209. } else {
  1210. Valid = FALSE;
  1211. }
  1212. }
  1213. break;
  1214. case TEXT('T'):
  1215. if(_tcsnicmp(Arg+1,TEXT("tempdrive:"),10)
  1216. || !(UserSpecifiedLocalSourceDrive = (TCHAR)_totupper(Arg[11]))
  1217. || (UserSpecifiedLocalSourceDrive < TEXT('A'))
  1218. || (UserSpecifiedLocalSourceDrive > TEXT('Z'))) {
  1219. Valid = FALSE;
  1220. }
  1221. break;
  1222. case TEXT('U'):
  1223. if (_tcsicmp (Arg+1, TEXT("UpgradeAdvisor")) == 0) {
  1224. UpgradeAdvisorMode = TRUE;
  1225. break;
  1226. }
  1227. //
  1228. // Accept unattend and unattended as synonyms
  1229. //
  1230. b = FALSE;
  1231. if(!_tcsnicmp(Arg+1,TEXT("unattended"),10)) {
  1232. b = TRUE;
  1233. u = 11;
  1234. } else {
  1235. if(!_tcsnicmp(Arg+1,TEXT("unattend"),8)) {
  1236. b = TRUE;
  1237. u = 9;
  1238. }
  1239. }
  1240. if(b) {
  1241. if(!CheckUpgradeOnly && UnattendedOperation) {
  1242. Valid = FALSE;
  1243. break;
  1244. }
  1245. UnattendedOperation = TRUE;
  1246. UnattendSwitchSpecified = TRUE;
  1247. UnattendedShutdownTimeout = _tcstoul(Arg+u,&Colon,10);
  1248. if(UnattendedShutdownTimeout == (DWORD)(-1)) {
  1249. UnattendedShutdownTimeout = 0;
  1250. }
  1251. if(*Colon == 0) {
  1252. break;
  1253. }
  1254. if(*Colon++ != TEXT(':')) {
  1255. Valid = FALSE;
  1256. break;
  1257. }
  1258. if(*Colon) {
  1259. // UnattendedScriptFile = Colon;
  1260. //
  1261. // Get the name of the unattended script file
  1262. //
  1263. UnattendedScriptFile = MALLOC(MAX_PATH*sizeof(TCHAR));
  1264. if(UnattendedScriptFile) {
  1265. if(!GetFullPathName(
  1266. Colon,
  1267. MAX_PATH,
  1268. UnattendedScriptFile,
  1269. &p)) {
  1270. Valid = FALSE;
  1271. }
  1272. } else {
  1273. Valid = FALSE;
  1274. }
  1275. } else {
  1276. Valid = FALSE;
  1277. }
  1278. } else if(!_tcsnicmp(Arg+1,TEXT("udf:"),4)) {
  1279. if(!Arg[5] || (Arg[5] == TEXT(',')) || UniquenessId) {
  1280. Valid = FALSE;
  1281. break;
  1282. }
  1283. //
  1284. // Get p to point to the filename if there is one specified,
  1285. // and terminate the ID part.
  1286. //
  1287. if(p = _tcschr(Arg+6,TEXT(','))) {
  1288. *p++ = 0;
  1289. if(*p == 0) {
  1290. Valid = FALSE;
  1291. break;
  1292. }
  1293. }
  1294. UniquenessId = Arg + 5;
  1295. UniquenessDatabaseFile = p;
  1296. } else {
  1297. Valid = FALSE;
  1298. }
  1299. break;
  1300. case TEXT('#'):
  1301. InternalProcessCmdLineArg(Arg);
  1302. break;
  1303. default:
  1304. Valid = FALSE;
  1305. break;
  1306. }
  1307. } else {
  1308. Valid = FALSE;
  1309. }
  1310. if(!Valid && !BadParam) {
  1311. BadParam = Arg;
  1312. }
  1313. }
  1314. if(Valid) {
  1315. if( DebugLevel == 0 ) {
  1316. DebugLevel = Winnt32LogInformation;
  1317. }
  1318. if( DebugFileLog == NULL ) {
  1319. TCHAR Buffer[MAX_PATH];
  1320. MyGetWindowsDirectory( Buffer, MAX_PATH );
  1321. ConcatenatePaths( Buffer, S_WINNT32LOGFILE, MAX_PATH );
  1322. DebugFileLog = DupString( Buffer );
  1323. }
  1324. if( DebugFileLog )
  1325. StartDebugLog(DebugFileLog,DebugLevel);
  1326. // If we do PID encryption (/Encrypt on the command line)
  1327. // we don't read the unattend file. We will write the encrypted PID to it later.
  1328. if (!PIDEncryption)
  1329. {
  1330. Valid = GetArgsFromUnattendFile();
  1331. }
  1332. }
  1333. else
  1334. {
  1335. if (PIDEncryption)
  1336. {
  1337. // Invalid encrypt command line, Time frame invalid
  1338. DebugLog (Winnt32LogInformation, TEXT("Invalid encrypt command line, Time frame invalid."), 0);
  1339. }
  1340. else if(BatchMode) {
  1341. //
  1342. // Tell SMS about bad paramters
  1343. //
  1344. SaveMessageForSMS( MSG_INVALID_PARAMETER, BadParam );
  1345. } else {
  1346. //
  1347. // Show user the valid command line parameters
  1348. //
  1349. MyWinHelp(NULL,HELP_CONTEXT,IDH_USAGE);
  1350. }
  1351. }
  1352. return(Valid);
  1353. }
  1354. BOOL
  1355. RememberOptionalDir(
  1356. IN LPCTSTR Directory,
  1357. IN UINT Flags
  1358. )
  1359. /*++
  1360. Routine Description:
  1361. This routine adds a directory to the list of optional directories
  1362. to be copied. If the directory is already present it is not added
  1363. again.
  1364. Arguments:
  1365. Directory - supplies name of directory to be copied.
  1366. Flags - supplies flags for the directory. If the directory already
  1367. existed in the list, the current flags are NOT overwritten.
  1368. Return Value:
  1369. Boolean value indicating outcome. If FALSE, the caller can assume that
  1370. we've overflowed the number of allowed optional dirs.
  1371. --*/
  1372. {
  1373. UINT u;
  1374. //
  1375. // See if we have room.
  1376. //
  1377. if(OptionalDirectoryCount == MAX_OPTIONALDIRS) {
  1378. return(FALSE);
  1379. }
  1380. //
  1381. // If already there, do nothing.
  1382. //
  1383. for(u=0; u<OptionalDirectoryCount; u++) {
  1384. if(!lstrcmpi(OptionalDirectories[u],Directory)) {
  1385. return(TRUE);
  1386. }
  1387. }
  1388. //
  1389. // OK, add it.
  1390. //
  1391. DebugLog (Winnt32LogInformation, TEXT("Optional Directory <%1> added"), 0, Directory);
  1392. lstrcpy(OptionalDirectories[OptionalDirectoryCount],Directory);
  1393. OptionalDirectoryFlags[OptionalDirectoryCount] = Flags;
  1394. OptionalDirectoryCount++;
  1395. return(TRUE);
  1396. }
  1397. BOOL
  1398. CheckBuildNumber(
  1399. )
  1400. /*++
  1401. Routine Description:
  1402. This routine checks the build number of the NT system we're currently
  1403. running. Note that the build number is stored in a global variable
  1404. because we'll need it again later.
  1405. Arguments:
  1406. None.
  1407. Return Value:
  1408. Boolean value indicating whether to allow an upgrade from this build.
  1409. --*/
  1410. {
  1411. return( BuildNumber <= NT40 || BuildNumber >= NT50B1 );
  1412. }
  1413. BOOL
  1414. LoadSetupapi(
  1415. VOID
  1416. )
  1417. {
  1418. TCHAR Name[MAX_PATH], *p;
  1419. WIN32_FIND_DATA FindData;
  1420. HANDLE FindHandle;
  1421. HMODULE Setupapi;
  1422. BOOL WeLoadedLib = FALSE;
  1423. BOOL b;
  1424. PCTSTR Header;
  1425. //
  1426. // Use the setupapi.dll that was loaded by an upgrade module
  1427. //
  1428. Setupapi = GetModuleHandle (TEXT("SETUPAPI.DLL"));
  1429. if (!Setupapi) {
  1430. //
  1431. // Upgrade module did not load SETUPAPI.DLL, so we must load it.
  1432. // If setupapi.dll is in the system directory, use the one that's there.
  1433. //
  1434. GetSystemDirectory(Name,MAX_PATH);
  1435. ConcatenatePaths(Name,TEXT("SETUPAPI.DLL"),MAX_PATH);
  1436. FindHandle = FindFirstFile(Name,&FindData);
  1437. if(FindHandle == INVALID_HANDLE_VALUE) {
  1438. //
  1439. // Not there. Fetch the dll out of the win95 upgrade
  1440. // support directory.
  1441. //
  1442. if(GetModuleFileName(NULL,Name,MAX_PATH) && (p = _tcsrchr(Name,TEXT('\\')))){
  1443. *p= 0;
  1444. ConcatenatePaths(Name,WINNT_WIN95UPG_95_DIR,MAX_PATH);
  1445. ConcatenatePaths(Name,TEXT("SETUPAPI.DLL"),MAX_PATH);
  1446. Setupapi = LoadLibraryEx(Name,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
  1447. }
  1448. } else {
  1449. //
  1450. // Already in system directory.
  1451. //
  1452. FindClose(FindHandle);
  1453. Setupapi = LoadLibrary(TEXT("SETUPAPI.DLL"));
  1454. }
  1455. if (Setupapi) {
  1456. WeLoadedLib = TRUE;
  1457. } else {
  1458. b = FALSE;
  1459. }
  1460. }
  1461. if(Setupapi) {
  1462. #ifdef UNICODE
  1463. b = (((FARPROC)SetupapiDecompressOrCopyFile = GetProcAddress(Setupapi,"SetupDecompressOrCopyFileW")) != NULL);
  1464. b = b && ((FARPROC)SetupapiCabinetRoutine = GetProcAddress(Setupapi,"SetupIterateCabinetW"));
  1465. b = b && ((FARPROC)SetupapiOpenInfFile = GetProcAddress(Setupapi,"SetupOpenInfFileW"));
  1466. b = b && ((FARPROC)SetupapiGetLineCount = GetProcAddress(Setupapi,"SetupGetLineCountW"));
  1467. b = b && ((FARPROC)SetupapiGetStringField = GetProcAddress(Setupapi,"SetupGetStringFieldW"));
  1468. b = b && ((FARPROC)SetupapiGetLineByIndex = GetProcAddress(Setupapi,"SetupGetLineByIndexW"));
  1469. b = b && ((FARPROC)SetupapiFindFirstLine = GetProcAddress(Setupapi,"SetupFindFirstLineW"));
  1470. b = b && ((FARPROC)SetupapiFindNextMatchLine = GetProcAddress(Setupapi,"SetupFindNextMatchLineW"));
  1471. //
  1472. // needed for DU
  1473. //
  1474. b = b && ((FARPROC)SetupapiQueueCopy = GetProcAddress(Setupapi,"SetupQueueCopyW"));
  1475. b = b && ((FARPROC)SetupapiCommitFileQueue = GetProcAddress(Setupapi,"SetupCommitFileQueueW"));
  1476. b = b && ((FARPROC)SetupapiDefaultQueueCallback = GetProcAddress(Setupapi,"SetupDefaultQueueCallbackW"));
  1477. //
  1478. // needed in unsupdrv.c
  1479. //
  1480. (FARPROC)SetupapiGetSourceFileLocation = GetProcAddress(Setupapi,"SetupGetSourceFileLocationW");
  1481. #else
  1482. b = (((FARPROC)SetupapiDecompressOrCopyFile = GetProcAddress(Setupapi,"SetupDecompressOrCopyFileA")) != NULL);
  1483. b = b && ((FARPROC)SetupapiCabinetRoutine = GetProcAddress(Setupapi,"SetupIterateCabinetA"));
  1484. b = b && ((FARPROC)SetupapiOpenInfFile = GetProcAddress(Setupapi,"SetupOpenInfFileA"));
  1485. b = b && ((FARPROC)SetupapiGetLineCount = GetProcAddress(Setupapi,"SetupGetLineCountA"));
  1486. b = b && ((FARPROC)SetupapiGetStringField = GetProcAddress(Setupapi,"SetupGetStringFieldA"));
  1487. b = b && ((FARPROC)SetupapiGetLineByIndex = GetProcAddress(Setupapi,"SetupGetLineByIndexA"));
  1488. b = b && ((FARPROC)SetupapiFindFirstLine = GetProcAddress(Setupapi,"SetupFindFirstLineA"));
  1489. b = b && ((FARPROC)SetupapiFindNextMatchLine = GetProcAddress(Setupapi,"SetupFindNextMatchLineA"));
  1490. //
  1491. // needed for DU
  1492. //
  1493. b = b && ((FARPROC)SetupapiQueueCopy = GetProcAddress(Setupapi,"SetupQueueCopyA"));
  1494. b = b && ((FARPROC)SetupapiCommitFileQueue = GetProcAddress(Setupapi,"SetupCommitFileQueueA"));
  1495. b = b && ((FARPROC)SetupapiDefaultQueueCallback = GetProcAddress(Setupapi,"SetupDefaultQueueCallbackA"));
  1496. //
  1497. // needed in unsupdrv.c
  1498. //
  1499. (FARPROC)SetupapiGetSourceFileLocation = GetProcAddress(Setupapi,"SetupGetSourceFileLocationA");
  1500. #endif
  1501. b = b && ((FARPROC)SetupapiCloseInfFile = GetProcAddress(Setupapi,"SetupCloseInfFile"));
  1502. //
  1503. // needed for DU
  1504. //
  1505. b = b && ((FARPROC)SetupapiOpenFileQueue = GetProcAddress(Setupapi,"SetupOpenFileQueue"));
  1506. b = b && ((FARPROC)SetupapiCloseFileQueue = GetProcAddress(Setupapi,"SetupCloseFileQueue"));
  1507. b = b && ((FARPROC)SetupapiInitDefaultQueueCallback = GetProcAddress(Setupapi,"SetupInitDefaultQueueCallback"));
  1508. b = b && ((FARPROC)SetupapiTermDefaultQueueCallback = GetProcAddress(Setupapi,"SetupTermDefaultQueueCallback"));
  1509. b = b && ((FARPROC)SetupapiGetFieldCount = GetProcAddress(Setupapi,"SetupGetFieldCount"));
  1510. b = b && ((FARPROC)SetupapiFindNextLine = GetProcAddress(Setupapi,"SetupFindNextLine"));
  1511. (FARPROC)fnSetupOpenLog = GetProcAddress(Setupapi, "SetupOpenLog");
  1512. #ifdef UNICODE
  1513. (FARPROC)fnSetupLogError = GetProcAddress(Setupapi, "SetupLogErrorW");
  1514. #else
  1515. (FARPROC)fnSetupLogError = GetProcAddress(Setupapi, "SetupLogErrorA");
  1516. #endif
  1517. (FARPROC)fnSetupCloseLog = GetProcAddress(Setupapi, "SetupCloseLog");
  1518. }
  1519. //
  1520. // If the below if() fails, we must be on a platform that has
  1521. // a setupapi.dll without the new log API. In that case, neither
  1522. // upgrade DLLs have loaded their own setupapi, so we don't care
  1523. // about logging, and we eat the error.
  1524. //
  1525. if (fnSetupOpenLog && fnSetupLogError && fnSetupCloseLog) {
  1526. if (!Winnt32Restarted ()) {
  1527. //
  1528. // Log APIs exist, so delete setupact.log and setuperr.log, write header
  1529. //
  1530. fnSetupOpenLog (TRUE);
  1531. Header = GetStringResource (MSG_LOG_BEGIN);
  1532. if (Header) {
  1533. fnSetupLogError (Header, LogSevInformation);
  1534. FreeStringResource (Header);
  1535. }
  1536. fnSetupCloseLog();
  1537. }
  1538. }
  1539. if(!b) {
  1540. if (WeLoadedLib) {
  1541. FreeLibrary(Setupapi);
  1542. }
  1543. MessageBoxFromMessage(
  1544. NULL,
  1545. MSG_CANT_LOAD_SETUPAPI,
  1546. FALSE,
  1547. AppTitleStringId,
  1548. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  1549. TEXT("setupapi.dll")
  1550. );
  1551. }
  1552. return b;
  1553. }
  1554. VOID
  1555. LoadUpgradeSupport(
  1556. VOID
  1557. )
  1558. /*++
  1559. Routine Description:
  1560. This routine loads the Win95 upgrade dll or the NT upgrade dll and
  1561. retreives its significant entry points.
  1562. Arguments:
  1563. None.
  1564. Return Value:
  1565. --*/
  1566. {
  1567. DWORD d;
  1568. DWORD i;
  1569. LPTSTR *sourceDirectories;
  1570. HKEY hKey;
  1571. DWORD dwErr = ERROR_SUCCESS;
  1572. DWORD dwSize;
  1573. TCHAR buffer[MAX_PATH];
  1574. PTSTR p;
  1575. TCHAR dst[MAX_PATH];
  1576. TCHAR src[MAX_PATH];
  1577. ZeroMemory(&UpgradeSupport,sizeof(UpgradeSupport));
  1578. if (!ISNT()) {
  1579. //
  1580. // Don't load on server
  1581. //
  1582. // assert that the Server global variable is accurate
  1583. MYASSERT (UpgradeProductType != UNKNOWN);
  1584. if (Server) {
  1585. return;
  1586. }
  1587. //
  1588. // Form full Win95 path of DLL.
  1589. //
  1590. BuildPath(buffer, WINNT_WIN95UPG_95_DIR, WINNT_WIN95UPG_95_DLL);
  1591. } else {
  1592. //
  1593. // Form full NT path of DLL.
  1594. //
  1595. BuildPath(buffer, WINNT_WINNTUPG_DIR, WINNT_WINNTUPG_DLL);
  1596. }
  1597. if (FindPathToWinnt32File (buffer, UpgradeSupport.DllPath, MAX_PATH)) {
  1598. //
  1599. // Load the library. Use LoadLibraryEx to get the system to resolve DLL
  1600. // references starting in the dir where w95upg.dll is, instead of the
  1601. // directory where winnt32.exe is.
  1602. //
  1603. // If we're upgrading from NT5, use the system's setupapi.
  1604. //
  1605. //
  1606. // HACK HACK HACK - see NTBUG9: 354926
  1607. // some OEM machines have KnownDlls registered, but actually missing
  1608. // this leads to a failure of LoadLibrary
  1609. // we need a workaround for this
  1610. //
  1611. PSTRINGLIST missingKnownDlls = NULL;
  1612. FixMissingKnownDlls (&missingKnownDlls, TEXT("imagehlp.dll\0"));
  1613. if (!ISNT()) {
  1614. UpgradeSupport.DllModuleHandle = LoadLibraryEx(
  1615. UpgradeSupport.DllPath,
  1616. NULL,
  1617. LOAD_WITH_ALTERED_SEARCH_PATH
  1618. );
  1619. } else {
  1620. UpgradeSupport.DllModuleHandle = LoadLibraryEx(
  1621. UpgradeSupport.DllPath,
  1622. NULL,
  1623. (BuildNumber > NT40) ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH
  1624. );
  1625. }
  1626. if (missingKnownDlls) {
  1627. DWORD rc = GetLastError ();
  1628. UndoFixMissingKnownDlls (missingKnownDlls);
  1629. SetLastError (rc);
  1630. }
  1631. } else {
  1632. //
  1633. // just for display purposes, use default path
  1634. //
  1635. GetModuleFileName (NULL, UpgradeSupport.DllPath, MAX_PATH);
  1636. p = _tcsrchr (UpgradeSupport.DllPath, TEXT('\\'));
  1637. if (p) {
  1638. *p = 0;
  1639. }
  1640. ConcatenatePaths (UpgradeSupport.DllPath, buffer, MAX_PATH);
  1641. SetLastError (ERROR_FILE_NOT_FOUND);
  1642. }
  1643. if(!UpgradeSupport.DllModuleHandle) {
  1644. d = GetLastError();
  1645. if(d == ERROR_DLL_NOT_FOUND) {
  1646. d = ERROR_FILE_NOT_FOUND;
  1647. }
  1648. MessageBoxFromMessageAndSystemError(
  1649. NULL,
  1650. MSG_UPGRADE_DLL_ERROR,
  1651. d,
  1652. AppTitleStringId,
  1653. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  1654. UpgradeSupport.DllPath
  1655. );
  1656. goto c0;
  1657. } else {
  1658. DebugLog (Winnt32LogInformation, TEXT("Loaded upgrade module: <%1>"), 0, UpgradeSupport.DllPath);
  1659. }
  1660. //
  1661. // Get entry points.
  1662. //
  1663. (FARPROC)UpgradeSupport.InitializeRoutine = GetProcAddress(
  1664. UpgradeSupport.DllModuleHandle,
  1665. WINNT32_PLUGIN_INIT_NAME
  1666. );
  1667. (FARPROC)UpgradeSupport.GetPagesRoutine = GetProcAddress(
  1668. UpgradeSupport.DllModuleHandle,
  1669. WINNT32_PLUGIN_GETPAGES_NAME
  1670. );
  1671. (FARPROC)UpgradeSupport.WriteParamsRoutine = GetProcAddress(
  1672. UpgradeSupport.DllModuleHandle,
  1673. WINNT32_PLUGIN_WRITEPARAMS_NAME
  1674. );
  1675. (FARPROC)UpgradeSupport.CleanupRoutine = GetProcAddress(
  1676. UpgradeSupport.DllModuleHandle,
  1677. WINNT32_PLUGIN_CLEANUP_NAME
  1678. );
  1679. #ifdef _X86_
  1680. if (IsNEC98()){
  1681. (FARPROC)W95SetAutoBootFlag = GetProcAddress(
  1682. UpgradeSupport.DllModuleHandle,
  1683. WINNT32_PLUGIN_SETAUTOBOOT_NAME
  1684. );
  1685. }
  1686. info.Boot16 = &g_Boot16;
  1687. if (!ISNT()) {
  1688. (FARPROC)UpgradeSupport.OptionalDirsRoutine = GetProcAddress (
  1689. UpgradeSupport.DllModuleHandle,
  1690. WINNT32_PLUGIN_GETOPTIONALDIRS_NAME
  1691. );
  1692. }
  1693. #endif
  1694. if(!UpgradeSupport.InitializeRoutine
  1695. || !UpgradeSupport.GetPagesRoutine
  1696. || !UpgradeSupport.WriteParamsRoutine
  1697. || !UpgradeSupport.CleanupRoutine) {
  1698. //
  1699. // Entry points couldn't be found. The upgrade dll is corrupt.
  1700. //
  1701. MessageBoxFromMessage(
  1702. NULL,
  1703. MSG_UPGRADE_DLL_CORRUPT,
  1704. FALSE,
  1705. AppTitleStringId,
  1706. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  1707. UpgradeSupport.DllPath
  1708. );
  1709. goto c1;
  1710. }
  1711. //
  1712. // Fill in the info structure. This will be passed to the DLL's init routine.
  1713. //
  1714. info.Size = sizeof(info);
  1715. info.UnattendedFlag = &UnattendedOperation;
  1716. info.CancelledFlag = &Cancelled;
  1717. info.AbortedFlag = &Aborted;
  1718. info.UpgradeFlag = &Upgrade;
  1719. info.LocalSourceModeFlag = &MakeLocalSource;
  1720. info.CdRomInstallFlag = &RunFromCD;
  1721. info.UnattendedScriptFile = &UnattendedScriptFile;
  1722. info.UpgradeOptions = &UpgradeOptions;
  1723. info.NotEnoughSpaceBlockFlag = &BlockOnNotEnoughSpace;
  1724. info.LocalSourceDrive = &LocalSourceDriveOffset;
  1725. info.LocalSourceSpaceRequired = &LocalSourceSpaceRequired;
  1726. info.ForceNTFSConversion = &ForceNTFSConversion;
  1727. info.ProductFlavor = &ProductFlavor;
  1728. info.SetupFlags = &dwSetupFlags;
  1729. //
  1730. // Version info fields
  1731. //
  1732. info.ProductType = &UpgradeProductType;
  1733. info.BuildNumber = VER_PRODUCTBUILD;
  1734. info.ProductVersion = VER_PRODUCTVERSION_W;
  1735. #if DBG
  1736. info.Debug = TRUE;
  1737. #else
  1738. info.Debug = FALSE;
  1739. #endif
  1740. #ifdef PRERELEASE
  1741. info.PreRelease = TRUE;
  1742. #else
  1743. info.PreRelease = FALSE;
  1744. #endif
  1745. //
  1746. // Source directories
  1747. //
  1748. sourceDirectories = (LPTSTR *) MALLOC(sizeof(LPTSTR) * MAX_SOURCE_COUNT);
  1749. if (sourceDirectories) {
  1750. for (i=0;i<MAX_SOURCE_COUNT;i++) {
  1751. sourceDirectories[i] = NativeSourcePaths[i];
  1752. }
  1753. }
  1754. info.SourceDirectories = sourceDirectories;
  1755. info.SourceDirectoryCount = &SourceCount;
  1756. info.UnattendSwitchSpecified = &UnattendSwitchSpecified;
  1757. if (!IsArc()) {
  1758. #ifdef _X86_ // references_X86_-only stuff
  1759. if (!ISNT()) {
  1760. //
  1761. // Fill in win9xupg specific information. This is done so that the win9xupg
  1762. // team can add more parameters to the structure without disturbing other
  1763. // upgrade dll writers. If a paramter is needed in both cases, it should
  1764. // be placed in the info structure above.
  1765. //
  1766. Win9xInfo.Size = sizeof (Win9xInfo);
  1767. Win9xInfo.BaseInfo = &info;
  1768. Win9xInfo.WinDirSpace = &WinDirSpaceFor9x;
  1769. Win9xInfo.RequiredMb = &UpgRequiredMb;
  1770. Win9xInfo.AvailableMb = &UpgAvailableMb;
  1771. Win9xInfo.DynamicUpdateLocalDir = g_DynUpdtStatus->WorkingDir;
  1772. Win9xInfo.DynamicUpdateDrivers = g_DynUpdtStatus->SelectedDrivers;
  1773. Win9xInfo.UpginfsUpdated = &UpginfsUpdated;
  1774. //
  1775. // Save the location of the original location of w95upg.dll. Because of dll
  1776. // replacement, this may be different than the actual w95upg.dll location
  1777. // used.
  1778. //
  1779. GetModuleFileName (NULL, UpgradeSourcePath, MAX_PATH);
  1780. p = _tcsrchr (UpgradeSourcePath, TEXT('\\'));
  1781. if (p) {
  1782. *p = 0;
  1783. }
  1784. ConcatenatePaths (UpgradeSourcePath, WINNT_WIN95UPG_95_DIR, MAX_PATH);
  1785. Win9xInfo.UpgradeSourcePath = UpgradeSourcePath;
  1786. //
  1787. // Copy over optional directories just as we did with source directories above.
  1788. //
  1789. sourceDirectories = (LPTSTR *) MALLOC(sizeof(LPTSTR) * MAX_OPTIONALDIRS);
  1790. if (sourceDirectories) {
  1791. for (i=0;i<MAX_OPTIONALDIRS;i++) {
  1792. sourceDirectories[i] = OptionalDirectories[i];
  1793. }
  1794. }
  1795. Win9xInfo.OptionalDirectories = sourceDirectories;
  1796. Win9xInfo.OptionalDirectoryCount = &OptionalDirectoryCount;
  1797. Win9xInfo.UpgradeFailureReason = &UpgradeFailureReason;
  1798. //
  1799. // Read disk sectors routine. Win9xUpg uses this when looking for other os installations.
  1800. //
  1801. Win9xInfo.ReadDiskSectors = ReadDiskSectors;
  1802. d = UpgradeSupport.InitializeRoutine((PWINNT32_PLUGIN_INIT_INFORMATION_BLOCK) &Win9xInfo);
  1803. }
  1804. else {
  1805. d = UpgradeSupport.InitializeRoutine(&info);
  1806. }
  1807. #endif // _X86_
  1808. } else {
  1809. #ifdef UNICODE // Always true for ARC, never true for Win9x upgrade
  1810. //
  1811. // Call the DLL's init routine and get-pages routine. If either fails tell the user.
  1812. //
  1813. d = UpgradeSupport.InitializeRoutine(&info);
  1814. #endif // UNICODE
  1815. } // if (!IsArc())
  1816. if(d == NO_ERROR) {
  1817. d = UpgradeSupport.GetPagesRoutine(
  1818. &UpgradeSupport.AfterWelcomePageCount,
  1819. &UpgradeSupport.Pages1,
  1820. &UpgradeSupport.AfterOptionsPageCount,
  1821. &UpgradeSupport.Pages2,
  1822. &UpgradeSupport.BeforeCopyPageCount,
  1823. &UpgradeSupport.Pages3
  1824. );
  1825. }
  1826. //
  1827. // By returning ERROR_REQUEST_ABORTED, an upgrade dll can refuse to upgrade the machine.
  1828. // In this case, no message will be generated by this routine and the option to upgrade
  1829. // will be grayed out on the wizard page. In the case of all other error messages, winnt32
  1830. // will warn the user that the upgrade dll failed to initialize. The upgrade.dll is expected
  1831. // to provide whatever UI is necessary before returning from its init routine.
  1832. //
  1833. if (UpgradeFailureReason > REASON_LAST_REASON) {
  1834. UpgradeFailureReason = REASON_LAST_REASON;
  1835. }
  1836. if(d == NO_ERROR) {
  1837. return;
  1838. }
  1839. if (d != ERROR_REQUEST_ABORTED) {
  1840. SkipVirusScannerCheck = TRUE;
  1841. MessageBoxFromMessageAndSystemError(
  1842. NULL,
  1843. MSG_UPGRADE_INIT_ERROR,
  1844. d,
  1845. AppTitleStringId,
  1846. MB_OK | MB_ICONERROR | MB_TASKMODAL
  1847. );
  1848. c1:
  1849. FreeLibrary(UpgradeSupport.DllModuleHandle);
  1850. ZeroMemory (&UpgradeSupport, sizeof (UpgradeSupport));
  1851. }
  1852. c0:
  1853. Upgrade = FALSE;
  1854. return;
  1855. }
  1856. #ifdef _X86_
  1857. BOOL
  1858. CheckVirusScanners (
  1859. VOID
  1860. )
  1861. /*++
  1862. Routine Description:
  1863. This routine is used to check for virus scanners on win9x machines that can
  1864. impeed setup (either in a clean install or upgrade case.) The function simply
  1865. calls an entry point within the w95upg.dll and that module performs the
  1866. actual check.
  1867. Arguments:
  1868. None.
  1869. Return Value:
  1870. TRUE if no virus scanners were detected that could cause problems. FALSE if a virus
  1871. scanner was detected that could cause setup to fail. We rely on the w95upg.dll code
  1872. to provide an appropriate message to the user before returning to us.
  1873. --*/
  1874. {
  1875. HANDLE dllHandle;
  1876. PWINNT32_PLUGIN_VIRUSSCANNER_CHECK_ROUTINE virusScanRoutine;
  1877. //
  1878. // This check is win9xupg specific.
  1879. //
  1880. if (ISNT()) {
  1881. return TRUE;
  1882. }
  1883. dllHandle = GetModuleHandle (WINNT_WIN95UPG_95_DLL);
  1884. //
  1885. // If the module was not loaded, we'll skip this check.
  1886. //
  1887. if (!dllHandle) {
  1888. return TRUE;
  1889. }
  1890. //
  1891. // Get entry points.
  1892. //
  1893. (FARPROC) virusScanRoutine = GetProcAddress(dllHandle, WINNT32_PLUGIN_VIRUSSCANCHECK_NAME);
  1894. if (!virusScanRoutine) {
  1895. //
  1896. // corrupt dll or something
  1897. //
  1898. return FALSE;
  1899. }
  1900. //
  1901. // Now, simply call the routine. It will handle the actuall checking as well as informing the user.
  1902. //
  1903. return virusScanRoutine ();
  1904. }
  1905. #endif
  1906. BOOL
  1907. ValidateSourceLocation(
  1908. VOID
  1909. )
  1910. /*++
  1911. Routine Description:
  1912. This routine checks the initial source location to see if it's
  1913. valid. The first source location must be valid for setup to
  1914. work, and this catches typos by the user. It cannot detect
  1915. transient network conditions, so this is not foolproof.
  1916. We check this by looking for a required file, dosnet.inf, at
  1917. the source location.
  1918. Arguments:
  1919. None.
  1920. Return Value:
  1921. TRUE if the source location appears valid
  1922. --*/
  1923. {
  1924. TCHAR FileName[MAX_PATH];
  1925. lstrcpy( FileName, NativeSourcePaths[0]);
  1926. ConcatenatePaths(FileName, InfName, MAX_PATH);
  1927. if (FileExists( FileName, NULL )) {
  1928. //
  1929. // also look for system32\ntdll.dll as a second check
  1930. //
  1931. lstrcpy( FileName, NativeSourcePaths[0]);
  1932. ConcatenatePaths(FileName, TEXT("system32\\ntdll.dll"), MAX_PATH);
  1933. return(FileExists( FileName, NULL ));
  1934. }
  1935. return(FALSE);
  1936. }
  1937. VOID
  1938. pRemoveOutdatedBackupImage (
  1939. VOID
  1940. )
  1941. {
  1942. REMOVEUNINSTALLIMAGE removeFn;
  1943. HMODULE lib;
  1944. UINT build;
  1945. //
  1946. // Is this current build > build we plan to install?
  1947. //
  1948. if (!ISNT() || !Upgrade) {
  1949. return;
  1950. }
  1951. build = GetMediaProductBuildNumber();
  1952. if (!build) {
  1953. return;
  1954. }
  1955. if (build == BuildNumber) {
  1956. return;
  1957. }
  1958. //
  1959. // Attempt to remove uninstall image
  1960. //
  1961. lib = LoadLibraryA ("osuninst.dll");
  1962. if (!lib) {
  1963. return;
  1964. }
  1965. removeFn = (REMOVEUNINSTALLIMAGE) GetProcAddress (lib, "RemoveUninstallImage");
  1966. if (removeFn) {
  1967. removeFn();
  1968. }
  1969. FreeLibrary (lib);
  1970. }
  1971. BOOL
  1972. GetProductType (
  1973. VOID
  1974. )
  1975. {
  1976. TCHAR buffer[256];
  1977. if (!FullInfName[0]) {
  1978. if (!FindPathToWinnt32File (InfName, FullInfName, MAX_PATH)) {
  1979. FullInfName[0] = 0;
  1980. return FALSE;
  1981. }
  1982. }
  1983. //
  1984. // get some data from the main inf
  1985. //
  1986. if (!GetPrivateProfileString (
  1987. TEXT("Miscellaneous"),
  1988. TEXT("ProductType"),
  1989. TEXT(""),
  1990. buffer,
  1991. 256,
  1992. FullInfName
  1993. )) {
  1994. DebugLog (
  1995. Winnt32LogError,
  1996. TEXT("%1 key in [%2] section is missing from %3; aborting operation"),
  1997. 0,
  1998. TEXT("ProductType"),
  1999. TEXT("Miscellaneous"),
  2000. FullInfName
  2001. );
  2002. return FALSE;
  2003. }
  2004. // Test for valid product type (0 == pro, 6 == sbs)
  2005. if (buffer[0] < TEXT('0') || buffer[0] > TEXT('6') || buffer[1]) {
  2006. DebugLog (
  2007. Winnt32LogError,
  2008. TEXT("Invalid %1 value (%2) in %3"),
  2009. 0,
  2010. TEXT("ProductType"),
  2011. buffer,
  2012. FullInfName
  2013. );
  2014. return FALSE;
  2015. }
  2016. ProductFlavor = buffer[0] - TEXT('0');
  2017. Server = (ProductFlavor != PROFESSIONAL_PRODUCTTYPE && ProductFlavor != PERSONAL_PRODUCTTYPE);
  2018. UpgradeProductType = Server ? NT_SERVER : NT_WORKSTATION;
  2019. return TRUE;
  2020. }
  2021. UINT
  2022. GetMediaProductBuildNumber (
  2023. VOID
  2024. )
  2025. {
  2026. TCHAR buffer[256];
  2027. PCTSTR p;
  2028. PTSTR q;
  2029. UINT build;
  2030. if (!FullInfName[0]) {
  2031. if (!FindPathToWinnt32File (InfName, FullInfName, MAX_PATH)) {
  2032. return 0;
  2033. }
  2034. }
  2035. //
  2036. // get some data from the main inf
  2037. //
  2038. if (!GetPrivateProfileString (
  2039. TEXT("Version"),
  2040. TEXT("DriverVer"),
  2041. TEXT(""),
  2042. buffer,
  2043. 256,
  2044. FullInfName
  2045. )) {
  2046. DebugLog (
  2047. Winnt32LogError,
  2048. TEXT("Version key in [DriverVer] section is missing from %1; aborting operation"),
  2049. 0,
  2050. FullInfName
  2051. );
  2052. return 0;
  2053. }
  2054. p = _tcschr (buffer, TEXT(','));
  2055. if (p) {
  2056. //
  2057. // p should point to ",<major>.<minor>.<build>.0" -- extract <build>
  2058. //
  2059. p = _tcschr (p + 1, TEXT('.'));
  2060. if (p) {
  2061. p = _tcschr (p + 1, TEXT('.'));
  2062. if (p) {
  2063. p = _tcsinc (p);
  2064. q = _tcschr (p, TEXT('.'));
  2065. if (q) {
  2066. *q = 0;
  2067. } else {
  2068. p = NULL;
  2069. }
  2070. }
  2071. }
  2072. }
  2073. if (p) {
  2074. build = _tcstoul (p, &q, 10);
  2075. if (*q) {
  2076. p = NULL;
  2077. }
  2078. }
  2079. if (!p || build < NT51B2) {
  2080. DebugLog (
  2081. Winnt32LogError,
  2082. TEXT("Unexpected data %1, found in Version key in [DriverVer] section of %2; aborting operation"),
  2083. 0,
  2084. buffer,
  2085. FullInfName
  2086. );
  2087. return 0;
  2088. }
  2089. return build;
  2090. }
  2091. typedef HANDLE (WINAPI * PWINSTATIONOPENSERVERW)(LPWSTR);
  2092. typedef BOOLEAN (WINAPI * PWINSTATIONCLOSESERVER)(HANDLE);
  2093. UINT GetLoggedOnUserCount()
  2094. {
  2095. UINT iCount = 0;
  2096. HMODULE hwinsta;
  2097. PWINSTATIONOPENSERVERW pfnWinStationOpenServerW;
  2098. PWINSTATIONENUMERATEW pfnWinStationEnumerateW;
  2099. PWINSTATIONFREEMEMORY pfnWinStationFreeMemory;
  2100. PWINSTATIONCLOSESERVER pfnWinStationCloseServer;
  2101. /*
  2102. * Get handle to winsta.dll
  2103. */
  2104. hwinsta = LoadLibraryA("WINSTA");
  2105. if (hwinsta != NULL)
  2106. {
  2107. pfnWinStationOpenServerW = (PWINSTATIONOPENSERVERW)GetProcAddress(hwinsta, "WinStationOpenServerW");
  2108. pfnWinStationEnumerateW = (PWINSTATIONENUMERATEW)GetProcAddress(hwinsta, "WinStationEnumerateW");
  2109. pfnWinStationFreeMemory = (PWINSTATIONFREEMEMORY)GetProcAddress(hwinsta, "WinStationFreeMemory");
  2110. pfnWinStationCloseServer = (PWINSTATIONCLOSESERVER)GetProcAddress(hwinsta, "WinStationCloseServer");
  2111. if (pfnWinStationOpenServerW &&
  2112. pfnWinStationEnumerateW &&
  2113. pfnWinStationFreeMemory &&
  2114. pfnWinStationCloseServer)
  2115. {
  2116. HANDLE hServer;
  2117. // Open a connection to terminal services and get the number of sessions.
  2118. hServer = pfnWinStationOpenServerW((LPWSTR)SERVERNAME_CURRENT);
  2119. if (hServer != NULL)
  2120. {
  2121. PLOGONIDW pLogonIDs;
  2122. ULONG ulEntries;
  2123. if (pfnWinStationEnumerateW(hServer, &pLogonIDs, &ulEntries))
  2124. {
  2125. ULONG ul;
  2126. PLOGONIDW pLogonID;
  2127. /*
  2128. * Iterate the sessions looking for active and disconnected sessions only.
  2129. * Then match the user name and domain (case INsensitive) for a result.
  2130. */
  2131. for (ul = 0, pLogonID = pLogonIDs; ul < ulEntries; ul++, pLogonID++)
  2132. {
  2133. if ((pLogonID->State == State_Active) ||
  2134. (pLogonID->State == State_Disconnected) ||
  2135. (pLogonID->State == State_Shadow))
  2136. {
  2137. iCount++;
  2138. }
  2139. }
  2140. /*
  2141. * Free any resources used.
  2142. */
  2143. pfnWinStationFreeMemory(pLogonIDs);
  2144. }
  2145. pfnWinStationCloseServer(hServer);
  2146. }
  2147. }
  2148. FreeLibrary(hwinsta);
  2149. }
  2150. return iCount;
  2151. }
  2152. // From winuser.h, but since we cannot define WINVER >= 0x0500 I copied it here.
  2153. #define SM_REMOTESESSION 0x1000
  2154. BOOL DisplayExitWindowsWarnings(uExitWindowsFlags)
  2155. {
  2156. BOOL bRet = TRUE;
  2157. BOOL fIsRemote = GetSystemMetrics(SM_REMOTESESSION);
  2158. UINT iNumUsers = GetLoggedOnUserCount();
  2159. UINT uID = 0;
  2160. switch (uExitWindowsFlags)
  2161. {
  2162. case EWX_POWEROFF:
  2163. case EWX_SHUTDOWN:
  2164. {
  2165. if (fIsRemote)
  2166. {
  2167. // We are running as part of a terminal server session
  2168. if (iNumUsers > 1)
  2169. {
  2170. // Warn the user if remote shut down w/ active users
  2171. uID = IDS_SHUTDOWN_REMOTE_OTHERUSERS;
  2172. }
  2173. else
  2174. {
  2175. // Warn the user if remote shut down (won't be able to restart via TS client!)
  2176. uID = IDS_SHUTDOWN_REMOTE;
  2177. }
  2178. }
  2179. else
  2180. {
  2181. if (iNumUsers > 1)
  2182. {
  2183. // Warn the user if more than one user session active
  2184. uID = IDS_SHUTDOWN_OTHERUSERS;
  2185. }
  2186. }
  2187. }
  2188. break;
  2189. case EWX_REBOOT:
  2190. {
  2191. // Warn the user if more than one user session active.
  2192. if (iNumUsers > 1)
  2193. {
  2194. uID = IDS_RESTART_OTHERUSERS;
  2195. }
  2196. }
  2197. break;
  2198. }
  2199. if (uID != 0)
  2200. {
  2201. TCHAR szTitle[MAX_PATH];
  2202. TCHAR szMessage[MAX_PATH];
  2203. LoadString(hInst, IDS_APPTITLE, szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
  2204. LoadString(hInst, uID, szMessage, sizeof(szMessage)/sizeof(szMessage[0]));
  2205. if (MessageBox(NULL,
  2206. szMessage,
  2207. szTitle,
  2208. MB_ICONEXCLAMATION | MB_YESNO | MB_SYSTEMMODAL | MB_SETFOREGROUND) == IDNO)
  2209. {
  2210. bRet = FALSE;
  2211. }
  2212. }
  2213. return bRet;
  2214. }
  2215. #define SETUP_MEMORY_MIN_REQUIREMENT (50<<20) //50MB
  2216. #define SETUP_DISK_MIN_REQUIREMENT (70<<20) //70MB
  2217. BOOL
  2218. pIsEnoughVMAndDiskSpace(
  2219. OUT ULARGE_INTEGER * OutRemainFreeSpace, OPTIONAL
  2220. IN BOOL bCheckOnlyRAM OPTIONAL
  2221. )
  2222. {
  2223. PVOID pMemory;
  2224. TCHAR winDir[MAX_PATH];
  2225. TCHAR winDrive[] = TEXT("?:\\");
  2226. ULARGE_INTEGER RemainFreeSpace = {0, 0};
  2227. DWORD sectorPerCluster;
  2228. DWORD bytesPerSector;
  2229. ULARGE_INTEGER numberOfFreeClusters = {0, 0};
  2230. ULARGE_INTEGER totalNumberOfClusters = {0, 0};
  2231. BOOL bResult = TRUE;
  2232. if(OutRemainFreeSpace){
  2233. OutRemainFreeSpace->QuadPart = 0;
  2234. }
  2235. pMemory = VirtualAlloc(NULL, SETUP_MEMORY_MIN_REQUIREMENT, MEM_COMMIT, PAGE_NOACCESS);
  2236. if(!pMemory){
  2237. return FALSE;
  2238. }
  2239. if(!bCheckOnlyRAM){
  2240. MyGetWindowsDirectory(winDir, sizeof(winDir) / sizeof(winDir[0]));
  2241. winDrive[0] = winDir[0];
  2242. bCheckOnlyRAM = GetDriveType(winDrive) != DRIVE_FIXED;
  2243. }
  2244. if(!bCheckOnlyRAM){
  2245. if(GetDiskFreeSpaceNew(winDrive,
  2246. &sectorPerCluster,
  2247. &bytesPerSector,
  2248. &numberOfFreeClusters,
  2249. &totalNumberOfClusters)){
  2250. RemainFreeSpace.QuadPart = sectorPerCluster * bytesPerSector;
  2251. RemainFreeSpace.QuadPart *= numberOfFreeClusters.QuadPart;
  2252. if(OutRemainFreeSpace){
  2253. OutRemainFreeSpace->QuadPart = RemainFreeSpace.QuadPart;
  2254. }
  2255. if(RemainFreeSpace.QuadPart < SETUP_DISK_MIN_REQUIREMENT){
  2256. bResult = FALSE;
  2257. }
  2258. }
  2259. else{
  2260. MYASSERT(FALSE);
  2261. }
  2262. }
  2263. VirtualFree(pMemory, SETUP_MEMORY_MIN_REQUIREMENT, MEM_DECOMMIT);
  2264. return bResult;
  2265. }
  2266. LPTOP_LEVEL_EXCEPTION_FILTER pLastExceptionFilter = NULL;
  2267. LONG MyFilter(EXCEPTION_POINTERS *pep)
  2268. {
  2269. static BOOL fGotHere = FALSE;
  2270. PSETUP_FAULT_HANDLER pSetupFH = NULL;
  2271. HMODULE hmodFaultRep = NULL;
  2272. PFAULTHCreate pfnCreate = NULL;
  2273. PFAULTHDelete pfnDelete = NULL;
  2274. DWORD dwRetRep = EXCEPTION_CONTINUE_SEARCH;
  2275. DWORD dwLength;
  2276. TCHAR faulthDllPath[MAX_PATH];
  2277. TCHAR additionalFiles[DW_MAX_ADDFILES];
  2278. TCHAR title[DW_MAX_ERROR_CWC];
  2279. TCHAR errortext[DW_MAX_ERROR_CWC];
  2280. TCHAR lcid[10];
  2281. LCID dwlcid;
  2282. if( fGotHere) {
  2283. goto c0;
  2284. }
  2285. fGotHere = TRUE;
  2286. // No way to upload then quit
  2287. if( !IsNetConnectivityAvailable()) {
  2288. DebugLog (Winnt32LogWarning, TEXT("Warning: Faulthandler did not find netconnectivity."), 0);
  2289. goto c0;
  2290. }
  2291. if( !FindPathToWinnt32File( TEXT(SETUP_FAULTH_APPNAME),faulthDllPath,MAX_PATH)) {
  2292. DebugLog (Winnt32LogWarning, TEXT("Warning: Could not find faulthandler %1"), 0, TEXT(SETUP_FAULTH_APPNAME));
  2293. goto c0;
  2294. }
  2295. additionalFiles[0] = TEXT('0');
  2296. //The buffer size should be able to hold both files. Be careful when adding more!
  2297. MYASSERT( 2*MAX_PATH < DW_MAX_ADDFILES);
  2298. if (MyGetWindowsDirectory (additionalFiles, DW_MAX_ADDFILES)) {
  2299. ConcatenatePaths (additionalFiles, S_WINNT32LOGFILE, DW_MAX_ADDFILES);
  2300. }
  2301. dwLength = lstrlen( additionalFiles);
  2302. // Check for case where we could not get winnt32.log
  2303. if( dwLength > 0) {
  2304. dwLength++; //Reserve space for pipe
  2305. }
  2306. if (MyGetWindowsDirectory (additionalFiles+dwLength, DW_MAX_ADDFILES-dwLength)) {
  2307. ConcatenatePaths (additionalFiles+dwLength, S_DEFAULT_NT_COMPAT_FILENAME, DW_MAX_ADDFILES-dwLength);
  2308. // If we at least got the first file then add the separator.
  2309. if( dwLength) {
  2310. additionalFiles[dwLength-1] = TEXT('|');
  2311. }
  2312. }
  2313. hmodFaultRep = LoadLibrary(faulthDllPath);
  2314. if (hmodFaultRep == NULL) {
  2315. DebugLog (Winnt32LogError, TEXT("Error: Could not load faulthandler %1."), 0, TEXT(SETUP_FAULTH_APPNAME));
  2316. goto c0;
  2317. }
  2318. pfnCreate = (PFAULTHCreate)GetProcAddress(hmodFaultRep, FAULTH_CREATE_NAME);
  2319. pfnDelete = (PFAULTHDelete)GetProcAddress(hmodFaultRep, FAULTH_DELETE_NAME);
  2320. if (pfnCreate == NULL || pfnDelete == NULL) {
  2321. DebugLog (Winnt32LogError, TEXT("Error: Could not get faulthandler exports."), 0);
  2322. goto c0;
  2323. }
  2324. pSetupFH = (*pfnCreate)();
  2325. if( pSetupFH == NULL) {
  2326. DebugLog (Winnt32LogError, TEXT("Error: Could not get faulthandler object."), 0);
  2327. goto c0;
  2328. }
  2329. if( pSetupFH->IsSupported(pSetupFH) == FALSE) {
  2330. DebugLog (Winnt32LogError, TEXT("Error: Dr Watson not supported."), 0);
  2331. goto c0;
  2332. }
  2333. title[0] = TEXT('\0');
  2334. lcid[0] = TEXT('\0');
  2335. errortext[0] = TEXT('\0');
  2336. LoadString(hInst, IDS_APPTITLE, title, sizeof(title)/sizeof(title[0]));
  2337. LoadString(hInst, IDS_DRWATSON_ERRORTEXT, errortext, sizeof(errortext)/sizeof(errortext[0]));
  2338. LoadString(hInst, IDS_DRWATSON_LCID, lcid, sizeof(lcid)/sizeof(lcid[0]));
  2339. if( !StringToInt( lcid, &dwlcid)) {
  2340. dwlcid = 1033;
  2341. }
  2342. pSetupFH->SetLCID(pSetupFH, dwlcid);
  2343. pSetupFH->SetURLA(pSetupFH, SETUP_URL);
  2344. #ifdef UNICODE
  2345. pSetupFH->SetAdditionalFilesW(pSetupFH, additionalFiles);
  2346. pSetupFH->SetAppNameW(pSetupFH, title);
  2347. pSetupFH->SetErrorTextW(pSetupFH, errortext);
  2348. #else
  2349. pSetupFH->SetAdditionalFilesA(pSetupFH, additionalFiles);
  2350. pSetupFH->SetAppNameA(pSetupFH, title);
  2351. pSetupFH->SetErrorTextA(pSetupFH, errortext);
  2352. #endif
  2353. CloseDebugLog(); //Close log file or else it cannot be uploaded.
  2354. dwRetRep = pSetupFH->Report(pSetupFH, pep, 0);
  2355. (*pfnDelete)(pSetupFH);
  2356. // Pass the error to the default unhandled exception handler
  2357. // which will terminate the process.
  2358. dwRetRep = EXCEPTION_EXECUTE_HANDLER;
  2359. c0:
  2360. if (hmodFaultRep != NULL) {
  2361. FreeLibrary(hmodFaultRep);
  2362. }
  2363. SetUnhandledExceptionFilter( pLastExceptionFilter);
  2364. return dwRetRep;
  2365. }
  2366. #ifdef TEST_EXCEPTION
  2367. struct {
  2368. DWORD dwException;
  2369. DWORD dwSetupArea;
  2370. } exceptionInfo;
  2371. void DoException( DWORD dwSetupArea)
  2372. {
  2373. TCHAR _testBuffer[10];
  2374. TCHAR *_ptestCh = 0;
  2375. if( exceptionInfo.dwSetupArea == dwSetupArea) {
  2376. switch( exceptionInfo.dwException) {
  2377. case 1:
  2378. *_ptestCh = TEXT('1');
  2379. MessageBox(NULL,TEXT("Exception not hit!"),TEXT("Access violation"),MB_OK);
  2380. break;
  2381. case 2:
  2382. {
  2383. DWORD i;
  2384. for( i =0; i < 0xffffffff;i++) {
  2385. _testBuffer[i] = TEXT('1');
  2386. }
  2387. }
  2388. MessageBox(NULL,TEXT("Exception not hit!"),TEXT("Buffer Overflow"),MB_OK);
  2389. break;
  2390. case 3:
  2391. {
  2392. LPVOID pv;
  2393. DWORD i;
  2394. for (i = 0; i < 0xffffffff; i++) {
  2395. pv = MALLOC(2048);
  2396. }
  2397. }
  2398. MessageBox(NULL,TEXT("Exception not hit!"),TEXT("Stack Overflow"),MB_OK);
  2399. break;
  2400. case 4:
  2401. {
  2402. typedef DWORD (*FAULT_FN)(void);
  2403. FAULT_FN pfn;
  2404. BYTE rgc[2048];
  2405. FillMemory(rgc, sizeof(rgc), 0);
  2406. pfn = (FAULT_FN)(DWORD_PTR)rgc;
  2407. (*pfn)();
  2408. }
  2409. MessageBox(NULL,TEXT("Exception not hit!"),TEXT("Invalid Instruction"),MB_OK);
  2410. break;
  2411. case 5:
  2412. for(;dwSetupArea;dwSetupArea--) ;
  2413. exceptionInfo.dwSetupArea = 4/dwSetupArea;
  2414. MessageBox(NULL,TEXT("Exception not hit!"),TEXT("Divide by zero"),MB_OK);
  2415. break;
  2416. default:
  2417. break;
  2418. }
  2419. }
  2420. }
  2421. void GetTestException( void)
  2422. {
  2423. TCHAR exceptionType[32];
  2424. TCHAR exceptionSetupArea[32];
  2425. exceptionType[0] = TEXT('\0');
  2426. exceptionSetupArea[0] = TEXT('\0');
  2427. exceptionInfo.dwException = 0;
  2428. exceptionInfo.dwSetupArea = 0;
  2429. GetPrivateProfileString( TEXT("Exception"),
  2430. TEXT("ExceptionType"),
  2431. TEXT("none"),
  2432. exceptionType,
  2433. sizeof(exceptionType)/sizeof(exceptionType[0]),
  2434. TEXT("c:\\except.inf"));
  2435. GetPrivateProfileString( TEXT("Exception"),
  2436. TEXT("ExceptionSetupArea"),
  2437. TEXT("none"),
  2438. exceptionSetupArea,
  2439. sizeof(exceptionSetupArea)/sizeof(exceptionSetupArea[0]),
  2440. TEXT("c:\\except.inf"));
  2441. StringToInt( exceptionType, &exceptionInfo.dwException);
  2442. StringToInt( exceptionSetupArea, &exceptionInfo.dwSetupArea);
  2443. }
  2444. #endif
  2445. HRESULT WriteEncryptedPIDtoUnattend(LPTSTR szPID)
  2446. {
  2447. HRESULT hr = E_FAIL;
  2448. LPTSTR szLine = NULL;
  2449. HANDLE hFile;
  2450. szLine = GlobalAlloc(GPTR, (lstrlen(szPID) + 3)*sizeof(TCHAR)); // + 3 for 2 " and \0
  2451. if (szLine)
  2452. {
  2453. wsprintf(szLine, TEXT("\"%s\""), szPID);
  2454. if (WritePrivateProfileString(WINNT_USERDATA, WINNT_US_PRODUCTKEY, szLine, UnattendedScriptFile) &&
  2455. WritePrivateProfileString(WINNT_USERDATA, WINNT_US_PRODUCTID, NULL, UnattendedScriptFile))
  2456. {
  2457. hr = S_OK;
  2458. }
  2459. else
  2460. {
  2461. // Error message, Unable to write
  2462. DebugLog (Winnt32LogInformation, TEXT("Unable to write to the unattend file."), 0);
  2463. }
  2464. GlobalFree(szLine);
  2465. if (hr == S_OK)
  2466. {
  2467. hFile = CreateFile(UnattendedScriptFile,
  2468. GENERIC_READ | GENERIC_WRITE,
  2469. 0,
  2470. NULL,
  2471. OPEN_EXISTING,
  2472. FILE_ATTRIBUTE_NORMAL,
  2473. NULL);
  2474. if (hFile != INVALID_HANDLE_VALUE)
  2475. {
  2476. SYSTEMTIME st;
  2477. FILETIME ft;
  2478. ZeroMemory(&st, sizeof(st));
  2479. st.wDay = 1;
  2480. st.wMonth = 4;
  2481. st.wYear = 2002;
  2482. SystemTimeToFileTime(&st, &ft); // converts to file time format
  2483. LocalFileTimeToFileTime(&ft, &ft); // Make sure we get this as UTC
  2484. SetFileTime(hFile, &ft, &ft, &ft); // Set it.
  2485. CloseHandle(hFile);
  2486. }
  2487. }
  2488. }
  2489. return hr;
  2490. }
  2491. DWORD
  2492. winnt32 (
  2493. IN PCSTR LocalSourcePath, OPTIONAL
  2494. IN HWND Dlg, OPTIONAL
  2495. IN HANDLE WinNT32Stub, OPTIONAL
  2496. OUT PCSTR* RestartCmdLine OPTIONAL
  2497. )
  2498. /*++
  2499. Routine Description:
  2500. winnt32 is the main setup routine.
  2501. Arguments:
  2502. LocalSourcePath - Specifies the local path of installation in case
  2503. this DLL is running from a local directory
  2504. after download; always ANSI if not NULL
  2505. Dlg - Specifies the handle of the welcome dialog displayed by
  2506. the stub; it will stay on screen untill the wizard dialog
  2507. appears; may be NULL
  2508. WinNT32Stub - Specifies the handle of an event that will be
  2509. signaled before the Wizard appears on the screen;
  2510. may be NULL
  2511. RestartCmdLine - Receives a pointer to a command line to be executed
  2512. by the caller after this function returns;
  2513. always ANSI
  2514. Return Value:
  2515. none
  2516. --*/
  2517. {
  2518. HMODULE SMSHandle = NULL;
  2519. SMSPROC InstallStatusMIF = NULL;
  2520. HANDLE Mutex;
  2521. BOOL b;
  2522. TCHAR Text[MAX_PATH];
  2523. PCTSTR Footer;
  2524. DWORD i;
  2525. BOOL rc = ERROR_SUCCESS;
  2526. BOOL bScreenSaverOn = FALSE;
  2527. PCTSTR skuPersonal;
  2528. #if !defined(UNICODE)
  2529. ULARGE_INTEGER RemainFreeSpace;
  2530. #endif
  2531. #ifdef TEST_EXCEPTION
  2532. GetTestException();
  2533. DoException( 1);
  2534. #endif
  2535. // Initialize these variables because the exceptionfilter calls FindPathToWinnt32File
  2536. #ifndef UNICODE
  2537. //
  2538. // if running on Win9x, there may be a LocalSourcePath passed as parameter
  2539. // use that
  2540. //
  2541. g_LocalSourcePath = LocalSourcePath;
  2542. #endif
  2543. AlternateSourcePath[0] = 0;
  2544. g_DynUpdtStatus = NULL;
  2545. SourceCount = 0;
  2546. pLastExceptionFilter = SetUnhandledExceptionFilter(MyFilter);
  2547. #ifdef TEST_EXCEPTION
  2548. DoException( 2);
  2549. #endif
  2550. SetErrorMode(SEM_FAILCRITICALERRORS);
  2551. InitCommonControls();
  2552. #if !defined(UNICODE)
  2553. //
  2554. // Check virtual memory requirements (only for regular Win9x winnt32 execution)
  2555. //
  2556. if(!IsWinPEMode()){
  2557. RemainFreeSpace.QuadPart = 0;
  2558. if(!pIsEnoughVMAndDiskSpace(&RemainFreeSpace, FALSE)){
  2559. if(!RemainFreeSpace.QuadPart){
  2560. MessageBoxFromMessage(
  2561. NULL,
  2562. MSG_OUT_OF_MEMORY,
  2563. FALSE,
  2564. AppTitleStringId,
  2565. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2566. );
  2567. }
  2568. else{
  2569. MessageBoxFromMessage(
  2570. NULL,
  2571. MSG_COPY_ERROR_DISKFULL,
  2572. FALSE,
  2573. AppTitleStringId,
  2574. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2575. );
  2576. }
  2577. rc = -1;
  2578. goto EXITNOW;
  2579. }
  2580. }
  2581. #endif
  2582. //
  2583. // Init Dynamic update status
  2584. //
  2585. g_DynUpdtStatus = MALLOC (sizeof (*g_DynUpdtStatus));
  2586. if (!g_DynUpdtStatus) {
  2587. rc = -1;
  2588. goto EXITNOW;
  2589. }
  2590. //
  2591. // start with all defaults
  2592. //
  2593. ZeroMemory (g_DynUpdtStatus, sizeof (*g_DynUpdtStatus));
  2594. g_DynUpdtStatus->Connection = INVALID_HANDLE_VALUE;
  2595. #if defined(REMOTE_BOOT)
  2596. g_DynUpdtStatus->Disabled = TRUE;
  2597. #endif
  2598. //
  2599. // If we are running WINNT32 under WINPE we disable Dynamic Update as WINPE
  2600. // is primarily for OEM's and Dynamic Update feature is not meant for OEM's
  2601. //
  2602. if (IsWinPEMode()){
  2603. g_DynUpdtStatus->Disabled = TRUE;
  2604. }
  2605. // Save the screen saver state
  2606. SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &bScreenSaverOn ,0);
  2607. // Disable the screen saver
  2608. SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL ,0);
  2609. //
  2610. // Gather os version info, before we parse arguments
  2611. // since we use ISNT() function
  2612. //
  2613. OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  2614. GetVersionEx(&OsVersion);
  2615. BuildNumber = OsVersion.dwBuildNumber;
  2616. OsVersionNumber = OsVersion.dwMajorVersion*100 + OsVersion.dwMinorVersion;
  2617. //
  2618. // Parse/check arguments first.
  2619. //
  2620. if (!ParseArguments()) {
  2621. rc = 1;
  2622. goto c0;
  2623. }
  2624. // if we are running to encrypt the PID into an unattend file, don't log the command line.
  2625. if (!PIDEncryption)
  2626. {
  2627. DebugLog (Winnt32LogInformation, TEXT("The command line is: <%1>"), 0, GetCommandLine ());
  2628. }
  2629. //
  2630. // also log the location of the upgrade module
  2631. //
  2632. if (GetModuleFileName (hInst, Text, MAX_PATH)) {
  2633. DebugLog (Winnt32LogInformation, TEXT("Main module path: <%1>"), 0, Text);
  2634. }
  2635. if (CheckUpgradeOnly)
  2636. {
  2637. AppTitleStringId = IDS_APPTITLE_CHECKUPGRADE;
  2638. }
  2639. //
  2640. // If we didn't get any source paths on the command line,
  2641. // make one up here. The path will be the path where we were run from.
  2642. //
  2643. if(!SourceCount) {
  2644. PTSTR p;
  2645. if (!GetModuleFileName (NULL, NativeSourcePaths[0],MAX_PATH) ||
  2646. !(p = _tcsrchr (NativeSourcePaths[0], TEXT('\\')))) {
  2647. rc = 1;
  2648. MessageBoxFromMessage(
  2649. NULL,
  2650. GetLastError(),
  2651. TRUE,
  2652. AppTitleStringId,
  2653. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2654. );
  2655. goto c1;
  2656. }
  2657. //
  2658. // check if running from a private build
  2659. //
  2660. *p = 0;
  2661. if ((p = _tcsrchr (NativeSourcePaths[0], TEXT('\\'))) != NULL &&
  2662. lstrcmpi (p + 1, INTERNAL_WINNT32_DIR) == 0
  2663. ) {
  2664. *p = 0;
  2665. }
  2666. SourceCount = 1;
  2667. }
  2668. //
  2669. // setup the SourcePaths array from the legacy source paths array
  2670. //
  2671. for (i = 0; i < MAX_SOURCE_COUNT; i++) {
  2672. if (NativeSourcePaths[i]) {
  2673. LPTSTR p;
  2674. lstrcpy(SourcePaths[i], NativeSourcePaths[i]);
  2675. p = _tcsrchr (SourcePaths[i], TEXT('\\'));
  2676. if (p) {
  2677. *++p = TEXT('\0');
  2678. }
  2679. }
  2680. }
  2681. //
  2682. // Validate the source location
  2683. //
  2684. if (!ValidateSourceLocation()) {
  2685. rc = 1;
  2686. MessageBoxFromMessage(
  2687. NULL,
  2688. MSG_INVALID_SOURCEPATH,
  2689. FALSE,
  2690. IDS_APPTITLE,
  2691. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  2692. NULL );
  2693. goto c0;
  2694. }
  2695. //
  2696. //At this point we have the NativeSourcePaths setup and it si safe for operations involving it to be called
  2697. //
  2698. if (PIDEncryption)
  2699. {
  2700. rc = 1;
  2701. if (UnattendedScriptFile)
  2702. {
  2703. BOOL bDontCare, bSelect;
  2704. GetSourceInstallType(0);
  2705. if (ValidatePidEx(ProductId, &bDontCare, &bSelect) && bSelect)
  2706. {
  2707. LPTSTR szEncryptedPID = NULL;
  2708. HRESULT hr = PrepareEncryptedPID(ProductId, PIDDays, &szEncryptedPID);
  2709. if (hr != S_OK)
  2710. {
  2711. DebugLog (Winnt32LogInformation, TEXT("PrepareEncryptedPID failed: <hr=0x%1!lX!>"), 0, hr);
  2712. // Error Excryption failed
  2713. }
  2714. else
  2715. {
  2716. if (WriteEncryptedPIDtoUnattend(szEncryptedPID) == S_OK)
  2717. {
  2718. DebugLog (Winnt32LogInformation, TEXT("Encrypted PID succeeded"), 0);
  2719. }
  2720. if (szEncryptedPID)
  2721. {
  2722. GlobalFree(szEncryptedPID);
  2723. }
  2724. rc = 0;
  2725. }
  2726. }
  2727. else
  2728. {
  2729. DebugLog (Winnt32LogInformation, TEXT("PID is not a valid or not a valid VL key."), 0);
  2730. }
  2731. }
  2732. else
  2733. {
  2734. // No unattend switch specified
  2735. DebugLog (Winnt32LogInformation, TEXT("No unattend file specified."), 0);
  2736. }
  2737. goto c0;
  2738. }
  2739. if( RunningBVTs ){
  2740. CopyExtraBVTDirs();
  2741. }
  2742. if (!DynamicUpdateInitialize ()) {
  2743. DebugLog (
  2744. Winnt32LogError,
  2745. TEXT("DynamicUpdateInitialize failed: no dynamic update processing will be done"),
  2746. 0
  2747. );
  2748. g_DynUpdtStatus->Disabled = TRUE;
  2749. }
  2750. if (!GetProductType()) {
  2751. MessageBoxFromMessage(
  2752. NULL,
  2753. MSG_INVALID_INF_FILE,
  2754. FALSE,
  2755. AppTitleStringId,
  2756. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
  2757. FullInfName[0] ? FullInfName : InfName
  2758. );
  2759. rc = 1;
  2760. goto c0;
  2761. }
  2762. if (!g_DynUpdtStatus->Disabled) {
  2763. if (Winnt32Restarted ()) {
  2764. DebugLog (Winnt32LogWarning, TEXT("\r\n*** Winnt32 restarted ***\r\n"), 0);
  2765. if (g_DynUpdtStatus->RestartAnswerFile[0]) {
  2766. #ifdef PRERELEASE
  2767. TCHAR buf[MAX_PATH];
  2768. if (MyGetWindowsDirectory (buf, sizeof (buf) / sizeof (TCHAR))) {
  2769. ConcatenatePaths (buf, S_RESTART_TXT, sizeof (buf) / sizeof (TCHAR));
  2770. if (CopyFile (g_DynUpdtStatus->RestartAnswerFile, buf, FALSE)) {
  2771. DebugLog (DynUpdtLogLevel, TEXT("Winnt32 restart file backed up to %1"), 0, buf);
  2772. }
  2773. }
  2774. #endif
  2775. } else {
  2776. DebugLog (DynUpdtLogLevel, TEXT("No restart file is used"), 0);
  2777. }
  2778. }
  2779. }
  2780. //
  2781. // Init support for SMS.
  2782. //
  2783. try {
  2784. if( SMSHandle = LoadLibrary( TEXT("ISMIF32")) ) {
  2785. InstallStatusMIF = (SMSPROC)GetProcAddress(SMSHandle,"InstallStatusMIF");
  2786. }
  2787. if(LastMessage = MALLOC(1))
  2788. LastMessage[0] = '\0';
  2789. } except(EXCEPTION_EXECUTE_HANDLER) {
  2790. }
  2791. Winnt32Dlg = Dlg;
  2792. WinNT32StubEvent = WinNT32Stub;
  2793. // If the user specified /cmdcons (install the recovery consol) , don't show the
  2794. // billboards.
  2795. if (!BuildCmdcons && !CheckUpgradeOnly
  2796. #if 0
  2797. //
  2798. // BUGBUG - we should do this but we need to provide some other UI feedback
  2799. //
  2800. && g_DynUpdtStatus->WorkingDir
  2801. #endif
  2802. )
  2803. {
  2804. CreateMainWindow();
  2805. PrepareBillBoard(BackgroundWnd2);
  2806. if (hinstBB)
  2807. {
  2808. if (!LoadString (
  2809. hInst,
  2810. IDS_ESC_TOCANCEL,
  2811. Text,
  2812. sizeof(Text)/sizeof(TCHAR)
  2813. )) {
  2814. Text[0] = 0;
  2815. }
  2816. BB_SetInfoText(Text);
  2817. UpdateWindow (BackgroundWnd2);
  2818. }
  2819. else
  2820. {
  2821. // If we could not load the billboard dll, destroy the backbround window
  2822. // This window is currently only here to catch pressing ESC and forward
  2823. // this to the wizard dialog proc. If the wizard is always visible, this
  2824. // is not needed.
  2825. DestroyWindow(BackgroundWnd2);
  2826. BackgroundWnd2 = NULL;
  2827. }
  2828. }
  2829. if (!LoadString (hInst, IDS_TIMEESTIMATE_UNKNOWN, Text,
  2830. sizeof(Text)/sizeof(TCHAR)))
  2831. {
  2832. Text[0] = 0;
  2833. }
  2834. // BB_SetTimeEstimateText does nothing if the billboard dll is not loaded.
  2835. BB_SetTimeEstimateText((PTSTR)Text);
  2836. //
  2837. // Only let one of this guy run.
  2838. // account for TS case (make the mutex global)
  2839. //
  2840. #ifdef UNICODE
  2841. wsprintf (Text, TEXT("Global\\%s"), TEXT("Winnt32 Is Running"));
  2842. Mutex = CreateMutex(NULL,FALSE,Text);
  2843. // NT4 without TS does not support the "Global\Mutex name", make sure that
  2844. // if we could not create the Mutext that the error code is ERROR_PATH_NOT_FOUND
  2845. // If that is the case fall back and use the name with out the Global prefix.
  2846. if ((Mutex == NULL) && (GetLastError() == ERROR_PATH_NOT_FOUND)) {
  2847. #else
  2848. Mutex = NULL;
  2849. if(Mutex == NULL) {
  2850. #endif
  2851. Mutex = CreateMutex(NULL,FALSE,TEXT("Winnt32 Is Running"));
  2852. if(Mutex == NULL) {
  2853. rc = 1;
  2854. //
  2855. // An error (like out of memory) has occurred.
  2856. // Bail now.
  2857. //
  2858. MessageBoxFromMessage(
  2859. NULL,
  2860. MSG_OUT_OF_MEMORY,
  2861. FALSE,
  2862. AppTitleStringId,
  2863. MB_OK | MB_ICONERROR | MB_TASKMODAL
  2864. );
  2865. goto c0;
  2866. }
  2867. }
  2868. //
  2869. // Make sure we are the only process with a handle to our named mutex.
  2870. //
  2871. if ((Mutex == NULL) || (GetLastError() == ERROR_ALREADY_EXISTS)) {
  2872. rc = 1;
  2873. MessageBoxFromMessage(
  2874. NULL,
  2875. MSG_ALREADY_RUNNING,
  2876. FALSE,
  2877. AppTitleStringId,
  2878. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL
  2879. );
  2880. goto c1;
  2881. }
  2882. //
  2883. // Ensure that the user has privilege/access to run this app.
  2884. //
  2885. if(!IsUserAdmin()
  2886. || !DoesUserHavePrivilege(SE_SHUTDOWN_NAME)
  2887. || !DoesUserHavePrivilege(SE_BACKUP_NAME)
  2888. || !DoesUserHavePrivilege(SE_RESTORE_NAME)
  2889. || !DoesUserHavePrivilege(SE_SYSTEM_ENVIRONMENT_NAME)) {
  2890. rc = 1;
  2891. MessageBoxFromMessage(
  2892. NULL,
  2893. MSG_NOT_ADMIN,
  2894. FALSE,
  2895. AppTitleStringId,
  2896. MB_OK | MB_ICONSTOP | MB_TASKMODAL
  2897. );
  2898. goto c1;
  2899. }
  2900. #if 0
  2901. //
  2902. // Don't run if we're a TS client.
  2903. //
  2904. if( (ISNT()) &&
  2905. (BuildNumber >= NT40) ) {
  2906. //
  2907. // From winuser.h
  2908. //
  2909. #define SM_REMOTESESSION 0x1000
  2910. if( GetSystemMetrics(SM_REMOTESESSION) == TRUE ) {
  2911. rc = 1;
  2912. //
  2913. // Someone is trying to run us inside of a TerminalServer client!!
  2914. // Bail.
  2915. //
  2916. MessageBoxFromMessage(
  2917. NULL,
  2918. MSG_TS_CLIENT_FAIL,
  2919. FALSE,
  2920. IDS_APPTITLE,
  2921. MB_OK | MB_ICONSTOP | MB_TASKMODAL
  2922. );
  2923. goto c1;
  2924. }
  2925. }
  2926. #endif
  2927. //
  2928. // inititialize com
  2929. //
  2930. CoInitialize(NULL);
  2931. #if defined(REMOTE_BOOT)
  2932. //
  2933. // Determine whether this is a remote boot client.
  2934. //
  2935. RemoteBoot = FALSE;
  2936. *MachineDirectory = 0;
  2937. if (ISNT()) {
  2938. HMODULE hModuleKernel32 = LoadLibrary(TEXT("kernel32"));
  2939. if (hModuleKernel32) {
  2940. BOOL (*getSystemInfoEx)(
  2941. IN SYSTEMINFOCLASS dwSystemInfoClass,
  2942. OUT LPVOID lpSystemInfoBuffer,
  2943. IN OUT LPDWORD nSize);
  2944. (FARPROC)getSystemInfoEx = GetProcAddress(
  2945. hModuleKernel32,
  2946. #if defined(UNICODE)
  2947. "GetSystemInfoExW"
  2948. #else
  2949. "GetSystemInfoExA"
  2950. #endif
  2951. );
  2952. if (getSystemInfoEx != NULL) {
  2953. BOOL flag;
  2954. DWORD size = sizeof(BOOL);
  2955. if (getSystemInfoEx(SystemInfoRemoteBoot, &flag, &size)) {
  2956. RemoteBoot = flag;
  2957. size = MAX_PATH * sizeof(TCHAR);
  2958. if (!getSystemInfoEx(
  2959. SystemInfoRemoteBootServerPath,
  2960. MachineDirectory,
  2961. &size)) {
  2962. DWORD error = GetLastError();
  2963. MYASSERT( !"GetSystemInfoExW failed!" );
  2964. } else {
  2965. PTCHAR p;
  2966. #if defined(UNICODE)
  2967. p = wcsrchr(MachineDirectory, L'\\');
  2968. #else
  2969. p = strrchr(MachineDirectory, '\\');
  2970. #endif
  2971. MYASSERT(p != NULL);
  2972. *p = 0;
  2973. }
  2974. }
  2975. }
  2976. FreeLibrary(hModuleKernel32);
  2977. }
  2978. }
  2979. #endif // defined(REMOTE_BOOT)
  2980. #ifdef _X86_
  2981. if (IsNEC98 ()) {
  2982. //
  2983. // don't install on NEC98 machines (#141004)
  2984. //
  2985. MessageBoxFromMessage(
  2986. NULL,
  2987. MSG_PLATFORM_NOT_SUPPORTED,
  2988. FALSE,
  2989. AppTitleStringId,
  2990. MB_OK | MB_ICONSTOP | MB_TASKMODAL
  2991. );
  2992. rc = 1;
  2993. goto c1;
  2994. }
  2995. //
  2996. // Check setup sources and platform.
  2997. // NEC98 NT5 have 98PNTN16.DLL.
  2998. // I use this file for check platform NEC98 or x86.
  2999. //
  3000. {
  3001. #define WINNT_NEC98SPECIFIC_MODULE TEXT("98PTN16.DLL")
  3002. TCHAR MyPath[MAX_PATH];
  3003. int CheckNEC98Sources=FALSE;
  3004. WIN32_FIND_DATA fdata;
  3005. PTSTR p;
  3006. if( !GetModuleFileName (NULL, MyPath, MAX_PATH) || !(p=_tcsrchr (MyPath, TEXT('\\')))) {
  3007. rc = 1;
  3008. goto c1;
  3009. }
  3010. p = 0;
  3011. ConcatenatePaths (MyPath, WINNT_NEC98SPECIFIC_MODULE, MAX_PATH);
  3012. if (FindFirstFile(MyPath, &fdata) != INVALID_HANDLE_VALUE){
  3013. CheckNEC98Sources=TRUE;
  3014. }
  3015. if(CheckNEC98Sources){
  3016. if (!IsNEC98()){
  3017. rc = 1;
  3018. MessageBoxFromMessage(
  3019. NULL,
  3020. MSG_INCORRECT_PLATFORM,
  3021. FALSE,
  3022. AppTitleStringId,
  3023. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL
  3024. );
  3025. goto c1;
  3026. }
  3027. } else {
  3028. if (IsNEC98()){
  3029. rc = 1;
  3030. MessageBoxFromMessage(
  3031. NULL,
  3032. MSG_INCORRECT_PLATFORM,
  3033. FALSE,
  3034. AppTitleStringId,
  3035. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL
  3036. );
  3037. goto c1;
  3038. }
  3039. }
  3040. }
  3041. //
  3042. // Some NEC98 Windows NT4 system is installed DMITOOL
  3043. // This AP block the CreateFile API
  3044. // Setup need to check this AP
  3045. //
  3046. if (IsNEC98() && ISNT()){
  3047. if (NEC98CheckDMI() == TRUE){
  3048. rc = 1;
  3049. MessageBoxFromMessage(
  3050. NULL,
  3051. MSG_NEC98_NEED_UNINSTALL_DMITOOL,
  3052. FALSE,
  3053. AppTitleStringId,
  3054. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL
  3055. );
  3056. goto c1;
  3057. }
  3058. }
  3059. LocateFirstFloppyDrive();
  3060. //
  3061. // Fix up boot messages.
  3062. // NEC98 FAT16/FAT32 boot code does't have message area.
  3063. //
  3064. if (!IsNEC98())
  3065. {
  3066. if(!PatchTextIntoBootCode()) {
  3067. rc = 1;
  3068. MessageBoxFromMessage(
  3069. NULL,
  3070. MSG_BOOT_TEXT_TOO_LONG,
  3071. FALSE,
  3072. AppTitleStringId,
  3073. MB_OK | MB_ICONERROR | MB_TASKMODAL
  3074. );
  3075. goto c1;
  3076. }
  3077. }
  3078. //
  3079. // Disallow installing/upgrading on a 386 or 486
  3080. // 3.51 and Win9x ran on 386's so this check is still necessary.
  3081. //
  3082. {
  3083. SYSTEM_INFO SysInfo;
  3084. #ifdef UNICODE
  3085. TCHAR buff[100];
  3086. #endif
  3087. GetSystemInfo(&SysInfo);
  3088. if (SysInfo.dwProcessorType == PROCESSOR_INTEL_386 ||
  3089. SysInfo.dwProcessorType == PROCESSOR_INTEL_486) {
  3090. rc = 1;
  3091. MessageBoxFromMessage(
  3092. NULL,
  3093. MSG_REQUIRES_586,
  3094. FALSE,
  3095. AppTitleStringId,
  3096. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL
  3097. );
  3098. goto c1;
  3099. }
  3100. #ifdef UNICODE
  3101. //
  3102. // Disallow IA64 machines from running an x86
  3103. // version of winnt32.exe.
  3104. //
  3105. {
  3106. ULONG_PTR p;
  3107. NTSTATUS status;
  3108. status = NtQueryInformationProcess (
  3109. NtCurrentProcess (),
  3110. ProcessWow64Information,
  3111. &p,
  3112. sizeof (p),
  3113. NULL
  3114. );
  3115. if (NT_SUCCESS (status) && p) {
  3116. rc = 1;
  3117. //
  3118. // 32-bit code running on Win64
  3119. //
  3120. MessageBoxFromMessage(
  3121. NULL,
  3122. MSG_NO_CROSS_PLATFORM,
  3123. FALSE,
  3124. AppTitleStringId,
  3125. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL
  3126. );
  3127. goto c1;
  3128. }
  3129. }
  3130. #endif
  3131. }
  3132. #endif // _X86_
  3133. if (!g_DynUpdtStatus->Disabled) {
  3134. if (g_DynUpdtStatus->PrepareWinnt32) {
  3135. if (!g_DynUpdtStatus->DynamicUpdatesSource[0]) {
  3136. //
  3137. // no share to update was specified
  3138. //
  3139. MessageBoxFromMessage(
  3140. NULL,
  3141. MSG_NO_UPDATE_SHARE,
  3142. FALSE,
  3143. AppTitleStringId,
  3144. MB_OK | MB_ICONSTOP | MB_TASKMODAL
  3145. );
  3146. rc = 1;
  3147. goto c1;
  3148. }
  3149. } else {
  3150. //
  3151. // spec change: even if /unattend is specified, still do DU
  3152. //
  3153. #if 0
  3154. if (UnattendedOperation && !g_DynUpdtStatus->UserSpecifiedUpdates) {
  3155. //
  3156. // if unattended, disable Dynamic Setup page by default
  3157. //
  3158. g_DynUpdtStatus->Disabled = TRUE;
  3159. }
  3160. #endif
  3161. }
  3162. }
  3163. //
  3164. // Load extension/downlevel DLLs.
  3165. //
  3166. // Don't load upgrade support if we're running in WinPE.
  3167. //
  3168. if (!IsWinPEMode()) {
  3169. LoadUpgradeSupport();
  3170. }
  3171. else {
  3172. ZeroMemory(&UpgradeSupport, sizeof(UpgradeSupport));
  3173. Upgrade = FALSE;
  3174. }
  3175. //
  3176. // Load setupapi. Do this *AFTER* we load upgrade support,
  3177. // because one of the upgrade support dlls might link to or load
  3178. // setupapi.dll. That dll might be picky but we can use any old
  3179. // setupapi.dll for what we need.
  3180. //
  3181. if (!LoadSetupapi()) {
  3182. rc = 1;
  3183. goto c1;
  3184. }
  3185. #ifdef _X86_
  3186. //
  3187. // If this is a win9x machine, check to ensure that there are no
  3188. // virus scanners that could block a successful upgrade _or_
  3189. // clean install.
  3190. //
  3191. if (!ISNT() && !SkipVirusScannerCheck && !CheckVirusScanners()) {
  3192. rc = 1;
  3193. goto c1;
  3194. }
  3195. #endif
  3196. if(!IsArc()) {
  3197. #ifdef _X86_
  3198. if(!InitializeArcStuff(NULL)) {
  3199. rc = 1;
  3200. goto c1;
  3201. }
  3202. #endif // _X86_
  3203. } else {
  3204. #ifdef UNICODE // Always true for ARC, never true for Win9x upgrade
  3205. if(!ArcInitializeArcStuff(NULL)) {
  3206. rc = 1;
  3207. goto c1;
  3208. }
  3209. #endif // UNICODE
  3210. } // if (!IsArc())
  3211. //
  3212. // Don't allow upgrades from early NT 5 builds.
  3213. //
  3214. if( !CheckBuildNumber() ) {
  3215. MessageBoxFromMessage(
  3216. NULL,
  3217. MSG_CANT_UPGRADE_FROM_BUILD_NUMBER,
  3218. FALSE,
  3219. AppTitleStringId,
  3220. MB_OK | MB_ICONSTOP | MB_TASKMODAL
  3221. );
  3222. Upgrade = FALSE;
  3223. }
  3224. #if defined(REMOTE_BOOT)
  3225. //
  3226. // If this is a remote boot client, it MUST upgrade. It cannot install a new
  3227. // version of the OS. If upgrade has been disabled for some reason, stop now.
  3228. //
  3229. if (RemoteBoot && !Upgrade) {
  3230. rc = 1;
  3231. MessageBoxFromMessage(
  3232. NULL,
  3233. MSG_REQUIRES_UPGRADE,
  3234. FALSE,
  3235. AppTitleStringId,
  3236. MB_OK | MB_ICONINFORMATION | MB_TASKMODAL
  3237. );
  3238. goto c1;
  3239. }
  3240. #endif // defined(REMOTE_BOOT)
  3241. //if(UnattendedOperation && UnattendedScriptFile && !FetchArguments()) {
  3242. // rc = 1;
  3243. // goto c1;
  3244. //}
  3245. //
  3246. // Set up various other option defaults.
  3247. //
  3248. InitVariousOptions();
  3249. if (!g_DynUpdtStatus->PrepareWinnt32) {
  3250. //
  3251. // Make sure the Source files and target operating system
  3252. // are of the same locale. If they aren't, we'll disable
  3253. // ability to upgrade.
  3254. //
  3255. // Init the locale engine.
  3256. //
  3257. //
  3258. if( InitLanguageDetection( NativeSourcePaths[0], TEXT("intl.inf") ) ) {
  3259. if( !SkipLocaleCheck && (Upgrade || UpgradeFailureReason) && !IsLanguageMatched) {
  3260. //
  3261. // Tell the user we can't upgrade then kill his ability to do so.
  3262. //
  3263. MessageBoxFromMessage( NULL,
  3264. MSG_UPGRADE_LANG_ERROR,
  3265. FALSE,
  3266. IDS_APPTITLE,
  3267. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  3268. NULL );
  3269. Upgrade = FALSE;
  3270. }
  3271. }
  3272. //
  3273. // Now that we have done the language check, go ahead and see if we have a message
  3274. // to give to the user about why they cannot upgrade.
  3275. //
  3276. if (IsLanguageMatched && UpgradeFailureReason && UpgradeFailureMessages[UpgradeFailureReason]) {
  3277. //
  3278. // Tell the user we can't upgrade then kill his ability to do so.
  3279. //
  3280. MessageBoxFromMessage( NULL,
  3281. UpgradeFailureMessages[UpgradeFailureReason],
  3282. FALSE,
  3283. IDS_APPTITLE,
  3284. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  3285. NULL );
  3286. Upgrade = FALSE;
  3287. }
  3288. //
  3289. // Check to see if we're on a cluster. If so, and the user
  3290. // didn't specify a tempdrive, then it's possible for us to
  3291. // select a shared disk, which may not be available for us
  3292. // when we come back up into textmode. Warn the user.
  3293. //
  3294. // Note that we need to wait until now because RunFromCD
  3295. // doesn't get set until InitVariousOptions().
  3296. //
  3297. if( ISNT() &&
  3298. (RunFromCD == FALSE) &&
  3299. (!UserSpecifiedLocalSourceDrive) ) {
  3300. int i;
  3301. HMODULE ClusApiHandle;
  3302. FARPROC MyProc;
  3303. HANDLE hCluster;
  3304. BOOL OnCluster = FALSE;
  3305. try {
  3306. if( ClusApiHandle = LoadLibrary( TEXT("clusapi") ) ) {
  3307. if( MyProc = GetProcAddress(ClusApiHandle,"OpenCluster")) {
  3308. hCluster = (HANDLE)MyProc(NULL);
  3309. if( hCluster != NULL ) {
  3310. //
  3311. // Fire.
  3312. //
  3313. OnCluster = TRUE;
  3314. if( MyProc = GetProcAddress( ClusApiHandle, "CloseCluster")) {
  3315. MyProc( hCluster );
  3316. }
  3317. }
  3318. }
  3319. FreeLibrary( ClusApiHandle );
  3320. }
  3321. } except(EXCEPTION_EXECUTE_HANDLER) {
  3322. }
  3323. if( OnCluster ) {
  3324. i = MessageBoxFromMessage( NULL,
  3325. MSG_CLUSTER_WARNING,
  3326. FALSE,
  3327. IDS_APPTITLE,
  3328. MB_OKCANCEL | MB_ICONEXCLAMATION,
  3329. NULL );
  3330. if(i == IDCANCEL) {
  3331. rc = 1;
  3332. goto c1;
  3333. }
  3334. }
  3335. }
  3336. }
  3337. //
  3338. // setup source install type(retail,oem,or select)
  3339. //
  3340. GetSourceInstallType(0);
  3341. _tcscpy( InstallDir, DEFAULT_INSTALL_DIR );
  3342. //
  3343. // Create a mutex to serialize error ui.
  3344. //
  3345. UiMutex = CreateMutex(NULL,FALSE,NULL);
  3346. if(!UiMutex) {
  3347. rc = 1;
  3348. MessageBoxFromMessage(
  3349. NULL,
  3350. GetLastError(),
  3351. TRUE,
  3352. AppTitleStringId,
  3353. MB_OK | MB_ICONERROR | MB_TASKMODAL
  3354. );
  3355. goto c1;
  3356. }
  3357. //
  3358. // Attempt to disable the PM engine from powering down
  3359. // the machine while the wizard is going. The API we're
  3360. // going to call doesn't exist on all versions of Windows,
  3361. // so manually try and load the entry point. If we fail,
  3362. // so be it.
  3363. //
  3364. {
  3365. typedef EXECUTION_STATE (WINAPI *PTHREADPROC) (IN EXECUTION_STATE esFlags);
  3366. HMODULE Kernel32Handle;
  3367. PTHREADPROC MyProc;
  3368. if( Kernel32Handle = LoadLibrary( TEXT("kernel32") ) ) {
  3369. if( MyProc = (PTHREADPROC)GetProcAddress(Kernel32Handle,"SetThreadExecutionState")) {
  3370. MyProc( ES_SYSTEM_REQUIRED |
  3371. ES_DISPLAY_REQUIRED |
  3372. ES_CONTINUOUS );
  3373. }
  3374. FreeLibrary( Kernel32Handle );
  3375. }
  3376. }
  3377. //
  3378. // Go off and do it.
  3379. //
  3380. if (Winnt32Dlg) {
  3381. DestroyWindow (Winnt32Dlg);
  3382. Winnt32Dlg = NULL;
  3383. }
  3384. if (WinNT32StubEvent) {
  3385. SetEvent (WinNT32StubEvent);
  3386. WinNT32StubEvent = NULL;
  3387. }
  3388. if( BuildCmdcons ) {
  3389. // if we were told to build a cmdcons boot we do this instead
  3390. if (!IsArc()) {
  3391. #ifdef _X86_
  3392. if (ISNT()) {
  3393. CalcThroughput();
  3394. DoBuildCmdcons();
  3395. } else {
  3396. //
  3397. // We don't support building a cmdcons from Win9x.
  3398. //
  3399. MessageBoxFromMessage( NULL,
  3400. MSG_CMDCONS_WIN9X,
  3401. FALSE,
  3402. IDS_APPTITLE,
  3403. MB_OK | MB_ICONEXCLAMATION,
  3404. NULL );
  3405. GlobalResult = FALSE;
  3406. }
  3407. #endif
  3408. } else {
  3409. #ifdef UNICODE
  3410. //
  3411. // We don't support building a cmdcons on Alpha platforms.
  3412. //
  3413. MessageBoxFromMessage( NULL,
  3414. MSG_CMDCONS_RISC,
  3415. FALSE,
  3416. IDS_APPTITLE,
  3417. MB_OK | MB_ICONEXCLAMATION,
  3418. NULL );
  3419. GlobalResult = FALSE;
  3420. #endif
  3421. }
  3422. } else if (g_DynUpdtStatus->PrepareWinnt32) {
  3423. if (!DynamicUpdateProcessFiles (&b)) {
  3424. MessageBoxFromMessage (
  3425. NULL,
  3426. MSG_PREPARE_SHARE_FAILED,
  3427. FALSE,
  3428. IDS_APPTITLE,
  3429. MB_OK | MB_ICONEXCLAMATION,
  3430. NULL
  3431. );
  3432. rc = 1;
  3433. }
  3434. //
  3435. // clean up stuff
  3436. //
  3437. if (g_DynUpdtStatus->WorkingDir[0]) {
  3438. MyDelnode (g_DynUpdtStatus->WorkingDir);
  3439. }
  3440. } else {
  3441. if (g_DynUpdtStatus->Disabled) {
  3442. DebugLog (Winnt32LogInformation, NULL, LOG_DYNUPDT_DISABLED);
  3443. }
  3444. CalcThroughput();
  3445. Wizard();
  3446. }
  3447. //
  3448. // Back from the wizard. Either clean up or shut down, as appropriate.
  3449. //
  3450. if(GlobalResult) {
  3451. #ifdef _X86_
  3452. MYASSERT (SystemPartitionDriveLetter);
  3453. MarkPartitionActive(SystemPartitionDriveLetter);
  3454. if(IsNEC98()){
  3455. // If System is NT and NEC98 Driver assign.
  3456. // We need delete registry key "DriveLetter=C" in setupreg.hive
  3457. if (ISNT() && (IsDriveAssignNEC98() == TRUE)){
  3458. DeleteNEC98DriveAssignFlag();
  3459. }
  3460. //
  3461. // If floppyless setup, set AUTO-BOOT flag in boot sector on NEC98
  3462. //
  3463. if((Floppyless || UnattendedOperation)) {
  3464. SetAutomaticBootselector();
  3465. }
  3466. }
  3467. #endif
  3468. //
  3469. // Uninstall: blow away existing backup of OS, if we are upgrading to
  3470. // a newer build.
  3471. //
  3472. pRemoveOutdatedBackupImage();
  3473. //
  3474. // SMS: report success
  3475. //
  3476. if(InstallStatusMIF) {
  3477. PSTR Buffer;
  3478. FormatMessageA(
  3479. FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  3480. hInst,
  3481. MSG_SMS_SUCCEED,
  3482. 0,
  3483. (PSTR)&Buffer,
  3484. 0,
  3485. NULL
  3486. );
  3487. InstallStatusMIF(
  3488. "setupinf",
  3489. "Microsoft",
  3490. "Windows NT",
  3491. "5.0",
  3492. "",
  3493. "",
  3494. Buffer,
  3495. TRUE
  3496. );
  3497. LocalFree( Buffer );
  3498. }
  3499. //
  3500. // Close the log if it was open
  3501. //
  3502. if (fnSetupCloseLog) {
  3503. Footer = GetStringResource (MSG_LOG_END);
  3504. if (Footer) {
  3505. fnSetupOpenLog (FALSE);
  3506. fnSetupLogError (Footer, LogSevInformation);
  3507. FreeStringResource (Footer);
  3508. fnSetupCloseLog();
  3509. }
  3510. }
  3511. //
  3512. // Success. Attempt to shut down the system. On NT we have
  3513. // a cool API that does this with a countdown. On Win95 we don't.
  3514. // On NT5 and beyond, we have an even cooler API that takes
  3515. // a reason for shutting down. Don't statically link to it
  3516. // or else this will fall over when run from an NT4 machine.
  3517. //
  3518. if(AutomaticallyShutDown) {
  3519. #ifdef RUN_SYSPARSE
  3520. DWORD ret;
  3521. // Wait up to 90 seconds for sysparse to finish
  3522. if (!NoSysparse && piSysparse.hProcess) {
  3523. ret = WaitForSingleObject( piSysparse.hProcess, 0);
  3524. if( ret != WAIT_OBJECT_0) {
  3525. DialogBox(
  3526. hInst,
  3527. MAKEINTRESOURCE(IDD_SYSPARSE),
  3528. GetBBhwnd(),
  3529. SysParseDlgProc
  3530. );
  3531. }
  3532. CloseHandle(piSysparse.hProcess);
  3533. CloseHandle(piSysparse.hThread);
  3534. piSysparse.hProcess = NULL;
  3535. }
  3536. #endif
  3537. //
  3538. // On upgrades we disable System Restore. This saves us space in GUI mode by cleaning out its cache.
  3539. // We do this only at the point where we reboot. In the /noreboot case we decide to ignore this
  3540. // Not many people would run into that as it is a commandline option. The routine chaecks for presence of
  3541. // srclient.dll and only does this on the platforms it is present in.
  3542. //
  3543. DisableSystemRestore();
  3544. // reset the screen saver to what we found when we entered winnt32
  3545. // This is in the reboot case
  3546. SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, bScreenSaverOn, NULL,0);
  3547. if(ISNT()) {
  3548. HINSTANCE hAdvapi = GetModuleHandle(TEXT("advapi32.dll"));
  3549. PFNINITIATESYSTEMSHUTDOWNEX pfnShutdownEx = NULL;
  3550. LPCSTR lpProcName;
  3551. if (UnattendedOperation || DisplayExitWindowsWarnings(EWX_REBOOT))
  3552. {
  3553. #ifdef UNICODE
  3554. lpProcName = "InitiateSystemShutdownExW";
  3555. #else
  3556. lpProcName = "InitiateSystemShutdownExA";
  3557. #endif
  3558. LoadString(hInst,IDS_REBOOT_MESSAGE,Text,sizeof(Text)/sizeof(TCHAR));
  3559. if (hAdvapi) {
  3560. pfnShutdownEx = (PFNINITIATESYSTEMSHUTDOWNEX)
  3561. GetProcAddress(hAdvapi,
  3562. lpProcName);
  3563. }
  3564. //
  3565. // We checked up front whether we have the privilege,
  3566. // so getting it should be no problem. If we can't,
  3567. // then just let shutdown fail -- it will tell us why it failed.
  3568. //
  3569. EnablePrivilege(SE_SHUTDOWN_NAME,TRUE);
  3570. if (pfnShutdownEx) {
  3571. b = pfnShutdownEx(NULL,
  3572. Text,
  3573. UnattendedShutdownTimeout,
  3574. UnattendedShutdownTimeout != 0,
  3575. TRUE,
  3576. SHTDN_REASON_FLAG_PLANNED |
  3577. SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
  3578. (Upgrade ? SHTDN_REASON_MINOR_UPGRADE : SHTDN_REASON_MINOR_INSTALLATION)
  3579. );
  3580. //
  3581. // on 5.1, force a shutdown even if the machine was locked
  3582. // to maintain W2K compatibility
  3583. // only do this if an unattended install was in progress
  3584. //
  3585. if (!b && (GetLastError () == ERROR_MACHINE_LOCKED) && UnattendSwitchSpecified) {
  3586. b = pfnShutdownEx (
  3587. NULL,
  3588. Text,
  3589. 0,
  3590. TRUE,
  3591. TRUE,
  3592. SHTDN_REASON_FLAG_PLANNED |
  3593. SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
  3594. (Upgrade ? SHTDN_REASON_MINOR_UPGRADE : SHTDN_REASON_MINOR_INSTALLATION)
  3595. );
  3596. }
  3597. }
  3598. else {
  3599. b = InitiateSystemShutdown(NULL,
  3600. Text,
  3601. UnattendedShutdownTimeout,
  3602. UnattendedShutdownTimeout != 0,
  3603. TRUE);
  3604. }
  3605. }
  3606. } else {
  3607. b = ExitWindowsEx(EWX_REBOOT,0);
  3608. if(!b) {
  3609. b = ExitWindowsEx(EWX_REBOOT | EWX_FORCE,0);
  3610. }
  3611. }
  3612. if(!b) {
  3613. rc = 1;
  3614. MessageBoxFromMessageAndSystemError(
  3615. NULL,
  3616. MSG_REBOOT_FAILED,
  3617. GetLastError(),
  3618. AppTitleStringId,
  3619. MB_OK | MB_ICONWARNING | MB_TASKMODAL
  3620. );
  3621. goto c2;
  3622. }
  3623. }
  3624. } else {
  3625. if (CheckUpgradeOnly) {
  3626. //
  3627. // perform some DU cleanup here since the cleanup routine
  3628. // doesn't get called in /checkupgradeonly mode
  3629. //
  3630. if (g_DynUpdtStatus->ForceRemoveWorkingDir || !g_DynUpdtStatus->PreserveWorkingDir) {
  3631. if (g_DynUpdtStatus->WorkingDir[0] && !g_DynUpdtStatus->RestartWinnt32) {
  3632. MyDelnode (g_DynUpdtStatus->WorkingDir);
  3633. }
  3634. GetCurrentWinnt32RegKey (Text, MAX_PATH);
  3635. ConcatenatePaths (Text, WINNT_U_DYNAMICUPDATESHARE, MAX_PATH);
  3636. RegDeleteKey (HKEY_LOCAL_MACHINE, Text);
  3637. }
  3638. } else {
  3639. if (!g_DynUpdtStatus->RestartWinnt32 && !g_DynUpdtStatus->PrepareWinnt32) {
  3640. rc = 1;
  3641. }
  3642. }
  3643. }
  3644. c2:
  3645. CloseHandle(UiMutex);
  3646. c1:
  3647. //
  3648. // Destroy the mutex.
  3649. //
  3650. CloseHandle(Mutex);
  3651. c0:
  3652. // reset the screen saver to what we found when we entered winnt32
  3653. // This is if we don't reboot. e.g.: user canceled
  3654. SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, bScreenSaverOn, NULL,0);
  3655. //
  3656. // destroy the welcome dialog if still active
  3657. //
  3658. if (Dlg) {
  3659. DestroyWindow (Dlg);
  3660. Dlg = NULL;
  3661. }
  3662. //
  3663. // and release the original process if launched over a network
  3664. //
  3665. if (WinNT32Stub) {
  3666. SetEvent (WinNT32Stub);
  3667. WinNT32Stub = NULL;
  3668. }
  3669. if (g_EncryptedPID)
  3670. {
  3671. GlobalFree(g_EncryptedPID);
  3672. g_EncryptedPID = NULL;
  3673. }
  3674. //
  3675. // SMS: report failure
  3676. //
  3677. if(!GlobalResult && !g_DynUpdtStatus->RestartWinnt32 && InstallStatusMIF) {
  3678. PSTR Buffer;
  3679. FormatMessageA(
  3680. FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER |
  3681. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  3682. hInst,
  3683. MSG_SMS_FAIL,
  3684. 0,
  3685. (PSTR)&Buffer,
  3686. 0,
  3687. (va_list *)&LastMessage
  3688. );
  3689. InstallStatusMIF(
  3690. "setupinf",
  3691. "Microsoft",
  3692. "Windows NT",
  3693. "5.1",
  3694. "",
  3695. "",
  3696. Buffer,
  3697. FALSE
  3698. );
  3699. }
  3700. if(SMSHandle) {
  3701. FreeLibrary( SMSHandle );
  3702. }
  3703. //
  3704. // Now clean up our debug log if we're only checking
  3705. // the upgrade scenario.
  3706. //
  3707. if( CheckUpgradeOnly ) {
  3708. GatherOtherLogFiles();
  3709. }
  3710. //
  3711. // Close the debug log.
  3712. //
  3713. CloseDebugLog();
  3714. TerminateBillBoard();
  3715. if (BackgroundWnd2)
  3716. {
  3717. DestroyWindow (BackgroundWnd2);
  3718. BackgroundWnd2 = NULL;
  3719. }
  3720. if (hinstBB)
  3721. {
  3722. FreeLibrary(hinstBB);
  3723. hinstBB = NULL;
  3724. }
  3725. if (RestartCmdLine) {
  3726. #ifdef UNICODE
  3727. if (g_DynUpdtStatus->RestartCmdLine) {
  3728. INT i = 0;
  3729. INT size = (lstrlenW (g_DynUpdtStatus->RestartCmdLine) + 1) * 2;
  3730. PSTR ansi = HeapAlloc (GetProcessHeap (), 0, size);
  3731. if (ansi) {
  3732. i = WideCharToMultiByte(
  3733. CP_ACP,
  3734. 0,
  3735. g_DynUpdtStatus->RestartCmdLine,
  3736. size / 2,
  3737. ansi,
  3738. size,
  3739. NULL,
  3740. NULL
  3741. );
  3742. }
  3743. HeapFree (GetProcessHeap (), 0, g_DynUpdtStatus->RestartCmdLine);
  3744. if (i == 0 && ansi) {
  3745. HeapFree (GetProcessHeap (), 0, ansi);
  3746. ansi = NULL;
  3747. }
  3748. *RestartCmdLine = ansi;
  3749. } else {
  3750. *RestartCmdLine = NULL;
  3751. }
  3752. #else
  3753. *RestartCmdLine = g_DynUpdtStatus->RestartCmdLine;
  3754. #endif
  3755. g_DynUpdtStatus->RestartCmdLine = NULL;
  3756. } else {
  3757. if (g_DynUpdtStatus->RestartCmdLine) {
  3758. HeapFree (GetProcessHeap (), 0, g_DynUpdtStatus->RestartCmdLine);
  3759. }
  3760. }
  3761. if (g_DynUpdtStatus) {
  3762. FREE (g_DynUpdtStatus);
  3763. g_DynUpdtStatus = NULL;
  3764. }
  3765. EXITNOW:
  3766. SetUnhandledExceptionFilter( pLastExceptionFilter);
  3767. return rc;
  3768. }
  3769. BOOLEAN
  3770. AdjustPrivilege(
  3771. PWSTR Privilege
  3772. )
  3773. /*++
  3774. Routine Description:
  3775. This routine tries to adjust the priviliege of the current process.
  3776. Arguments:
  3777. Privilege - String with the name of the privilege to be adjusted.
  3778. Return Value:
  3779. Returns TRUE if the privilege could be adjusted.
  3780. Returns FALSE, otherwise.
  3781. --*/
  3782. {
  3783. HANDLE TokenHandle;
  3784. LUID_AND_ATTRIBUTES LuidAndAttributes;
  3785. TOKEN_PRIVILEGES TokenPrivileges;
  3786. if( !OpenProcessToken( GetCurrentProcess(),
  3787. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  3788. &TokenHandle ) ) {
  3789. return( FALSE );
  3790. }
  3791. if( !LookupPrivilegeValue( NULL,
  3792. (LPCTSTR)Privilege, // (LPWSTR)SE_SECURITY_NAME,
  3793. &( LuidAndAttributes.Luid ) ) ) {
  3794. return( FALSE );
  3795. }
  3796. LuidAndAttributes.Attributes = SE_PRIVILEGE_ENABLED;
  3797. TokenPrivileges.PrivilegeCount = 1;
  3798. TokenPrivileges.Privileges[0] = LuidAndAttributes;
  3799. if( !AdjustTokenPrivileges( TokenHandle,
  3800. FALSE,
  3801. &TokenPrivileges,
  3802. 0,
  3803. NULL,
  3804. NULL ) ) {
  3805. return( FALSE );
  3806. }
  3807. if( GetLastError() != NO_ERROR ) {
  3808. return( FALSE );
  3809. }
  3810. return( TRUE );
  3811. }
  3812. #ifdef _X86_
  3813. //
  3814. // winnt32.exe Floppyless setup for PC-9800
  3815. // setting automatic bootselector main function
  3816. //
  3817. VOID
  3818. SetAutomaticBootselector(
  3819. VOID
  3820. )
  3821. {
  3822. //
  3823. // This function check System.
  3824. // If System is NT, call SetAutomaticBootselectorNT(),
  3825. // If System is 95, call SetAutomaticBootselector95(),
  3826. //
  3827. if (ISNT()){
  3828. SetAutomaticBootselectorNT();
  3829. } else {
  3830. // Now I run on Win95 or Memphis.
  3831. SetAutomaticBootselector95();
  3832. }
  3833. }
  3834. VOID
  3835. SetAutomaticBootselectorNT(
  3836. VOID
  3837. )
  3838. {
  3839. // must use WIN32 function.
  3840. ULONG i,bps;
  3841. PUCHAR pBuffer,pUBuffer;
  3842. WCHAR DevicePath[128];
  3843. HANDLE hDisk;
  3844. NTSTATUS Sts;
  3845. DISK_GEOMETRY MediaInfo;
  3846. DWORD DataSize;
  3847. struct _NEC98_partition_table {
  3848. BYTE BootableFlag;
  3849. BYTE SystemType;
  3850. BYTE Reserve[2];
  3851. BYTE IPLStartSector;
  3852. BYTE IPLStartHead;
  3853. WORD IPLStartCylinder;
  3854. BYTE StartSector;
  3855. BYTE StartHead;
  3856. WORD StartCylinder;
  3857. BYTE EndSector;
  3858. BYTE EndHead;
  3859. WORD EndCylinder;
  3860. CHAR SystemName[16];
  3861. } *PartitionTable;
  3862. LONG StartSector;
  3863. LONG HiddenSector;
  3864. BOOL b;
  3865. //
  3866. // Determine the number of hard disks attached to the system
  3867. // and allocate space for an array of Disk Descriptors.
  3868. //
  3869. for(i=0; i<40; i++){
  3870. swprintf(DevicePath,L"\\\\.\\PHYSICALDRIVE%u",i);
  3871. hDisk = CreateFileW( DevicePath,
  3872. 0,
  3873. FILE_SHARE_READ, NULL,
  3874. OPEN_EXISTING, 0, NULL);
  3875. if(hDisk == INVALID_HANDLE_VALUE) {
  3876. continue;
  3877. }
  3878. b = DeviceIoControl(
  3879. hDisk,
  3880. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  3881. NULL,
  3882. 0,
  3883. &MediaInfo,
  3884. sizeof(DISK_GEOMETRY),
  3885. &DataSize,
  3886. NULL
  3887. );
  3888. CloseHandle(hDisk);
  3889. //
  3890. // It's really a hard disk.
  3891. //
  3892. if(b == 0){
  3893. continue;
  3894. }
  3895. if(MediaInfo.MediaType == RemovableMedia) {
  3896. continue;
  3897. }
  3898. hDisk = CreateFileW( DevicePath,
  3899. GENERIC_READ|GENERIC_WRITE,
  3900. FILE_SHARE_READ, NULL,
  3901. OPEN_EXISTING, 0, NULL);
  3902. if(hDisk == INVALID_HANDLE_VALUE) {
  3903. continue;
  3904. }
  3905. if (CheckATACardonNT4(hDisk)){
  3906. CloseHandle(hDisk);
  3907. continue;
  3908. }
  3909. if ((bps = GetHDBps(hDisk)) == 0){
  3910. CloseHandle(hDisk);
  3911. continue;
  3912. }
  3913. pUBuffer = MALLOC(bps * 3);
  3914. pBuffer = ALIGN(pUBuffer, bps);
  3915. RtlZeroMemory(pBuffer, bps * 2);
  3916. Sts = SpReadWriteDiskSectors(hDisk,0,1,bps,pBuffer, NEC_READSEC);
  3917. if(!NT_SUCCESS(Sts)) {
  3918. FREE(pUBuffer);
  3919. CloseHandle(hDisk);
  3920. continue;
  3921. }
  3922. //
  3923. // If PC-AT HD, No action.
  3924. //
  3925. if (!(pBuffer[4] == 'I'
  3926. && pBuffer[5] == 'P'
  3927. && pBuffer[6] == 'L'
  3928. && pBuffer[7] == '1')){
  3929. FREE(pUBuffer);
  3930. CloseHandle(hDisk);
  3931. continue;
  3932. }
  3933. if ((pBuffer[bps - 5] == 0) && pBuffer[bps - 6] == 0){
  3934. FREE(pUBuffer);
  3935. CloseHandle(hDisk);
  3936. continue;
  3937. }
  3938. //
  3939. // Clear BootRecord
  3940. //
  3941. pBuffer[bps - 5] = 0x00;
  3942. pBuffer[bps - 6] = 0x00;
  3943. SpReadWriteDiskSectors(hDisk,0,1,bps,pBuffer, NEC_WRITESEC);
  3944. FREE(pUBuffer);
  3945. CloseHandle(hDisk);
  3946. }
  3947. MYASSERT (SystemPartitionDriveLetter);
  3948. HiddenSector = CalcHiddenSector((TCHAR)SystemPartitionDriveLetter, (SHORT)bps);
  3949. if(GetSystemPosition(&hDisk, &MediaInfo ) != 0xff) {
  3950. b = DeviceIoControl(
  3951. hDisk,
  3952. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  3953. NULL,
  3954. 0,
  3955. &MediaInfo,
  3956. sizeof(DISK_GEOMETRY),
  3957. &DataSize,
  3958. NULL
  3959. );
  3960. pUBuffer = MALLOC(bps * 3);
  3961. pBuffer = ALIGN(pUBuffer, bps);
  3962. RtlZeroMemory(pBuffer, bps * 2);
  3963. bps = MediaInfo.BytesPerSector;
  3964. Sts = SpReadWriteDiskSectors(hDisk,0,2,bps,pBuffer, NEC_READSEC);
  3965. PartitionTable = (struct _NEC98_partition_table *)(pBuffer + 512);
  3966. if(NT_SUCCESS(Sts)) {
  3967. //
  3968. // Update BootRecord
  3969. //
  3970. for (i = 0; i <16; i++, PartitionTable++){
  3971. if (((PartitionTable->SystemType) & 0x7f) == 0)
  3972. break;
  3973. StartSector =
  3974. (((PartitionTable->StartCylinder * MediaInfo.TracksPerCylinder)
  3975. + PartitionTable->StartHead) * MediaInfo.SectorsPerTrack)
  3976. + PartitionTable->StartSector;
  3977. if (StartSector == HiddenSector){
  3978. pBuffer[bps - 5] = (UCHAR)i;
  3979. pBuffer[bps - 6] = 0x80;
  3980. PartitionTable->BootableFlag |= 0x80;
  3981. Sts = SpReadWriteDiskSectors(hDisk,0,2,bps,pBuffer, NEC_WRITESEC);
  3982. }
  3983. }
  3984. }
  3985. FREE(pUBuffer);
  3986. CloseHandle(hDisk);
  3987. }
  3988. }
  3989. // I970721
  3990. VOID
  3991. SetAutomaticBootselector95(
  3992. VOID
  3993. )
  3994. {
  3995. int bBootDrvLtr;
  3996. if(!W95SetAutoBootFlag) {
  3997. //
  3998. // Entry points couldn't be found. The upgrade dll is corrupt.
  3999. //
  4000. MessageBoxFromMessage(
  4001. NULL,
  4002. MSG_UPGRADE_DLL_CORRUPT,
  4003. FALSE,
  4004. AppTitleStringId,
  4005. MB_OK | MB_ICONERROR | MB_TASKMODAL,
  4006. UpgradeSupport.DllPath
  4007. );
  4008. } else {
  4009. MYASSERT (SystemPartitionDriveLetter);
  4010. bBootDrvLtr = (int)SystemPartitionDriveLetter;
  4011. if (Upgrade)
  4012. W95SetAutoBootFlag(bBootDrvLtr);
  4013. else {
  4014. W95SetABFwFresh(bBootDrvLtr);
  4015. }
  4016. }
  4017. }
  4018. //
  4019. // disksectors read and write function
  4020. // I970721
  4021. //
  4022. NTSTATUS
  4023. SpReadWriteDiskSectors(
  4024. IN HANDLE Handle,
  4025. IN ULONG SectorNumber,
  4026. IN ULONG SectorCount,
  4027. IN ULONG BytesPerSector,
  4028. IN OUT PVOID AlignedBuffer,
  4029. IN BOOL ReadWriteSec
  4030. )
  4031. /*++
  4032. Routine Description:
  4033. Reads or writes one or more disk sectors.
  4034. Arguments:
  4035. Handle - supplies handle to open partition object from which
  4036. sectors are to be read or written. The handle must be
  4037. opened for synchronous I/O.
  4038. Return Value:
  4039. NTSTATUS value indicating outcome of I/O operation.
  4040. --*/
  4041. {
  4042. DWORD IoSize, IoSize2;
  4043. OVERLAPPED Offset;
  4044. IO_STATUS_BLOCK IoStatusBlock;
  4045. NTSTATUS Status;
  4046. //
  4047. // Calculate the large integer byte offset of the first sector
  4048. // and the size of the I/O.
  4049. //
  4050. Offset.Offset = SectorNumber * BytesPerSector;
  4051. Offset.OffsetHigh = 0;
  4052. Offset.hEvent = NULL;
  4053. IoSize = SectorCount * BytesPerSector;
  4054. //
  4055. // Perform the I/O.
  4056. //
  4057. if ( ReadWriteSec == NEC_READSEC){
  4058. (NTSTATUS)Status = ReadFile(
  4059. Handle,
  4060. AlignedBuffer,
  4061. IoSize,
  4062. &IoSize2,
  4063. &Offset
  4064. );
  4065. } else {
  4066. (NTSTATUS)Status = WriteFile(
  4067. Handle,
  4068. AlignedBuffer,
  4069. IoSize,
  4070. &IoSize2,
  4071. &Offset
  4072. );
  4073. }
  4074. return(Status);
  4075. }
  4076. //
  4077. // Get WindowsNT System Position
  4078. // I970721
  4079. //
  4080. UCHAR
  4081. GetSystemPosition(
  4082. PHANDLE phDisk,
  4083. PDISK_GEOMETRY pSystemMediaInfo
  4084. )
  4085. {
  4086. HANDLE Handle;
  4087. DWORD DataSize;
  4088. TCHAR HardDiskName[] = TEXT("\\\\.\\?:");
  4089. WCHAR Buffer[128];
  4090. WCHAR DevicePath[128];
  4091. WCHAR DriveName[3];
  4092. WCHAR DiskNo;
  4093. UCHAR Position = 0xff, i, errorpt=0;
  4094. PWCHAR p, stop;
  4095. STORAGE_DEVICE_NUMBER number;
  4096. DWORD ExtentSize, err_no;
  4097. BOOL b;
  4098. PVOLUME_DISK_EXTENTS Extent;
  4099. MYASSERT (SystemPartitionDriveLetter);
  4100. HardDiskName[4] = SystemPartitionDriveLetter;
  4101. DriveName[0] = SystemPartitionDriveLetter;
  4102. DriveName[1] = ':';
  4103. DriveName[2] = 0;
  4104. if(QueryDosDeviceW(DriveName,Buffer,sizeof(Buffer)/sizeof(WCHAR))) {
  4105. //
  4106. // Get SystemPartition Harddisk Geometry
  4107. //
  4108. Handle = CreateFile(
  4109. HardDiskName,
  4110. GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
  4111. NULL,
  4112. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
  4113. );
  4114. if(Handle != INVALID_HANDLE_VALUE) {
  4115. DeviceIoControl(
  4116. Handle,
  4117. IOCTL_DISK_GET_DRIVE_GEOMETRY,
  4118. NULL,
  4119. 0,
  4120. pSystemMediaInfo,
  4121. sizeof(DISK_GEOMETRY),
  4122. &DataSize,
  4123. NULL
  4124. );
  4125. //
  4126. // Get SystemPartition Potition
  4127. //
  4128. if (BuildNumber <= NT40){ //check NT Version
  4129. p = wcsstr(Buffer,L"\\Partition");
  4130. Position = (UCHAR)wcstol((p + 10) ,&stop ,10);
  4131. //
  4132. // QueryDosDevice in NT3.51 is buggy.
  4133. // This API return "\\Harddisk\...." or
  4134. // "\\harddisk\...."
  4135. // We need work around.
  4136. //
  4137. p = wcsstr(Buffer,L"arddisk");
  4138. DiskNo = (*(p + 7) - 0x30);
  4139. } else {
  4140. b = DeviceIoControl(Handle, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0,
  4141. &number, sizeof(number), &DataSize, NULL);
  4142. if (b) {
  4143. Position = (UCHAR) number.PartitionNumber;
  4144. DiskNo = (UCHAR) number.DeviceNumber;
  4145. } else {
  4146. Extent = malloc(1024);
  4147. ExtentSize = 1024;
  4148. if(!Extent) {
  4149. CloseHandle( Handle );
  4150. return(Position);
  4151. }
  4152. b = DeviceIoControl(Handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
  4153. NULL, 0,
  4154. (PVOID)Extent, ExtentSize, &DataSize, NULL);
  4155. if (!b) {
  4156. free(Extent);
  4157. CloseHandle( Handle );
  4158. return(Position);
  4159. }
  4160. if (Extent->NumberOfDiskExtents != 1){
  4161. free(Extent);
  4162. CloseHandle( Handle );
  4163. return(Position);
  4164. }
  4165. DiskNo = (TCHAR)Extent->Extents->DiskNumber;
  4166. Position = 0;
  4167. free(Extent);
  4168. }
  4169. }
  4170. CloseHandle(Handle);
  4171. swprintf(DevicePath,L"\\\\.\\PHYSICALDRIVE%u",DiskNo);
  4172. *phDisk = CreateFileW( DevicePath, GENERIC_READ | GENERIC_WRITE,
  4173. FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL
  4174. );
  4175. }
  4176. }
  4177. return(Position);
  4178. }
  4179. BOOL
  4180. IsNEC98(
  4181. VOID
  4182. )
  4183. {
  4184. static BOOL Checked = FALSE;
  4185. static BOOL Is98;
  4186. if(!Checked) {
  4187. Is98 = ((GetKeyboardType(0) == 7) && ((GetKeyboardType(1) & 0xff00) == 0x0d00));
  4188. Checked = TRUE;
  4189. }
  4190. return(Is98);
  4191. }
  4192. VOID
  4193. LocateFirstFloppyDrive(
  4194. VOID
  4195. )
  4196. {
  4197. UINT rc;
  4198. TCHAR i;
  4199. if(!IsNEC98()) {
  4200. FirstFloppyDriveLetter = TEXT('A');
  4201. return;
  4202. }
  4203. //
  4204. // MyGetDriveType returns DRIVE_REMOVABLE, if drive is floppy.
  4205. //
  4206. for(i = TEXT('A'); i <= TEXT('Y'); i++) {
  4207. if((rc = MyGetDriveType(i)) == DRIVE_REMOVABLE) {
  4208. FirstFloppyDriveLetter = i;
  4209. return;
  4210. }
  4211. }
  4212. //
  4213. // None found yet, set it to Z
  4214. //
  4215. FirstFloppyDriveLetter = TEXT('Z');
  4216. }
  4217. VOID
  4218. DeleteNEC98DriveAssignFlag(
  4219. VOID
  4220. )
  4221. {
  4222. TCHAR HiveName[MAX_PATH];
  4223. TCHAR tmp[256];
  4224. LONG res;
  4225. HKEY hhive;
  4226. lstrcpy(HiveName,LocalBootDirectory);
  4227. ConcatenatePaths(HiveName,TEXT("setupreg.hiv"),MAX_PATH);
  4228. AdjustPrivilege((unsigned short *)SE_RESTORE_NAME);
  4229. res = RegLoadKey(HKEY_LOCAL_MACHINE, TEXT("$WINNT32"), HiveName);
  4230. if (res != ERROR_SUCCESS){
  4231. return;
  4232. }
  4233. res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("$WINNT32\\setup"), 0, KEY_ALL_ACCESS, &hhive);
  4234. if (res != ERROR_SUCCESS){
  4235. RegUnLoadKey(HKEY_LOCAL_MACHINE, TEXT("$WINNT32"));
  4236. return;
  4237. }
  4238. res = RegDeleteValue(hhive, TEXT("DriveLetter"));
  4239. res = RegCloseKey(hhive);
  4240. res = RegUnLoadKey(HKEY_LOCAL_MACHINE, TEXT("$WINNT32"));
  4241. }
  4242. VOID
  4243. W95SetABFwFresh(
  4244. int bBootDrvLtr
  4245. )
  4246. {
  4247. //
  4248. // These items are used to call 98ptn32.dll.
  4249. //
  4250. //
  4251. // Almost below codes are copied from win95upg\w95upg\init9x\init9x.c
  4252. //
  4253. typedef BOOL (CALLBACK WIN95_PLUGIN_98PTN32_SETBOOTFLAG_PROTOTYPE)(int, WORD);
  4254. typedef WIN95_PLUGIN_98PTN32_SETBOOTFLAG_PROTOTYPE * PWIN95_PLUGIN_98PTN32_SETBOOTFLAG;
  4255. #define WIN95_98PTN32_SETBOOTFLAG_W L"SetBootable95ptn32"
  4256. #define WIN95_98PTN32_SETBOOTFLAG_A "SetBootable95ptn32"
  4257. #define NEC98_DLL_NAME_W L"98PTN32.DLL"
  4258. #define NEC98_DLL_NAME_A "98PTN32.DLL"
  4259. #ifdef UNICODE
  4260. #define WIN95_98PTN32_SETBOOTFLAG WIN95_98PTN32_SETBOOTFLAG_W
  4261. #define NEC98_DLL_NAME NEC98_DLL_NAME_W
  4262. #else
  4263. #define WIN95_98PTN32_SETBOOTFLAG WIN95_98PTN32_SETBOOTFLAG_A
  4264. #define NEC98_DLL_NAME NEC98_DLL_NAME_A
  4265. #endif
  4266. #define SB_BOOTABLE 0x0001
  4267. #define SB_UNBOOTABLE 0x0002
  4268. #define MSK_BOOTABLE 0x000f
  4269. #define SB_AUTO 0x0010
  4270. #define MSK_AUTO 0x00f0
  4271. TCHAR MyPath[MAX_PATH], *p;
  4272. HINSTANCE g_Pc98ModuleHandle = NULL;
  4273. PWIN95_PLUGIN_98PTN32_SETBOOTFLAG SetBootFlag16;
  4274. //
  4275. // Obtain PC-98 helper routine addresses
  4276. // Generate directory of WINNT32
  4277. //
  4278. if( !GetModuleFileName (NULL, MyPath, MAX_PATH) || (!(p =_tcsrchr(MyPath, TEXT('\\')))))
  4279. return;
  4280. *p= 0;
  4281. ConcatenatePaths (MyPath, NEC98_DLL_NAME, MAX_PATH);
  4282. //
  4283. // Load library
  4284. //
  4285. g_Pc98ModuleHandle = LoadLibraryEx(
  4286. MyPath,
  4287. NULL,
  4288. LOAD_WITH_ALTERED_SEARCH_PATH
  4289. );
  4290. if(!g_Pc98ModuleHandle){
  4291. return;
  4292. }
  4293. //
  4294. // Get entry points
  4295. //
  4296. (FARPROC)SetBootFlag16 = GetProcAddress (g_Pc98ModuleHandle, (const char *)WIN95_98PTN32_SETBOOTFLAG);
  4297. if(!SetBootFlag16){
  4298. FreeLibrary(g_Pc98ModuleHandle);
  4299. return;
  4300. }
  4301. //
  4302. // Set auto boot flag on System drive use 16 bit DLL.
  4303. //
  4304. SetBootFlag16(bBootDrvLtr, SB_BOOTABLE | SB_AUTO);
  4305. FreeLibrary(g_Pc98ModuleHandle);
  4306. }
  4307. //
  4308. // Some NEC98 Windows NT4 system is installed DMITOOL
  4309. // This AP block the CreateFile API
  4310. // Setup need to check this AP
  4311. //
  4312. // Return
  4313. // TRUE ... DMITOOL is installed
  4314. // False .. DMITOOL is not installed
  4315. BOOL
  4316. NEC98CheckDMI()
  4317. {
  4318. HKEY hKey;
  4319. LONG Error;
  4320. TCHAR buf[100];
  4321. DWORD bufsize = sizeof(buf)/sizeof(TCHAR);
  4322. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  4323. TEXT("SOFTWARE\\NEC\\PcAssistant\\Common"),
  4324. 0, KEY_READ, &hKey) != ERROR_SUCCESS ) {
  4325. return(FALSE);
  4326. }
  4327. if (RegQueryValueEx(hKey, TEXT("Ver"), NULL,
  4328. NULL, (unsigned char *)buf,
  4329. &bufsize ) != ERROR_SUCCESS ) {
  4330. RegCloseKey( hKey );
  4331. return(FALSE);
  4332. }
  4333. RegCloseKey( hKey );
  4334. //
  4335. // We need check major Version is '2.
  4336. //
  4337. if ((TCHAR)*buf != (TCHAR)'2')
  4338. return(FALSE);
  4339. return(TRUE);
  4340. }
  4341. #endif
  4342. typedef BOOL (WINAPI* INITBILLBOARD)(HWND , LPCTSTR, DWORD);
  4343. typedef BOOL (WINAPI* TERMBILLBOARD)();
  4344. void PrepareBillBoard(HWND hwnd)
  4345. {
  4346. TCHAR szPath[MAX_PATH];
  4347. INITBILLBOARD pinitbb;
  4348. BOOL bMagnifierRunning = FALSE;
  4349. // Check if Magnifier is running.
  4350. HANDLE hEvent = CreateEvent(NULL, TRUE, TRUE, TEXT("MSMagnifierAlreadyExistsEvent"));
  4351. bMagnifierRunning = (!hEvent || GetLastError() == ERROR_ALREADY_EXISTS);
  4352. if (hEvent)
  4353. {
  4354. CloseHandle(hEvent);
  4355. }
  4356. // If the Magnifier is not set yet, set it.
  4357. if (!AccessibleMagnifier)
  4358. {
  4359. AccessibleMagnifier = bMagnifierRunning;
  4360. }
  4361. // If running on Win9x and Magnifier is running, don't use the billboard.
  4362. if (ISNT())
  4363. {
  4364. bMagnifierRunning = FALSE;
  4365. }
  4366. if (!bMagnifierRunning && FindPathToWinnt32File (
  4367. #ifndef UNICODE
  4368. TEXT("winntbba.dll"),
  4369. #else
  4370. TEXT("winntbbu.dll"),
  4371. #endif
  4372. szPath,
  4373. MAX_PATH
  4374. )) {
  4375. hinstBB = LoadLibrary (szPath);
  4376. if (hinstBB)
  4377. {
  4378. pinitbb = (INITBILLBOARD)GetProcAddress(hinstBB, "InitBillBoard");
  4379. if (pinitbb)
  4380. {
  4381. // Set no billboard text, just the background
  4382. if (!(*pinitbb)(hwnd, TEXT(""), ProductFlavor))
  4383. {
  4384. FreeLibrary(hinstBB);
  4385. hinstBB = NULL;
  4386. }
  4387. }
  4388. }
  4389. }
  4390. }
  4391. void TerminateBillBoard()
  4392. {
  4393. TERMBILLBOARD pTermBillBoard;
  4394. if (hinstBB)
  4395. {
  4396. if (pTermBillBoard = (TERMBILLBOARD)GetProcAddress(hinstBB, "TermBillBoard"))
  4397. pTermBillBoard ();
  4398. }
  4399. }
  4400. //
  4401. // This function is here so that when the wizard is hidden and the users
  4402. // task switches between other apps and setup, that we can handle the
  4403. // ESC key and forward it to the wizard dialog proc.
  4404. LRESULT
  4405. CALLBACK
  4406. MainBackgroundWndProc (
  4407. HWND hwnd,
  4408. UINT uMsg,
  4409. WPARAM wParam,
  4410. LPARAM lParam
  4411. )
  4412. {
  4413. switch (uMsg)
  4414. {
  4415. case WM_CHAR:
  4416. if (wParam == VK_ESCAPE)
  4417. {
  4418. // Forward this to the wizard dlg proc.
  4419. SendMessage(WizardHandle, uMsg, wParam, lParam);
  4420. return 0;
  4421. }
  4422. break;
  4423. }
  4424. return DefWindowProc (hwnd, uMsg, wParam, lParam);
  4425. }
  4426. void CreateMainWindow()
  4427. {
  4428. RECT rect;
  4429. WNDCLASSEX wcx;
  4430. TCHAR Caption[512];
  4431. GetWindowRect (GetDesktopWindow(), &rect);
  4432. ZeroMemory (&wcx, sizeof (wcx));
  4433. wcx.cbSize = sizeof (wcx);
  4434. wcx.style = CS_HREDRAW | CS_VREDRAW| CS_NOCLOSE;
  4435. wcx.lpfnWndProc = MainBackgroundWndProc;
  4436. wcx.hInstance = hInst;
  4437. wcx.lpszClassName = TEXT("Winnt32Background");
  4438. RegisterClassEx (&wcx);
  4439. if (!LoadString (
  4440. hInst,
  4441. AppTitleStringId,
  4442. Caption,
  4443. sizeof(Caption)/sizeof(TCHAR)
  4444. )) {
  4445. Caption[0] = 0;
  4446. }
  4447. BackgroundWnd2 = CreateWindowEx (
  4448. WS_EX_APPWINDOW,
  4449. TEXT("Winnt32Background"),
  4450. Caption,
  4451. WS_CLIPCHILDREN|WS_POPUP|WS_VISIBLE,
  4452. rect.left,
  4453. rect.top,
  4454. rect.right,
  4455. rect.bottom,
  4456. NULL,
  4457. NULL,
  4458. hInst,
  4459. 0
  4460. );
  4461. }
  4462. VOID
  4463. DisableSystemRestore( void )
  4464. /*
  4465. Description:
  4466. Procedure to disable system restore on upgrades. This way we save a lot of space
  4467. as disabling system restore will clear out the old files under
  4468. System Volume Information\_restore.{guid}".
  4469. */
  4470. {
  4471. HMODULE SRClient = NULL;
  4472. if( Upgrade ){
  4473. SRClient = LoadLibrary(TEXT("SRCLIENT.DLL"));
  4474. if( !SRClient )
  4475. return;
  4476. else{
  4477. if( ((FARPROC)SRClientDisableSR = GetProcAddress( SRClient, "DisableSR")) != NULL){
  4478. //Call the routine
  4479. SRClientDisableSR( NULL );
  4480. DebugLog(Winnt32LogInformation, TEXT("System Restore was disabled"), 0);
  4481. }
  4482. }
  4483. FreeLibrary( SRClient );
  4484. }
  4485. return;
  4486. }
  4487. #ifdef RUN_SYSPARSE
  4488. VOID
  4489. pCenterWindowOnDesktop (
  4490. HWND WndToCenter
  4491. )
  4492. /*++
  4493. Routine Description:
  4494. Centers a dialog relative to the 'work area' of the desktop.
  4495. Arguments:
  4496. WndToCenter - window handle of dialog to center
  4497. Return Value:
  4498. None.
  4499. --*/
  4500. {
  4501. RECT rcFrame, rcWindow;
  4502. LONG x, y, w, h;
  4503. POINT point;
  4504. HWND Desktop = GetDesktopWindow ();
  4505. point.x = point.y = 0;
  4506. ClientToScreen(Desktop, &point);
  4507. GetWindowRect(WndToCenter, &rcWindow);
  4508. GetClientRect(Desktop, &rcFrame);
  4509. w = rcWindow.right - rcWindow.left + 1;
  4510. h = rcWindow.bottom - rcWindow.top + 1;
  4511. x = point.x + ((rcFrame.right - rcFrame.left + 1 - w) / 2);
  4512. y = point.y + ((rcFrame.bottom - rcFrame.top + 1 - h) / 2);
  4513. //
  4514. // Get the work area for the current desktop (i.e., the area that
  4515. // the tray doesn't occupy).
  4516. //
  4517. if(!SystemParametersInfo (SPI_GETWORKAREA, 0, (PVOID)&rcFrame, 0)) {
  4518. //
  4519. // For some reason SPI failed, so use the full screen.
  4520. //
  4521. rcFrame.top = rcFrame.left = 0;
  4522. rcFrame.right = GetSystemMetrics(SM_CXSCREEN);
  4523. rcFrame.bottom = GetSystemMetrics(SM_CYSCREEN);
  4524. }
  4525. if(x + w > rcFrame.right) {
  4526. x = rcFrame.right - w;
  4527. } else if(x < rcFrame.left) {
  4528. x = rcFrame.left;
  4529. }
  4530. if(y + h > rcFrame.bottom) {
  4531. y = rcFrame.bottom - h;
  4532. } else if(y < rcFrame.top) {
  4533. y = rcFrame.top;
  4534. }
  4535. MoveWindow(WndToCenter, x, y, w, h, FALSE);
  4536. }
  4537. LRESULT
  4538. SysParseDlgProc(
  4539. IN HWND hdlg,
  4540. IN UINT msg,
  4541. IN WPARAM wParam,
  4542. IN LPARAM lParam
  4543. )
  4544. {
  4545. static DWORD ElapsedTime = 0;
  4546. static UINT_PTR timer = 0;
  4547. DWORD ret;
  4548. switch(msg) {
  4549. case WM_INITDIALOG:
  4550. pCenterWindowOnDesktop( hdlg);
  4551. timer = SetTimer( hdlg, WMX_SYSPARSE_DONE, 1000, NULL);
  4552. if ( !timer) {
  4553. EndDialog(hdlg,TRUE);
  4554. }
  4555. return( TRUE );
  4556. case WM_TIMER:
  4557. ElapsedTime++;
  4558. ret = WaitForSingleObject( piSysparse.hProcess, 0);
  4559. if ( ret == WAIT_OBJECT_0) {
  4560. KillTimer (hdlg, timer);
  4561. EndDialog(hdlg,TRUE);
  4562. } else if ( ElapsedTime >= 90) {
  4563. KillTimer (hdlg, timer);
  4564. TerminateProcess( piSysparse.hProcess, ERROR_TIMEOUT);
  4565. EndDialog(hdlg,TRUE);
  4566. }
  4567. return( TRUE );
  4568. default:
  4569. break;
  4570. }
  4571. return( FALSE );
  4572. }
  4573. #endif