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

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