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.

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