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.

1030 lines
29 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. scanstate.c
  5. Abstract:
  6. Implements the app layer of the v1 compatibility app.
  7. Author:
  8. Jim Schmidt (jimschm) 14-Mar-2000
  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 "v2app.h"
  20. #include <lm.h>
  21. #ifdef DEBUG
  22. #include <shellapi.h>
  23. #endif
  24. #include "logmsg.h"
  25. #include "common.h"
  26. #define DBG_SCANSTATE "ScanState"
  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 SCANSTATE_SAVE 0x00000001
  40. #define SCANSTATE_COMPLETED 0x00000002
  41. #define RETURN_SUCCESS 0
  42. #define RETURN_FATAL_ERROR 1
  43. #define RETURN_ERROR 2
  44. #define RETURN_IGNORED_ERROR 3
  45. //
  46. // Macros
  47. //
  48. // None
  49. //
  50. // Types
  51. //
  52. typedef NET_API_STATUS(WINAPI NETWKSTAGETINFO)(PWSTR, DWORD, PBYTE *);
  53. typedef NETWKSTAGETINFO *PNETWKSTAGETINFO;
  54. typedef NET_API_STATUS(WINAPI NETAPIBUFFERFREE)(PVOID);
  55. typedef NETAPIBUFFERFREE *PNETAPIBUFFERFREE;
  56. //
  57. // Globals
  58. //
  59. BOOL g_OverwriteImage = FALSE;
  60. BOOL g_ContinueOnError = FALSE;
  61. DWORD g_ReturnCode = RETURN_SUCCESS;
  62. TCHAR g_JournalPath[MAX_PATH_PLUS_NUL];
  63. BOOL g_Break;
  64. BOOL g_TestMode;
  65. //
  66. // Macro expansion list
  67. //
  68. #define REQUIRED_INFS \
  69. DEFMAC(OSFILES, TEXT("USMTDef.inf")) \
  70. //
  71. // Private function prototypes
  72. //
  73. #ifdef PRERELEASE
  74. MESSAGECALLBACK pSaveMsgCallback;
  75. #endif
  76. //
  77. // Macro expansion definition
  78. //
  79. //
  80. // This is the structure used for required infs
  81. //
  82. typedef struct {
  83. PCTSTR InfId;
  84. PCTSTR InfName;
  85. } REQUIREDINF_STRUCT, *PREQUIREDINF_STRUCT;
  86. //
  87. // Declare a global array of required infs
  88. //
  89. #define DEFMAC(infid,infname) {TEXT(#infid),infname},
  90. static REQUIREDINF_STRUCT g_RequiredInfs[] = {
  91. REQUIRED_INFS
  92. {NULL, NULL}
  93. };
  94. #undef DEFMAC
  95. //
  96. // Code
  97. //
  98. VOID
  99. pHelpAndExit (
  100. VOID
  101. )
  102. {
  103. PrintMsgOnConsole (MSG_HELP);
  104. #ifdef PRERELEASE
  105. printf ("\nAdditional PRERELEASE options:\n\n"
  106. "/tf Uses full transport instead of v1 transport\n"
  107. "/tc Enable compression\n"
  108. "/ta Enable automatic capability (for homenet transport)\n"
  109. "/ti:<tag> Specify an identity tag for the homenet transport\n"
  110. " Default is user name\n"
  111. "/t:<name> Specifies transport to use\n"
  112. );
  113. #endif
  114. TerminateAppCommon();
  115. UtTerminate ();
  116. exit (1);
  117. }
  118. VOID
  119. pCleanUpApp (
  120. VOID
  121. )
  122. {
  123. IsmTerminate();
  124. if (g_JournalPath[0]) {
  125. DeleteFile (g_JournalPath);
  126. g_JournalPath[0] = 0;
  127. }
  128. }
  129. BOOL
  130. WINAPI
  131. CtrlCRoutine (
  132. IN DWORD ControlSignal
  133. )
  134. {
  135. PrintMsgOnConsole (MSG_EXITING);
  136. LOG ((LOG_WARNING, (PCSTR) MSG_TOOL_STOPPED));
  137. g_Break = TRUE;
  138. IsmSetCancel();
  139. while (IsmCurrentlyExecuting()) {
  140. Sleep (1000);
  141. }
  142. pCleanUpApp();
  143. printf ("\n");
  144. exit (1);
  145. }
  146. ULONG_PTR
  147. pSaveMsgCallback (
  148. UINT Message,
  149. ULONG_PTR Arg
  150. )
  151. {
  152. PTRANSCOPY_ERROR transCopyError;
  153. #ifdef PRERELEASE
  154. PRMEDIA_EXTRADATA extraData;
  155. #endif
  156. switch (Message) {
  157. case TRANSPORTMESSAGE_IMAGE_EXISTS:
  158. return g_OverwriteImage;
  159. case TRANSPORTMESSAGE_SRC_COPY_ERROR:
  160. transCopyError = (PTRANSCOPY_ERROR) Arg;
  161. if (transCopyError) {
  162. if (StringIMatch (transCopyError->ObjectType, TEXT("File"))) {
  163. if ((transCopyError->Error == ERROR_FILE_NOT_FOUND) ||
  164. (transCopyError->Error == ERROR_PATH_NOT_FOUND) ||
  165. (transCopyError->Error == ERROR_ACCESS_DENIED) ||
  166. (transCopyError->Error == ERROR_INVALID_NAME)
  167. ) {
  168. return APPRESPONSE_IGNORE;
  169. }
  170. if ((transCopyError->Error == ERROR_FILENAME_EXCED_RANGE) && g_ContinueOnError) {
  171. return APPRESPONSE_IGNORE;
  172. }
  173. }
  174. }
  175. return APPRESPONSE_FAIL;
  176. #ifdef PRERELEASE
  177. case TRANSPORTMESSAGE_RMEDIA_SAVE:
  178. extraData = (PRMEDIA_EXTRADATA) Arg;
  179. if (!extraData) {
  180. return (MessageBox (
  181. NULL,
  182. TEXT("Please insert the next media in your drive."),
  183. TEXT("ScanState"),
  184. MB_OKCANCEL
  185. ) == IDOK);
  186. }
  187. if (extraData->MediaNumber == 1) {
  188. switch (extraData->LastError) {
  189. case RMEDIA_ERR_NOERROR:
  190. return TRUE;
  191. case RMEDIA_ERR_WRONGMEDIA:
  192. return (MessageBox (
  193. NULL,
  194. TEXT("You have inserted the wrong media.\n\nPlease insert the first media in your drive."),
  195. TEXT("ScanState"),
  196. MB_OKCANCEL
  197. ) == IDOK);
  198. case RMEDIA_ERR_DISKFULL:
  199. return (MessageBox (
  200. NULL,
  201. TEXT("The media you inserted does not have enough free space.\n\nPlease insert the first media in your drive."),
  202. TEXT("ScanState"),
  203. MB_OKCANCEL
  204. ) == IDOK);
  205. case RMEDIA_ERR_WRITEPROTECT:
  206. return (MessageBox (
  207. NULL,
  208. TEXT("The media you inserted is write protected.\n\nPlease insert the first media in your drive."),
  209. TEXT("ScanState"),
  210. MB_OKCANCEL
  211. ) == IDOK);
  212. case RMEDIA_ERR_NOTREADY:
  213. return (MessageBox (
  214. NULL,
  215. 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."),
  216. TEXT("ScanState"),
  217. MB_OKCANCEL
  218. ) == IDOK);
  219. case RMEDIA_ERR_CRITICAL:
  220. return FALSE;
  221. default:
  222. return (MessageBox (
  223. NULL,
  224. TEXT("Your media is toast.\n\nPlease insert the first media in your drive."),
  225. TEXT("ScanState"),
  226. MB_OKCANCEL
  227. ) == IDOK);
  228. }
  229. } else {
  230. switch (extraData->LastError) {
  231. case RMEDIA_ERR_NOERROR:
  232. return TRUE;
  233. case RMEDIA_ERR_WRONGMEDIA:
  234. return (MessageBox (
  235. NULL,
  236. TEXT("You have inserted the wrong media.\n\nPlease insert the next media in your drive."),
  237. TEXT("ScanState"),
  238. MB_OKCANCEL
  239. ) == IDOK);
  240. case RMEDIA_ERR_DISKFULL:
  241. return (MessageBox (
  242. NULL,
  243. TEXT("The media you inserted does not have enough free space.\n\nPlease insert the next media in your drive."),
  244. TEXT("ScanState"),
  245. MB_OKCANCEL
  246. ) == IDOK);
  247. case RMEDIA_ERR_WRITEPROTECT:
  248. return (MessageBox (
  249. NULL,
  250. TEXT("The media you inserted is write protected.\n\nPlease insert the next media in your drive."),
  251. TEXT("ScanState"),
  252. MB_OKCANCEL
  253. ) == IDOK);
  254. case RMEDIA_ERR_NOTREADY:
  255. return (MessageBox (
  256. NULL,
  257. 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."),
  258. TEXT("ScanState"),
  259. MB_OKCANCEL
  260. ) == IDOK);
  261. case RMEDIA_ERR_CRITICAL:
  262. return FALSE;
  263. default:
  264. return (MessageBox (
  265. NULL,
  266. TEXT("Your media is toast.\n\nPlease insert the next media in your drive."),
  267. TEXT("ScanState"),
  268. MB_OKCANCEL
  269. ) == IDOK);
  270. }
  271. }
  272. #endif
  273. }
  274. return FALSE;
  275. }
  276. VOID
  277. pMyLogCallback (
  278. IN PLOGARG LogArg
  279. )
  280. {
  281. if (LogArg->Debug) {
  282. DEBUGDIRECT (LogArg->Type, LogArg->FormattedMessage);
  283. } else {
  284. if (StringIMatchA (LogArg->Type, LOG_ERROR)) {
  285. if (g_ReturnCode == RETURN_SUCCESS) {
  286. g_ReturnCode = g_ContinueOnError?RETURN_IGNORED_ERROR:RETURN_ERROR;
  287. }
  288. if (g_ReturnCode == RETURN_IGNORED_ERROR) {
  289. g_ReturnCode = g_ContinueOnError?RETURN_IGNORED_ERROR:RETURN_ERROR;
  290. }
  291. if (!g_ContinueOnError) {
  292. IsmSetCancel();
  293. }
  294. } else if (StringIMatchA (LogArg->Type, LOG_FATAL_ERROR) ||
  295. StringIMatchA (LogArg->Type, LOG_MODULE_ERROR)) {
  296. g_ReturnCode = RETURN_FATAL_ERROR;
  297. }
  298. LOGDIRECT (LogArg->Type, LogArg->FormattedMessage);
  299. }
  300. }
  301. #ifdef DEBUG
  302. VOID
  303. pStopAndDisplayInfs (
  304. IN PGROWBUFFER InputInfs,
  305. IN BOOL Begin
  306. )
  307. {
  308. MULTISZ_ENUM infEnum;
  309. if (MessageBox (
  310. NULL,
  311. TEXT("ScanState stopped. Do you want to display all loaded INFs?"),
  312. Begin?TEXT("ScanState-Begin"):TEXT("ScanState-End"),
  313. MB_YESNO
  314. ) == IDYES) {
  315. //
  316. // now let's open append all INF files and pass the HINF to
  317. // everybody.
  318. //
  319. if (EnumFirstMultiSz (&infEnum, (PCTSTR)InputInfs->Buf)) {
  320. do {
  321. ShellExecute (NULL, TEXT("open"), infEnum.CurrentString, NULL, NULL, SW_SHOWNORMAL);
  322. } while (EnumNextMultiSz (&infEnum));
  323. }
  324. MessageBox (NULL, TEXT("Press OK to continue..."), TEXT("ScanState-Begin"), MB_OK);
  325. }
  326. }
  327. #endif
  328. BOOL
  329. pIsIE4Installed (
  330. VOID
  331. )
  332. {
  333. LONG hResult;
  334. REGSAM prevMode;
  335. HKEY ieKey = NULL;
  336. DWORD valueType = REG_SZ;
  337. DWORD valueSize = 0;
  338. PTSTR valueData = NULL;
  339. PTSTR numPtr = NULL;
  340. PTSTR dotPtr = NULL;
  341. INT major = 0;
  342. INT minor = 0;
  343. TCHAR saved;
  344. BOOL result = FALSE;
  345. prevMode = SetRegOpenAccessMode (KEY_READ);
  346. ieKey = OpenRegKeyStr (TEXT("HKLM\\Software\\Microsoft\\Internet Explorer"));
  347. SetRegOpenAccessMode (prevMode);
  348. if (ieKey) {
  349. hResult = RegQueryValueEx (ieKey, TEXT("Version"), NULL, &valueType, NULL, &valueSize);
  350. if ((hResult == ERROR_SUCCESS) || (hResult == ERROR_MORE_DATA)) {
  351. valueData = (PTSTR)HeapAlloc (GetProcessHeap (), 0, valueSize * 2);
  352. if (valueData) {
  353. hResult = RegQueryValueEx (ieKey, TEXT("Version"), NULL, &valueType, (PBYTE)valueData, &valueSize);
  354. if ((hResult == ERROR_SUCCESS) && (valueType == REG_SZ)) {
  355. // let's see if it the version is the correct one
  356. numPtr = valueData;
  357. dotPtr = _tcschr (numPtr, TEXT('.'));
  358. if (dotPtr) {
  359. saved = *dotPtr;
  360. *dotPtr = 0;
  361. major = _ttoi (numPtr);
  362. *dotPtr = saved;
  363. } else {
  364. major = _ttoi (numPtr);
  365. }
  366. if (dotPtr) {
  367. numPtr = _tcsinc (dotPtr);
  368. dotPtr = _tcschr (numPtr, TEXT('.'));
  369. if (dotPtr) {
  370. saved = *dotPtr;
  371. *dotPtr = 0;
  372. minor = _ttoi (numPtr);
  373. *dotPtr = saved;
  374. } else {
  375. minor = _ttoi (numPtr);
  376. }
  377. }
  378. if ((major >= 5) ||
  379. ((major == 4) && (minor >= 71))
  380. ) {
  381. result = TRUE;
  382. }
  383. }
  384. HeapFree (GetProcessHeap (), 0, valueData);
  385. valueData = NULL;
  386. }
  387. }
  388. CloseRegKey (ieKey);
  389. }
  390. return result;
  391. }
  392. BOOL
  393. pCheckSystemRequirements (
  394. VOID
  395. )
  396. {
  397. HKEY domainLogonKey;
  398. PDWORD data;
  399. BOOL result = TRUE;
  400. TCHAR userName[MAX_USER_NAME];
  401. DWORD size;
  402. NET_API_STATUS rc;
  403. PWKSTA_INFO_102 buffer;
  404. HANDLE netApi32Lib;
  405. PNETWKSTAGETINFO netWkstaGetInfo;
  406. PNETAPIBUFFERFREE netApiBufferFree;
  407. BYTE sid[256];
  408. DWORD sidSize = 256;
  409. WCHAR domain[256];
  410. DWORD domainSize = 256;
  411. SID_NAME_USE use;
  412. if (!ISNT()) {
  413. //
  414. // Require the Log On To Domain setting to be checked
  415. //
  416. SetLastError (ERROR_SUCCESS);
  417. domainLogonKey = OpenRegKeyStr (TEXT("HKLM\\Network\\Logon"));
  418. if (!domainLogonKey) {
  419. LOG ((LOG_ERROR, (PCSTR) MSG_NETWORK_LOGON_KEY));
  420. return FALSE;
  421. }
  422. data = (PDWORD) GetRegValueBinary (domainLogonKey, TEXT("LMLogon"));
  423. if (!data) {
  424. data = (PDWORD) GetRegValueDword (domainLogonKey, TEXT("LMLogon"));
  425. if (!data) {
  426. LOG ((LOG_ERROR, (PCSTR) MSG_NETWORK_LMLOGON_KEY));
  427. result = FALSE;
  428. } else {
  429. if (!(*data)) {
  430. LOG ((LOG_ERROR, (PCSTR) MSG_NO_DOMAIN_LOGON));
  431. result = FALSE;
  432. }
  433. FreeAlloc (data);
  434. }
  435. } else {
  436. if (!(*data)) {
  437. LOG ((LOG_ERROR, (PCSTR) MSG_NO_DOMAIN_LOGON));
  438. result = FALSE;
  439. }
  440. FreeAlloc (data);
  441. }
  442. CloseRegKey (domainLogonKey);
  443. } else {
  444. //
  445. // Require domain membership
  446. //
  447. netApi32Lib = LoadLibrary (TEXT("netapi32.dll"));
  448. if (netApi32Lib) {
  449. netWkstaGetInfo = (PNETWKSTAGETINFO) GetProcAddress (netApi32Lib, "NetWkstaGetInfo");
  450. netApiBufferFree = (PNETAPIBUFFERFREE) GetProcAddress (netApi32Lib, "NetApiBufferFree");
  451. } else {
  452. netWkstaGetInfo = NULL;
  453. netApiBufferFree = NULL;
  454. }
  455. if (!netWkstaGetInfo || !netApiBufferFree) {
  456. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_LOAD_NETAPI32));
  457. result = FALSE;
  458. } else {
  459. rc = netWkstaGetInfo (NULL, 102, (PBYTE *) &buffer);
  460. if (rc == NO_ERROR) {
  461. result = buffer->wki102_langroup && (buffer->wki102_langroup[0] != 0);
  462. if (result) {
  463. DEBUGMSGW ((DBG_SCANSTATE, "Getting account type of %s", buffer->wki102_langroup));
  464. sidSize = ARRAYSIZE(sid);
  465. domainSize = ARRAYSIZE(domain);
  466. result = LookupAccountNameW (
  467. NULL,
  468. buffer->wki102_langroup,
  469. sid,
  470. &sidSize,
  471. domain,
  472. &domainSize,
  473. &use
  474. );
  475. DEBUGMSG ((DBG_SCANSTATE, "Account type result is %u (use=%u)", result, use));
  476. LOG_IF ((!result, LOG_ERROR, (PCSTR) MSG_NOT_JOINED_TO_DOMAIN));
  477. }
  478. ELSE_DEBUGMSG ((DBG_SCANSTATE, "No langroup specified"));
  479. netApiBufferFree (buffer);
  480. } else {
  481. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_GET_WORKSTATION_PROPS));
  482. result = FALSE;
  483. }
  484. }
  485. if (netApi32Lib) {
  486. FreeLibrary (netApi32Lib);
  487. }
  488. }
  489. // let's check to see if IE4 is installed on this machine
  490. if (result && !pIsIE4Installed ()) {
  491. LOG ((LOG_ERROR, (PCSTR) MSG_NEED_IE4));
  492. return FALSE;
  493. }
  494. //
  495. // Make sure a user name is specified
  496. //
  497. if (result) {
  498. size = ARRAYSIZE(userName);
  499. if (!GetUserName (userName, &size)) {
  500. result = FALSE;
  501. } else if (*userName == 0) {
  502. result = FALSE;
  503. }
  504. LOG_IF ((!result, LOG_ERROR, (PCSTR) MSG_LOGGED_ON_USER_REQUIRED));
  505. }
  506. return result;
  507. }
  508. VOID
  509. __cdecl
  510. _tmain (
  511. IN INT Argc,
  512. IN PCTSTR Argv[]
  513. )
  514. {
  515. TCHAR appPath[MAX_PATH_PLUS_NUL];
  516. TCHAR ismPath[MAX_PATH_PLUS_NUL];
  517. PCTSTR commandLine = NULL;
  518. PTSTR p;
  519. MIG_TRANSPORTID transportId;
  520. MIG_TRANSPORTSTORAGEID transportStorageId;
  521. MULTISZ_ENUM infEnum;
  522. HINF infHandle = INVALID_HANDLE_VALUE;
  523. ENVENTRY_STRUCT infHandleStruct;
  524. INT numInfs = 0;
  525. PTSTR buffer;
  526. MULTISZ_ENUM e;
  527. DWORD appStatus;
  528. BOOL skipExecute = FALSE;
  529. BOOL storagePathIsValid = FALSE;
  530. BOOL imageExists = FALSE;
  531. BOOL terminateIsm = FALSE;
  532. BOOL logEnabled = FALSE;
  533. PCTSTR msg;
  534. #ifdef UNICODE
  535. PCSTR ansimsg;
  536. #endif
  537. PCTSTR argArray[1];
  538. TOOLARGS args;
  539. BOOL fail;
  540. ZeroMemory (&args, sizeof (args));
  541. SET_RESETLOG();
  542. UtInitialize (NULL);
  543. InitAppCommon();
  544. SuppressAllLogPopups (TRUE);
  545. // this part is for matching thread's locale to the console code page
  546. CallSetThreadUILanguage ();
  547. PrintMsgOnConsole (MSG_RUNNING);
  548. // initialize app journal path
  549. g_JournalPath[0] = 0;
  550. if (GetWindowsDirectory (g_JournalPath, ARRAYSIZE (g_JournalPath))) {
  551. StringCopy (AppendWack (g_JournalPath), TEXT("SCANSTATE.JRN"));
  552. }
  553. GetModuleFileName (NULL, appPath, ARRAYSIZE(appPath));
  554. p = _tcsrchr (appPath, TEXT('\\'));
  555. if (p) {
  556. *p = 0;
  557. }
  558. //
  559. // Parse the command line
  560. //
  561. fail = TRUE;
  562. switch (ParseToolCmdLine (TRUE, &args, Argc, Argv)) {
  563. case PARSE_SUCCESS:
  564. fail = FALSE;
  565. break;
  566. case PARSE_MULTI_LOG:
  567. PrintMsgOnConsole (MSG_MULTI_LOG);
  568. g_ReturnCode = RETURN_FATAL_ERROR;
  569. goto END;
  570. case PARSE_BAD_LOG:
  571. argArray[0] = args.LogFile;
  572. msg = ParseMessageID (MSG_CANT_OPEN_LOG, argArray);
  573. if (msg) {
  574. #ifdef UNICODE
  575. ansimsg = ConvertWtoA (msg);
  576. printf ("%s", ansimsg);
  577. FreeConvertedStr (ansimsg);
  578. #else
  579. printf ("%s", msg);
  580. #endif
  581. FreeStringResource (msg);
  582. }
  583. g_ReturnCode = RETURN_FATAL_ERROR;
  584. goto END;
  585. default:
  586. break;
  587. }
  588. if (fail) {
  589. pHelpAndExit();
  590. }
  591. g_TestMode = args.TestMode;
  592. g_OverwriteImage = args.OverwriteImage;
  593. g_ContinueOnError = args.ContinueOnError;
  594. #ifdef DEBUG
  595. {
  596. if (DoesFileExist (TEXT("C:\\SCANSTATE.BEGIN"))) {
  597. pStopAndDisplayInfs (&args.InputInf, TRUE);
  598. }
  599. }
  600. #endif
  601. LogReInit (NULL, NULL, (args.LogFile ? args.LogFile : TEXT("scanstate.log")), NULL);
  602. logEnabled = TRUE;
  603. // Let's log the command line that was used
  604. commandLine = GetCommandLine ();
  605. if (commandLine) {
  606. LOG ((LOG_INFORMATION, (PCSTR)MSG_COMMAND_LINE_USED, commandLine));
  607. }
  608. //
  609. // Check requirements
  610. //
  611. if (args.BadInfs.End || args.MultiInfs.End) {
  612. SetLastError (ERROR_BAD_COMMAND);
  613. if (EnumFirstMultiSz (&e, (PCTSTR) args.BadInfs.Buf)) {
  614. do {
  615. LOG ((LOG_ERROR, (PCSTR) MSG_INF_FILE_NOT_FOUND, e.CurrentString));
  616. } while (EnumNextMultiSz (&e));
  617. }
  618. if (EnumFirstMultiSz (&e, (PCTSTR) args.MultiInfs.Buf)) {
  619. do {
  620. LOG ((LOG_ERROR, (PCSTR) MSG_INF_SPECIFIED_MORE_THAN_ONE, e.CurrentString));
  621. } while (EnumNextMultiSz (&e));
  622. }
  623. g_ReturnCode = RETURN_FATAL_ERROR;
  624. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CMD_LINE_ERROR));
  625. goto END;
  626. }
  627. if (!GetFilePath (TEXT("migism.inf"), ismPath, ARRAYSIZE(ismPath))) {
  628. g_ReturnCode = RETURN_FATAL_ERROR;
  629. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_ISM_INF_MISSING));
  630. goto END;
  631. }
  632. if (!g_TestMode) {
  633. if (!pCheckSystemRequirements()) {
  634. g_ReturnCode = RETURN_FATAL_ERROR;
  635. goto END;
  636. }
  637. }
  638. //
  639. // Initialize ISM
  640. //
  641. if (!IsmInitialize (ismPath, pSaveMsgCallback, pMyLogCallback)) {
  642. g_ReturnCode = RETURN_FATAL_ERROR;
  643. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_START_ISM));
  644. goto END;
  645. }
  646. terminateIsm = TRUE;
  647. SetLogVerbosity (args.VerboseLevel);
  648. SetConsoleCtrlHandler (CtrlCRoutine, TRUE);
  649. IsmSetPlatform (PLATFORM_SOURCE);
  650. // upload environment variables
  651. UploadEnvVars (PLATFORM_SOURCE);
  652. infHandle = InitRequiredInfs (appPath, (PCSTR) MSG_CANT_OPEN_REQUIRED_FILE);
  653. if (args.InputInf.Buf) {
  654. IsmSetEnvironmentData (
  655. PLATFORM_SOURCE,
  656. NULL,
  657. S_INF_FILE_MULTISZ,
  658. args.InputInf.Buf,
  659. (WORD) args.InputInf.End
  660. );
  661. //
  662. // now let's open append all INF files and pass the HINF to
  663. // everybody.
  664. //
  665. if (EnumFirstMultiSz (&infEnum, (PCTSTR)args.InputInf.Buf)) {
  666. buffer = DuplicateTextEx (NULL, S_INF_OBJECT_NAME, 2, &p); // Up to 2 digits of numbers
  667. do {
  668. if (infHandle == INVALID_HANDLE_VALUE) {
  669. infHandle = SetupOpenInfFile (infEnum.CurrentString, NULL, INF_STYLE_WIN4 | INF_STYLE_OLDNT, NULL);
  670. if (infHandle == INVALID_HANDLE_VALUE) {
  671. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_FILE, infEnum.CurrentString));
  672. }
  673. } else {
  674. if (!SetupOpenAppendInfFile (infEnum.CurrentString, infHandle, NULL)) {
  675. LOG ((LOG_ERROR, (PCSTR) MSG_CANT_OPEN_FILE, infEnum.CurrentString));
  676. }
  677. }
  678. // Save Inf for right side use
  679. if (numInfs < 100) {
  680. numInfs++;
  681. _stprintf(p, TEXT("%d"), numInfs);
  682. IsmAddControlFile (buffer, infEnum.CurrentString);
  683. }
  684. } while (EnumNextMultiSz (&infEnum));
  685. FreeText (buffer);
  686. }
  687. }
  688. if (infHandle != INVALID_HANDLE_VALUE) {
  689. infHandleStruct.Type = ENVENTRY_BINARY;
  690. infHandleStruct.EnvBinaryData = (PVOID)(&infHandle);
  691. infHandleStruct.EnvBinaryDataSize = sizeof (HINF);
  692. IsmSetEnvironmentValue (PLATFORM_SOURCE, NULL, S_GLOBAL_INF_HANDLE, &infHandleStruct);
  693. }
  694. if (args.UserOn) {
  695. IsmSetEnvironmentFlag (PLATFORM_SOURCE, NULL, S_ENV_HKCU_V1);
  696. IsmSetEnvironmentFlag (PLATFORM_SOURCE, NULL, S_ENV_HKCU_ON);
  697. }
  698. if (args.FilesOn) {
  699. IsmSetEnvironmentFlag (PLATFORM_SOURCE, NULL, S_ENV_ALL_FILES);
  700. }
  701. //
  702. // Start ETM modules
  703. //
  704. if (!IsmStartEtmModules ()) {
  705. if (!IsmCheckCancel()) {
  706. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_START_ETMS));
  707. }
  708. goto END;
  709. }
  710. //
  711. // Initialize transport
  712. //
  713. if (!IsmStartTransport ()) {
  714. if (!IsmCheckCancel()) {
  715. LOG ((LOG_FATAL_ERROR, "Can't start the transport."));
  716. }
  717. goto END;
  718. }
  719. transportStorageId = IsmRegisterTransport (args.TransportName);
  720. if (args.FullTransport) {
  721. transportId = IsmSelectTransport (transportStorageId, TRANSPORTTYPE_FULL, args.Capabilities);
  722. } else {
  723. transportId = IsmSelectTransport (transportStorageId, TRANSPORTTYPE_LIGHT, args.Capabilities);
  724. }
  725. if (!args.TransportNameSpecified) {
  726. BfCreateDirectory (args.StoragePath);
  727. }
  728. if (!transportId) {
  729. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_TRANSPORT_UNAVAILABLE));
  730. goto END;
  731. }
  732. #ifdef PRERELEASE
  733. IsmSetEnvironmentString (PLATFORM_SOURCE, NULL, TRANSPORT_ENVVAR_HOMENET_TAG, args.Tag);
  734. #endif
  735. if (!IsmSetTransportStorage (
  736. PLATFORM_SOURCE,
  737. transportId,
  738. transportStorageId,
  739. args.Capabilities,
  740. args.StoragePath,
  741. &storagePathIsValid,
  742. &imageExists
  743. ) || storagePathIsValid == FALSE
  744. ) {
  745. if (!IsmCheckCancel()) {
  746. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_TRANSPORT_STORAGE_INVALID, args.StoragePath));
  747. }
  748. goto END;
  749. }
  750. #ifdef PRERELEASE
  751. if (args.Capabilities & CAPABILITY_AUTOMATED) {
  752. if (!imageExists) {
  753. LOG ((
  754. LOG_FATAL_ERROR,
  755. "Can't select %s as the transport; need to run loadstate first.",
  756. args.TransportName
  757. ));
  758. goto END;
  759. }
  760. }
  761. #endif
  762. appStatus = ReadAppStatus (g_JournalPath);
  763. if (appStatus == SCANSTATE_SAVE) {
  764. skipExecute = IsmResumeSave ();
  765. }
  766. if (!skipExecute) {
  767. //
  768. // Execute the preparsing to populate the components
  769. //
  770. if (IsmExecute (args.FullTransport?EXECUTETYPE_EXECUTESOURCE_PARSING:EXECUTETYPE_VIRTUALCOMPUTER_PARSING)) {
  771. IsmSelectMasterGroup (MASTERGROUP_ALL, TRUE);
  772. if (!args.SystemOn) {
  773. IsmSelectMasterGroup (MASTERGROUP_SYSTEM, FALSE);
  774. IsmSelectMasterGroup (MASTERGROUP_USER, FALSE);
  775. IsmSelectMasterGroup (MASTERGROUP_APP, FALSE);
  776. }
  777. SelectComponentsViaInf (infHandle);
  778. //
  779. // Enumerate the system, gather data and analyze
  780. //
  781. if (IsmExecute (args.FullTransport?EXECUTETYPE_EXECUTESOURCE:EXECUTETYPE_VIRTUALCOMPUTER)) {
  782. //
  783. // Display report
  784. //
  785. //
  786. // Save the state
  787. //
  788. // write the app status
  789. WriteAppStatus (g_JournalPath, SCANSTATE_SAVE);
  790. // before we save, let's see if we wanted to change the user name and/or domain
  791. if (args.NewDomainName) {
  792. IsmSetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, TEXT("ALTUSERDOMAIN"), args.NewDomainName);
  793. }
  794. if (args.NewUserName) {
  795. IsmSetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, TEXT("ALTUSERNAME"), args.NewUserName);
  796. }
  797. if (!IsmSave ()) {
  798. if (!IsmCheckCancel()) {
  799. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_SAVE));
  800. }
  801. }
  802. // write the app status
  803. WriteAppStatus (g_JournalPath, SCANSTATE_COMPLETED);
  804. } else {
  805. if (!IsmCheckCancel()) {
  806. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_EXECUTE_SOURCE));
  807. }
  808. }
  809. } else {
  810. if (!IsmCheckCancel()) {
  811. LOG ((LOG_FATAL_ERROR, (PCSTR) MSG_CANT_EXECUTE_SOURCE));
  812. }
  813. }
  814. }
  815. //
  816. // We're done!
  817. //
  818. SetupCloseInfFile (infHandle);
  819. #ifdef DEBUG
  820. {
  821. if (DoesFileExist (TEXT("C:\\SCANSTATE.END"))) {
  822. pStopAndDisplayInfs (&args.InputInf, FALSE);
  823. }
  824. }
  825. #endif
  826. END:
  827. if (terminateIsm) {
  828. if (!g_Break) {
  829. pCleanUpApp();
  830. }
  831. }
  832. GbFree (&args.BadInfs);
  833. GbFree (&args.MultiInfs);
  834. GbFree (&args.InputInf);
  835. if (!g_Break) {
  836. if (g_ReturnCode == RETURN_SUCCESS) {
  837. PrintMsgOnConsole (MSG_SUCCESS);
  838. } else if (g_ReturnCode == RETURN_IGNORED_ERROR) {
  839. if (logEnabled) {
  840. PrintMsgOnConsole (MSG_IGNORE_FAILED_WITH_LOG);
  841. } else {
  842. PrintMsgOnConsole (MSG_IGNORE_FAILED_NO_LOG);
  843. }
  844. g_ReturnCode = RETURN_SUCCESS;
  845. } else {
  846. if (logEnabled) {
  847. PrintMsgOnConsole (MSG_FAILED_WITH_LOG);
  848. } else {
  849. PrintMsgOnConsole (MSG_FAILED_NO_LOG);
  850. }
  851. }
  852. }
  853. TerminateAppCommon();
  854. UtTerminate ();
  855. while (g_Break) {
  856. // infinite loop, because we'll get terminated in the ctrl+c handler
  857. Sleep (50);
  858. }
  859. exit (g_ReturnCode);
  860. }