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.

1163 lines
25 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. initnt.c
  5. Abstract:
  6. Code that performs initialization for the NT side of migration, and
  7. also implements workers that syssetup.dll calls.
  8. Author:
  9. Jim Schmidt (jimschm) 01-Oct-1996
  10. Revision History:
  11. jimschm 23-Sep-1998 New commonnt lib
  12. jimschm 31-Dec-1997 Moved here from w95upgnt\dll
  13. jimschm 21-Nov-1997 Updated for NEC98, some cleaned up and
  14. code commenting
  15. --*/
  16. #include "pch.h"
  17. #include "initntp.h"
  18. #ifndef UNICODE
  19. #error UNICODE required
  20. #endif
  21. //
  22. // Local prototypes
  23. //
  24. BOOL pReadUserOptions (VOID);
  25. VOID pReadStringMap (VOID);
  26. // Things set by FirstInitRoutine
  27. HANDLE g_hHeap;
  28. HINSTANCE g_hInst;
  29. TCHAR g_DllDir[MAX_TCHAR_PATH];
  30. TCHAR g_WinDir[MAX_TCHAR_PATH];
  31. TCHAR g_WinDrive[MAX_TCHAR_PATH];
  32. TCHAR g_SystemDir[MAX_TCHAR_PATH];
  33. TCHAR g_System32Dir[MAX_TCHAR_PATH];
  34. TCHAR g_ProgramFiles[MAX_TCHAR_PATH];
  35. TCHAR g_ProgramFilesCommon[MAX_TCHAR_PATH];
  36. TCHAR g_Win95Name[MAX_TCHAR_PATH]; // holds Windows 95, Windows 98, etc...
  37. PCTSTR g_AdministratorStr;
  38. TCHAR g_Win9xBootDrivePath[] = TEXT("C:\\");
  39. // Things set by SysSetupInit
  40. HWND g_ParentWnd;
  41. HWND g_ProgressBar;
  42. HINF g_UnattendInf = INVALID_HANDLE_VALUE;
  43. HINF g_WkstaMigInf = INVALID_HANDLE_VALUE;
  44. HINF g_UserMigInf = INVALID_HANDLE_VALUE;
  45. TCHAR g_TempDir[MAX_TCHAR_PATH];
  46. TCHAR g_OurCopyOfSourceDir[MAX_TCHAR_PATH];
  47. PCTSTR g_SourceDir;
  48. POOLHANDLE g_UserOptionPool = NULL;
  49. PCTSTR g_MsgYes;
  50. PCTSTR g_MsgNo;
  51. USEROPTIONS g_ConfigOptions;
  52. PMAPSTRUCT g_StringMap;
  53. //
  54. // Initialization code
  55. //
  56. static int g_LibCount = 0;
  57. typedef BOOL (WINAPI INITROUTINE_PROTOTYPE)(HINSTANCE, DWORD, LPVOID);
  58. typedef INITROUTINE_PROTOTYPE * INITROUTINE;
  59. //
  60. // MigUtil_Entry *must* be first
  61. //
  62. #define LIBLIST \
  63. LIBRARY_NAME(MigUtil_Entry) \
  64. LIBRARY_NAME(Win95Reg_Entry) \
  65. LIBRARY_NAME(MemDb_Entry) \
  66. LIBRARY_NAME(FileEnum_Entry) \
  67. LIBRARY_NAME(CommonNt_Entry) \
  68. LIBRARY_NAME(MigMain_Entry) \
  69. LIBRARY_NAME(Merge_Entry) \
  70. LIBRARY_NAME(RuleHlpr_Entry) \
  71. LIBRARY_NAME(DosMigNt_Entry) \
  72. LIBRARY_NAME(Ras_Entry) \
  73. LIBRARY_NAME(Tapi_Entry) \
  74. #define LIBRARY_NAME(x) INITROUTINE_PROTOTYPE x;
  75. LIBLIST
  76. #undef LIBRARY_NAME
  77. #define LIBRARY_NAME(x) x,
  78. static INITROUTINE g_InitRoutine[] = {LIBLIST /*,*/ NULL};
  79. //
  80. // Buffer for persistent strings used for the life of the DLL
  81. //
  82. static PGROWBUFFER g_PersistentStrings;
  83. //
  84. // Implementation
  85. //
  86. BOOL
  87. FirstInitRoutine (
  88. HINSTANCE hInstance
  89. )
  90. /*++
  91. Routine Description:
  92. FirstInitRoutine is the very first function called during the
  93. initialization of the DLL. It sets up globals such as the heap
  94. pointer and instance handle. This routine must be called before
  95. any library entry point is called.
  96. Arguments:
  97. hInstance - (OS-supplied) instance handle for the DLL
  98. Return Value:
  99. Returns TRUE if the global variables could be initialized, or FALSE
  100. if an error occurred.
  101. --*/
  102. {
  103. PTSTR p;
  104. //
  105. // Get the process heap & instance handle
  106. //
  107. g_hHeap = HeapCreate (0, 0x20000, 0);
  108. if (!g_hHeap) {
  109. LOG ((LOG_ERROR, "Cannot create a private heap."));
  110. g_hHeap = GetProcessHeap();
  111. }
  112. g_hInst = hInstance;
  113. // No DLL_THREAD_ATTACH or DLL_THREAD_DETECH needed
  114. DisableThreadLibraryCalls (hInstance);
  115. // Init common controls
  116. InitCommonControls();
  117. // Get DLL path and strip directory
  118. GetModuleFileName (hInstance, g_DllDir, MAX_TCHAR_PATH);
  119. p = _tcsrchr (g_DllDir, TEXT('\\'));
  120. MYASSERT (p);
  121. *p = 0;
  122. // Set g_WinDir
  123. if (!GetWindowsDirectory (g_WinDir, sizeof (g_WinDir) / sizeof (g_WinDir[0]))) {
  124. return FALSE;
  125. }
  126. // Set g_WinDrive
  127. _tsplitpath (g_WinDir, g_WinDrive, NULL, NULL, NULL);
  128. // Set g_SystemDir
  129. wsprintf (g_SystemDir, TEXT("%s\\%s"), g_WinDir, TEXT("system"));
  130. // Set g_System32Dir
  131. GetSystemDirectory (g_System32Dir, sizeof (g_System32Dir) / sizeof (g_System32Dir[0]));
  132. return TRUE;
  133. }
  134. BOOL
  135. InitLibs (
  136. HINSTANCE hInstance,
  137. DWORD dwReason,
  138. LPVOID lpReserved
  139. )
  140. /*++
  141. Routine Description:
  142. InitLibs calls all library entry points in the g_InitRoutine array.
  143. If an entry point fails, all libraries are unloaded in reverse order
  144. and InitLibs returns FALSE.
  145. Arguments:
  146. hInstance - (OS-supplied) instance handle for the DLL
  147. dwReason - (OS-supplied) indicates attach or detatch from process or
  148. thread -- in this case always DLL_PROCESS_ATTACH
  149. lpReserved - (OS-supplied) unused
  150. Return Value:
  151. Returns TRUE if all libraries successfully initialized, or FALSE if
  152. a library could not initialize. If TRUE is returned, TerminateLibs
  153. must be called for the DLL_PROCESS_DETACH message.
  154. --*/
  155. {
  156. if(!pSetupInitializeUtils()) {
  157. return FALSE;
  158. }
  159. SET_RESETLOG();
  160. //
  161. // Init each LIB
  162. //
  163. for (g_LibCount = 0 ; g_InitRoutine[g_LibCount] ; g_LibCount++) {
  164. if (!g_InitRoutine[g_LibCount] (hInstance, dwReason, lpReserved)) {
  165. TerminateLibs (hInstance, DLL_PROCESS_DETACH, lpReserved);
  166. return FALSE;
  167. }
  168. }
  169. return TRUE;
  170. }
  171. BOOL
  172. FinalInitRoutine (
  173. VOID
  174. )
  175. /*++
  176. Routine Description:
  177. FinalInitRoutine completes all initialization that requires completely
  178. initialized libraries.
  179. Arguments:
  180. none
  181. Return Value:
  182. TRUE if initialization completed successfully, or FALSE if an error occurred.
  183. --*/
  184. {
  185. PCTSTR TempStr;
  186. //
  187. // Load common message strings
  188. //
  189. g_PersistentStrings = CreateAllocTable();
  190. if (!g_PersistentStrings) {
  191. return FALSE;
  192. }
  193. // Get Administrator account name
  194. g_AdministratorStr = GetStringResourceEx (g_PersistentStrings, MSG_ADMINISTRATOR_ACCOUNT);
  195. if (!g_AdministratorStr) {
  196. g_AdministratorStr = S_EMPTY;
  197. }
  198. if(ISPC98()){
  199. //
  200. // Update the boot drive letter (set by migutil) to the system partition
  201. //
  202. g_BootDriveLetterW = g_BootDriveLetterA = (int)g_System32Dir[0];
  203. *((PSTR) g_BootDrivePathA) = g_BootDriveLetterA;
  204. *((PWSTR) g_BootDrivePathW) = g_BootDriveLetterW;
  205. }
  206. // Set Program Files directory
  207. TempStr = (PTSTR) GetStringResource (MSG_PROGRAM_FILES_DIR);
  208. MYASSERT (TempStr);
  209. StringCopy (g_ProgramFiles, TempStr);
  210. g_ProgramFiles [0] = g_WinDir [0];
  211. FreeStringResource (TempStr);
  212. StringCopy (g_ProgramFilesCommon, g_ProgramFiles);
  213. StringCat (g_ProgramFilesCommon, TEXT("\\"));
  214. StringCat (g_ProgramFilesCommon, S_COMMONDIR);
  215. return TRUE;
  216. }
  217. VOID
  218. FirstCleanupRoutine (
  219. VOID
  220. )
  221. /*++
  222. Routine Description:
  223. FirstCleanupRoutine is called to perform any cleanup that requires
  224. libraries to still be loaded.
  225. Arguments:
  226. none
  227. Return Value:
  228. none
  229. --*/
  230. {
  231. TCHAR buffer[MEMDB_MAX];
  232. //
  233. // Terminate progress bar table
  234. //
  235. TerminateProcessingTable();
  236. //
  237. // If Win9x Side saved a LOGSAVETO location into memdb, then we need to save the
  238. // debugnt log to that location.
  239. //
  240. MemDbGetEndpointValueEx(MEMDB_CATEGORY_LOGSAVETO,NULL,NULL,buffer);
  241. AppendWack(buffer);
  242. StringCat(buffer,TEXT("debugnt.log"));
  243. CopyFile(TEXT("debugnt.log"),buffer,FALSE);
  244. //
  245. // Clean up persistent strings
  246. //
  247. if (g_PersistentStrings) {
  248. DestroyAllocTable (g_PersistentStrings);
  249. }
  250. }
  251. VOID
  252. TerminateLibs (
  253. HINSTANCE hInstance,
  254. DWORD dwReason,
  255. LPVOID lpReserved
  256. )
  257. /*++
  258. Routine Description:
  259. TerminateLibs is called to unload all libraries in the reverse order
  260. that they were initialized. Each entry point of successfully
  261. initialized library is called.
  262. Arguments:
  263. hInstance - (OS-supplied) instance handle for the DLL
  264. dwReason - (OS-supplied) indicates attach or detatch from process or
  265. thread -- in this case always DLL_PROCESS_DETACH
  266. lpReserved - (OS-supplied) unused
  267. Return Value:
  268. none
  269. --*/
  270. {
  271. INT i;
  272. for (i = g_LibCount - 1 ; i >= 0 ; i--) {
  273. g_InitRoutine[i] (hInstance, dwReason, lpReserved);
  274. }
  275. g_LibCount = 0;
  276. pSetupUninitializeUtils();
  277. }
  278. VOID
  279. FinalCleanupRoutine (
  280. VOID
  281. )
  282. /*++
  283. Routine Description:
  284. FinalCleanupRoutine is after all library entry points have been
  285. called for cleanup. This routine cleans up all resources that a
  286. library will not clean up.
  287. Arguments:
  288. none
  289. Return Value:
  290. none
  291. --*/
  292. {
  293. // Nothing to do now
  294. }
  295. BOOL
  296. pGetInfVal (
  297. IN HINF Inf,
  298. IN PCTSTR Section,
  299. IN PCTSTR Key,
  300. IN PTSTR Buffer,
  301. IN DWORD BufferSize
  302. )
  303. {
  304. INFCONTEXT ic;
  305. if (!SetupFindFirstLine (Inf, Section, Key, &ic))
  306. return FALSE;
  307. if (!SetupGetStringField (&ic, 1, Buffer, BufferSize, NULL))
  308. return FALSE;
  309. return TRUE;
  310. }
  311. typedef BOOL (OPTIONHANDLERFUN)(PTSTR, PVOID * Option, PTSTR Value);
  312. typedef OPTIONHANDLERFUN * POPTIONHANDLERFUN;
  313. BOOL pHandleBoolOption (PTSTR, PVOID *, PTSTR);
  314. BOOL pHandleIntOption (PTSTR, PVOID *, PTSTR);
  315. BOOL pHandleTriStateOption (PTSTR, PVOID *, PTSTR);
  316. BOOL pHandleMultiSzOption (PTSTR, PVOID *, PTSTR);
  317. BOOL pHandleStringOption (PTSTR, PVOID *, PTSTR);
  318. BOOL pHandleSaveReportTo (PTSTR, PVOID *, PTSTR);
  319. BOOL pHandleBoot16 (PTSTR, PVOID *, PTSTR);
  320. BOOL pGetDefaultPassword (PTSTR, PVOID *, PTSTR);
  321. typedef struct {
  322. PTSTR OptionName;
  323. PVOID Option;
  324. POPTIONHANDLERFUN DefaultHandler;
  325. POPTIONHANDLERFUN SpecialHandler;
  326. PVOID Default;
  327. } OPTIONSTRUCT, *POPTIONSTRUCT;
  328. #define INT_MAX_NUMBER_OF_DIGIT 11
  329. PTSTR pGetIntStrForOption(INT Value)
  330. {
  331. PTSTR strIntDefaultValue = AllocText(INT_MAX_NUMBER_OF_DIGIT + 1);
  332. if(strIntDefaultValue)
  333. _itot(Value, strIntDefaultValue, 10);
  334. return strIntDefaultValue;
  335. }
  336. #define BOOLOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleBoolOption, (h), (PVOID) (BOOL) (d) ? S_YES : S_NO},
  337. #define INTOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleIntOption, (h), (PVOID)(d)},
  338. #define TRISTATEOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleTriStateOption, (h), (PVOID) (INT) (d == TRISTATE_AUTO)? S_AUTO: (d == TRISTATE_YES)? S_YES : S_NO},
  339. #define MULTISZOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleMultiSzOption, (h), (PVOID) (d)},
  340. #define STRINGOPTION(o,h,d) {TEXT(#o), &(g_ConfigOptions.##o), pHandleStringOption, (h), (PVOID) (d)},
  341. OPTIONSTRUCT g_OptionsList[] = {OPTION_LIST /*,*/ {NULL,NULL,NULL,NULL}};
  342. PVOID g_OptionsTable = NULL;
  343. #define HANDLEOPTION(Os,Value) {Os->SpecialHandler ? \
  344. Os->SpecialHandler (Os->OptionName,Os->Option,Value) : \
  345. Os->DefaultHandler (Os->OptionName,Os->Option,Value); \
  346. }
  347. POPTIONSTRUCT
  348. pFindOption (
  349. PTSTR OptionName
  350. )
  351. {
  352. POPTIONSTRUCT rOption = NULL;
  353. UINT rc;
  354. //
  355. // find the matching option struct for this, and
  356. // call the handler.
  357. //
  358. rc = pSetupStringTableLookUpStringEx (
  359. g_OptionsTable,
  360. OptionName,
  361. STRTAB_CASE_INSENSITIVE,
  362. (PBYTE) &rOption,
  363. sizeof (POPTIONSTRUCT)
  364. );
  365. DEBUGMSG_IF ((rc == -1, DBG_WARNING, "Unknown option found: %s", OptionName));
  366. return rOption;
  367. }
  368. VOID
  369. pInitUserOptionsTable (
  370. VOID
  371. )
  372. {
  373. POPTIONSTRUCT os;
  374. LONG rc;
  375. os = g_OptionsList;
  376. while (os->OptionName) {
  377. //
  378. // Add the option struct to a string table for quick retrieval.
  379. //
  380. rc = pSetupStringTableAddStringEx (
  381. g_OptionsTable,
  382. os->OptionName,
  383. STRTAB_CASE_INSENSITIVE,
  384. (PBYTE) &os,
  385. sizeof (POPTIONSTRUCT)
  386. );
  387. if (rc == -1) {
  388. LOG ((LOG_ERROR, "User Options: Can't add to string table"));
  389. break;
  390. }
  391. os++;
  392. }
  393. }
  394. BOOL
  395. pHandleBoolOption (
  396. IN PTSTR Name,
  397. IN PVOID * OptionVar,
  398. IN PTSTR Value
  399. )
  400. {
  401. BOOL rSuccess = TRUE;
  402. BOOL *option = (BOOL *) OptionVar;
  403. if (StringIMatch (Value, S_YES) ||
  404. StringIMatch (Value, S_ONE) ||
  405. StringIMatch (Value, TEXT("TRUE"))) {
  406. *option = TRUE;
  407. }
  408. else {
  409. *option = FALSE;
  410. }
  411. return rSuccess;
  412. }
  413. BOOL
  414. pHandleIntOption (
  415. IN PTSTR Name,
  416. IN PVOID * OptionVar,
  417. IN PTSTR Value
  418. )
  419. {
  420. BOOL rSuccess = TRUE;
  421. PINT option = (PINT) OptionVar;
  422. MYASSERT(Name && OptionVar);
  423. if (!Value) {
  424. Value = TEXT("0");
  425. }
  426. *option = _ttoi((PCTSTR)Value);
  427. return rSuccess;
  428. }
  429. BOOL
  430. pHandleTriStateOption (
  431. IN PTSTR Name,
  432. IN PVOID * OptionVar,
  433. IN PTSTR Value
  434. )
  435. {
  436. BOOL rSuccess = TRUE;
  437. PINT option = (PINT) OptionVar;
  438. MYASSERT(Name && OptionVar);
  439. if (!Value) {
  440. Value = S_AUTO;
  441. }
  442. if (StringIMatch (Value, S_YES) ||
  443. StringIMatch (Value, S_ONE) ||
  444. StringIMatch (Value, S_TRUE) ||
  445. StringIMatch (Value, S_REQUIRED)) {
  446. *option = TRISTATE_YES;
  447. }
  448. else {
  449. if(StringIMatch (Value, S_NO) ||
  450. StringIMatch (Value, S_STR_FALSE) ||
  451. StringIMatch (Value, S_ZERO)) {
  452. *option = TRISTATE_NO;
  453. }
  454. else {
  455. *option = TRISTATE_AUTO;
  456. }
  457. }
  458. return rSuccess;
  459. }
  460. BOOL
  461. pHandleMultiSzOption (
  462. IN PTSTR Name,
  463. IN PVOID * OptionVar,
  464. IN PTSTR Value
  465. )
  466. {
  467. BOOL rSuccess = TRUE;
  468. if (Value) {
  469. *OptionVar = PoolMemDuplicateMultiSz (g_UserOptionPool, Value);
  470. }
  471. ELSE_DEBUGMSG ((DBG_WHOOPS, "Multi-Sz config option has nul value"));
  472. return rSuccess;
  473. }
  474. BOOL
  475. pHandleStringOption (
  476. IN PTSTR Name,
  477. IN PVOID * OptionVar,
  478. IN PTSTR Value
  479. )
  480. {
  481. if (!Value) {
  482. *OptionVar = S_EMPTY;
  483. }
  484. else {
  485. *OptionVar = PoolMemDuplicateMultiSz (g_UserOptionPool, Value);
  486. }
  487. return TRUE;
  488. }
  489. BOOL
  490. pHandleSaveReportTo (
  491. IN PTSTR Name,
  492. IN PVOID * OptionVar,
  493. IN PTSTR Value
  494. )
  495. {
  496. return pHandleStringOption (Name, OptionVar, Value);
  497. }
  498. BOOL
  499. pHandleBoot16 (
  500. IN PTSTR Name,
  501. IN PVOID * OptionVar,
  502. IN PTSTR Value
  503. )
  504. {
  505. BOOL rSuccess = TRUE;
  506. PTSTR * option = (PTSTR *) OptionVar;
  507. if (!Value ||
  508. StringIMatch (Value, S_YES) ||
  509. StringIMatch (Value, S_TRUE) ||
  510. StringIMatch (Value, S_ONE)) {
  511. *option = S_YES;
  512. g_Boot16 = BOOT16_YES;
  513. }
  514. else if (Value &&
  515. (StringIMatch (Value, S_BOOT16_UNSPECIFIED) ||
  516. StringIMatch (Value, S_BOOT16_AUTOMATIC))) {
  517. *option = S_BOOT16_AUTOMATIC;
  518. g_Boot16 = BOOT16_AUTOMATIC;
  519. }
  520. else {
  521. g_Boot16 = BOOT16_NO;
  522. *option = S_NO;
  523. }
  524. return rSuccess;
  525. }
  526. BOOL
  527. pGetDefaultPassword (
  528. IN PTSTR Name,
  529. IN PVOID * OptionVar,
  530. IN PTSTR Value
  531. )
  532. {
  533. return pHandleStringOption (Name, OptionVar, Value);
  534. }
  535. BOOL
  536. pReadUserOptions (
  537. VOID
  538. )
  539. {
  540. PTSTR curParameter;
  541. PTSTR curValue;
  542. BOOL rSuccess = TRUE;
  543. POPTIONSTRUCT os;
  544. INFSTRUCT is = INITINFSTRUCT_GROWBUFFER;
  545. ZeroMemory(&g_ConfigOptions,sizeof(USEROPTIONS));
  546. g_OptionsTable = pSetupStringTableInitializeEx (sizeof (POPTIONSTRUCT), 0);
  547. if (!g_OptionsTable) {
  548. LOG ((LOG_ERROR, "User Options: Unable to initialize string table."));
  549. return FALSE;
  550. }
  551. pInitUserOptionsTable ();
  552. if (InfFindFirstLine(g_UnattendInf,S_WIN9XUPGUSEROPTIONS,NULL,&is)) {
  553. //
  554. // There is at least one item. Loop through all user options, processing each.
  555. //
  556. do {
  557. //
  558. // Get the parameter and value from this line and pass it on.
  559. //
  560. curParameter = InfGetStringField (&is, 0);
  561. if (curParameter) {
  562. curParameter = PoolMemDuplicateString (g_UserOptionPool, curParameter);
  563. }
  564. curValue = InfGetMultiSzField (&is, 1);
  565. if (curValue) {
  566. curValue = PoolMemDuplicateMultiSz (g_UserOptionPool, curValue);
  567. }
  568. if (curParameter) {
  569. os = pFindOption (curParameter);
  570. if (os) {
  571. HANDLEOPTION (os, curValue);
  572. }
  573. }
  574. else {
  575. //
  576. // If we couldn't get the current parameter, it is a serious enough error
  577. // to abort processing of the unattend file user options.
  578. //
  579. LOG ((LOG_ERROR,"An error occurred while attempting to read user options from the unattend file."));
  580. rSuccess = FALSE;
  581. }
  582. } while (rSuccess && InfFindNextLine(&is));
  583. }
  584. else {
  585. LOG ((LOG_ERROR,"No win9xupgrade section in unattend script file."));
  586. }
  587. InfCleanUpInfStruct (&is);
  588. if (g_ConfigOptions.DoLog) {
  589. SET_DOLOG();
  590. }
  591. pSetupStringTableDestroy (g_OptionsTable);
  592. return rSuccess;
  593. }
  594. BOOL
  595. SysSetupInit (
  596. IN HWND ProgressBar,
  597. IN PCWSTR UnattendFile,
  598. IN PCWSTR SourceDir
  599. )
  600. {
  601. HINF hUnattendInf;
  602. BOOL b = FALSE;
  603. TCHAR duWorkingDir[MAX_PATH];
  604. PTSTR TempStr;
  605. //
  606. // This routine is called after the DLL initialization routines
  607. // have completed.
  608. //
  609. #ifdef PRERELEASE
  610. {
  611. TCHAR Buf[32];
  612. STARTUPINFO si;
  613. BOOL ProcessStarted;
  614. ZeroMemory (&si, sizeof (si));
  615. si.cb = sizeof (si);
  616. if (GetPrivateProfileString (
  617. TEXT("Debug"),
  618. TEXT("Debug"),
  619. TEXT("0"),
  620. Buf,
  621. 32,
  622. ISPC98() ? TEXT("a:\\debug.inf") : TEXT("c:\\debug.inf")
  623. )
  624. ) {
  625. if (_ttoi (Buf)) {
  626. #pragma prefast(suppress:301, "Pre-release only use of WinExec, used for debugging only")
  627. ProcessStarted = WinExec ("cmd.exe", SW_SHOW) > 31;
  628. if (ProcessStarted) {
  629. MessageBox (NULL, TEXT("Ready to debug."), TEXT("Debug"), MB_OK|MB_SETFOREGROUND);
  630. //CloseHandle (pi.hProcess);
  631. } else {
  632. DEBUGMSG ((DBG_ERROR, "Could not start cmd.exe, GLE=%u", GetLastError()));
  633. }
  634. }
  635. }
  636. }
  637. #endif
  638. //
  639. // Open the answer file and keep it open until SysSetupTerminate is called
  640. //
  641. hUnattendInf = InfOpenInfFile (UnattendFile);
  642. if (hUnattendInf == INVALID_HANDLE_VALUE) {
  643. LOG ((LOG_ERROR, "InitNT: Cannot open %s", UnattendFile));
  644. return FALSE;
  645. }
  646. //
  647. // Read the DynamicUpdate directory location and set the INF patch directory accordingly
  648. // NOTE: this must be done before opening wkstamig.inf etc.
  649. //
  650. if (pGetInfVal (
  651. hUnattendInf,
  652. WINNT_SETUPPARAMS,
  653. WINNT_SP_DYNUPDTWORKINGDIR,
  654. duWorkingDir,
  655. ARRAYSIZE(duWorkingDir)
  656. )) {
  657. DEBUGMSG((DBG_NAUSEA, "Found %s=%s", WINNT_SP_DYNUPDTWORKINGDIR, duWorkingDir));
  658. TempStr = JoinPaths (duWorkingDir, S_UPGINFSDIR);
  659. InitInfReplaceTable (TempStr);
  660. FreePathString (TempStr);
  661. }
  662. //
  663. // Create a pool for user options.
  664. //
  665. g_UserOptionPool = PoolMemInitNamedPool ("User Option Pool - NT Side");
  666. if (!g_UserOptionPool) {
  667. DEBUGMSG((DBG_ERROR,"Cannot initialize user option pool."));
  668. return FALSE;
  669. }
  670. //
  671. // Open wkstamig.inf for general use
  672. //
  673. g_WkstaMigInf = InfOpenInfFile (S_WKSTAMIG_INF);
  674. if (g_WkstaMigInf == INVALID_HANDLE_VALUE) {
  675. LOG ((LOG_ERROR, "InitNT: Unable to open %s", S_WKSTAMIG_INF));
  676. return FALSE;
  677. }
  678. //
  679. // Open usermig.inf for general use
  680. //
  681. g_UserMigInf = InfOpenInfFile (S_USERMIG_INF);
  682. if (g_UserMigInf == INVALID_HANDLE_VALUE) {
  683. LOG ((LOG_ERROR, "InitNT: Unable to open %s", S_USERMIG_INF));
  684. return FALSE;
  685. }
  686. //
  687. // Initialize our globals
  688. //
  689. g_UnattendInf = hUnattendInf;
  690. StringCopy (g_OurCopyOfSourceDir, SourceDir);
  691. g_SourceDir = g_OurCopyOfSourceDir;
  692. g_ParentWnd = GetParent (ProgressBar);
  693. LogReInit (&g_ParentWnd, NULL);
  694. g_ProgressBar = ProgressBar;
  695. if (ISPC98()) {
  696. TCHAR win9xBootDrive[6];
  697. //
  698. // Get g_Win9xBootDrive from answer file's [Data] section
  699. //
  700. if (pGetInfVal (
  701. g_UnattendInf,
  702. WINNT_DATA,
  703. WINNT_D_WIN9XBOOTDRIVE,
  704. win9xBootDrive,
  705. sizeof (win9xBootDrive) / sizeof (TCHAR)
  706. )) {
  707. g_Win9xBootDrivePath[0] = win9xBootDrive[0];
  708. } else {
  709. LOG ((LOG_ERROR, "InitNT: Cannot retrieve %s in [%s] of %s",
  710. WINNT_DATA, WINNT_D_WIN9XBOOTDRIVE, UnattendFile));
  711. }
  712. }
  713. //
  714. // Get g_TempDir from answer file's [Data] section
  715. //
  716. if (!pGetInfVal (
  717. g_UnattendInf,
  718. WINNT_DATA,
  719. WINNT_D_MIGTEMPDIR,
  720. g_TempDir,
  721. sizeof (g_TempDir) / sizeof (TCHAR)
  722. )) {
  723. LOG ((LOG_ERROR, "InitNT: Cannot retrieve %s in [%s] of %s",
  724. WINNT_DATA, WINNT_D_MIGTEMPDIR, UnattendFile));
  725. goto cleanup;
  726. }
  727. //
  728. // Get user settings from command line
  729. //
  730. pReadUserOptions();
  731. //
  732. // Read [String Map] section and put pairs in the corresponding map
  733. //
  734. pReadStringMap ();
  735. // Done!
  736. b = TRUE;
  737. cleanup:
  738. if (!b) {
  739. SysSetupTerminate();
  740. }
  741. return b;
  742. }
  743. VOID
  744. SysSetupTerminate (
  745. VOID
  746. )
  747. {
  748. //
  749. // Close the answer file
  750. //
  751. if (g_UnattendInf != INVALID_HANDLE_VALUE) {
  752. InfCloseInfFile (g_UnattendInf);
  753. g_UnattendInf = INVALID_HANDLE_VALUE;
  754. }
  755. //
  756. // Close wkstamig.inf
  757. //
  758. if (g_WkstaMigInf != INVALID_HANDLE_VALUE) {
  759. InfCloseInfFile (g_WkstaMigInf);
  760. g_WkstaMigInf = INVALID_HANDLE_VALUE;
  761. }
  762. if (g_UserMigInf != INVALID_HANDLE_VALUE) {
  763. InfCloseInfFile (g_UserMigInf);
  764. g_UserMigInf = INVALID_HANDLE_VALUE;
  765. }
  766. //
  767. // Clean up user option pool.
  768. //
  769. if (g_UserOptionPool) {
  770. PoolMemDestroyPool(g_UserOptionPool);
  771. }
  772. //
  773. // Set current directory to the root of C:
  774. //
  775. SetCurrentDirectory (g_BootDrivePath);
  776. #ifdef PRERELEASE
  777. {
  778. TCHAR Buf[32];
  779. if (GetPrivateProfileString (
  780. TEXT("Debug"),
  781. TEXT("GuiModePause"),
  782. TEXT("0"),
  783. Buf,
  784. 32,
  785. ISPC98() ? TEXT("a:\\debug.inf") : TEXT("c:\\debug.inf")
  786. )
  787. ) {
  788. if (_ttoi (Buf)) {
  789. MessageBox (NULL, TEXT("Paused."), TEXT("Debug"), MB_OK|MB_SETFOREGROUND);
  790. }
  791. }
  792. }
  793. #endif
  794. }
  795. BOOL
  796. PerformMigration (
  797. IN HWND Unused,
  798. IN PCWSTR UnattendFile,
  799. IN PCWSTR SourceDir // i.e. f:\i386
  800. )
  801. {
  802. BOOL rSuccess = TRUE;
  803. //
  804. // Initialize Migmain.
  805. //
  806. if (!MigMain_Init()) {
  807. LOG ((LOG_ERROR, "W95UpgNt_Migrate: MigMain_Init failed"));
  808. rSuccess = FALSE;
  809. }
  810. //
  811. // Do the migration!
  812. //
  813. else if (!MigMain_Migrate()) {
  814. LOG ((LOG_ERROR, "W95UpgNt_Migrate: MigMain_Migrate failed"));
  815. rSuccess = FALSE;
  816. }
  817. //
  818. // If we were unsuccessful anywhere along the way, Migration could be in big
  819. // trouble. Inform the user.
  820. //
  821. if (!rSuccess) {
  822. LOG ((LOG_ERROR, (PCSTR)MSG_MIGRATION_IS_TOAST, g_Win95Name));
  823. }
  824. ELSE_DEBUGMSG((DBG_VERBOSE, "W95UpgNt_Migrate: Successful completion..."));
  825. return rSuccess;
  826. }
  827. VOID
  828. pReadStringMap (
  829. VOID
  830. )
  831. {
  832. INFSTRUCT is = INITINFSTRUCT_POOLHANDLE;
  833. PTSTR Key, Value;
  834. INT SubstringMatch;
  835. PTSTR ExpKey, ExpValue;
  836. MYASSERT (g_WkstaMigInf);
  837. if (InfFindFirstLine (g_WkstaMigInf, S_STRINGMAP, NULL, &is)) {
  838. do {
  839. Key = InfGetStringField (&is, 0);
  840. if (!Key) {
  841. continue;
  842. }
  843. Value = InfGetStringField (&is, 1);
  844. if (!Value) {
  845. continue;
  846. }
  847. if (!InfGetIntField (&is, 2, &SubstringMatch)) {
  848. SubstringMatch = 0;
  849. }
  850. ExpKey = ExpandEnvironmentText (Key);
  851. ExpValue = ExpandEnvironmentText (Value);
  852. AddStringMappingPair (
  853. SubstringMatch ? g_SubStringMap : g_CompleteMatchMap,
  854. ExpKey,
  855. ExpValue
  856. );
  857. FreeText (ExpKey);
  858. FreeText (ExpValue);
  859. } while (InfFindNextLine (&is));
  860. }
  861. InfCleanUpInfStruct (&is);
  862. }