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.

1155 lines
27 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. migdlls.c
  5. Abstract:
  6. The functions in this module are used to support migration DLLs.
  7. Author:
  8. Jim Schmidt (jimschm) 04-Feb-1997
  9. Revision History:
  10. jimschm 23-Sep-1998 Changed to use new IPC mechanism
  11. jimschm 22-Apr-1998 Added USERPROFILE environment variable to MigrateUserNT
  12. jimschm 08-Jan-1997 Added alive event, giving certain DLLs up to 30 minutes
  13. to complete their work.
  14. jimschm 08-Dec-1997 Added support for domains (MigrateUserNT's user name
  15. param is multi-sz)
  16. --*/
  17. #include "pch.h"
  18. #include "migmainp.h"
  19. #ifndef UNICODE
  20. #error UNICODE required
  21. #endif
  22. HANDLE g_AliveEvent;
  23. BOOL
  24. pConnectToDll (
  25. VOID
  26. );
  27. VOID
  28. pDisconnectFromDll (
  29. VOID
  30. );
  31. DWORD
  32. pRunMigrationDll (
  33. VOID
  34. );
  35. DWORD
  36. pCallInitializeNt (
  37. IN PCTSTR WorkingDir,
  38. IN PCTSTR *SourceDirArray,
  39. IN PVOID Reserved,
  40. IN DWORD ReservedBytes
  41. );
  42. DWORD
  43. pCallMigrateUserNt (
  44. IN PCTSTR WorkingDir,
  45. IN PCTSTR UnattendFile,
  46. IN PCTSTR RootKey,
  47. IN PCTSTR Win9xUserName,
  48. IN PCTSTR UserDomain,
  49. IN PCTSTR FixedUserName,
  50. IN PVOID Reserved,
  51. IN DWORD ReservedBytes
  52. );
  53. DWORD
  54. pCallMigrateSystemNt (
  55. IN PCTSTR WorkingDir,
  56. IN PCTSTR UnattendFile,
  57. IN PVOID Reserved,
  58. IN DWORD ReservedBytes
  59. );
  60. static
  61. VOID
  62. pSetCwd (
  63. OUT PTSTR SavedWorkDir,
  64. IN PCTSTR NewWorkDir
  65. );
  66. static TCHAR g_DllPath[MAX_TCHAR_PATH];
  67. static TCHAR g_WorkingDir[MAX_TCHAR_PATH];
  68. static TCHAR g_DllDesc[MAX_TCHAR_PATH];
  69. static VENDORINFOW g_VendorInfo;
  70. static TCHAR g_FixedUser[MAX_USER_NAME];
  71. static TCHAR g_UserOnWin9x[MAX_USER_NAME];
  72. static HINSTANCE g_hLibrary;
  73. P_INITIALIZE_NT InitializeNT;
  74. P_MIGRATE_USER_NT MigrateUserNT;
  75. P_MIGRATE_SYSTEM_NT MigrateSystemNT;
  76. VOID
  77. pLogDllFailure (
  78. IN HWND Parent,
  79. IN UINT MessageId
  80. )
  81. /*++
  82. Routine Description:
  83. pLogDllFailure prepares arguments for the specified MessageId, and then
  84. displays a popup and adds a log entry. This function gives the user
  85. information on what to do when the DLL fails.
  86. Arguments:
  87. Parent - Specifies the parent window handle of the popup, or NULL if no
  88. popup is to be displayed.
  89. MessageId - Specifies the message ID for the error.
  90. Return Value:
  91. None.
  92. --*/
  93. {
  94. PCTSTR FixupPhone;
  95. PCTSTR FixupUrl;
  96. PCTSTR FixupInstructions;
  97. PCTSTR LineBreak = S_EMPTY;
  98. PCTSTR ArgArray[1];
  99. //
  100. // Generate fixup strings
  101. //
  102. if (g_VendorInfo.SupportNumber[0]) {
  103. ArgArray[0] = g_VendorInfo.SupportNumber;
  104. FixupPhone = ParseMessageID (MSG_MIGDLL_SUPPORT_PHONE_FIXUP, ArgArray);
  105. LineBreak = TEXT("\n");
  106. } else {
  107. FixupPhone = S_EMPTY;
  108. }
  109. if (g_VendorInfo.SupportUrl[0]) {
  110. ArgArray[0] = g_VendorInfo.SupportUrl;
  111. FixupUrl = ParseMessageID (MSG_MIGDLL_SUPPORT_URL_FIXUP, ArgArray);
  112. LineBreak = TEXT("\n");
  113. } else {
  114. FixupUrl = S_EMPTY;
  115. }
  116. if (g_VendorInfo.InstructionsToUser[0]) {
  117. ArgArray[0] = g_VendorInfo.InstructionsToUser;
  118. FixupInstructions = ParseMessageID (MSG_MIGDLL_INSTRUCTIONS_FIXUP, ArgArray);
  119. LineBreak = TEXT("\n");
  120. } else {
  121. FixupInstructions = S_EMPTY;
  122. }
  123. //
  124. // Display popup and log the error
  125. //
  126. LOG ((
  127. LOG_ERROR,
  128. (PCSTR) MessageId,
  129. g_DllDesc,
  130. g_VendorInfo.CompanyName,
  131. FixupPhone,
  132. FixupUrl,
  133. FixupInstructions,
  134. LineBreak
  135. ));
  136. }
  137. VOID
  138. pSetCwd (
  139. OUT PTSTR SavedWorkDir,
  140. IN PCTSTR NewWorkDir
  141. )
  142. {
  143. GetCurrentDirectory (MAX_TCHAR_PATH, SavedWorkDir);
  144. SetCurrentDirectory (NewWorkDir);
  145. }
  146. BOOL
  147. pCreateEnvironment (
  148. PVOID *BlockPtr
  149. )
  150. {
  151. return CreateEnvironmentBlock (BlockPtr, NULL, FALSE);
  152. }
  153. VOID
  154. pSetEnvironmentBlock (
  155. PVOID Block
  156. )
  157. {
  158. DEBUGMSG ((DBG_VERBOSE, "Block: %s", Block));
  159. }
  160. DWORD
  161. ProcessMigrationDLLs (
  162. DWORD Request
  163. )
  164. {
  165. MEMDB_ENUM e;
  166. DWORD rc;
  167. DWORD Ticks = 0;
  168. if (Request == REQUEST_QUERYTICKS) {
  169. if (MemDbEnumItems (&e, MEMDB_CATEGORY_MIGRATION_DLL)) {
  170. do {
  171. Ticks += TICKS_MIGRATION_DLL;
  172. } while (MemDbEnumNextValue (&e));
  173. }
  174. return Ticks;
  175. }
  176. #ifdef PRERELEASE
  177. if (g_ConfigOptions.DiffMode) {
  178. TakeSnapShot();
  179. }
  180. #endif
  181. if (MemDbEnumItems (&e, MEMDB_CATEGORY_MIGRATION_DLL)) {
  182. do {
  183. //
  184. // Retrieve DLL location and settings
  185. //
  186. // Obtain the DLL name and working directory
  187. if (!MemDbGetEndpointValueEx (
  188. MEMDB_CATEGORY_MIGRATION_DLL,
  189. e.szName,
  190. MEMDB_FIELD_DLL,
  191. g_DllPath)
  192. ) {
  193. LOG ((LOG_ERROR, "DLL path for %s is not listed in memdb; DLL not processed", e.szName));
  194. continue; // not expected
  195. }
  196. // Obtain the working directory
  197. if (!MemDbGetEndpointValueEx (
  198. MEMDB_CATEGORY_MIGRATION_DLL,
  199. e.szName,
  200. MEMDB_FIELD_WD,
  201. g_WorkingDir)
  202. ) {
  203. LOG ((LOG_ERROR, "Working Directory for %s is not listed in memdb; DLL not processed", e.szName));
  204. continue; // not expected
  205. }
  206. // Obtain a description
  207. if (!MemDbGetEndpointValueEx (
  208. MEMDB_CATEGORY_MIGRATION_DLL,
  209. e.szName,
  210. MEMDB_FIELD_DESC,
  211. g_DllDesc
  212. )) {
  213. StringCopy (g_DllDesc, GetString (MSG_DEFAULT_MIGDLL_DESC));
  214. }
  215. ZeroMemory (&g_VendorInfo, sizeof (g_VendorInfo));
  216. MemDbGetEndpointValueEx (
  217. MEMDB_CATEGORY_MIGRATION_DLL,
  218. e.szName,
  219. MEMDB_FIELD_COMPANY_NAME,
  220. g_VendorInfo.CompanyName
  221. );
  222. MemDbGetEndpointValueEx (
  223. MEMDB_CATEGORY_MIGRATION_DLL,
  224. e.szName,
  225. MEMDB_FIELD_SUPPORT_PHONE,
  226. g_VendorInfo.SupportNumber
  227. );
  228. MemDbGetEndpointValueEx (
  229. MEMDB_CATEGORY_MIGRATION_DLL,
  230. e.szName,
  231. MEMDB_FIELD_SUPPORT_URL,
  232. g_VendorInfo.SupportUrl
  233. );
  234. MemDbGetEndpointValueEx (
  235. MEMDB_CATEGORY_MIGRATION_DLL,
  236. e.szName,
  237. MEMDB_FIELD_SUPPORT_INSTRUCTIONS,
  238. g_VendorInfo.InstructionsToUser
  239. );
  240. //
  241. // Establish connection with migisol.exe
  242. //
  243. if (!pConnectToDll()) {
  244. continue;
  245. }
  246. //
  247. // Tell migisol.exe to load migration DLL and call NT functions
  248. //
  249. rc = pRunMigrationDll();
  250. //
  251. // If not success, return a setup failure
  252. //
  253. if (rc != ERROR_SUCCESS) {
  254. SetLastError (rc);
  255. pLogDllFailure (g_ParentWnd, MSG_MIGDLL_ERROR);
  256. }
  257. //
  258. // Disconnect from migisol.exe and kill the potentially
  259. // stalled process
  260. //
  261. pDisconnectFromDll();
  262. TickProgressBarDelta (TICKS_MIGRATION_DLL);
  263. } while (MemDbEnumNextValue (&e));
  264. } /* if */
  265. #ifdef PRERELEASE
  266. if (g_ConfigOptions.DiffMode) {
  267. CHAR szMigdllDifPath[] = "c:\\migdll.dif";
  268. if (ISPC98()) {
  269. szMigdllDifPath[0] = (CHAR)g_System32Dir[0];
  270. }
  271. GenerateDiffOutputA (szMigdllDifPath, NULL, TRUE);
  272. }
  273. #endif
  274. return ERROR_SUCCESS;
  275. } /* ProcessMigrationDLLs */
  276. BOOL
  277. pConnectToDll (
  278. VOID
  279. )
  280. {
  281. BOOL b = TRUE;
  282. TCHAR MigIsolPath[MAX_TCHAR_PATH];
  283. g_AliveEvent = CreateEvent (NULL, FALSE, FALSE, TEXT("MigDllAlive"));
  284. DEBUGMSG_IF ((!g_AliveEvent, DBG_WHOOPS, "Could not create MigDllAlive event"));
  285. if (!g_ConfigOptions.TestDlls) {
  286. //
  287. // Establish IPC connection
  288. //
  289. wsprintf (MigIsolPath, TEXT("%s\\%s"), g_System32Dir, S_MIGISOL_EXE);
  290. b = OpenIpc (FALSE, MigIsolPath, g_DllPath, g_System32Dir);
  291. if (!b) {
  292. LOG ((LOG_WARNING, "Can't establish IPC connection for %s, wd=%s", g_DllPath, g_System32Dir));
  293. pLogDllFailure (g_ParentWnd, MSG_CREATE_PROCESS_ERROR);
  294. }
  295. } else {
  296. g_hLibrary = LoadLibrary (g_DllPath);
  297. // If it fails, assume the DLL does not want to be loaded
  298. if (!g_hLibrary) {
  299. LOG ((LOG_ERROR, "Cannot load %s", g_DllPath));
  300. return FALSE;
  301. }
  302. // Get proc addresses for NT-side functions
  303. InitializeNT = (P_INITIALIZE_NT) GetProcAddress (g_hLibrary, PLUGIN_INITIALIZE_NT);
  304. MigrateUserNT = (P_MIGRATE_USER_NT) GetProcAddress (g_hLibrary, PLUGIN_MIGRATE_USER_NT);
  305. MigrateSystemNT = (P_MIGRATE_SYSTEM_NT) GetProcAddress (g_hLibrary, PLUGIN_MIGRATE_SYSTEM_NT);
  306. if (!InitializeNT || !MigrateUserNT || !MigrateSystemNT) {
  307. b = FALSE;
  308. }
  309. }
  310. return b;
  311. }
  312. VOID
  313. pDisconnectFromDll (
  314. VOID
  315. )
  316. {
  317. if (g_AliveEvent) {
  318. CloseHandle (g_AliveEvent);
  319. g_AliveEvent = NULL;
  320. }
  321. if (!g_ConfigOptions.TestDlls) {
  322. CloseIpc();
  323. }
  324. else {
  325. if (g_hLibrary) {
  326. FreeLibrary (g_hLibrary);
  327. g_hLibrary = NULL;
  328. }
  329. }
  330. }
  331. BOOL
  332. pGetUserFromIndex (
  333. DWORD Index
  334. )
  335. {
  336. USERPOSITION up;
  337. DWORD rc;
  338. g_UserOnWin9x[0] = 0;
  339. if (Index == INDEX_DEFAULT_USER) {
  340. StringCopy (g_FixedUser, g_DefaultUserName);
  341. } else if (Index == INDEX_LOGON_PROMPT) {
  342. StringCopy (g_FixedUser, S_DOT_DEFAULT);
  343. } else if (Index == INDEX_ADMINISTRATOR) {
  344. StringCopy (g_FixedUser, g_AdministratorStr);
  345. } else {
  346. rc = Win95RegGetFirstUser (&up, g_FixedUser);
  347. if (rc != ERROR_SUCCESS) {
  348. LOG ((LOG_ERROR, "Get User From Index: Win95RegGetFirstUser failed"));
  349. return FALSE;
  350. }
  351. for (Index -= INDEX_MAX ; Win95RegHaveUser(&up) && Index > 0 ; Index--) {
  352. Win95RegGetNextUser (&up, g_FixedUser);
  353. }
  354. if (!Win95RegHaveUser(&up)) {
  355. return FALSE;
  356. }
  357. StringCopy (g_UserOnWin9x, g_FixedUser);
  358. GetFixedUserName (g_FixedUser);
  359. }
  360. if (!g_UserOnWin9x[0]) {
  361. StringCopy (g_UserOnWin9x, g_FixedUser);
  362. }
  363. return TRUE;
  364. }
  365. DWORD
  366. pRunMigrationDll (
  367. VOID
  368. )
  369. {
  370. DWORD rc;
  371. BOOL AbortThisDll;
  372. BOOL UnloadRegKey;
  373. TCHAR UnattendFile[MAX_TCHAR_PATH];
  374. TCHAR RootKey[MAX_REGISTRY_KEY];
  375. TCHAR HiveFile[MAX_TCHAR_PATH];
  376. DWORD Index;
  377. BOOL IsLogonPromptAccount;
  378. PCTSTR SourceDirArray[2];
  379. PCTSTR I386SourceDir;
  380. PCTSTR p;
  381. TCHAR Domain[MAX_USER_NAME];
  382. BOOL Env;
  383. PVOID Block;
  384. HKEY NewHkcu;
  385. LONG MapResult;
  386. //
  387. // Initialize unattend file and root key
  388. //
  389. wsprintf (UnattendFile, TEXT("%s\\system32\\$winnt$.inf"), g_WinDir);
  390. //
  391. // Call InitializeNT
  392. //
  393. if (ISPC98()) {
  394. I386SourceDir = JoinPaths (g_SourceDir, TEXT("NEC98"));
  395. } else {
  396. I386SourceDir = JoinPaths (g_SourceDir, TEXT("I386"));
  397. }
  398. if (!I386SourceDir) {
  399. return GetLastError();
  400. }
  401. SourceDirArray[0] = I386SourceDir;
  402. SourceDirArray[1] = NULL;
  403. rc = pCallInitializeNt (g_WorkingDir, SourceDirArray, NULL, 0);
  404. if (rc != ERROR_SUCCESS) {
  405. return rc;
  406. }
  407. FreePathString (I386SourceDir);
  408. //
  409. // The user loop
  410. //
  411. // For each user, call DLL's MigrateUser function
  412. AbortThisDll = FALSE;
  413. Index = 0;
  414. while (!AbortThisDll) {
  415. if (Index == INDEX_LOGON_PROMPT) {
  416. wsprintf (RootKey, TEXT("HKU\\%s"), S_DOT_DEFAULT);
  417. IsLogonPromptAccount = TRUE;
  418. } else {
  419. wsprintf (RootKey, TEXT("HKU\\%s"), S_TEMP_USER_KEY);
  420. IsLogonPromptAccount = FALSE;
  421. }
  422. if (!pGetUserFromIndex (Index)) {
  423. break;
  424. }
  425. Index++;
  426. //
  427. // If the following lookup fails, it is because the user isn't supposed to
  428. // migrate, or migration failed.
  429. //
  430. if (!IsLogonPromptAccount) {
  431. if (-1 == pSetupStringTableLookUpStringEx (
  432. g_HiveTable,
  433. g_FixedUser,
  434. STRTAB_CASE_INSENSITIVE,
  435. HiveFile,
  436. sizeof (HiveFile)
  437. )
  438. ) {
  439. DEBUGMSG ((
  440. DBG_VERBOSE,
  441. "pRunMigrationDll: pSetupStringTableLookUpStringEx could not find name of hive for user %s",
  442. g_FixedUser
  443. ));
  444. continue;
  445. }
  446. }
  447. //
  448. // Load NT user hive
  449. //
  450. UnloadRegKey = FALSE;
  451. Env = FALSE;
  452. NewHkcu = NULL;
  453. MapResult = 0;
  454. if (!AbortThisDll) {
  455. // Don't load .default
  456. if (!IsLogonPromptAccount) {
  457. rc = RegUnLoadKey (HKEY_USERS, S_TEMP_USER_KEY);
  458. if (rc != ERROR_SUCCESS) {
  459. DumpOpenKeys ();
  460. SetLastError (rc);
  461. DEBUGMSG_IF ((rc != ERROR_INVALID_PARAMETER, DBG_ERROR, "Error unloading regkey!"));
  462. }
  463. rc = RegLoadKey (HKEY_USERS, S_TEMP_USER_KEY, HiveFile);
  464. if (rc != ERROR_SUCCESS) {
  465. SetLastError(rc);
  466. LOG ((
  467. LOG_ERROR,
  468. "Run Migration Dll: RegLoadKey could not load user hive for %s (%s)",
  469. g_FixedUser,
  470. HiveFile
  471. ));
  472. AbortThisDll = TRUE;
  473. } else {
  474. UnloadRegKey = TRUE;
  475. }
  476. }
  477. }
  478. if (!AbortThisDll) {
  479. NewHkcu = OpenRegKeyStr (RootKey);
  480. if (NewHkcu) {
  481. MapResult = RegOverridePredefKey (HKEY_CURRENT_USER, NewHkcu);
  482. if (MapResult != ERROR_SUCCESS) {
  483. LOG ((LOG_ERROR, "Can't override HKCU"));
  484. }
  485. }
  486. Env = pCreateEnvironment (&Block);
  487. if (Env) {
  488. pSetEnvironmentBlock (&Block);
  489. DestroyEnvironmentBlock (&Block);
  490. }
  491. }
  492. // Call loaded DLL's MigrateUser function
  493. if (!AbortThisDll) {
  494. if (g_DomainUserName) {
  495. p = _tcschr (g_DomainUserName, TEXT('\\'));
  496. } else {
  497. p = NULL;
  498. }
  499. if (p) {
  500. StringCopyAB (Domain, g_DomainUserName, p);
  501. } else {
  502. Domain[0] = 0;
  503. }
  504. rc = pCallMigrateUserNt (
  505. g_WorkingDir,
  506. UnattendFile,
  507. RootKey,
  508. IsLogonPromptAccount ? TEXT("") : g_UserOnWin9x,
  509. Domain,
  510. IsLogonPromptAccount ? TEXT("") : g_FixedUser,
  511. NULL,
  512. 0
  513. );
  514. if (rc != ERROR_SUCCESS) {
  515. AbortThisDll = TRUE;
  516. }
  517. }
  518. // Restore predefined key
  519. if (NewHkcu && MapResult == ERROR_SUCCESS) {
  520. MapResult = RegOverridePredefKey (HKEY_CURRENT_USER, NULL);
  521. if (MapResult != ERROR_SUCCESS) {
  522. LOG ((LOG_ERROR, "Can't restore HKCU"));
  523. }
  524. CloseRegKey (NewHkcu);
  525. }
  526. // Unload temporary key
  527. if (UnloadRegKey) {
  528. UnloadRegKey = FALSE;
  529. rc = RegUnLoadKey (HKEY_USERS, S_TEMP_USER_KEY);
  530. if (rc != ERROR_SUCCESS) {
  531. DumpOpenKeys ();
  532. SetLastError (rc);
  533. DEBUGMSG_IF ((rc != ERROR_INVALID_PARAMETER, DBG_ERROR, "Error unloading regkey (second case)!"));
  534. }
  535. }
  536. } /* while */
  537. //
  538. // System processing
  539. //
  540. Env = pCreateEnvironment (&Block);
  541. if (Env) {
  542. pSetEnvironmentBlock (&Block);
  543. DestroyEnvironmentBlock (&Block);
  544. }
  545. // Call MigrateSystemNT
  546. if (!AbortThisDll) {
  547. rc = pCallMigrateSystemNt (
  548. g_WorkingDir,
  549. UnattendFile,
  550. NULL,
  551. 0
  552. );
  553. if (rc != ERROR_SUCCESS) {
  554. AbortThisDll = TRUE;
  555. }
  556. }
  557. return rc;
  558. }
  559. DWORD
  560. pFinishHandshake (
  561. IN PCTSTR FunctionName
  562. )
  563. {
  564. DWORD TechnicalLogId;
  565. DWORD GuiLogId;
  566. DWORD rc = ERROR_SUCCESS;
  567. BOOL b;
  568. UINT Count = 40; // about 5 minutes
  569. UINT AliveAllowance = 10; // about 30 minutes
  570. do {
  571. //
  572. // No OUT parameters on the NT side, so we don't care
  573. // about the return data
  574. //
  575. b = GetIpcCommandResults (
  576. IPC_GET_RESULTS_NT,
  577. NULL,
  578. NULL,
  579. &rc,
  580. &TechnicalLogId,
  581. &GuiLogId
  582. );
  583. //
  584. // If error code is returned, stuff it in setupact.log
  585. //
  586. if (b && rc != ERROR_SUCCESS) {
  587. LOG ((
  588. LOG_WARNING,
  589. "Migration DLL %s returned %u (0x%08X) in %s",
  590. g_DllDesc,
  591. rc,
  592. rc,
  593. FunctionName
  594. ));
  595. }
  596. //
  597. // Loop if no data received, but process is alive
  598. //
  599. if (!b) {
  600. if (!IsIpcProcessAlive()) {
  601. rc = ERROR_NOACCESS;
  602. break;
  603. }
  604. // continue if command was not sent yet but exe is still OK
  605. Count--;
  606. if (Count == 0) {
  607. if (WaitForSingleObject (g_AliveEvent, 0) == WAIT_OBJECT_0) {
  608. DEBUGMSG ((DBG_WARNING, "Alive allowance given to migration DLL"));
  609. AliveAllowance--;
  610. if (AliveAllowance) {
  611. Count = 24; // about 3 minutes
  612. }
  613. }
  614. if (Count == 0) {
  615. rc = ERROR_SEM_TIMEOUT;
  616. break;
  617. }
  618. }
  619. }
  620. } while (!b);
  621. if (b) {
  622. //
  623. // Recognize log messages
  624. //
  625. if (TechnicalLogId) {
  626. //
  627. // LOG message with three args: DllDesc, DllPath, User
  628. //
  629. LOG ((
  630. LOG_ERROR,
  631. (PCSTR) TechnicalLogId,
  632. g_DllDesc,
  633. g_DllPath,
  634. g_FixedUser
  635. ));
  636. }
  637. if (GuiLogId) {
  638. LOG ((
  639. LOG_ERROR,
  640. (PCSTR) GuiLogId,
  641. g_DllDesc,
  642. g_DllPath,
  643. g_FixedUser
  644. ));
  645. }
  646. }
  647. return rc;
  648. }
  649. DWORD
  650. pCallInitializeNt (
  651. IN PCTSTR WorkingDir,
  652. IN PCTSTR *SourceDirArray,
  653. IN PVOID Reserved,
  654. IN DWORD ReservedBytes
  655. )
  656. {
  657. DWORD rc = ERROR_SUCCESS;
  658. GROWBUFFER GrowBuf = GROWBUF_INIT;
  659. INT Count;
  660. PBYTE BufPtr;
  661. PDWORD ReservedBytesPtr;
  662. TCHAR SavedCwd [MAX_TCHAR_PATH];
  663. if (!g_ConfigOptions.TestDlls) {
  664. __try {
  665. MultiSzAppend (&GrowBuf, WorkingDir);
  666. //
  667. // Prepare multi-sz directory list
  668. //
  669. for (Count = 0 ; SourceDirArray[Count] ; Count++) {
  670. MultiSzAppend (&GrowBuf, SourceDirArray[Count]);
  671. }
  672. MultiSzAppend (&GrowBuf, S_EMPTY);
  673. ReservedBytesPtr = (PDWORD) GrowBuffer (&GrowBuf, sizeof (ReservedBytes));
  674. *ReservedBytesPtr = ReservedBytes;
  675. if (ReservedBytes) {
  676. BufPtr = GrowBuffer (&GrowBuf, ReservedBytes);
  677. CopyMemory (BufPtr, Reserved, ReservedBytes);
  678. }
  679. if (!SendIpcCommand (
  680. IPC_INITIALIZE,
  681. GrowBuf.Buf,
  682. GrowBuf.End
  683. )) {
  684. LOG ((LOG_ERROR, "Call InitializeNT failed to send command"));
  685. rc = GetLastError();
  686. __leave;
  687. }
  688. rc = pFinishHandshake (TEXT("InitializeNT"));
  689. if (rc != ERROR_SUCCESS) {
  690. LOG ((
  691. LOG_ERROR,
  692. "Call InitializeNT failed to complete handshake, rc=%u",
  693. rc
  694. ));
  695. }
  696. }
  697. __finally {
  698. FreeGrowBuffer (&GrowBuf);
  699. }
  700. }
  701. else {
  702. pSetCwd (
  703. SavedCwd, // old
  704. WorkingDir // new
  705. );
  706. __try {
  707. //
  708. // Prepare multi-sz directory list
  709. //
  710. for (Count = 0 ; SourceDirArray[Count] ; Count++) {
  711. MultiSzAppend (&GrowBuf, SourceDirArray[Count]);
  712. }
  713. MultiSzAppend (&GrowBuf, S_EMPTY);
  714. rc = InitializeNT (WorkingDir, (PCTSTR) GrowBuf.Buf, Reserved);
  715. FreeGrowBuffer (&GrowBuf);
  716. }
  717. __finally {
  718. SetCurrentDirectory (SavedCwd);
  719. }
  720. }
  721. return rc;
  722. }
  723. DWORD
  724. pCallMigrateUserNt (
  725. IN PCTSTR WorkingDir,
  726. IN PCTSTR UnattendFile,
  727. IN PCTSTR RootKey,
  728. IN PCTSTR Win9xUserName,
  729. IN PCTSTR UserDomain,
  730. IN PCTSTR FixedUserName,
  731. IN PVOID Reserved,
  732. IN DWORD ReservedBytes
  733. )
  734. {
  735. DWORD rc = ERROR_SUCCESS;
  736. GROWBUFFER GrowBuf = GROWBUF_INIT;
  737. PDWORD ReservedBytesPtr;
  738. PVOID BufPtr;
  739. TCHAR SavedCwd [MAX_TCHAR_PATH];
  740. TCHAR UserBuf[MAX_USER_NAME * 3];
  741. PTSTR p;
  742. TCHAR OrgUserProfilePath[MAX_TCHAR_PATH];
  743. TCHAR UserProfilePath[MAX_TCHAR_PATH];
  744. if (FixedUserName[0]) {
  745. GetUserProfilePath (FixedUserName, &p);
  746. StackStringCopy (UserProfilePath, p);
  747. FreePathString (p);
  748. DEBUGMSG ((DBG_VERBOSE, "Profile path for %s is %s", FixedUserName, UserProfilePath));
  749. } else {
  750. UserProfilePath[0] = 0;
  751. }
  752. GetEnvironmentVariable (S_USERPROFILE, OrgUserProfilePath, MAX_TCHAR_PATH);
  753. SetEnvironmentVariable (S_USERPROFILE, UserProfilePath);
  754. if (!g_ConfigOptions.TestDlls) {
  755. __try {
  756. MultiSzAppend (&GrowBuf, UnattendFile);
  757. MultiSzAppend (&GrowBuf, RootKey);
  758. MultiSzAppend (&GrowBuf, Win9xUserName);
  759. MultiSzAppend (&GrowBuf, UserDomain);
  760. MultiSzAppend (&GrowBuf, FixedUserName);
  761. MultiSzAppend (&GrowBuf, UserProfilePath);
  762. ReservedBytesPtr = (PDWORD) GrowBuffer (&GrowBuf, sizeof (ReservedBytes));
  763. *ReservedBytesPtr = ReservedBytes;
  764. if (ReservedBytes) {
  765. BufPtr = GrowBuffer (&GrowBuf, ReservedBytes);
  766. CopyMemory (BufPtr, Reserved, ReservedBytes);
  767. }
  768. if (!SendIpcCommand (
  769. IPC_MIGRATEUSER,
  770. GrowBuf.Buf,
  771. GrowBuf.End
  772. )) {
  773. LOG ((LOG_ERROR, "Call MigrateUserNT failed to send command"));
  774. rc = GetLastError();
  775. __leave;
  776. }
  777. rc = pFinishHandshake (TEXT("MigrateUserNT"));
  778. if (rc != ERROR_SUCCESS) {
  779. LOG ((
  780. LOG_ERROR,
  781. "Call MigrateUserNT failed to complete handshake, rc=%u",
  782. rc
  783. ));
  784. }
  785. }
  786. __finally {
  787. FreeGrowBuffer (&GrowBuf);
  788. }
  789. } else {
  790. pSetCwd (
  791. SavedCwd, // old
  792. WorkingDir // new
  793. );
  794. __try {
  795. HINF UnattendHandle;
  796. HKEY UserRegHandle;
  797. UnattendHandle = InfOpenInfFile (UnattendFile);
  798. if (UnattendHandle == INVALID_HANDLE_VALUE) {
  799. __leave;
  800. }
  801. UserRegHandle = OpenRegKeyStr (RootKey);
  802. if (!UserRegHandle) {
  803. rc = GetLastError();
  804. InfCloseInfFile (UnattendHandle);
  805. __leave;
  806. }
  807. //
  808. // Transfer user, user domain and fixed name to a buffer
  809. //
  810. if (Win9xUserName) {
  811. StringCopy (UserBuf, Win9xUserName);
  812. } else {
  813. UserBuf[0] = 0;
  814. }
  815. p = GetEndOfString (UserBuf) + 1;
  816. if (UserDomain) {
  817. StringCopy (p, UserDomain);
  818. } else {
  819. p[0] = 0;
  820. }
  821. p = GetEndOfString (p) + 1;
  822. if (UserDomain) {
  823. StringCopy (p, FixedUserName);
  824. } else {
  825. p[0] = 0;
  826. }
  827. //
  828. // Call the entry point
  829. //
  830. rc = MigrateUserNT (
  831. UnattendHandle,
  832. UserRegHandle,
  833. UserBuf[0] ? UserBuf : NULL,
  834. Reserved
  835. );
  836. CloseRegKey (UserRegHandle);
  837. InfCloseInfFile (UnattendHandle);
  838. }
  839. __finally {
  840. SetCurrentDirectory (SavedCwd);
  841. }
  842. }
  843. SetEnvironmentVariable (S_USERPROFILE, OrgUserProfilePath);
  844. return rc;
  845. }
  846. DWORD
  847. pCallMigrateSystemNt (
  848. IN PCTSTR WorkingDir,
  849. IN PCTSTR UnattendFile,
  850. IN PVOID Reserved,
  851. IN DWORD ReservedBytes
  852. )
  853. {
  854. DWORD rc = ERROR_SUCCESS;
  855. GROWBUFFER GrowBuf = GROWBUF_INIT;
  856. PDWORD ReservedBytesPtr;
  857. PVOID BufPtr;
  858. TCHAR SavedCwd [MAX_TCHAR_PATH];
  859. if (!g_ConfigOptions.TestDlls) {
  860. __try {
  861. MultiSzAppend (&GrowBuf, UnattendFile);
  862. ReservedBytesPtr = (PDWORD) GrowBuffer (&GrowBuf, sizeof (ReservedBytes));
  863. *ReservedBytesPtr = ReservedBytes;
  864. if (ReservedBytes) {
  865. BufPtr = GrowBuffer (&GrowBuf, ReservedBytes);
  866. CopyMemory (BufPtr, Reserved, ReservedBytes);
  867. }
  868. if (!SendIpcCommand (IPC_MIGRATESYSTEM, GrowBuf.Buf, GrowBuf.End)) {
  869. LOG ((LOG_ERROR, "Call MigrateSystemNT failed to send command"));
  870. rc = GetLastError();
  871. __leave;
  872. }
  873. rc = pFinishHandshake (TEXT("MigrateSystemNT"));
  874. if (rc != ERROR_SUCCESS) {
  875. LOG ((
  876. LOG_ERROR,
  877. "Call MigrateSystemNT failed to complete handshake, rc=%u",
  878. rc
  879. ));
  880. }
  881. }
  882. __finally {
  883. FreeGrowBuffer (&GrowBuf);
  884. }
  885. }
  886. else {
  887. pSetCwd (
  888. SavedCwd, // old
  889. WorkingDir // new
  890. );
  891. __try {
  892. HINF UnattendHandle;
  893. UnattendHandle = InfOpenInfFile (UnattendFile);
  894. if (UnattendHandle == INVALID_HANDLE_VALUE) {
  895. rc = GetLastError();
  896. __leave;
  897. }
  898. rc = MigrateSystemNT (UnattendHandle, Reserved);
  899. InfCloseInfFile (UnattendHandle);
  900. }
  901. __finally {
  902. SetCurrentDirectory (SavedCwd);
  903. }
  904. }
  905. return rc;
  906. }