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.

886 lines
21 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. common.c
  5. Abstract:
  6. Implements code common to two or more apps.
  7. Author:
  8. Jim Schmidt (jimschm) 17-Oct-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 "common.h"
  20. //
  21. // Strings
  22. //
  23. // none
  24. //
  25. // Constants
  26. //
  27. #define LOG_VERBOSE_BIT 0x01
  28. #define LOG_UNUSED_BIT 0x02 // for v1 compatibility, do not use
  29. #define LOG_STATUS_BIT 0x04
  30. #define LOG_DEBUGGER_BIT 0x08
  31. #define LOG_UPDATE_BIT 0x10
  32. //
  33. // Macros
  34. //
  35. // none
  36. //
  37. // Types
  38. //
  39. // none
  40. //
  41. // Globals
  42. //
  43. // none
  44. //
  45. // Macro expansion list
  46. //
  47. #define REQUIRED_INFS \
  48. DEFMAC(OSFILES, TEXT("USMTDef.inf")) \
  49. //
  50. // Private function prototypes
  51. //
  52. // none
  53. //
  54. // Macro expansion definition
  55. //
  56. // this is the structure used for handling required infs
  57. typedef struct {
  58. PCTSTR InfId;
  59. PCTSTR InfName;
  60. } REQUIREDINF_STRUCT, *PREQUIREDINF_STRUCT;
  61. // declare a global array of required infs
  62. #define DEFMAC(infid,infname) {TEXT(#infid),infname},
  63. static REQUIREDINF_STRUCT g_RequiredInfs[] = {
  64. REQUIRED_INFS
  65. {NULL, NULL}
  66. };
  67. #undef DEFMAC
  68. //
  69. // Code
  70. //
  71. VOID
  72. InitAppCommon (
  73. VOID
  74. )
  75. {
  76. InfGlobalInit (FALSE);
  77. RegInitialize();
  78. }
  79. VOID
  80. TerminateAppCommon (
  81. VOID
  82. )
  83. {
  84. RegTerminate();
  85. InfGlobalInit (FALSE);
  86. }
  87. HINF
  88. InitRequiredInfs (
  89. IN PCTSTR AppPath,
  90. IN PCSTR FailMsgId
  91. )
  92. {
  93. PCTSTR fullPath;
  94. HINF result = INVALID_HANDLE_VALUE;
  95. PREQUIREDINF_STRUCT p = g_RequiredInfs;
  96. while (p->InfId) {
  97. fullPath = JoinPaths (AppPath, p->InfName);
  98. if (DoesFileExist (fullPath)) {
  99. if (result == INVALID_HANDLE_VALUE) {
  100. result = SetupOpenInfFile (fullPath, NULL, INF_STYLE_WIN4 | INF_STYLE_OLDNT, NULL);
  101. if (result == INVALID_HANDLE_VALUE) {
  102. LOG ((LOG_ERROR, FailMsgId, p->InfId, fullPath));
  103. }
  104. } else {
  105. if (!SetupOpenAppendInfFile (fullPath, result, NULL)) {
  106. LOG ((LOG_ERROR, FailMsgId, p->InfId, fullPath));
  107. }
  108. }
  109. } else {
  110. LOG ((LOG_ERROR, FailMsgId, p->InfId, fullPath));
  111. }
  112. FreePathString (fullPath);
  113. p++;
  114. }
  115. return result;
  116. }
  117. VOID
  118. PrintMsgOnConsole (
  119. IN UINT MsgId
  120. )
  121. {
  122. PCTSTR msg;
  123. msg = GetStringResource (MsgId);
  124. if (msg) {
  125. _tprintf (TEXT("%s"), msg);
  126. FreeStringResource (msg);
  127. }
  128. }
  129. VOID
  130. UploadEnvVars (
  131. IN MIG_PLATFORMTYPEID Platform
  132. )
  133. {
  134. PCTSTR envVars = NULL;
  135. MULTISZ_ENUM e;
  136. PTSTR envString;
  137. PTSTR p;
  138. //
  139. // we are going to write here all defined environment variables
  140. //
  141. envVars = (PCTSTR) GetEnvironmentStrings();
  142. if (envVars) {
  143. if (EnumFirstMultiSz (&e, envVars)) {
  144. do {
  145. envString = DuplicatePathString (e.CurrentString, 0);
  146. p = _tcschr (envString, TEXT('='));
  147. //
  148. // Get rid of empty environment strings or the dummy env string starting
  149. // with '='
  150. //
  151. if (!p || p == envString) {
  152. FreePathString (envString);
  153. continue;
  154. }
  155. *p = 0;
  156. p = _tcsinc (p);
  157. if (p) {
  158. IsmSetEnvironmentString (Platform, S_SYSENVVAR_GROUP, envString, p);
  159. }
  160. FreePathString (envString);
  161. } while (EnumNextMultiSz (&e));
  162. }
  163. }
  164. }
  165. VOID
  166. SetLogVerbosity (
  167. IN INT VerboseLevel
  168. )
  169. {
  170. LOG_LEVEL logBitmap = 0;
  171. if (VerboseLevel < 0) {
  172. VerboseLevel = 0;
  173. }
  174. // Always ON
  175. logBitmap = LL_FATAL_ERROR | LL_MODULE_ERROR | LL_ERROR;
  176. // ON for VERBOSE_BIT
  177. if (VerboseLevel & LOG_VERBOSE_BIT) {
  178. logBitmap |= LL_WARNING | LL_INFORMATION;
  179. }
  180. // ON for STATUS_BIT
  181. if (VerboseLevel & LOG_STATUS_BIT) {
  182. logBitmap |= LL_STATUS;
  183. }
  184. // ON for UPDATE_BIT
  185. if (VerboseLevel & LOG_UPDATE_BIT) {
  186. logBitmap |= LL_UPDATE;
  187. }
  188. #ifdef PRERELEASE
  189. LogSetVerboseBitmap (
  190. logBitmap,
  191. LL_FATAL_ERROR|LL_MODULE_ERROR|LL_ERROR|LL_WARNING|LL_INFORMATION|LL_STATUS|LL_UPDATE,
  192. VerboseLevel & LOG_DEBUGGER_BIT
  193. );
  194. #else
  195. LogSetVerboseBitmap (
  196. logBitmap,
  197. LL_FATAL_ERROR|LL_MODULE_ERROR|LL_ERROR|LL_WARNING|LL_INFORMATION,
  198. VerboseLevel & LOG_DEBUGGER_BIT
  199. );
  200. #endif
  201. }
  202. BOOL
  203. GetFilePath (
  204. IN PCTSTR UserSpecifiedFile,
  205. OUT PTSTR Buffer,
  206. IN UINT BufferTchars
  207. )
  208. {
  209. PTSTR tempBuffer = NULL;
  210. TCHAR infDir[MAX_MBCHAR_PATH];
  211. TCHAR modulePath[MAX_MBCHAR_PATH];
  212. TCHAR currentDir[MAX_MBCHAR_PATH];
  213. PTSTR p;
  214. PCTSTR userFile = NULL;
  215. PTSTR dontCare;
  216. __try {
  217. //
  218. // Locate the file using the full path specified by the user, or
  219. // if only a file spec was given, use the following priorities:
  220. //
  221. // 1. Current directory
  222. // 2. Directory where the tool is
  223. // 3. INF directory
  224. //
  225. // In all cases, return the full path to the file.
  226. //
  227. if (Buffer) {
  228. *Buffer = 0;
  229. } else {
  230. __leave;
  231. }
  232. tempBuffer = AllocText (BufferTchars);
  233. *tempBuffer = 0;
  234. if (!_tcsrchr (UserSpecifiedFile, TEXT('\\'))) {
  235. //
  236. // Compute INF directory, module directory and current directory
  237. //
  238. if (!GetWindowsDirectory (infDir, ARRAYSIZE(infDir) - 5)) {
  239. MYASSERT (FALSE);
  240. __leave;
  241. }
  242. StringCat (infDir, TEXT("\\inf"));
  243. if (!GetModuleFileName (NULL, modulePath, ARRAYSIZE(modulePath))) {
  244. MYASSERT (FALSE);
  245. __leave;
  246. }
  247. p = _tcsrchr (modulePath, TEXT('\\'));
  248. if (p) {
  249. *p = 0;
  250. } else {
  251. MYASSERT (FALSE);
  252. __leave;
  253. }
  254. if (!GetCurrentDirectory (ARRAYSIZE(currentDir), currentDir)) {
  255. MYASSERT (FALSE);
  256. __leave;
  257. }
  258. //
  259. // Let's see if it's in the current dir
  260. //
  261. userFile = JoinPaths (currentDir, UserSpecifiedFile);
  262. if (DoesFileExist (userFile)) {
  263. GetFullPathName (
  264. userFile,
  265. BufferTchars,
  266. tempBuffer,
  267. &dontCare
  268. );
  269. } else {
  270. //
  271. // Let's try the module dir
  272. //
  273. FreePathString (userFile);
  274. userFile = JoinPaths (modulePath, UserSpecifiedFile);
  275. if (DoesFileExist (userFile)) {
  276. GetFullPathName (
  277. userFile,
  278. BufferTchars,
  279. tempBuffer,
  280. &dontCare
  281. );
  282. } else {
  283. //
  284. // Let's try the INF dir
  285. //
  286. FreePathString (userFile);
  287. userFile = JoinPaths (infDir, UserSpecifiedFile);
  288. if (DoesFileExist (userFile)) {
  289. GetFullPathName (
  290. userFile,
  291. BufferTchars,
  292. tempBuffer,
  293. &dontCare
  294. );
  295. }
  296. }
  297. }
  298. } else {
  299. //
  300. // Use the full path that the user specified
  301. //
  302. GetFullPathName (
  303. UserSpecifiedFile,
  304. BufferTchars,
  305. tempBuffer,
  306. &dontCare
  307. );
  308. if (*tempBuffer && !DoesFileExist (tempBuffer)) {
  309. *tempBuffer = 0;
  310. }
  311. }
  312. //
  313. // Transfer output into caller's buffer. Note the TCHAR conversion.
  314. //
  315. StringCopy (Buffer, tempBuffer);
  316. }
  317. __finally {
  318. if (userFile) {
  319. FreePathString (userFile);
  320. }
  321. if (tempBuffer) {
  322. FreeText (tempBuffer);
  323. }
  324. }
  325. return (Buffer && (*Buffer != 0));
  326. }
  327. VOID
  328. WriteAppStatus (
  329. IN PCTSTR AppJournal,
  330. IN DWORD Status
  331. )
  332. {
  333. HANDLE appJrnHandle;
  334. if (AppJournal && AppJournal [0]) {
  335. appJrnHandle = BfOpenFile (AppJournal);
  336. if (!appJrnHandle) {
  337. appJrnHandle = BfCreateFile (AppJournal);
  338. }
  339. if (appJrnHandle) {
  340. if (BfSetFilePointer (appJrnHandle, 0)) {
  341. BfWriteFile (appJrnHandle, (PBYTE)(&Status), sizeof (DWORD));
  342. }
  343. FlushFileBuffers (appJrnHandle);
  344. CloseHandle (appJrnHandle);
  345. }
  346. }
  347. }
  348. DWORD
  349. ReadAppStatus (
  350. IN PCTSTR AppJournal
  351. )
  352. {
  353. HANDLE appJrnHandle;
  354. DWORD result = 0;
  355. if (AppJournal && AppJournal [0]) {
  356. appJrnHandle = BfOpenReadFile (AppJournal);
  357. if (appJrnHandle) {
  358. if (BfSetFilePointer (appJrnHandle, 0)) {
  359. if (!BfReadFile (appJrnHandle, (PBYTE)(&result), sizeof (DWORD))) {
  360. result = 0;
  361. }
  362. }
  363. CloseHandle (appJrnHandle);
  364. }
  365. }
  366. return result;
  367. }
  368. VOID
  369. SelectComponentsViaInf (
  370. IN HINF Inf
  371. )
  372. {
  373. INFSTRUCT is = INITINFSTRUCT_GROWBUFFER;
  374. PCTSTR data;
  375. //
  376. // Enable or disable components based on the unlocalized tag name,
  377. // or by the localized string
  378. //
  379. if (InfFindFirstLine (Inf, TEXT("Disabled Components"), NULL, &is)) {
  380. do {
  381. data = InfGetStringField (&is, 1);
  382. if (data) {
  383. if (!IsmSelectComponent (data, 0, FALSE)) {
  384. IsmSelectComponent (data, COMPONENT_NAME, FALSE);
  385. }
  386. }
  387. } while (InfFindNextLine (&is));
  388. }
  389. if (InfFindFirstLine (Inf, TEXT("Enabled Components"), NULL, &is)) {
  390. do {
  391. data = InfGetStringField (&is, 1);
  392. if (data) {
  393. if (!IsmSelectComponent (data, 0, TRUE)) {
  394. IsmSelectComponent (data, COMPONENT_NAME, TRUE);
  395. }
  396. }
  397. } while (InfFindNextLine (&is));
  398. }
  399. }
  400. PARSERESULT
  401. ParseToolCmdLine (
  402. IN BOOL ScanState,
  403. OUT PTOOLARGS Args,
  404. IN INT Argc,
  405. IN PCTSTR Argv[]
  406. )
  407. {
  408. INT i;
  409. PCTSTR infFileFromCmdLine;
  410. TCHAR fullInfPath[MAX_TCHAR_PATH];
  411. MULTISZ_ENUM e;
  412. HANDLE h;
  413. BOOL logCreated = FALSE;
  414. BOOL everythingOn = TRUE;
  415. BOOL xSwitch = FALSE;
  416. #ifdef PRERELEASE
  417. DWORD tagSize;
  418. #endif
  419. ZeroMemory (Args, sizeof (TOOLARGS));
  420. Args->VerboseLevel = -1;
  421. Args->TransportName = S_RELIABLE_STORAGE_TRANSPORT;
  422. #ifdef PRERELEASE
  423. tagSize = ARRAYSIZE(Args->Tag);
  424. GetUserName (Args->Tag, &tagSize);
  425. #endif
  426. for (i = 1 ; i < Argc ; i++) {
  427. if (Argv[i][0] == TEXT('-') || Argv[i][0] == '/') {
  428. switch ((CHARTYPE) _totlower ((CHARTYPE) _tcsnextc (&Argv[i][1]))) {
  429. case TEXT('i'):
  430. if (Argv[i][2] == TEXT('x') && !Argv[i][3]) {
  431. if (ScanState) {
  432. return PARSE_OTHER_ERROR;
  433. }
  434. if (Args->NoScanStateInfs) {
  435. return PARSE_OTHER_ERROR;
  436. }
  437. Args->NoScanStateInfs = TRUE;
  438. break;
  439. }
  440. if (Argv[i][2] == TEXT(':')) {
  441. infFileFromCmdLine = &Argv[i][3];
  442. } else if (i + 1 < Argc) {
  443. i++;
  444. infFileFromCmdLine = Argv[i];
  445. } else {
  446. return PARSE_OTHER_ERROR;
  447. }
  448. if (!GetFilePath (infFileFromCmdLine, fullInfPath, ARRAYSIZE(fullInfPath))) {
  449. GbMultiSzAppend (&Args->BadInfs, infFileFromCmdLine);
  450. break;
  451. }
  452. //
  453. // Make sure fullInfPath was not already specified
  454. //
  455. if (Args->InputInf.End) {
  456. if (EnumFirstMultiSz (&e, (PCTSTR) Args->InputInf.Buf)) {
  457. do {
  458. if (StringIMatch (e.CurrentString, fullInfPath)) {
  459. GbMultiSzAppend (&Args->MultiInfs, infFileFromCmdLine);
  460. *fullInfPath = 0;
  461. break;
  462. }
  463. } while (EnumNextMultiSz (&e));
  464. }
  465. if (*fullInfPath == 0) {
  466. break;
  467. }
  468. }
  469. //
  470. // INF file is valid
  471. //
  472. GbMultiSzAppend (&Args->InputInf, fullInfPath);
  473. break;
  474. case TEXT('l'):
  475. if (Args->LogFile) {
  476. return PARSE_MULTI_LOG;
  477. }
  478. if (Argv[i][2] == TEXT(':')) {
  479. Args->LogFile = &(Argv[i][3]);
  480. } else if (i + 1 < Argc) {
  481. i++;
  482. Args->LogFile = Argv[i];
  483. } else {
  484. return PARSE_OTHER_ERROR;
  485. }
  486. h = BfCreateFile (Args->LogFile);
  487. if (!h) {
  488. return PARSE_BAD_LOG;
  489. }
  490. CloseHandle (h);
  491. logCreated = TRUE;
  492. break;
  493. case TEXT('v'):
  494. if (Args->VerboseLevel >= 0) {
  495. return PARSE_MULTI_VERBOSE;
  496. }
  497. if (Argv[i][2] == TEXT(':')) {
  498. _stscanf (&(Argv[i][3]), TEXT("%d"), &Args->VerboseLevel);
  499. } else if (i + 1 < Argc) {
  500. if (_tcsnextc (Argv[i + 1]) >= TEXT('0') &&
  501. _tcsnextc (Argv[i + 1]) <= TEXT('9')
  502. ) {
  503. i++;
  504. _stscanf (Argv[i], TEXT("%d"), &Args->VerboseLevel);
  505. } else {
  506. Args->VerboseLevel = 1;
  507. }
  508. } else {
  509. return PARSE_OTHER_ERROR;
  510. }
  511. #ifndef PRERELEASE
  512. if (Args->VerboseLevel > 7) {
  513. #else
  514. Args->VerboseLevel |= LOG_UPDATE_BIT;
  515. if (Args->VerboseLevel > 0x1F) {
  516. #endif
  517. return PARSE_OTHER_ERROR;
  518. }
  519. break;
  520. case TEXT('x'):
  521. if (xSwitch) {
  522. return PARSE_OTHER_ERROR;
  523. }
  524. if (Argv[i][2]) {
  525. return PARSE_OTHER_ERROR;
  526. }
  527. everythingOn = FALSE;
  528. xSwitch = TRUE;
  529. break;
  530. case TEXT('s'):
  531. if (Args->SystemOn) {
  532. return PARSE_OTHER_ERROR;
  533. }
  534. if (Argv[i][2]) {
  535. return PARSE_OTHER_ERROR;
  536. }
  537. Args->SystemOn = TRUE;
  538. everythingOn = FALSE;
  539. break;
  540. case TEXT('u'):
  541. if (Args->UserOn) {
  542. return PARSE_OTHER_ERROR;
  543. }
  544. if (Argv[i][2]) {
  545. return PARSE_OTHER_ERROR;
  546. }
  547. Args->UserOn = TRUE;
  548. everythingOn = FALSE;
  549. break;
  550. case TEXT('f'):
  551. if (Args->FilesOn) {
  552. return PARSE_OTHER_ERROR;
  553. }
  554. if (Argv[i][2]) {
  555. return PARSE_OTHER_ERROR;
  556. }
  557. Args->FilesOn = TRUE;
  558. everythingOn = FALSE;
  559. break;
  560. case TEXT('q'):
  561. if (ScanState) {
  562. Args->OverwriteImage = TRUE;
  563. Args->TestMode = TRUE;
  564. } else {
  565. Args->CurrentUser = TRUE;
  566. }
  567. break;
  568. case TEXT('o'):
  569. if (!ScanState) {
  570. return PARSE_OTHER_ERROR;
  571. }
  572. if (Args->OverwriteImage) {
  573. return PARSE_OTHER_ERROR;
  574. }
  575. if (Argv[i][2]) {
  576. return PARSE_OTHER_ERROR;
  577. }
  578. Args->OverwriteImage = TRUE;
  579. break;
  580. case TEXT('c'):
  581. if (Argv[i][2]) {
  582. return PARSE_OTHER_ERROR;
  583. }
  584. if (ScanState) {
  585. if (Args->ContinueOnError) {
  586. return PARSE_OTHER_ERROR;
  587. }
  588. Args->ContinueOnError = TRUE;
  589. } else {
  590. return PARSE_OTHER_ERROR;
  591. }
  592. break;
  593. case TEXT('d'):
  594. if (ScanState) {
  595. return PARSE_OTHER_ERROR;
  596. }
  597. if (Args->DelayedOpsOn) {
  598. return PARSE_OTHER_ERROR;
  599. }
  600. if (Argv[i][2]) {
  601. return PARSE_OTHER_ERROR;
  602. }
  603. Args->DelayedOpsOn = TRUE;
  604. break;
  605. #ifdef PRERELEASE
  606. case TEXT('t'):
  607. switch ((CHARTYPE) _totlower (Argv[i][2])) {
  608. case TEXT('f'):
  609. if (Argv[i][3]) {
  610. return PARSE_OTHER_ERROR;
  611. }
  612. if (Args->FullTransport) {
  613. return PARSE_OTHER_ERROR;
  614. }
  615. Args->FullTransport = TRUE;
  616. break;
  617. case TEXT('c'):
  618. if (Argv[i][3]) {
  619. return PARSE_OTHER_ERROR;
  620. }
  621. if (Args->Capabilities & CAPABILITY_COMPRESSED) {
  622. return PARSE_OTHER_ERROR;
  623. }
  624. Args->Capabilities |= CAPABILITY_COMPRESSED;
  625. break;
  626. case TEXT('a'):
  627. if (Argv[i][3]) {
  628. return PARSE_OTHER_ERROR;
  629. }
  630. if (Args->Capabilities & CAPABILITY_AUTOMATED) {
  631. return PARSE_OTHER_ERROR;
  632. }
  633. Args->Capabilities |= CAPABILITY_AUTOMATED;
  634. break;
  635. case TEXT('i'):
  636. if (Argv[i][3] != TEXT(':')) {
  637. return PARSE_OTHER_ERROR;
  638. }
  639. StackStringCopy (Args->Tag, &Argv[i][4]);
  640. break;
  641. case 0:
  642. case TEXT(':'):
  643. if (Args->TransportNameSpecified) {
  644. return PARSE_OTHER_ERROR;
  645. }
  646. Args->TransportNameSpecified = TRUE;
  647. if (Argv[i][2]) {
  648. if (!Argv[i][3]) {
  649. return PARSE_OTHER_ERROR;
  650. }
  651. Args->TransportName = &Argv[i][3];
  652. } else {
  653. if (i + 1 >= Argc) {
  654. return PARSE_OTHER_ERROR;
  655. } else {
  656. i++;
  657. Args->TransportName = Argv[i];
  658. }
  659. }
  660. break;
  661. default:
  662. return PARSE_OTHER_ERROR;
  663. }
  664. break;
  665. case TEXT('r'):
  666. if (ScanState) {
  667. return PARSE_OTHER_ERROR;
  668. }
  669. if (Args->Recovery) {
  670. return PARSE_OTHER_ERROR;
  671. }
  672. if (Argv[i][2]) {
  673. return PARSE_OTHER_ERROR;
  674. }
  675. Args->Recovery = TRUE;
  676. break;
  677. #endif
  678. default:
  679. return PARSE_OTHER_ERROR;
  680. }
  681. } else if (!Args->StoragePath) {
  682. Args->StoragePath = Argv[i];
  683. } else {
  684. return PARSE_OTHER_ERROR;
  685. }
  686. }
  687. if (!Args->StoragePath) {
  688. if (!Args->DelayedOpsOn) {
  689. return PARSE_MISSING_STORAGE_PATH;
  690. }
  691. }
  692. if (everythingOn) {
  693. Args->SystemOn = TRUE;
  694. Args->UserOn = TRUE;
  695. Args->FilesOn = TRUE;
  696. }
  697. if (Args->InputInf.Buf) {
  698. GbMultiSzAppend (&Args->InputInf, TEXT(""));
  699. }
  700. return PARSE_SUCCESS;
  701. }