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.

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