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

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