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.

1723 lines
42 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. app.c
  5. Abstract:
  6. Implements a set of functions to manage data for an application section.
  7. Author:
  8. Jim Schmidt (jimschm) 05-Jun-2000
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. //
  13. // Includes
  14. //
  15. #include "pch.h"
  16. #include "v1p.h"
  17. #define DBG_FOO "Foo"
  18. //
  19. // Strings
  20. //
  21. // None
  22. //
  23. // Constants
  24. //
  25. #define MAX_EXPANDED_STRING 4096
  26. //
  27. // Macros
  28. //
  29. // None
  30. //
  31. // Types
  32. //
  33. // None
  34. //
  35. // Globals
  36. //
  37. PMHANDLE g_AppPool;
  38. extern BOOL g_VcmMode; // in sgmqueue.c
  39. GROWLIST g_SectionStack = INIT_GROWLIST;
  40. //
  41. // Macro expansion list
  42. //
  43. // None
  44. //
  45. // Private function prototypes
  46. //
  47. BOOL
  48. pParseAppEnvSection (
  49. IN MIG_PLATFORMTYPEID Platform,
  50. IN HINF InfFile,
  51. IN PCTSTR Application,
  52. IN PCTSTR Section
  53. );
  54. //
  55. // Macro expansion definition
  56. //
  57. // None
  58. //
  59. // Code
  60. //
  61. VOID
  62. InitAppModule (
  63. VOID
  64. )
  65. {
  66. g_AppPool = PmCreateNamedPool ("v1 App");
  67. }
  68. VOID
  69. TerminateAppModule (
  70. VOID
  71. )
  72. {
  73. PmDestroyPool (g_AppPool);
  74. INVALID_POINTER (g_AppPool);
  75. }
  76. UINT
  77. pSafeTcharCount (
  78. IN PCTSTR String
  79. )
  80. {
  81. if (String) {
  82. return TcharCount (String);
  83. }
  84. return 0;
  85. }
  86. PCTSTR
  87. GetMostSpecificSection (
  88. IN PINFSTRUCT InfStruct,
  89. IN HINF InfFile,
  90. IN PCTSTR BaseSection
  91. )
  92. {
  93. PTSTR specificSection;
  94. MIG_OSVERSIONINFO versionInfo;
  95. UINT tchars;
  96. if (!IsmGetOsVersionInfo (PLATFORM_SOURCE, &versionInfo)) {
  97. return NULL;
  98. }
  99. tchars = TcharCount (BaseSection) + 1;
  100. tchars += pSafeTcharCount (versionInfo.OsTypeName) + 1;
  101. tchars += pSafeTcharCount (versionInfo.OsMajorVersionName) + 1;
  102. tchars += pSafeTcharCount (versionInfo.OsMinorVersionName) + 1;
  103. specificSection = AllocText (tchars);
  104. if (versionInfo.OsTypeName &&
  105. versionInfo.OsMajorVersionName &&
  106. versionInfo.OsMinorVersionName
  107. ) {
  108. wsprintf (
  109. specificSection,
  110. TEXT("%s.%s.%s.%s"),
  111. BaseSection,
  112. versionInfo.OsTypeName,
  113. versionInfo.OsMajorVersionName,
  114. versionInfo.OsMinorVersionName
  115. );
  116. if (InfFindFirstLine (InfFile, specificSection, NULL, InfStruct)) {
  117. return specificSection;
  118. }
  119. }
  120. if (versionInfo.OsTypeName &&
  121. versionInfo.OsMajorVersionName
  122. ) {
  123. wsprintf (
  124. specificSection,
  125. TEXT("%s.%s.%s"),
  126. BaseSection,
  127. versionInfo.OsTypeName,
  128. versionInfo.OsMajorVersionName
  129. );
  130. if (InfFindFirstLine (InfFile, specificSection, NULL, InfStruct)) {
  131. return specificSection;
  132. }
  133. }
  134. if (versionInfo.OsTypeName) {
  135. wsprintf (
  136. specificSection,
  137. TEXT("%s.%s"),
  138. BaseSection,
  139. versionInfo.OsTypeName
  140. );
  141. if (InfFindFirstLine (InfFile, specificSection, NULL, InfStruct)) {
  142. return specificSection;
  143. }
  144. }
  145. FreeText (specificSection);
  146. return NULL;
  147. }
  148. BOOL
  149. pCheckForRecursion (
  150. IN PCTSTR Section
  151. )
  152. {
  153. UINT count;
  154. UINT u;
  155. count = GlGetSize (&g_SectionStack);
  156. for (u = 0 ; u < count ; u++) {
  157. if (StringIMatch (GlGetString (&g_SectionStack, u), Section)) {
  158. return TRUE;
  159. }
  160. }
  161. return FALSE;
  162. }
  163. VOID
  164. pPushSection (
  165. IN PCTSTR Section
  166. )
  167. {
  168. GlAppendString (&g_SectionStack, Section);
  169. }
  170. VOID
  171. pPopSection (
  172. IN PCTSTR Section
  173. )
  174. {
  175. UINT u;
  176. u = GlGetSize (&g_SectionStack);
  177. while (u > 0) {
  178. u--;
  179. if (StringIMatch (GlGetString (&g_SectionStack, u), Section)) {
  180. GlDeleteItem (&g_SectionStack, u);
  181. return;
  182. }
  183. }
  184. MYASSERT (FALSE);
  185. }
  186. UINT
  187. pGetDisplayTypeFromString (
  188. IN PCTSTR String
  189. )
  190. {
  191. if (!String) {
  192. return 0;
  193. }
  194. if (StringIMatch (String, TEXT("EXT"))) {
  195. return COMPONENT_EXTENSION;
  196. }
  197. if (StringIMatch (String, TEXT("FILE"))) {
  198. return COMPONENT_FILE;
  199. }
  200. if (StringIMatch (String, TEXT("DIR"))) {
  201. return COMPONENT_FOLDER;
  202. }
  203. return 0;
  204. }
  205. BOOL
  206. pAddFilesAndFoldersComponent (
  207. IN PCTSTR ComponentString, OPTIONAL
  208. IN PCTSTR TypeString,
  209. IN PCTSTR MultiSz,
  210. IN UINT MasterGroup,
  211. IN OUT PBOOL MarkAsPreferred
  212. )
  213. {
  214. MULTISZ_ENUM e;
  215. TCHAR expandBuffer[MAX_PATH];
  216. UINT displayType;
  217. displayType = pGetDisplayTypeFromString (TypeString);
  218. if (!displayType) {
  219. LOG ((LOG_ERROR, (PCSTR) MSG_INVALID_FNF_TYPE, TypeString));
  220. return TRUE;
  221. }
  222. if (EnumFirstMultiSz (&e, MultiSz)) {
  223. do {
  224. //
  225. // Expand e.CurrentString
  226. //
  227. MappingSearchAndReplaceEx (
  228. g_EnvMap,
  229. e.CurrentString,
  230. expandBuffer,
  231. 0,
  232. NULL,
  233. ARRAYSIZE(expandBuffer),
  234. 0,
  235. NULL,
  236. NULL
  237. );
  238. //
  239. // Add component
  240. //
  241. IsmAddComponentAlias (
  242. ComponentString,
  243. MasterGroup,
  244. expandBuffer,
  245. displayType,
  246. FALSE
  247. );
  248. if (ComponentString && *MarkAsPreferred) {
  249. IsmSelectPreferredAlias (ComponentString, expandBuffer, displayType);
  250. *MarkAsPreferred = FALSE;
  251. }
  252. } while (EnumNextMultiSz (&e));
  253. } else {
  254. LOG ((LOG_WARNING, (PCSTR) MSG_EMPTY_FNF_SPEC, TypeString));
  255. }
  256. return TRUE;
  257. }
  258. BOOL
  259. pAddFilesAndFoldersSection (
  260. IN HINF InfFile,
  261. IN PCTSTR Section,
  262. IN UINT MasterGroup,
  263. IN BOOL GroupAllUnderSection,
  264. IN PBOOL MarkAsPreferred
  265. )
  266. {
  267. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  268. PCTSTR type;
  269. PCTSTR multiSz;
  270. BOOL result = TRUE;
  271. PCTSTR decoratedSection = NULL;
  272. if (GroupAllUnderSection) {
  273. decoratedSection = JoinText (TEXT("$"), Section);
  274. }
  275. if (InfFindFirstLine (InfFile, Section, NULL, &is)) {
  276. do {
  277. InfResetInfStruct (&is);
  278. type = InfGetStringField (&is, 1);
  279. multiSz = InfGetMultiSzField (&is, 2);
  280. result = pAddFilesAndFoldersComponent (
  281. decoratedSection,
  282. type,
  283. multiSz,
  284. MasterGroup,
  285. MarkAsPreferred
  286. );
  287. } while (result && InfFindNextLine (&is));
  288. }
  289. InfCleanUpInfStruct (&is);
  290. FreeText (decoratedSection);
  291. if (!result) {
  292. LOG ((LOG_ERROR, (PCSTR) MSG_SECTION_ERROR, Section));
  293. }
  294. return result;
  295. }
  296. BOOL
  297. pAddFilesAndFoldersComponentOrSection (
  298. IN HINF InfFile,
  299. IN PCTSTR ComponentString, OPTIONAL
  300. IN PCTSTR TypeString,
  301. IN PCTSTR MultiSz,
  302. IN UINT MasterGroup,
  303. IN PBOOL MarkAsPreferred
  304. )
  305. {
  306. MULTISZ_ENUM e;
  307. BOOL result = TRUE;
  308. if (StringIMatch (TypeString, TEXT("Section"))) {
  309. if (EnumFirstMultiSz (&e, MultiSz)) {
  310. do {
  311. result = pAddFilesAndFoldersSection (InfFile, e.CurrentString, MasterGroup, TRUE, MarkAsPreferred);
  312. } while (result && EnumNextMultiSz (&e));
  313. }
  314. } else {
  315. result = pAddFilesAndFoldersComponent (ComponentString, TypeString, MultiSz, MasterGroup, MarkAsPreferred);
  316. }
  317. return result;
  318. }
  319. BOOL
  320. AddAppSpecificEnvVar (
  321. IN MIG_PLATFORMTYPEID Platform,
  322. IN PCTSTR AppTag,
  323. IN PCTSTR VariableName,
  324. IN PCTSTR VariableData OPTIONAL
  325. )
  326. {
  327. TCHAR destBuffer[MAX_TCHAR_PATH * 4];
  328. PMAPSTRUCT mapArray[1];
  329. UINT mapCount = 0;
  330. BOOL updated;
  331. PTSTR buffer;
  332. PTSTR p;
  333. PTSTR q;
  334. BOOL ignoreLastPercent = FALSE;
  335. PCTSTR undefText;
  336. //
  337. // Verify VariableName is legal
  338. //
  339. if (_tcsnextc (VariableName) == TEXT('%')) {
  340. VariableName++;
  341. ignoreLastPercent = TRUE;
  342. }
  343. if (*VariableName == 0) {
  344. LOG ((LOG_WARNING, (PCSTR) MSG_EMPTY_APP_ENV_VAR));
  345. return FALSE;
  346. }
  347. //
  348. // Transfer VariableName into %<VariableName>%
  349. //
  350. buffer = AllocText (SizeOfString (VariableName) + 2);
  351. MYASSERT (buffer);
  352. if (!buffer) {
  353. return FALSE;
  354. }
  355. p = buffer;
  356. *p++ = TEXT('%');
  357. *p = 0;
  358. p = StringCat (p, VariableName);
  359. if (ignoreLastPercent) {
  360. q = _tcsdec (buffer, p);
  361. if (q) {
  362. if (_tcsnextc (q) == TEXT('%')) {
  363. p = q;
  364. }
  365. }
  366. }
  367. *p++ = TEXT('%');
  368. *p = 0;
  369. //
  370. // Add %<VariableName>% -> VariableData to string mapping table
  371. //
  372. if (VariableData) {
  373. if (Platform == PLATFORM_SOURCE) {
  374. // let's see if this already exists
  375. mapArray[mapCount] = g_EnvMap;
  376. updated = MappingMultiTableSearchAndReplaceEx (
  377. mapArray,
  378. mapCount + 1,
  379. buffer,
  380. destBuffer,
  381. 0,
  382. NULL,
  383. ARRAYSIZE (destBuffer),
  384. STRMAP_COMPLETE_MATCH_ONLY,
  385. NULL,
  386. NULL
  387. );
  388. if (updated) {
  389. LOG ((LOG_ERROR, (PCSTR) MSG_DUPLICATE_ENV_VAR, buffer));
  390. }
  391. IsmSetEnvironmentString (PLATFORM_SOURCE, S_SYSENVVAR_GROUP, VariableName, VariableData);
  392. AddStringMappingPair (g_EnvMap, buffer, VariableData);
  393. } else {
  394. MYASSERT (Platform == PLATFORM_DESTINATION);
  395. // let's see if this already exists
  396. mapArray[mapCount] = g_DestEnvMap;
  397. updated = MappingMultiTableSearchAndReplaceEx (
  398. mapArray,
  399. mapCount + 1,
  400. buffer,
  401. destBuffer,
  402. 0,
  403. NULL,
  404. ARRAYSIZE (destBuffer),
  405. STRMAP_COMPLETE_MATCH_ONLY,
  406. NULL,
  407. NULL
  408. );
  409. if (updated) {
  410. LOG ((LOG_ERROR, (PCSTR) MSG_DUPLICATE_ENV_VAR, buffer));
  411. }
  412. AddRemappingEnvVar (g_DestEnvMap, g_FileNodeFilterMap, NULL, VariableName, VariableData);
  413. }
  414. } else {
  415. LOG ((LOG_INFORMATION, (PCSTR) MSG_UNDEF_APP_VAR, buffer));
  416. undefText = JoinTextEx (NULL, TEXT("--> "), TEXT(" <--"), buffer, 0, NULL);
  417. AddStringMappingPair (g_UndefMap, buffer, undefText);
  418. FreeText (undefText);
  419. }
  420. FreeText (buffer);
  421. return TRUE;
  422. }
  423. BOOL
  424. AppCheckAndLogUndefVariables (
  425. IN MIG_PLATFORMTYPEID Platform,
  426. IN PCTSTR Application,
  427. IN PCTSTR UnexpandedString
  428. )
  429. {
  430. TCHAR buffer[MAX_TCHAR_PATH * 4];
  431. PMAPSTRUCT mapArray[1];
  432. UINT mapCount = 0;
  433. BOOL updated;
  434. mapArray[mapCount] = g_UndefMap;
  435. updated = MappingMultiTableSearchAndReplaceEx (
  436. mapArray,
  437. mapCount + 1,
  438. UnexpandedString,
  439. buffer,
  440. 0,
  441. NULL,
  442. ARRAYSIZE(buffer),
  443. 0,
  444. NULL,
  445. NULL
  446. );
  447. if (updated) {
  448. if (buffer [0]) {
  449. LOG ((LOG_INFORMATION, (PCSTR) MSG_UNDEF_BUT_GOOD_VAR, buffer));
  450. }
  451. } else {
  452. if (buffer [0]) {
  453. LOG ((LOG_INFORMATION, (PCSTR) MSG_ENV_VAR_COULD_BE_BAD, buffer));
  454. }
  455. }
  456. return updated;
  457. }
  458. BOOL
  459. AppSearchAndReplace (
  460. IN MIG_PLATFORMTYPEID Platform,
  461. IN PCTSTR Application,
  462. IN PCTSTR UnexpandedString,
  463. OUT PTSTR ExpandedString,
  464. IN UINT ExpandedStringTchars
  465. )
  466. {
  467. PMAPSTRUCT mapArray[1];
  468. UINT mapCount = 0;
  469. BOOL updated;
  470. PCTSTR newString = NULL;
  471. PCTSTR percent;
  472. PCTSTR endPercent;
  473. PCTSTR equals;
  474. BOOL result = TRUE;
  475. //
  476. // Let's expand the incoming string by using the source machine defined environment variables.
  477. //
  478. newString = IsmExpandEnvironmentString (Platform, S_SYSENVVAR_GROUP, UnexpandedString, NULL);
  479. if (Platform == PLATFORM_SOURCE) {
  480. mapArray[mapCount] = g_EnvMap;
  481. } else {
  482. MYASSERT (Platform == PLATFORM_DESTINATION);
  483. mapArray[mapCount] = g_DestEnvMap;
  484. }
  485. updated = MappingMultiTableSearchAndReplaceEx (
  486. mapArray,
  487. mapCount + 1,
  488. newString,
  489. ExpandedString,
  490. 0,
  491. NULL,
  492. ExpandedStringTchars,
  493. 0,
  494. NULL,
  495. NULL
  496. );
  497. if (newString) {
  498. IsmReleaseMemory (newString);
  499. newString = NULL;
  500. }
  501. //
  502. // Alert the user to an unexpanded environment variable
  503. //
  504. if (!updated) {
  505. percent = ExpandedString;
  506. do {
  507. percent = _tcschr (percent, TEXT('%'));
  508. if (percent) {
  509. percent = _tcsinc (percent);
  510. endPercent = _tcschr (percent, TEXT('%'));
  511. if (endPercent > percent) {
  512. equals = percent;
  513. while (equals < endPercent) {
  514. if (_tcsnextc (equals) == TEXT('=')) {
  515. break;
  516. }
  517. equals = _tcsinc (equals);
  518. }
  519. if (equals >= endPercent) {
  520. result = FALSE;
  521. break;
  522. }
  523. }
  524. }
  525. } while (percent && endPercent);
  526. }
  527. return result;
  528. }
  529. BOOL
  530. pGetDataFromObjectSpec (
  531. IN MIG_PLATFORMTYPEID Platform,
  532. IN PCTSTR Application,
  533. IN PCTSTR InfObjectType,
  534. IN PCTSTR InfObjectName,
  535. IN PCTSTR ArgumentMultiSz, OPTIONAL
  536. OUT PTSTR OutContentBuffer, OPTIONAL
  537. IN UINT OutContentBufferTchars,
  538. OUT PBOOL TestResults OPTIONAL
  539. )
  540. {
  541. ATTRIB_DATA attribData;
  542. BOOL test;
  543. MYASSERT (Application);
  544. MYASSERT (InfObjectType);
  545. MYASSERT (InfObjectName);
  546. ZeroMemory (&attribData, sizeof (ATTRIB_DATA));
  547. attribData.Platform = Platform;
  548. attribData.ScriptSpecifiedType = InfObjectType;
  549. attribData.ScriptSpecifiedObject = InfObjectName;
  550. attribData.ApplicationName = Application;
  551. if (AllocScriptType (&attribData)) {
  552. if (g_VcmMode && attribData.ObjectName) {
  553. if (IsmDoesObjectExist (attribData.ObjectTypeId, attribData.ObjectName)) {
  554. IsmMakePersistentObject (attribData.ObjectTypeId, attribData.ObjectName);
  555. }
  556. }
  557. if (attribData.ReturnString) {
  558. if (OutContentBuffer) {
  559. StringCopyTcharCount (
  560. OutContentBuffer,
  561. attribData.ReturnString,
  562. OutContentBufferTchars
  563. );
  564. }
  565. }
  566. if (TestResults) {
  567. if (ArgumentMultiSz) {
  568. test = TestAttributes (g_AppPool, ArgumentMultiSz, &attribData);
  569. } else {
  570. test = (attribData.ReturnString != NULL);
  571. }
  572. *TestResults = test;
  573. }
  574. FreeScriptType (&attribData);
  575. } else {
  576. return FALSE;
  577. }
  578. return TRUE;
  579. }
  580. VOID
  581. pAddPlatformEnvVar (
  582. IN HINF InfFile,
  583. IN MIG_PLATFORMTYPEID Platform,
  584. IN PCTSTR Application,
  585. IN PCTSTR Section,
  586. IN PCTSTR Variable,
  587. IN PCTSTR Type,
  588. IN PCTSTR Data,
  589. IN PCTSTR ArgMultiSz,
  590. IN PINFSTRUCT InfStruct
  591. )
  592. {
  593. BOOL exists;
  594. BOOL validString;
  595. PCTSTR p;
  596. PCTSTR end;
  597. TCHAR variableData[MAX_PATH + 1];
  598. PCTSTR varDataLong = NULL;
  599. ZeroMemory (&variableData, sizeof (variableData));
  600. //
  601. // Variable data is specified in the object represented by <data>
  602. //
  603. if (!pGetDataFromObjectSpec (
  604. Platform,
  605. Application,
  606. Type,
  607. Data,
  608. ArgMultiSz,
  609. variableData,
  610. ARRAYSIZE(variableData) - 1,
  611. &exists
  612. )) {
  613. switch (GetLastError()) {
  614. case ERROR_INVALID_DATA:
  615. LOG ((
  616. LOG_WARNING,
  617. (PCSTR) MSG_DETECT_DATA_OBJECT_IS_BAD,
  618. Data,
  619. Variable
  620. ));
  621. InfLogContext (LOG_WARNING, InfFile, InfStruct);
  622. break;
  623. case ERROR_INVALID_DATATYPE:
  624. LOG ((
  625. LOG_ERROR,
  626. (PCSTR) MSG_DETECT_DATA_TYPE_IS_BAD,
  627. Type,
  628. Variable
  629. ));
  630. InfLogContext (LOG_ERROR, InfFile, InfStruct);
  631. break;
  632. }
  633. } else {
  634. validString = FALSE;
  635. if (exists) {
  636. p = variableData;
  637. end = variableData + MAX_PATH;
  638. while (p < end) {
  639. if (_tcsnextc (p) < 32) {
  640. break;
  641. }
  642. p = _tcsinc (p);
  643. }
  644. if (*p == 0 && p < end && p > variableData) {
  645. validString = TRUE;
  646. }
  647. }
  648. if (validString) {
  649. if (IsValidFileSpec (variableData)) {
  650. varDataLong = BfGetLongFileName (variableData);
  651. } else {
  652. varDataLong = variableData;
  653. }
  654. }
  655. if (!validString && exists) {
  656. LOG ((LOG_INFORMATION, (PCSTR) MSG_DATA_IS_NOT_A_STRING, Variable));
  657. } else {
  658. LOG_IF ((
  659. validString,
  660. LOG_INFORMATION,
  661. (PCSTR) MSG_APP_ENV_DEF_INFO,
  662. Variable,
  663. Type,
  664. Data,
  665. variableData
  666. ));
  667. LOG_IF ((
  668. !validString,
  669. LOG_INFORMATION,
  670. (PCSTR) MSG_NUL_APP_ENV_DEF_INFO,
  671. Variable,
  672. Type,
  673. Data
  674. ));
  675. AddAppSpecificEnvVar (
  676. Platform,
  677. Application,
  678. Variable,
  679. validString ? varDataLong : NULL
  680. );
  681. }
  682. if (varDataLong && (varDataLong != variableData)) {
  683. FreePathString (varDataLong);
  684. varDataLong = NULL;
  685. }
  686. }
  687. }
  688. PCTSTR
  689. pProcessArgEnvironmentVars (
  690. IN MIG_PLATFORMTYPEID Platform,
  691. IN PCTSTR Application,
  692. IN PCTSTR Args,
  693. IN BOOL MultiSz,
  694. OUT PGROWBUFFER UpdatedData
  695. )
  696. {
  697. MULTISZ_ENUM e;
  698. TCHAR buffer[MAX_EXPANDED_STRING];
  699. UpdatedData->End = 0;
  700. if (MultiSz) {
  701. if (EnumFirstMultiSz (&e, Args)) {
  702. do {
  703. AppSearchAndReplace (
  704. Platform,
  705. Application,
  706. e.CurrentString,
  707. buffer,
  708. MAX_EXPANDED_STRING
  709. );
  710. GbMultiSzAppend (UpdatedData, buffer);
  711. } while (EnumNextMultiSz (&e));
  712. }
  713. } else {
  714. AppSearchAndReplace (
  715. Platform,
  716. Application,
  717. Args,
  718. buffer,
  719. MAX_EXPANDED_STRING
  720. );
  721. GbMultiSzAppend (UpdatedData, buffer);
  722. }
  723. return (PCTSTR) UpdatedData->Buf;
  724. }
  725. BOOL
  726. pParseAppEnvSectionWorker (
  727. IN MIG_PLATFORMTYPEID Platform,
  728. IN PINFSTRUCT InfStruct,
  729. IN HINF InfFile,
  730. IN PCTSTR Application,
  731. IN PCTSTR Section
  732. )
  733. {
  734. BOOL result = FALSE;
  735. PCTSTR variable;
  736. PCTSTR type;
  737. PCTSTR data;
  738. PCTSTR args;
  739. PCTSTR updatedData;
  740. PCTSTR updatedArgs;
  741. PTSTR lastChar;
  742. GROWBUFFER dataBuf = INIT_GROWBUFFER;
  743. GROWBUFFER argBuf = INIT_GROWBUFFER;
  744. //
  745. // Section must not be on the stack
  746. //
  747. if (pCheckForRecursion (Section)) {
  748. LOG ((LOG_ERROR, (PCSTR) MSG_ENV_SECTION_RECURSION, Section));
  749. // Assume success
  750. return TRUE;
  751. }
  752. //
  753. // Format is
  754. //
  755. // <variable> = <type>, <data> [, <arguments>]
  756. //
  757. // <type> specifies one of the supported parse types (see parse.c),
  758. // or "Text" when <data> is arbitrary text
  759. //
  760. // <data> is specific to <type>
  761. //
  762. // <arguments> specify qualifiers. If they evaluate to FALSE, then
  763. // the variable is not set.
  764. //
  765. __try {
  766. if (InfFindFirstLine (InfFile, Section, NULL, InfStruct)) {
  767. do {
  768. if (IsmCheckCancel()) {
  769. __leave;
  770. }
  771. InfResetInfStruct (InfStruct);
  772. variable = InfGetStringField (InfStruct, 0);
  773. type = InfGetStringField (InfStruct, 1);
  774. if (variable && StringIMatch (variable, TEXT("ProcessSection"))) {
  775. if (type && *type) {
  776. pPushSection (Section);
  777. result = pParseAppEnvSection (Platform, InfFile, Application, type);
  778. pPopSection (Section);
  779. if (!result) {
  780. __leave;
  781. }
  782. }
  783. }
  784. data = InfGetStringField (InfStruct, 2);
  785. args = InfGetMultiSzField (InfStruct, 3);
  786. if (variable) {
  787. //
  788. // Remove %s from the variable name
  789. //
  790. if (_tcsnextc (variable) == TEXT('%')) {
  791. lastChar = _tcsdec2 (variable, GetEndOfString (variable));
  792. if (lastChar > variable && _tcsnextc (lastChar) == TEXT('%')) {
  793. variable = _tcsinc (variable);
  794. *lastChar = 0;
  795. }
  796. }
  797. }
  798. if (!variable || !(*variable) || !type || !(*type) || !data) {
  799. LOG ((LOG_WARNING, (PCSTR) MSG_GARBAGE_LINE_IN_INF, Section));
  800. InfLogContext (LOG_WARNING, InfFile, InfStruct);
  801. continue;
  802. }
  803. //
  804. // Update all environment variables in data and args
  805. //
  806. updatedData = pProcessArgEnvironmentVars (
  807. Platform,
  808. Application,
  809. data,
  810. FALSE,
  811. &dataBuf
  812. );
  813. if (args && *args) {
  814. updatedArgs = pProcessArgEnvironmentVars (
  815. Platform,
  816. Application,
  817. args,
  818. TRUE,
  819. &argBuf
  820. );
  821. } else {
  822. updatedArgs = NULL;
  823. }
  824. //
  825. // Add the app-specific environment variables. If we are
  826. // on the destination, add both a source and destination
  827. // value (as they might be different).
  828. //
  829. pAddPlatformEnvVar (
  830. InfFile,
  831. Platform,
  832. Application,
  833. Section,
  834. variable,
  835. type,
  836. updatedData,
  837. updatedArgs,
  838. InfStruct
  839. );
  840. } while (InfFindNextLine (InfStruct));
  841. }
  842. result = TRUE;
  843. }
  844. __finally {
  845. GbFree (&dataBuf);
  846. GbFree (&argBuf);
  847. }
  848. return result;
  849. }
  850. BOOL
  851. pParseAppEnvSection (
  852. IN MIG_PLATFORMTYPEID Platform,
  853. IN HINF InfFile,
  854. IN PCTSTR Application,
  855. IN PCTSTR Section
  856. )
  857. {
  858. PCTSTR osSpecificSection;
  859. BOOL b;
  860. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  861. b = pParseAppEnvSectionWorker (Platform, &is, InfFile, Application, Section);
  862. if (b) {
  863. osSpecificSection = GetMostSpecificSection (&is, InfFile, Section);
  864. if (osSpecificSection) {
  865. b = pParseAppEnvSectionWorker (Platform, &is, InfFile, Application, osSpecificSection);
  866. FreeText (osSpecificSection);
  867. }
  868. }
  869. InfCleanUpInfStruct (&is);
  870. return b;
  871. }
  872. BOOL
  873. pParseAppDetectSectionPart (
  874. IN MIG_PLATFORMTYPEID Platform,
  875. IN PINFSTRUCT InfStruct,
  876. IN HINF InfFile,
  877. IN PCTSTR Application,
  878. IN PCTSTR Section
  879. )
  880. {
  881. BOOL result = TRUE;
  882. PCTSTR type;
  883. PCTSTR data;
  884. PCTSTR args;
  885. GROWBUFFER dataBuf = INIT_GROWBUFFER;
  886. GROWBUFFER argBuf = INIT_GROWBUFFER;
  887. PCTSTR updatedData;
  888. PCTSTR updatedArgs;
  889. PTSTR buffer;
  890. BOOL test;
  891. //
  892. // Section must not be on the stack
  893. //
  894. if (pCheckForRecursion (Section)) {
  895. LOG ((LOG_ERROR, (PCSTR) MSG_DETECT_SECTION_RECURSION, Section));
  896. // Assume successful detection
  897. return TRUE;
  898. }
  899. //
  900. // Format is
  901. //
  902. // <type>, <data> [, <arguments>]
  903. //
  904. // <type> specifies one of the supported parse types (see parse.c),
  905. // and may include environment variables specified in the
  906. // app's [App.Environment] section.
  907. //
  908. // <data> is specific to <type>. If <data> begins with a !, then the
  909. // existence of the object fails the detect test
  910. //
  911. // <arguments> specify qualifiers
  912. //
  913. __try {
  914. buffer = AllocText (MAX_EXPANDED_STRING); // arbitrary big text buffer
  915. if (InfFindFirstLine (InfFile, Section, NULL, InfStruct)) {
  916. do {
  917. if (IsmCheckCancel()) {
  918. __leave;
  919. }
  920. InfResetInfStruct (InfStruct);
  921. //
  922. // Obtain the line data
  923. //
  924. type = InfGetStringField (InfStruct, 0);
  925. if (type && StringIMatch (type, TEXT("ProcessSection"))) {
  926. data = InfGetStringField (InfStruct, 1);
  927. if (data && *data) {
  928. pPushSection (Section);
  929. result = ParseAppDetectSection (Platform, InfFile, Application, data);
  930. pPopSection (Section);
  931. continue;
  932. }
  933. }
  934. type = InfGetStringField (InfStruct, 1);
  935. data = InfGetStringField (InfStruct, 2);
  936. args = InfGetMultiSzField (InfStruct, 3);
  937. if (!type || !data) {
  938. LOG ((LOG_WARNING, (PCSTR) MSG_GARBAGE_LINE_IN_INF, Section));
  939. InfLogContext (LOG_WARNING, InfFile, InfStruct);
  940. continue;
  941. }
  942. //
  943. // Update all environment variables in data and args
  944. //
  945. updatedData = pProcessArgEnvironmentVars (
  946. PLATFORM_SOURCE,
  947. Application,
  948. data,
  949. FALSE,
  950. &dataBuf
  951. );
  952. if (args && *args) {
  953. updatedArgs = pProcessArgEnvironmentVars (
  954. PLATFORM_SOURCE,
  955. Application,
  956. args,
  957. TRUE,
  958. &argBuf
  959. );
  960. } else {
  961. updatedArgs = NULL;
  962. }
  963. //
  964. // Now try to obtain the data
  965. //
  966. if (pGetDataFromObjectSpec (
  967. Platform,
  968. Application,
  969. type,
  970. updatedData,
  971. updatedArgs,
  972. NULL,
  973. 0,
  974. &test
  975. )) {
  976. if (test) {
  977. LOG ((LOG_INFORMATION, (PCSTR) MSG_DETECT_INFO, type, updatedData));
  978. } else {
  979. LOG ((LOG_INFORMATION, (PCSTR) MSG_NOT_DETECT_INFO, type, updatedData));
  980. result = FALSE;
  981. break;
  982. }
  983. } else {
  984. result = FALSE;
  985. break;
  986. }
  987. } while (result && InfFindNextLine (InfStruct));
  988. }
  989. }
  990. __finally {
  991. FreeText (buffer);
  992. GbFree (&dataBuf);
  993. GbFree (&argBuf);
  994. }
  995. return result;
  996. }
  997. BOOL
  998. pParseOsAppDetectSection (
  999. IN MIG_PLATFORMTYPEID Platform,
  1000. IN PINFSTRUCT InfStruct,
  1001. IN HINF InfFile,
  1002. IN PCTSTR Application,
  1003. IN PCTSTR Section
  1004. )
  1005. {
  1006. PCTSTR osSpecificSection;
  1007. BOOL b;
  1008. b = pParseAppDetectSectionPart (Platform, InfStruct, InfFile, Application, Section);
  1009. if (b) {
  1010. osSpecificSection = GetMostSpecificSection (InfStruct, InfFile, Section);
  1011. if (osSpecificSection) {
  1012. b = pParseAppDetectSectionPart (Platform, InfStruct, InfFile, Application, osSpecificSection);
  1013. FreeText (osSpecificSection);
  1014. }
  1015. }
  1016. return b;
  1017. }
  1018. BOOL
  1019. ParseAppDetectSection (
  1020. IN MIG_PLATFORMTYPEID Platform,
  1021. IN HINF InfFile,
  1022. IN PCTSTR Application,
  1023. IN PCTSTR Section
  1024. )
  1025. {
  1026. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  1027. TCHAR number[32];
  1028. PCTSTR orSection;
  1029. UINT count;
  1030. BOOL orSectionProcessed = FALSE;
  1031. BOOL detected = FALSE;
  1032. BOOL done = FALSE;
  1033. //
  1034. // Process all "or" sections
  1035. //
  1036. count = 0;
  1037. do {
  1038. count++;
  1039. wsprintf (number, TEXT(".%u"), count);
  1040. orSection = JoinText (Section, number);
  1041. if (orSection) {
  1042. if (InfFindFirstLine (InfFile, orSection, NULL, &is)) {
  1043. orSectionProcessed = TRUE;
  1044. if (pParseOsAppDetectSection (Platform, &is, InfFile, Application, orSection)) {
  1045. detected = TRUE;
  1046. done = TRUE;
  1047. }
  1048. } else {
  1049. done = TRUE;
  1050. }
  1051. FreeText (orSection);
  1052. INVALID_POINTER (orSection);
  1053. } else {
  1054. done = TRUE;
  1055. }
  1056. } while (!done);
  1057. //
  1058. // If no "or" sections, process Section itself
  1059. //
  1060. if (!orSectionProcessed) {
  1061. detected = pParseOsAppDetectSection (Platform, &is, InfFile, Application, Section);
  1062. }
  1063. InfCleanUpInfStruct (&is);
  1064. return detected;
  1065. }
  1066. BOOL
  1067. pDoesAppSectionExists (
  1068. IN MIG_PLATFORMTYPEID Platform,
  1069. IN HINF InfFile,
  1070. IN PCTSTR Application
  1071. )
  1072. {
  1073. PCTSTR osSpecificSection;
  1074. BOOL b;
  1075. INFSTRUCT is = INITINFSTRUCT_GROWBUFFER;
  1076. b = InfFindFirstLine (InfFile, Application, NULL, &is);
  1077. if (!b) {
  1078. osSpecificSection = GetMostSpecificSection (&is, InfFile, Application);
  1079. if (osSpecificSection) {
  1080. b = TRUE;
  1081. FreeText (osSpecificSection);
  1082. }
  1083. }
  1084. InfCleanUpInfStruct (&is);
  1085. return b;
  1086. }
  1087. BOOL
  1088. pParseOneDestInstruction (
  1089. IN HINF InfHandle,
  1090. IN PCTSTR Type,
  1091. IN PCTSTR SectionMultiSz,
  1092. IN PINFSTRUCT InfStruct,
  1093. IN PCTSTR Application OPTIONAL
  1094. )
  1095. {
  1096. MULTISZ_ENUM e;
  1097. BOOL result = TRUE;
  1098. //
  1099. // First thing: look for nested sections
  1100. //
  1101. if (StringIMatch (Type, TEXT("ProcessSection"))) {
  1102. if (EnumFirstMultiSz (&e, SectionMultiSz)) {
  1103. do {
  1104. result = result & ParseOneApplication (
  1105. PLATFORM_DESTINATION,
  1106. InfHandle,
  1107. Application,
  1108. FALSE,
  1109. 0,
  1110. e.CurrentString,
  1111. NULL,
  1112. NULL,
  1113. NULL
  1114. );
  1115. } while (EnumNextMultiSz (&e));
  1116. }
  1117. return result;
  1118. }
  1119. return TRUE;
  1120. }
  1121. BOOL
  1122. pParseDestInfInstructionsWorker (
  1123. IN PINFSTRUCT InfStruct,
  1124. IN HINF InfHandle,
  1125. IN PCTSTR Application, OPTIONAL
  1126. IN PCTSTR Section
  1127. )
  1128. {
  1129. PCTSTR type;
  1130. PCTSTR sections;
  1131. GROWBUFFER multiSz = INIT_GROWBUFFER;
  1132. BOOL result = TRUE;
  1133. if (InfFindFirstLine (InfHandle, Section, NULL, InfStruct)) {
  1134. do {
  1135. if (IsmCheckCancel()) {
  1136. result = FALSE;
  1137. break;
  1138. }
  1139. InfResetInfStruct (InfStruct);
  1140. type = InfGetStringField (InfStruct, 0);
  1141. sections = InfGetMultiSzField (InfStruct, 1);
  1142. if (!type || !sections) {
  1143. LOG ((LOG_WARNING, (PCSTR) MSG_BAD_INF_LINE, Section));
  1144. InfLogContext (LOG_WARNING, InfHandle, InfStruct);
  1145. continue;
  1146. }
  1147. result = pParseOneDestInstruction (InfHandle, type, sections, InfStruct, Application);
  1148. } while (result && InfFindNextLine (InfStruct));
  1149. }
  1150. InfCleanUpInfStruct (InfStruct);
  1151. GbFree (&multiSz);
  1152. return result;
  1153. }
  1154. BOOL
  1155. ParseDestInfInstructions (
  1156. IN HINF InfHandle,
  1157. IN PCTSTR Application, OPTIONAL
  1158. IN PCTSTR Section
  1159. )
  1160. {
  1161. PCTSTR osSpecificSection;
  1162. BOOL b;
  1163. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  1164. PTSTR instrSection;
  1165. b = pParseDestInfInstructionsWorker (&is, InfHandle, Application, Section);
  1166. if (b) {
  1167. osSpecificSection = GetMostSpecificSection (&is, InfHandle, Section);
  1168. if (osSpecificSection) {
  1169. b = pParseDestInfInstructionsWorker (&is, InfHandle, Application, osSpecificSection);
  1170. FreeText (osSpecificSection);
  1171. }
  1172. }
  1173. InfCleanUpInfStruct (&is);
  1174. return b;
  1175. }
  1176. BOOL
  1177. ParseOneApplication (
  1178. IN MIG_PLATFORMTYPEID Platform,
  1179. IN HINF Inf,
  1180. IN PCTSTR Section,
  1181. IN BOOL PreParse,
  1182. IN UINT MasterGroup,
  1183. IN PCTSTR Application,
  1184. IN PCTSTR LocSection,
  1185. IN PCTSTR AliasType,
  1186. IN PCTSTR MultiSz
  1187. )
  1188. {
  1189. PCTSTR appSection = NULL;
  1190. BOOL detected = FALSE;
  1191. PCTSTR appEnvVar;
  1192. PCTSTR decoratedSection;
  1193. BOOL componentized = FALSE;
  1194. BOOL executeSection = FALSE;
  1195. BOOL markAsPreferred;
  1196. __try {
  1197. if (LocSection || AliasType) {
  1198. componentized = TRUE;
  1199. } else {
  1200. componentized = FALSE;
  1201. }
  1202. if (!Application) {
  1203. __leave;
  1204. }
  1205. decoratedSection = JoinText (TEXT("$"), Application);
  1206. if (Platform == PLATFORM_SOURCE) {
  1207. //
  1208. // locSection exists for all applications we want to send to
  1209. // the UI for approval. PreParse builds the list of apps we
  1210. // send to the UI. Only do detection if this is PreParsing
  1211. // localized apps, or not preparsing non-localized apps
  1212. //
  1213. if ((PreParse && componentized) ||
  1214. (!PreParse && !componentized)
  1215. ) {
  1216. appSection = JoinText (Application, TEXT(".Environment"));
  1217. if (!pParseAppEnvSection (PLATFORM_SOURCE, Inf, Application, appSection)) {
  1218. __leave;
  1219. }
  1220. FreeText (appSection);
  1221. appSection = NULL;
  1222. GlFree (&g_SectionStack);
  1223. appSection = JoinText (Application, TEXT(".Detect"));
  1224. detected = ParseAppDetectSection (Platform, Inf, Application, appSection);
  1225. FreeText (appSection);
  1226. appSection = NULL;
  1227. GlFree (&g_SectionStack);
  1228. if (!detected && pDoesAppSectionExists (Platform, Inf, Application)) {
  1229. detected = TRUE;
  1230. } else if (!detected) {
  1231. LOG ((LOG_INFORMATION, (PCSTR) MSG_APP_NOT_DETECT_INFO, Application));
  1232. } else {
  1233. LOG ((LOG_INFORMATION, (PCSTR) MSG_APP_DETECT_INFO, Application));
  1234. appEnvVar = JoinTextEx (NULL, Section, Application, TEXT("."), 0, NULL);
  1235. IsmSetEnvironmentFlag (PLATFORM_SOURCE, NULL, appEnvVar);
  1236. FreeText (appEnvVar);
  1237. }
  1238. if (componentized && detected) {
  1239. //
  1240. // we should put it in the selection list
  1241. //
  1242. if (LocSection) {
  1243. IsmAddComponentAlias (
  1244. decoratedSection,
  1245. MasterGroup,
  1246. LocSection,
  1247. COMPONENT_NAME,
  1248. FALSE
  1249. );
  1250. IsmSelectPreferredAlias (decoratedSection, LocSection, COMPONENT_NAME);
  1251. }
  1252. if (AliasType) {
  1253. markAsPreferred = (LocSection == NULL);
  1254. pAddFilesAndFoldersComponentOrSection (
  1255. Inf,
  1256. decoratedSection,
  1257. AliasType,
  1258. MultiSz,
  1259. MasterGroup,
  1260. &markAsPreferred
  1261. );
  1262. }
  1263. }
  1264. executeSection = (!PreParse) && detected;
  1265. } else {
  1266. executeSection = (!PreParse) && IsmIsComponentSelected (decoratedSection, 0);
  1267. }
  1268. // Now actually load the application instructions if it's not preparsing
  1269. if (executeSection) {
  1270. appSection = DuplicateText (Application);
  1271. if (!ParseInfInstructions (Inf, Application, appSection)) {
  1272. __leave;
  1273. }
  1274. FreeText (appSection);
  1275. appSection = NULL;
  1276. appEnvVar = JoinTextEx (NULL, Section, Application, TEXT("."), 0, NULL);
  1277. if (IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, appEnvVar)) {
  1278. appSection = JoinText (Application, TEXT(".Instructions"));
  1279. if (!ParseInfInstructions (Inf, Application, appSection)) {
  1280. __leave;
  1281. }
  1282. FreeText (appSection);
  1283. appSection = NULL;
  1284. }
  1285. FreeText (appEnvVar);
  1286. } else {
  1287. if (!PreParse) {
  1288. appEnvVar = JoinTextEx (NULL, Section, Application, TEXT("."), 0, NULL);
  1289. IsmDeleteEnvironmentVariable (PLATFORM_SOURCE, NULL, appEnvVar);
  1290. FreeText (appEnvVar);
  1291. }
  1292. }
  1293. } else {
  1294. MYASSERT (Platform == PLATFORM_DESTINATION);
  1295. appSection = JoinText (Application, TEXT(".Environment"));
  1296. if (!pParseAppEnvSection (PLATFORM_DESTINATION, Inf, Application, appSection)) {
  1297. __leave;
  1298. }
  1299. FreeText (appSection);
  1300. appSection = NULL;
  1301. GlFree (&g_SectionStack);
  1302. appEnvVar = JoinTextEx (NULL, Section, Application, TEXT("."), 0, NULL);
  1303. if (IsmIsEnvironmentFlagSet (PLATFORM_SOURCE, NULL, appEnvVar)) {
  1304. appSection = DuplicateText (Application);
  1305. if (!ParseDestInfInstructions (Inf, Application, appSection)) {
  1306. __leave;
  1307. }
  1308. FreeText (appSection);
  1309. appSection = NULL;
  1310. appSection = JoinText (Application, TEXT(".Instructions"));
  1311. if (!ParseDestInfInstructions (Inf, Application, appSection)) {
  1312. __leave;
  1313. }
  1314. FreeText (appSection);
  1315. appSection = NULL;
  1316. }
  1317. FreeText (appEnvVar);
  1318. }
  1319. FreeText (decoratedSection);
  1320. decoratedSection = NULL;
  1321. }
  1322. __finally {
  1323. if (appSection) {
  1324. FreeText (appSection);
  1325. appSection = NULL;
  1326. }
  1327. GlFree (&g_SectionStack);
  1328. }
  1329. return TRUE;
  1330. }
  1331. BOOL
  1332. ParseApplications (
  1333. IN MIG_PLATFORMTYPEID Platform,
  1334. IN HINF Inf,
  1335. IN PCTSTR Section,
  1336. IN BOOL PreParse,
  1337. IN UINT MasterGroup
  1338. )
  1339. {
  1340. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  1341. PCTSTR application;
  1342. BOOL result = FALSE;
  1343. PCTSTR locSection;
  1344. PCTSTR aliasType;
  1345. PCTSTR multiSz;
  1346. __try {
  1347. if (InfFindFirstLine (Inf, Section, NULL, &is)) {
  1348. do {
  1349. if (IsmCheckCancel()) {
  1350. __leave;
  1351. }
  1352. InfResetInfStruct (&is);
  1353. application = InfGetStringField (&is, 1);
  1354. locSection = InfGetStringField (&is, 2);
  1355. aliasType = InfGetStringField (&is, 3);
  1356. multiSz = InfGetMultiSzField (&is, 4);
  1357. if (application && !application[0]) {
  1358. application = NULL;
  1359. }
  1360. if (locSection && !locSection[0]) {
  1361. locSection = NULL;
  1362. }
  1363. if (aliasType && !aliasType[0]) {
  1364. aliasType = NULL;
  1365. }
  1366. if (multiSz && !multiSz[0]) {
  1367. multiSz = NULL;
  1368. }
  1369. if (!aliasType || !multiSz) {
  1370. aliasType = NULL;
  1371. multiSz = NULL;
  1372. }
  1373. ParseOneApplication (
  1374. Platform,
  1375. Inf,
  1376. Section,
  1377. PreParse,
  1378. MasterGroup,
  1379. application,
  1380. locSection,
  1381. aliasType,
  1382. multiSz
  1383. );
  1384. } while (InfFindNextLine (&is));
  1385. }
  1386. result = TRUE;
  1387. } __finally {
  1388. InfCleanUpInfStruct (&is);
  1389. }
  1390. return result;
  1391. }
  1392. BOOL
  1393. ProcessFilesAndFolders (
  1394. IN HINF InfHandle,
  1395. IN PCTSTR Section,
  1396. IN BOOL PreParse
  1397. )
  1398. {
  1399. BOOL b = TRUE;
  1400. BOOL markAsPreferred = TRUE;
  1401. if (PreParse) {
  1402. b = pAddFilesAndFoldersSection (InfHandle, Section, MASTERGROUP_FILES_AND_FOLDERS, FALSE, &markAsPreferred);
  1403. }
  1404. return b;
  1405. }