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.

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