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.

1391 lines
40 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. loadstate.c
  5. Abstract:
  6. <abstract>
  7. Author:
  8. <full name> (<alias>) <date>
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "ism.h"
  17. #include "modules.h"
  18. #include "trans.h"
  19. #include <tlhelp32.h>
  20. #include <shlobjp.h>
  21. #ifdef DEBUG
  22. #include <shellapi.h>
  23. #endif
  24. #include "logmsg.h"
  25. #include "common.h"
  26. #define DBG_LOADSTATE "LoadState"
  27. //
  28. // Strings
  29. //
  30. // None
  31. //
  32. // Constants
  33. //
  34. #define LOG_VERBOSE_BIT 0x01
  35. #define LOG_UNUSED_BIT 0x02 // for v1 compatibility, do not use
  36. #define LOG_STATUS_BIT 0x04
  37. #define LOG_DEBUGGER_BIT 0x08
  38. #define LOG_UPDATE_BIT 0x10
  39. #define LOADSTATE_LOAD 0x00000001
  40. #define LOADSTATE_EXECUTE 0x00000002
  41. #define LOADSTATE_COMPLETED 0x00000003
  42. #define RETURN_SUCCESS 0
  43. #define RETURN_FATAL_ERROR 1
  44. #define RETURN_ERROR 2
  45. #define RETURN_IGNORED_ERROR 3
  46. //
  47. // Macros
  48. //
  49. // None
  50. //
  51. // Types
  52. //
  53. typedef struct
  54. {
  55. UINT cbSize;
  56. SHELLSTATE ss;
  57. } REGSHELLSTATE, *PREGSHELLSTATE;
  58. //
  59. // Globals
  60. //
  61. PTSTR g_Explorer = NULL;
  62. BOOL g_ContinueOnError = FALSE;
  63. DWORD g_ReturnCode = ERROR_SUCCESS;
  64. TCHAR g_JournalPath[MAX_PATH_PLUS_NUL];
  65. BOOL g_Break;
  66. #ifdef PRERELEASE
  67. HANDLE g_CallbackEvent;
  68. #endif
  69. //
  70. // Macro expansion list
  71. //
  72. #define REQUIRED_INFS \
  73. DEFMAC(OSFILES, TEXT("USMTDef.inf")) \
  74. //
  75. // Private function prototypes
  76. //
  77. MESSAGECALLBACK pSaveMsgCallback;
  78. PTSTR
  79. pGetShellFolderPath (
  80. IN INT Folder
  81. );
  82. //
  83. // Macro expansion definition
  84. //
  85. //
  86. // This is the structure used for handling required infs
  87. //
  88. typedef struct {
  89. PCTSTR InfId;
  90. PCTSTR InfName;
  91. } REQUIREDINF_STRUCT, *PREQUIREDINF_STRUCT;
  92. //
  93. // Declare a global array of required infs
  94. //
  95. #define DEFMAC(infid,infname) {TEXT(#infid),infname},
  96. static REQUIREDINF_STRUCT g_RequiredInfs[] = {
  97. REQUIRED_INFS
  98. {NULL, NULL}
  99. };
  100. #undef DEFMAC
  101. //
  102. // Code
  103. //
  104. VOID
  105. pCleanUpApp (
  106. VOID
  107. )
  108. {
  109. IsmTerminate();
  110. if (g_JournalPath[0]) {
  111. DeleteFile (g_JournalPath);
  112. g_JournalPath[0] = 0;
  113. }
  114. #ifdef PRERELEASE
  115. CloseHandle (g_CallbackEvent);
  116. #endif
  117. }
  118. BOOL
  119. WINAPI
  120. CtrlCRoutine (
  121. IN DWORD ControlSignal
  122. )
  123. {
  124. PrintMsgOnConsole (MSG_EXITING);
  125. LOG ((LOG_WARNING, (PCSTR) MSG_TOOL_STOPPED));
  126. g_Break = TRUE;
  127. IsmSetCancel();
  128. while (IsmCurrentlyExecuting()) {
  129. Sleep (1000);
  130. }
  131. pCleanUpApp();
  132. printf ("\n");
  133. exit (1);
  134. }
  135. VOID
  136. pHelpAndExit (
  137. VOID
  138. )
  139. {
  140. PrintMsgOnConsole (MSG_HELP);
  141. #ifdef PRERELEASE
  142. printf ("\nAdditional PRERELEASE options:\n\n"
  143. "/tf Uses full transport instead of v1 transport\n"
  144. "/tc Enable compression\n"
  145. "/ta Enable automatic capability (for homenet transport)\n"
  146. "/ti:<tag> Specify an identity tag for the homenet transprot\n"
  147. " Default is user name\n"
  148. "/t:<name> Specifies transport to use\n"
  149. "/r Start in recovery mode\n"
  150. );
  151. #endif
  152. UtTerminate ();
  153. exit (1);
  154. }
  155. VOID
  156. pSwitchToClassicDesktop (
  157. IN PCTSTR Args
  158. )
  159. {
  160. HKEY key = NULL;
  161. TCHAR data[] = TEXT("0");
  162. //
  163. // The only thing that we need to do is to turn off:
  164. // HKCU\Software\Microsoft\Windows\CurrentVersion\ThemeManager [ThemeActive]
  165. //
  166. key = OpenRegKeyStr (TEXT("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager"));
  167. if (key) {
  168. RegSetValueEx (
  169. key,
  170. TEXT("ThemeActive"),
  171. 0,
  172. REG_SZ,
  173. (PBYTE)data,
  174. sizeof (data)
  175. );
  176. CloseRegKey (key);
  177. }
  178. }
  179. VOID
  180. pSwitchToClassicTaskBar (
  181. IN PCTSTR Args
  182. )
  183. {
  184. HKEY key = NULL;
  185. DWORD dataType;
  186. DWORD dataSize = 0;
  187. PBYTE data = NULL;
  188. PREGSHELLSTATE shellState = NULL;
  189. LONG result;
  190. //
  191. // The only thing that we need to do is to turn off the fStartPanelOn field in:
  192. // HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer [ShellState]
  193. //
  194. key = OpenRegKeyStr (TEXT("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"));
  195. if (key) {
  196. result = RegQueryValueEx (
  197. key,
  198. TEXT ("ShellState"),
  199. NULL,
  200. &dataType,
  201. NULL,
  202. &dataSize
  203. );
  204. if ((result == ERROR_SUCCESS) || (result == ERROR_MORE_DATA)) {
  205. data = MemAllocUninit (dataSize);
  206. if (data) {
  207. result = RegQueryValueEx (
  208. key,
  209. TEXT ("ShellState"),
  210. NULL,
  211. &dataType,
  212. data,
  213. &dataSize
  214. );
  215. if ((result == ERROR_SUCCESS) &&
  216. (dataType == REG_BINARY) &&
  217. (dataSize == sizeof (REGSHELLSTATE))
  218. ) {
  219. if (dataType == REG_BINARY) {
  220. shellState = (PREGSHELLSTATE) data;
  221. shellState->ss.fStartPanelOn = FALSE;
  222. RegSetValueEx (
  223. key,
  224. TEXT("ShellState"),
  225. 0,
  226. REG_BINARY,
  227. (PBYTE)data,
  228. dataSize
  229. );
  230. }
  231. }
  232. FreeAlloc (data);
  233. }
  234. }
  235. CloseRegKey (key);
  236. }
  237. }
  238. VOID
  239. pRegisterFonts (
  240. IN PCTSTR Args
  241. )
  242. {
  243. WIN32_FIND_DATA findData;
  244. HANDLE findHandle = INVALID_HANDLE_VALUE;
  245. PTSTR fontDir = NULL;
  246. TCHAR fontPattern [MAX_PATH];
  247. //
  248. // Let's (re)register all the fonts (in case the user migrated some new ones).
  249. //
  250. fontDir = pGetShellFolderPath (CSIDL_FONTS);
  251. if (fontDir) {
  252. StringCopyTcharCount (fontPattern, fontDir, ARRAYSIZE (fontPattern) - 4);
  253. StringCat (fontPattern, TEXT("\\*.*"));
  254. findHandle = FindFirstFile (fontPattern, &findData);
  255. if (findHandle != INVALID_HANDLE_VALUE) {
  256. do {
  257. AddFontResource (findData.cFileName);
  258. } while (FindNextFile (findHandle, &findData));
  259. FindClose (findHandle);
  260. }
  261. }
  262. }
  263. BOOL
  264. pLoadstateExecute (
  265. IN PCTSTR ExecuteArgs
  266. )
  267. {
  268. PCTSTR funcName = NULL;
  269. PCTSTR funcArgs = NULL;
  270. funcName = ExecuteArgs;
  271. if (!funcName || !(*funcName)) {
  272. return FALSE;
  273. }
  274. funcArgs = _tcschr (funcName, 0);
  275. if (funcArgs) {
  276. funcArgs ++;
  277. if (!(*funcArgs)) {
  278. funcArgs = NULL;
  279. }
  280. }
  281. // BUGBUG - temporary, make a macro expansion list out of it
  282. if (StringIMatch (funcName, TEXT("SwitchToClassicDesktop"))) {
  283. pSwitchToClassicDesktop (funcArgs);
  284. }
  285. if (StringIMatch (funcName, TEXT("SwitchToClassicTaskBar"))) {
  286. pSwitchToClassicTaskBar (funcArgs);
  287. }
  288. if (StringIMatch (funcName, TEXT("RegisterFonts"))) {
  289. pRegisterFonts (funcArgs);
  290. }
  291. return TRUE;
  292. }
  293. ULONG_PTR
  294. pSaveMsgCallback (
  295. UINT Message,
  296. ULONG_PTR Arg
  297. )
  298. {
  299. #ifdef PRERELEASE
  300. PRMEDIA_EXTRADATA extraData;
  301. #endif
  302. switch (Message) {
  303. #ifdef PRERELEASE
  304. case TRANSPORTMESSAGE_READY_TO_CONNECT:
  305. {
  306. TCHAR msg[512];
  307. wsprintf (msg, TEXT("Do you want to connect to %s?"), (PCTSTR) Arg);
  308. if (MessageBox (NULL, msg, TEXT("Question For You"), MB_YESNO|MB_SYSTEMMODAL) == IDYES) {
  309. SetEvent (g_CallbackEvent);
  310. return APPRESPONSE_SUCCESS;
  311. }
  312. return APPRESPONSE_FAIL;
  313. }
  314. case TRANSPORTMESSAGE_RMEDIA_LOAD:
  315. extraData = (PRMEDIA_EXTRADATA) Arg;
  316. if (!extraData) {
  317. return (MessageBox (
  318. NULL,
  319. TEXT("Please insert the next media in your drive."),
  320. TEXT("LoadState"),
  321. MB_OKCANCEL
  322. ) == IDOK);
  323. }
  324. if (extraData->MediaNumber == 1) {
  325. switch (extraData->LastError) {
  326. case RMEDIA_ERR_NOERROR:
  327. return TRUE;
  328. case RMEDIA_ERR_WRONGMEDIA:
  329. return (MessageBox (
  330. NULL,
  331. TEXT("You have inserted the wrong media.\n\nPlease insert the first media in your drive."),
  332. TEXT("LoadState"),
  333. MB_OKCANCEL
  334. ) == IDOK);
  335. case RMEDIA_ERR_DISKFULL:
  336. return (MessageBox (
  337. NULL,
  338. TEXT("The media you inserted does not have enough free space.\n\nPlease insert the first media in your drive."),
  339. TEXT("LoadState"),
  340. MB_OKCANCEL
  341. ) == IDOK);
  342. case RMEDIA_ERR_WRITEPROTECT:
  343. return (MessageBox (
  344. NULL,
  345. TEXT("The media you inserted is write protected.\n\nPlease insert the first media in your drive."),
  346. TEXT("LoadState"),
  347. MB_OKCANCEL
  348. ) == IDOK);
  349. case RMEDIA_ERR_NOTREADY:
  350. return (MessageBox (
  351. NULL,
  352. TEXT("The drive is not ready for use. Please check the drive and make sure that a disk is inserted and that the drive door is closed."),
  353. TEXT("LoadState"),
  354. MB_OKCANCEL
  355. ) == IDOK);
  356. case RMEDIA_ERR_CRITICAL:
  357. return FALSE;
  358. default:
  359. return (MessageBox (
  360. NULL,
  361. TEXT("Your media is toast.\n\nPlease insert the first media in your drive."),
  362. TEXT("LoadState"),
  363. MB_OKCANCEL
  364. ) == IDOK);
  365. }
  366. } else {
  367. switch (extraData->LastError) {
  368. case RMEDIA_ERR_NOERROR:
  369. return TRUE;
  370. case RMEDIA_ERR_WRONGMEDIA:
  371. return (MessageBox (
  372. NULL,
  373. TEXT("You have inserted the wrong media.\n\nPlease insert the next media in your drive."),
  374. TEXT("LoadState"),
  375. MB_OKCANCEL
  376. ) == IDOK);
  377. case RMEDIA_ERR_DISKFULL:
  378. return (MessageBox (
  379. NULL,
  380. TEXT("The media you inserted does not have enough free space.\n\nPlease insert the next media in your drive."),
  381. TEXT("LoadState"),
  382. MB_OKCANCEL
  383. ) == IDOK);
  384. case RMEDIA_ERR_WRITEPROTECT:
  385. return (MessageBox (
  386. NULL,
  387. TEXT("The media you inserted is write protected.\n\nPlease insert the next media in your drive."),
  388. TEXT("LoadState"),
  389. MB_OKCANCEL
  390. ) == IDOK);
  391. case RMEDIA_ERR_NOTREADY:
  392. return (MessageBox (
  393. NULL,
  394. TEXT("The drive is not ready for use. Please check the drive and make sure that a disk is inserted and that the drive door is closed."),
  395. TEXT("LoadState"),
  396. MB_OKCANCEL
  397. ) == IDOK);
  398. case RMEDIA_ERR_CRITICAL:
  399. return FALSE;
  400. default:
  401. return (MessageBox (
  402. NULL,
  403. TEXT("Your media is toast.\n\nPlease insert the next media in your drive."),
  404. TEXT("LoadState"),
  405. MB_OKCANCEL
  406. ) == IDOK);
  407. }
  408. }
  409. #endif
  410. case ISMMESSAGE_EXECUTE_REFRESH:
  411. pLoadstateExecute ((PCTSTR) Arg);
  412. return APPRESPONSE_SUCCESS;
  413. default:
  414. break;
  415. }
  416. return FALSE;
  417. }
  418. BOOL
  419. pIsUserAdmin (
  420. VOID
  421. )
  422. /*++
  423. Routine Description:
  424. This routine returns TRUE if the caller's process is a member of the
  425. Administrators local group.
  426. Caller is NOT expected to be impersonating anyone and IS expected to be
  427. able to open their own process and process token.
  428. Arguments:
  429. None.
  430. Return Value:
  431. TRUE - Caller has Administrators local group.
  432. FALSE - Caller does not have Administrators local group.
  433. --*/
  434. {
  435. HANDLE token;
  436. DWORD bytesRequired;
  437. PTOKEN_GROUPS groups;
  438. BOOL b;
  439. DWORD i;
  440. SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
  441. PSID administratorsGroup;
  442. if (ISWIN9X()) {
  443. return TRUE;
  444. }
  445. //
  446. // Open the process token.
  447. //
  448. if (!OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &token)) {
  449. return FALSE;
  450. }
  451. b = FALSE;
  452. groups = NULL;
  453. //
  454. // Get group information.
  455. //
  456. if (!GetTokenInformation (token, TokenGroups, NULL, 0, &bytesRequired) &&
  457. GetLastError() == ERROR_INSUFFICIENT_BUFFER
  458. ) {
  459. groups = (PTOKEN_GROUPS) MemAllocUninit (bytesRequired);
  460. b = GetTokenInformation (token, TokenGroups, groups, bytesRequired, &bytesRequired);
  461. }
  462. if (b) {
  463. b = AllocateAndInitializeSid (
  464. &ntAuthority,
  465. 2,
  466. SECURITY_BUILTIN_DOMAIN_RID,
  467. DOMAIN_ALIAS_RID_ADMINS,
  468. 0, 0, 0, 0, 0, 0,
  469. &administratorsGroup
  470. );
  471. if (b) {
  472. //
  473. // See if the user has the administrator group.
  474. //
  475. b = FALSE;
  476. for (i = 0 ; i < groups->GroupCount ; i++) {
  477. if (EqualSid (groups->Groups[i].Sid, administratorsGroup)) {
  478. b = TRUE;
  479. break;
  480. }
  481. }
  482. FreeSid (administratorsGroup);
  483. }
  484. }
  485. //
  486. // Clean up and return.
  487. //
  488. if (groups) {
  489. FreeAlloc (groups);
  490. }
  491. CloseHandle (token);
  492. return b;
  493. }
  494. VOID
  495. pMyLogCallback (
  496. IN PLOGARG LogArg
  497. )
  498. {
  499. if (LogArg->Debug) {
  500. DEBUGDIRECT (LogArg->Type, LogArg->FormattedMessage);
  501. } else {
  502. if (StringIMatchA (LogArg->Type, LOG_ERROR)) {
  503. if (g_ReturnCode == RETURN_SUCCESS) {
  504. g_ReturnCode = g_ContinueOnError?RETURN_IGNORED_ERROR:RETURN_ERROR;
  505. }
  506. if (g_ReturnCode == RETURN_IGNORED_ERROR) {
  507. g_ReturnCode = g_ContinueOnError?RETURN_IGNORED_ERROR:RETURN_ERROR;
  508. }
  509. } else if (StringIMatchA (LogArg->Type, LOG_MODULE_ERROR) ||
  510. StringIMatchA (LogArg->Type, LOG_FATAL_ERROR)) {
  511. g_ReturnCode = RETURN_FATAL_ERROR;
  512. }
  513. LOGDIRECT (LogArg->Type, LogArg->FormattedMessage);
  514. }
  515. }
  516. #ifdef DEBUG
  517. VOID
  518. pStopAndDisplayInfs (
  519. IN PGROWBUFFER InputInfs,
  520. IN BOOL Begin
  521. )
  522. {
  523. MULTISZ_ENUM infEnum;
  524. if (MessageBox (
  525. NULL,
  526. TEXT("LoadState stopped. Do you want to display all loaded INFs?"),
  527. Begin?TEXT("LoadState-Begin"):TEXT("LoadState-End"),
  528. MB_YESNO
  529. ) == IDYES) {
  530. //
  531. // now let's open append all INF files and pass the HINF to
  532. // everybody.
  533. //
  534. if (EnumFirstMultiSz (&infEnum, (PCTSTR)InputInfs->Buf)) {
  535. do {
  536. ShellExecute (NULL, TEXT("open"), infEnum.CurrentString, NULL, NULL, SW_SHOWNORMAL);
  537. } while (EnumNextMultiSz (&infEnum));
  538. }
  539. MessageBox (NULL, TEXT("Press OK to continue..."), TEXT("LoadState-Begin"), MB_OK);
  540. }
  541. }
  542. #endif
  543. BOOL
  544. pOpenOrAppendInfFile (
  545. IN HINF *InfHandle,
  546. IN PCTSTR Filename
  547. )
  548. {
  549. BOOL result = TRUE;
  550. if (*InfHandle == INVALID_HANDLE_VALUE) {
  551. *InfHandle = SetupOpenInfFile (Filename, NULL, INF_STYLE_WIN4 | INF_STYLE_OLDNT, NULL);
  552. if (*InfHandle == INVALID_HANDLE_VALUE) {
  553. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_FILE, Filename));
  554. result = FALSE;
  555. }
  556. } else {
  557. if (!SetupOpenAppendInfFile (Filename, *InfHandle, NULL)) {
  558. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_FILE, Filename));
  559. result = FALSE;
  560. }
  561. }
  562. return result;
  563. }
  564. PTSTR
  565. pGetShellFolderPath (
  566. IN INT Folder
  567. )
  568. {
  569. PTSTR result = NULL;
  570. HRESULT hResult;
  571. BOOL b;
  572. LPITEMIDLIST localpidl = NULL;
  573. IMalloc *mallocFn;
  574. hResult = SHGetMalloc (&mallocFn);
  575. if (hResult != S_OK) {
  576. return NULL;
  577. }
  578. hResult = SHGetSpecialFolderLocation (NULL, Folder, &localpidl);
  579. if (hResult == S_OK) {
  580. result = (PTSTR) LocalAlloc (LPTR, MAX_PATH);
  581. if (result) {
  582. b = SHGetPathFromIDList (localpidl, result);
  583. if (b) {
  584. return result;
  585. }
  586. LocalFree (result);
  587. }
  588. }
  589. if (localpidl) {
  590. mallocFn->lpVtbl->Free (mallocFn, localpidl);
  591. localpidl = NULL;
  592. }
  593. return result;
  594. }
  595. VOID
  596. __cdecl
  597. _tmain (
  598. IN INT Argc,
  599. IN PCTSTR Argv[]
  600. )
  601. {
  602. TCHAR appPath[MAX_PATH_PLUS_NUL];
  603. PCTSTR delayedCmd = NULL;
  604. TCHAR ismPath[MAX_PATH_PLUS_NUL];
  605. TCHAR infPath[MAX_PATH_PLUS_NUL];
  606. PTSTR iconLibRoot = NULL;
  607. TCHAR iconLibSrc[MAX_PATH] = TEXT("");
  608. TCHAR iconLibDest[MAX_PATH] = TEXT("");
  609. BOOL iconLibFound = FALSE;
  610. PCTSTR commandLine = NULL;
  611. DWORD err;
  612. PTSTR p;
  613. MIG_TRANSPORTID transportId;
  614. MIG_TRANSPORTSTORAGEID transportStorageId;
  615. MULTISZ_ENUM infEnum;
  616. HINF infHandle = INVALID_HANDLE_VALUE;
  617. ENVENTRY_STRUCT infHandleStruct;
  618. MIG_OBJECTSTRINGHANDLE objectPattern;
  619. MIG_OBJECT_ENUM objectEnum;
  620. MULTISZ_ENUM e;
  621. DWORD appStatus;
  622. BOOL loadResult;
  623. BOOL storagePathIsValid = FALSE;
  624. BOOL terminateIsm = FALSE;
  625. BOOL logEnabled = FALSE;
  626. PCTSTR msg;
  627. #ifdef UNICODE
  628. PCSTR ansimsg;
  629. #endif
  630. PCTSTR argArray[1];
  631. BOOL fail;
  632. TOOLARGS args;
  633. #ifdef PRERELEASE
  634. g_CallbackEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
  635. #endif
  636. SET_RESETLOG();
  637. UtInitialize (NULL);
  638. SuppressAllLogPopups (TRUE);
  639. // this part is for matching thread's locale to the console code page
  640. CallSetThreadUILanguage ();
  641. PrintMsgOnConsole (MSG_RUNNING);
  642. // initialize app journal path
  643. g_JournalPath [0] = 0;
  644. if (GetWindowsDirectory (g_JournalPath, ARRAYSIZE (g_JournalPath))) {
  645. StringCopy (AppendWack (g_JournalPath), TEXT("LOADSTATE.JRN"));
  646. }
  647. GetModuleFileName (NULL, appPath, ARRAYSIZE(appPath));
  648. delayedCmd = JoinText (appPath, TEXT(" /d"));
  649. p = _tcsrchr (appPath, TEXT('\\'));
  650. if (p) {
  651. *p = 0;
  652. }
  653. iconLibSrc [0] = 0;
  654. GetSystemDirectory (iconLibSrc, ARRAYSIZE(iconLibSrc));
  655. StringCopy (AppendWack (iconLibSrc), TEXT("usmt\\iconlib.dll"));
  656. //
  657. // Parse the command line
  658. //
  659. fail = TRUE;
  660. switch (ParseToolCmdLine (FALSE, &args, Argc, Argv)) {
  661. case PARSE_SUCCESS:
  662. fail = FALSE;
  663. break;
  664. case PARSE_MULTI_LOG:
  665. PrintMsgOnConsole (MSG_MULTI_LOG);
  666. g_ReturnCode = RETURN_FATAL_ERROR;
  667. goto END;
  668. case PARSE_BAD_LOG:
  669. argArray[0] = args.LogFile;
  670. msg = ParseMessageID (MSG_CANT_OPEN_LOG, argArray);
  671. if (msg) {
  672. #ifdef UNICODE
  673. ansimsg = ConvertWtoA (msg);
  674. printf ("%s", ansimsg);
  675. FreeConvertedStr (ansimsg);
  676. #else
  677. printf ("%s", msg);
  678. #endif
  679. FreeStringResource (msg);
  680. }
  681. g_ReturnCode = RETURN_FATAL_ERROR;
  682. goto END;
  683. default:
  684. break;
  685. }
  686. if (fail) {
  687. pHelpAndExit();
  688. }
  689. g_ContinueOnError = args.ContinueOnError;
  690. if (args.HackHiveOn) {
  691. // This is the second copy of loadstate.exe that's running.
  692. // We are going to wait for the first copy to finish and then
  693. // we are going to attempt to unload the user's hive.
  694. DWORD processId = 0;
  695. HANDLE processHandle = NULL;
  696. DWORD waitResult = 0;
  697. _stscanf (args.HackProcessId, TEXT("%lx"), &(processId));
  698. processHandle = OpenProcess (SYNCHRONIZE, TRUE, processId);
  699. if (processHandle) {
  700. waitResult = WaitForSingleObject (processHandle, INFINITE);
  701. // we don't really care about the result. We are going to
  702. // attempt to unload the hive anyway
  703. }
  704. // now let's try to unload the hive
  705. g_ReturnCode = RegUnLoadKey (HKEY_USERS, args.HackMappedHive);
  706. if (g_ReturnCode == ERROR_SUCCESS) {
  707. PrintMsgOnConsole (MSG_SUCCESS);
  708. } else {
  709. PrintMsgOnConsole (MSG_FAILED_NO_LOG);
  710. }
  711. UtTerminate ();
  712. while (g_Break) {
  713. // infinite loop, because we'll get terminated in the ctrl+c handler
  714. Sleep (50);
  715. }
  716. exit (g_ReturnCode);
  717. }
  718. #ifdef DEBUG
  719. {
  720. if (DoesFileExist (TEXT("C:\\LOADSTATE.BEGIN"))) {
  721. pStopAndDisplayInfs (&args.InputInf, TRUE);
  722. }
  723. }
  724. #endif
  725. LogReInit (NULL, NULL, args.LogFile ? args.LogFile : TEXT("loadstate.log"), NULL);
  726. logEnabled = TRUE;
  727. // Let's log the command line that was used
  728. commandLine = GetCommandLine ();
  729. if (commandLine) {
  730. LOG ((LOG_INFORMATION, (PCSTR)MSG_COMMAND_LINE_USED, commandLine));
  731. }
  732. //
  733. // Check requirements
  734. //
  735. if (args.BadInfs.End || args.MultiInfs.End) {
  736. SetLastError (ERROR_BAD_COMMAND);
  737. if (EnumFirstMultiSz (&e, (PCTSTR) args.BadInfs.Buf)) {
  738. do {
  739. LOG ((LOG_ERROR, (PCSTR) MSG_INF_FILE_NOT_FOUND, e.CurrentString));
  740. } while (EnumNextMultiSz (&e));
  741. }
  742. if (EnumFirstMultiSz (&e, (PCTSTR) args.MultiInfs.Buf)) {
  743. do {
  744. LOG ((LOG_ERROR, (PCSTR) MSG_INF_SPECIFIED_MORE_THAN_ONE, e.CurrentString));
  745. } while (EnumNextMultiSz (&e));
  746. }
  747. g_ReturnCode = RETURN_ERROR;
  748. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CMD_LINE_ERROR));
  749. goto END;
  750. }
  751. if (!GetFilePath (TEXT("migism.inf"), ismPath, ARRAYSIZE(ismPath))) {
  752. g_ReturnCode = RETURN_ERROR;
  753. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_ISM_INF_MISSING));
  754. goto END;
  755. }
  756. if (ISWIN9X()) {
  757. g_ReturnCode = RETURN_ERROR;
  758. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_NT_REQUIRED));
  759. goto END;
  760. }
  761. #ifndef UNICODE
  762. // ANSI version of loadstate.exe is not tested, let's not allow it to run
  763. g_ReturnCode = RETURN_ERROR;
  764. SetLastError (ERROR_APP_WRONG_OS);
  765. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_UNICODE_REQUIRED));
  766. goto END;
  767. #endif
  768. if (!pIsUserAdmin() && !args.DelayedOpsOn) {
  769. g_ReturnCode = RETURN_ERROR;
  770. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_ADMIN_REQUIRED));
  771. goto END;
  772. }
  773. //
  774. // Initialize ISM
  775. //
  776. if (!IsmInitialize (ismPath, pSaveMsgCallback, pMyLogCallback)) {
  777. g_ReturnCode = RETURN_ERROR;
  778. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_START_ISM));
  779. goto END;
  780. }
  781. terminateIsm = TRUE;
  782. SetLogVerbosity (args.VerboseLevel);
  783. SetConsoleCtrlHandler (CtrlCRoutine, TRUE);
  784. // upload environment variables
  785. UploadEnvVars (PLATFORM_DESTINATION);
  786. // we will try to copy iconlib.dll from our directory into "Common AppData" directory
  787. // If we don't succeed, we will not set the S_ENV_ICONLIB env variable
  788. iconLibFound = FALSE;
  789. iconLibRoot = pGetShellFolderPath (CSIDL_COMMON_APPDATA);
  790. if (iconLibRoot) {
  791. __try {
  792. StringCopy (iconLibDest, iconLibRoot);
  793. StringCopy (AppendWack (iconLibDest), TEXT("Microsoft"));
  794. if (!CreateDirectory (iconLibDest, NULL)) {
  795. err = GetLastError ();
  796. if (err != ERROR_ALREADY_EXISTS) {
  797. __leave;
  798. }
  799. }
  800. StringCopy (AppendWack (iconLibDest), TEXT("USMT"));
  801. if (!CreateDirectory (iconLibDest, NULL)) {
  802. err = GetLastError ();
  803. if (err != ERROR_ALREADY_EXISTS) {
  804. __leave;
  805. }
  806. }
  807. StringCopy (AppendWack (iconLibDest), TEXT("iconlib.dll"));
  808. if (!CopyFile (iconLibSrc, iconLibDest, TRUE)) {
  809. err = GetLastError ();
  810. if (err != ERROR_FILE_EXISTS) {
  811. __leave;
  812. }
  813. }
  814. iconLibFound = TRUE;
  815. }
  816. __finally {
  817. LocalFree (iconLibRoot);
  818. iconLibRoot = NULL;
  819. }
  820. }
  821. // Set the icon lib data
  822. if (iconLibFound) {
  823. IsmSetEnvironmentString (PLATFORM_DESTINATION, NULL, S_ENV_ICONLIB, iconLibDest);
  824. }
  825. infHandle = InitRequiredInfs (appPath, (PCSTR) MSG_CANT_OPEN_REQUIRED_FILE);
  826. if (infHandle != INVALID_HANDLE_VALUE) {
  827. infHandleStruct.Type = ENVENTRY_BINARY;
  828. infHandleStruct.EnvBinaryData = (PVOID)(&infHandle);
  829. infHandleStruct.EnvBinaryDataSize = sizeof (HINF);
  830. IsmSetEnvironmentValue (PLATFORM_DESTINATION, NULL, S_GLOBAL_INF_HANDLE, &infHandleStruct);
  831. }
  832. if (args.UserOn) {
  833. IsmSetEnvironmentFlag (PLATFORM_DESTINATION, NULL, S_ENV_HKCU_V1);
  834. IsmSetEnvironmentFlag (PLATFORM_DESTINATION, NULL, S_ENV_HKCU_ON);
  835. }
  836. if (args.FilesOn) {
  837. IsmSetEnvironmentFlag (PLATFORM_DESTINATION, NULL, S_ENV_ALL_FILES);
  838. }
  839. IsmSetPlatform (PLATFORM_DESTINATION);
  840. if (!args.CurrentUser) {
  841. IsmSetEnvironmentFlag (PLATFORM_DESTINATION, NULL, S_REQUIRE_DOMAIN_USER);
  842. IsmSetEnvironmentFlag (PLATFORM_DESTINATION, NULL, S_ENV_CREATE_USER);
  843. }
  844. //
  845. // Start ETM modules
  846. //
  847. if (!IsmStartEtmModules ()) {
  848. if (!IsmCheckCancel()) {
  849. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_START_ETMS));
  850. }
  851. goto END;
  852. }
  853. if (args.DelayedOpsOn) {
  854. appStatus = ReadAppStatus (g_JournalPath);
  855. if ((appStatus != LOADSTATE_COMPLETED) &&
  856. (appStatus != LOADSTATE_EXECUTE) &&
  857. (appStatus != 0)
  858. ) {
  859. // unknown state, just cleanup the delayed ops journal
  860. IsmExecute (EXECUTETYPE_DELAYEDOPERATIONSCLEANUP);
  861. } else {
  862. IsmSetRollbackJournalType (FALSE);
  863. if (appStatus == LOADSTATE_EXECUTE) {
  864. IsmRollback ();
  865. }
  866. // write the app status
  867. WriteAppStatus (g_JournalPath, LOADSTATE_EXECUTE);
  868. IsmExecute (EXECUTETYPE_DELAYEDOPERATIONS);
  869. // write the app status
  870. WriteAppStatus (g_JournalPath, LOADSTATE_COMPLETED);
  871. }
  872. } else {
  873. //
  874. // Initialize transport
  875. //
  876. if (!IsmStartTransport ()) {
  877. if (!IsmCheckCancel()) {
  878. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_START_TRANS));
  879. }
  880. goto END;
  881. }
  882. transportStorageId = IsmRegisterTransport (args.TransportName);
  883. if (args.FullTransport) {
  884. transportId = IsmSelectTransport (transportStorageId, TRANSPORTTYPE_FULL, args.Capabilities);
  885. } else {
  886. transportId = IsmSelectTransport (transportStorageId, TRANSPORTTYPE_LIGHT, args.Capabilities);
  887. }
  888. if (!transportId) {
  889. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_TRANSPORT_UNAVAILABLE));
  890. goto END;
  891. }
  892. #ifdef PRERELEASE
  893. IsmSetEnvironmentString (PLATFORM_DESTINATION, NULL, TRANSPORT_ENVVAR_HOMENET_TAG, args.Tag);
  894. #endif
  895. if (!IsmSetTransportStorage (
  896. PLATFORM_DESTINATION,
  897. transportId,
  898. transportStorageId,
  899. args.Capabilities,
  900. args.StoragePath,
  901. &storagePathIsValid,
  902. NULL
  903. ) ||
  904. storagePathIsValid == FALSE) {
  905. if (!IsmCheckCancel()) {
  906. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_TRANSPORT_STORAGE_INVALID, args.StoragePath));
  907. }
  908. goto END;
  909. }
  910. #ifdef PRERELEASE
  911. if (args.Capabilities & CAPABILITY_AUTOMATED) {
  912. WaitForSingleObject (g_CallbackEvent, INFINITE);
  913. }
  914. #endif
  915. appStatus = ReadAppStatus (g_JournalPath);
  916. if (appStatus != LOADSTATE_COMPLETED) {
  917. // if we need to, call IsmRollback
  918. if (appStatus == LOADSTATE_EXECUTE) {
  919. IsmRollback ();
  920. appStatus = LOADSTATE_LOAD;
  921. }
  922. #ifdef PRERELEASE
  923. if (!args.Recovery) {
  924. #endif
  925. // write the app status
  926. WriteAppStatus (g_JournalPath, LOADSTATE_LOAD);
  927. //
  928. // Recover the state
  929. //
  930. if (appStatus == LOADSTATE_LOAD) {
  931. loadResult = IsmResumeLoad ();
  932. if (!loadResult) {
  933. loadResult = IsmLoad ();
  934. }
  935. } else {
  936. loadResult = IsmLoad ();
  937. }
  938. if (loadResult) {
  939. // before we go further, let's see if we wanted to change the user name and/or domain
  940. if (args.NewDomainName) {
  941. IsmSetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, TEXT("ALTUSERDOMAIN"), args.NewDomainName);
  942. }
  943. if (args.NewUserName) {
  944. IsmSetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, TEXT("ALTUSERNAME"), args.NewUserName);
  945. }
  946. // Load INFs that were specified in scanstate
  947. if (!args.NoScanStateInfs) {
  948. objectPattern = IsmCreateSimpleObjectPattern (TEXT("External"), FALSE, S_INF_OBJECT_NAME TEXT("*"), TRUE);
  949. if (IsmEnumFirstSourceObject(&objectEnum, MIG_DATA_TYPE, objectPattern)) {
  950. do {
  951. if (IsmGetControlFile (objectEnum.ObjectTypeId, objectEnum.ObjectName, infPath)) {
  952. IsmAppendEnvironmentMultiSz (
  953. PLATFORM_DESTINATION,
  954. NULL,
  955. S_INF_FILE_MULTISZ,
  956. infPath
  957. );
  958. pOpenOrAppendInfFile (&infHandle, infPath);
  959. }
  960. } while (IsmEnumNextObject (&objectEnum));
  961. }
  962. IsmDestroyObjectHandle (objectPattern);
  963. }
  964. if (args.InputInf.Buf) {
  965. //
  966. // now let's open append all INF files and pass the HINF to
  967. // everybody.
  968. //
  969. if (EnumFirstMultiSz (&infEnum, (PCTSTR)args.InputInf.Buf)) {
  970. do {
  971. IsmAppendEnvironmentMultiSz (
  972. PLATFORM_DESTINATION,
  973. NULL,
  974. S_INF_FILE_MULTISZ,
  975. infEnum.CurrentString
  976. );
  977. pOpenOrAppendInfFile (&infHandle, infEnum.CurrentString);
  978. } while (EnumNextMultiSz (&infEnum));
  979. }
  980. }
  981. if (!args.FullTransport) {
  982. //
  983. // Execute the preparsing to populate components
  984. //
  985. if (IsmExecute (EXECUTETYPE_EXECUTESOURCE_PARSING)) {
  986. IsmSelectMasterGroup (MASTERGROUP_ALL, TRUE);
  987. if (!args.SystemOn) {
  988. IsmSelectMasterGroup (MASTERGROUP_SYSTEM, FALSE);
  989. IsmSelectMasterGroup (MASTERGROUP_USER, FALSE);
  990. IsmSelectMasterGroup (MASTERGROUP_APP, FALSE);
  991. }
  992. SelectComponentsViaInf (infHandle);
  993. //
  994. // Execute data gather
  995. //
  996. if (!IsmExecute (EXECUTETYPE_EXECUTESOURCE)) {
  997. if (!IsmCheckCancel()) {
  998. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_EXECUTE_SOURCE));
  999. }
  1000. }
  1001. } else {
  1002. if (!IsmCheckCancel()) {
  1003. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_EXECUTE_SOURCE));
  1004. }
  1005. }
  1006. }
  1007. //
  1008. // Apply saved state
  1009. //
  1010. // write the app status
  1011. WriteAppStatus (g_JournalPath, LOADSTATE_EXECUTE);
  1012. IsmSetDelayedOperationsCommand (delayedCmd);
  1013. if (!IsmExecute (EXECUTETYPE_EXECUTEDESTINATION)) {
  1014. if (!IsmCheckCancel()) {
  1015. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_EXECUTE_DEST));
  1016. }
  1017. }
  1018. } else {
  1019. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_FIND_SAVED_STATE));
  1020. }
  1021. #ifdef PRERELEASE
  1022. }
  1023. #endif
  1024. // write the app status
  1025. WriteAppStatus (g_JournalPath, LOADSTATE_COMPLETED);
  1026. }
  1027. }
  1028. //
  1029. // We're done!
  1030. //
  1031. SetupCloseInfFile (infHandle);
  1032. #ifdef DEBUG
  1033. {
  1034. if (DoesFileExist (TEXT("C:\\LOADSTATE.END"))) {
  1035. pStopAndDisplayInfs (&args.InputInf, FALSE);
  1036. }
  1037. }
  1038. #endif
  1039. END:
  1040. // If we were successfull, it is time to check for registry leaks
  1041. // We call OE DLL entries and sometimes they leak registry keys.
  1042. // When we create a new profile this is particularly bad because
  1043. // we cannot unload the hive.
  1044. if (!g_Break) {
  1045. if (g_ReturnCode == RETURN_SUCCESS) {
  1046. DWORD sizeNeeded;
  1047. HKEY tempKey = NULL;
  1048. PTSTR mappedKeyStr = NULL;
  1049. DWORD processId = 0;
  1050. TCHAR tempStr1 [sizeof (DWORD) * 2 + sizeof(TEXT(" /hp: 0x")) + 1];
  1051. PCTSTR tempStr2 = NULL;
  1052. PTSTR tempStr3 = NULL;
  1053. STARTUPINFO si;
  1054. PROCESS_INFORMATION pi;
  1055. // Let's get the location of the mapped hive
  1056. if (IsmGetEnvironmentString (
  1057. PLATFORM_DESTINATION,
  1058. NULL,
  1059. S_VER_HIVEMAPPEDLOCATION,
  1060. NULL,
  1061. 0,
  1062. &sizeNeeded
  1063. )) {
  1064. mappedKeyStr = AllocPathString (sizeNeeded);
  1065. if (mappedKeyStr) {
  1066. if (IsmGetEnvironmentString (
  1067. PLATFORM_DESTINATION,
  1068. NULL,
  1069. S_VER_HIVEMAPPEDLOCATION,
  1070. mappedKeyStr,
  1071. sizeNeeded,
  1072. NULL
  1073. )) {
  1074. tempKey = OpenRegKey (HKEY_USERS, mappedKeyStr);
  1075. if (tempKey) {
  1076. // Yep, we had a leak and the hive was not unloaded
  1077. LOG ((LOG_INFORMATION, (PCSTR)MSG_UNLOAD_HIVE_HACK));
  1078. // What we are going to do is we are going to launch
  1079. // ourself passing the mappedKeyStr and our process ID
  1080. processId = GetCurrentProcessId ();
  1081. if (processId) {
  1082. wsprintf (tempStr1, TEXT(" /hp:0x%08X "), processId);
  1083. tempStr2 = JoinText (TEXT("/hm:"), mappedKeyStr);
  1084. if (tempStr2) {
  1085. tempStr3 = JoinText (tempStr1, tempStr2);
  1086. if (tempStr3) {
  1087. if (GetModuleFileName (NULL, appPath, ARRAYSIZE(appPath))) {
  1088. ZeroMemory (&si, sizeof (si));
  1089. if (CreateProcess (
  1090. appPath,
  1091. tempStr3,
  1092. NULL,
  1093. NULL,
  1094. FALSE,
  1095. CREATE_NEW_CONSOLE,
  1096. NULL,
  1097. NULL,
  1098. &si,
  1099. &pi
  1100. )) {
  1101. CloseHandle (pi.hThread);
  1102. CloseHandle (pi.hProcess);
  1103. }
  1104. }
  1105. FreeText (tempStr3);
  1106. }
  1107. FreeText (tempStr2);
  1108. }
  1109. }
  1110. CloseRegKey (tempKey);
  1111. }
  1112. }
  1113. FreePathString (mappedKeyStr);
  1114. mappedKeyStr = NULL;
  1115. }
  1116. }
  1117. }
  1118. }
  1119. if (terminateIsm) {
  1120. if (!g_Break) {
  1121. pCleanUpApp();
  1122. }
  1123. }
  1124. if (delayedCmd) {
  1125. FreeText (delayedCmd);
  1126. delayedCmd = NULL;
  1127. }
  1128. GbFree (&args.InputInf);
  1129. GbFree (&args.BadInfs);
  1130. GbFree (&args.MultiInfs);
  1131. if (!g_Break) {
  1132. if (g_ReturnCode == RETURN_SUCCESS) {
  1133. PrintMsgOnConsole (MSG_SUCCESS);
  1134. } else if (g_ReturnCode == RETURN_IGNORED_ERROR) {
  1135. if (logEnabled) {
  1136. PrintMsgOnConsole (MSG_IGNORE_FAILED_WITH_LOG);
  1137. } else {
  1138. PrintMsgOnConsole (MSG_IGNORE_FAILED_NO_LOG);
  1139. }
  1140. g_ReturnCode = RETURN_SUCCESS;
  1141. } else {
  1142. if (logEnabled) {
  1143. PrintMsgOnConsole (MSG_FAILED_WITH_LOG);
  1144. } else {
  1145. PrintMsgOnConsole (MSG_FAILED_NO_LOG);
  1146. }
  1147. }
  1148. }
  1149. UtTerminate ();
  1150. while (g_Break) {
  1151. // infinite loop, because we'll get terminated in the ctrl+c handler
  1152. Sleep (50);
  1153. }
  1154. exit (g_ReturnCode);
  1155. }