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.

1594 lines
38 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. parse.c
  5. Abstract:
  6. Implements parsing of script entries.
  7. Author:
  8. Jim Schmidt (jimschm) 02-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_V1 "v1"
  18. //
  19. // Strings
  20. //
  21. // None
  22. //
  23. // Constants
  24. //
  25. // None
  26. //
  27. // Macros
  28. //
  29. // None
  30. //
  31. // Types
  32. //
  33. typedef BOOL (SCRIPTTYPE_ALLOC_FN)(
  34. IN OUT PATTRIB_DATA AttribData CALLER_INITIALIZED
  35. );
  36. typedef SCRIPTTYPE_ALLOC_FN *PSCRIPTTYPE_ALLOC_FN;
  37. typedef BOOL (SCRIPTTYPE_FREE_FN)(
  38. IN PATTRIB_DATA AttribData ZEROED
  39. );
  40. typedef SCRIPTTYPE_FREE_FN *PSCRIPTTYPE_FREE_FN;
  41. typedef struct {
  42. PCTSTR Tag;
  43. PSCRIPTTYPE_ALLOC_FN AllocFunction;
  44. PSCRIPTTYPE_FREE_FN FreeFunction;
  45. } TAG_TO_SCRIPTTYPEFN, *PTAG_TO_SCRIPTTYPEFN;
  46. //
  47. // Globals
  48. //
  49. // None
  50. //
  51. // Macro expansion list
  52. //
  53. #define SCRIPT_TYPES \
  54. DEFMAC(Registry, pAllocRegistryScriptType, pFreeIsmObjectScriptType) \
  55. DEFMAC(File, pAllocFileScriptType, pFreeIsmObjectScriptType) \
  56. DEFMAC(Directory, pAllocDirectoryScriptType, pFreeIsmObjectScriptType) \
  57. DEFMAC(Text, pAllocTextScriptType, pFreeTextScriptType) \
  58. DEFMAC(System, pAllocSystemScriptType, pFreeSystemScriptType) \
  59. DEFMAC(INIFile, pAllocIniFileScriptType, pFreeIniFileScriptType) \
  60. //
  61. // Private function prototypes
  62. //
  63. // None
  64. //
  65. // Macro expansion definition
  66. //
  67. #define DEFMAC(tag,fnA,fnF) SCRIPTTYPE_ALLOC_FN fnA; SCRIPTTYPE_FREE_FN fnF;
  68. SCRIPT_TYPES
  69. #undef DEFMAC
  70. #define DEFMAC(tag,fnA,fnF) {TEXT(#tag),fnA,fnF},
  71. TAG_TO_SCRIPTTYPEFN g_TagToScriptTypeFn[] = {
  72. SCRIPT_TYPES
  73. {NULL, NULL, NULL}
  74. };
  75. #undef DEFMAC
  76. //
  77. // Code
  78. //
  79. MIG_OBJECTSTRINGHANDLE
  80. MakeRegExBase (
  81. IN PCTSTR Node,
  82. IN PCTSTR Leaf
  83. )
  84. {
  85. MIG_OBJECTSTRINGHANDLE objectBase = NULL;
  86. PTSTR ptr;
  87. PTSTR nodeCopy = NULL;
  88. PCTSTR nodeBase = NULL;
  89. BOOL useLeaf = FALSE;
  90. if (Node) {
  91. ptr = _tcschr (Node, TEXT('\\'));
  92. if (!ptr) {
  93. return NULL;
  94. }
  95. if (StringIPrefix (Node, TEXT("HKR\\"))) {
  96. nodeCopy = JoinText (TEXT("HKCU"), ptr);
  97. } else {
  98. nodeCopy = DuplicateText (Node);
  99. }
  100. if (nodeCopy) {
  101. nodeBase = GetPatternBase (nodeCopy);
  102. if (nodeBase) {
  103. if (Leaf && !_tcschr (Leaf, TEXT('*'))) {
  104. useLeaf = TRUE;
  105. }
  106. objectBase = IsmCreateObjectHandle (nodeBase, useLeaf ? Leaf : NULL);
  107. FreePathString (nodeBase);
  108. }
  109. FreeText (nodeCopy);
  110. }
  111. }
  112. return objectBase;
  113. }
  114. MIG_OBJECTSTRINGHANDLE
  115. CreatePatternFromNodeLeaf (
  116. IN PCTSTR Node,
  117. IN PCTSTR Leaf
  118. )
  119. {
  120. MIG_OBJECTSTRINGHANDLE pattern;
  121. MIG_SEGMENTS nodeSegment;
  122. MIG_SEGMENTS leafSegment;
  123. PTSTR fixedNode = NULL;
  124. if (Node &&
  125. (StringIMatch (Node, S_HKR) ||
  126. StringIMatchTcharCount (Node, TEXT("HKR\\"), 4)
  127. )
  128. ) {
  129. fixedNode = JoinText (S_HKCU, Node + 3);
  130. nodeSegment.Segment = fixedNode;
  131. } else {
  132. nodeSegment.Segment = Node;
  133. }
  134. nodeSegment.IsPattern = TRUE;
  135. leafSegment.Segment = Leaf;
  136. leafSegment.IsPattern = TRUE;
  137. pattern = IsmCreateObjectPattern (&nodeSegment, Node ? 1 : 0, &leafSegment, Leaf ? 1 : 0);
  138. FreeText (fixedNode);
  139. if (!pattern) {
  140. LOG ((LOG_ERROR, (PCSTR) MSG_REG_SPEC_BAD_NODE_AND_LEAF, Node, Leaf));
  141. }
  142. return pattern;
  143. }
  144. MIG_OBJECTSTRINGHANDLE
  145. TurnRegStringIntoHandle (
  146. IN PCTSTR String,
  147. IN BOOL Pattern,
  148. OUT PBOOL HadLeaf OPTIONAL
  149. )
  150. /*++
  151. Routine Description:
  152. TurnRegStringIntoHandle converts the script's reg syntax into a cobra
  153. object.
  154. Arguments:
  155. String - Specifies the registry key and value in the script syntax.
  156. The string must be in the following format:
  157. <root>\<key>\* [<value>]
  158. Each part is optional.
  159. <root> specifies HKCU, HKR, HKLM or HKCC.
  160. <key> specifies a subkey (such as Software\Microsoft\Windows)
  161. * specifies all subkeys. If <value> is not specified, then all
  162. values and subvalues are also included.
  163. <value> specifies a specific value name
  164. Pattern - Specifies TRUE if the registry string can contain a pattern, or
  165. FALSE if it cannot.
  166. HadLeaf - Receives TRUE if String contains a leaf specification, FALSE
  167. otherwise
  168. Return Value:
  169. A handle to a cobra object string, or NULL if parsing failed.
  170. --*/
  171. {
  172. PTSTR strCopy;
  173. PTSTR p;
  174. PTSTR value = NULL;
  175. PTSTR valueEnd;
  176. PTSTR key;
  177. PTSTR keyEnd;
  178. BOOL tree = FALSE;
  179. MIG_SEGMENTS nodeSegment[2];
  180. UINT nodeCount;
  181. MIG_SEGMENTS leafSegment;
  182. UINT leafCount;
  183. MIG_OBJECTSTRINGHANDLE handle;
  184. BOOL noSubKeys;
  185. BOOL noWildcardLeaf;
  186. PCTSTR fixedKey = NULL;
  187. MYASSERT (String);
  188. if (!String) {
  189. return NULL;
  190. }
  191. if (Pattern) {
  192. noSubKeys = FALSE;
  193. noWildcardLeaf = FALSE;
  194. } else {
  195. noSubKeys = TRUE;
  196. noWildcardLeaf = TRUE;
  197. }
  198. //
  199. // Inbound syntax is key\* [value]
  200. //
  201. strCopy = DuplicateText (String);
  202. if (!strCopy) {
  203. return NULL;
  204. }
  205. key = (PTSTR) SkipSpace (strCopy);
  206. if (!key) {
  207. FreeText (strCopy);
  208. return NULL;
  209. }
  210. if (*key == TEXT('[')) {
  211. //
  212. // This is a value-only case
  213. //
  214. value = _tcsinc (key);
  215. key = NULL;
  216. } else {
  217. //
  218. // This is a key-value case, or key-only case
  219. //
  220. p = _tcschr (key, TEXT('['));
  221. if (p) {
  222. //
  223. // Save start of value
  224. //
  225. value = _tcsinc (p);
  226. } else {
  227. //
  228. // No value
  229. //
  230. p = GetEndOfString (key);
  231. }
  232. keyEnd = p;
  233. //
  234. // Find the true end of the key
  235. //
  236. p = _tcsdec2 (key, p);
  237. MYASSERT (p); // assert this is not a value-only case
  238. p = (PTSTR) SkipSpaceR (key, p);
  239. if (p) {
  240. keyEnd = _tcsinc (p);
  241. }
  242. //
  243. // Test for \* at the end
  244. //
  245. p = _tcsdec2 (key, keyEnd);
  246. MYASSERT (p);
  247. if (p && _tcsnextc (p) == TEXT('*')) {
  248. p = _tcsdec2 (key, p);
  249. if (p && _tcsnextc (p) == TEXT('\\')) {
  250. keyEnd = p;
  251. tree = (noSubKeys == FALSE);
  252. }
  253. }
  254. //
  255. // Trim the key
  256. //
  257. *keyEnd = 0;
  258. }
  259. //
  260. // Parse the value
  261. //
  262. if (value) {
  263. value = (PTSTR) SkipSpace (value);
  264. valueEnd = _tcschr (value, TEXT(']'));
  265. if (!valueEnd) {
  266. LOG ((LOG_ERROR, (PCSTR) MSG_INF_SYNTAX_ERROR, String));
  267. value = NULL;
  268. } else {
  269. //
  270. // Trim the space at the end of value
  271. //
  272. p = _tcsdec2 (value, valueEnd);
  273. if (p) {
  274. p = (PTSTR) SkipSpaceR (value, p);
  275. if (p) {
  276. valueEnd = _tcsinc (p);
  277. }
  278. }
  279. *valueEnd = 0;
  280. }
  281. }
  282. //
  283. // Create parsed pattern. Start with the node.
  284. //
  285. nodeSegment[0].Segment = key;
  286. nodeSegment[0].IsPattern = FALSE;
  287. nodeSegment[1].Segment = TEXT("\\*");
  288. nodeSegment[1].IsPattern = TRUE;
  289. if (tree) {
  290. nodeCount = 2;
  291. } else {
  292. nodeCount = 1;
  293. }
  294. //
  295. // compute the leaf
  296. //
  297. if (value) {
  298. leafSegment.Segment = value;
  299. leafSegment.IsPattern = FALSE;
  300. } else {
  301. leafSegment.Segment = TEXT("*");
  302. leafSegment.IsPattern = TRUE;
  303. }
  304. if (noWildcardLeaf && !value) {
  305. leafCount = 0;
  306. } else {
  307. leafCount = 1;
  308. }
  309. if (nodeCount && key &&
  310. (StringIMatch (key, S_HKR) ||
  311. StringIMatchTcharCount (key, TEXT("HKR\\"), 4)
  312. )
  313. ) {
  314. fixedKey = JoinText (S_HKCU, key + 3);
  315. nodeSegment[0].Segment = fixedKey;
  316. }
  317. handle = IsmCreateObjectPattern (
  318. nodeSegment,
  319. nodeCount,
  320. leafCount?&leafSegment:NULL,
  321. leafCount
  322. );
  323. FreeText (strCopy);
  324. FreeText (fixedKey);
  325. if (HadLeaf) {
  326. *HadLeaf = (value != NULL);
  327. }
  328. return handle;
  329. }
  330. PTSTR
  331. pCopyToDest (
  332. IN PTSTR Destination, OPTIONAL
  333. IN CHARTYPE Char,
  334. IN PUINT CharNr
  335. )
  336. {
  337. UINT len = 1;
  338. #ifdef UNICODE
  339. if (Destination) {
  340. *Destination++ = Char;
  341. }
  342. (*CharNr) ++;
  343. return Destination;
  344. #else
  345. if (IsCharLeadByte ((INT) Char)) {
  346. len ++;
  347. }
  348. if (Destination) {
  349. CopyMemory (Destination, &Char, len);
  350. Destination += len;
  351. }
  352. (*CharNr) += len;
  353. return Destination;
  354. #endif
  355. }
  356. // 1->? (if node, no \ or ., if leaf, no .), 2->* (if node, no \ or ., if leaf, no .) 3->* (no \) 4->* (unlimited)
  357. UINT
  358. pGetMode (
  359. IN PCTSTR Source,
  360. IN BOOL NodePattern,
  361. IN BOOL PatternAfterWack,
  362. IN BOOL FirstChar
  363. )
  364. {
  365. UINT ch;
  366. BOOL end = FALSE;
  367. UINT mode = 0;
  368. ch = _tcsnextc (Source);
  369. while (ch) {
  370. switch (ch) {
  371. case TEXT('?'):
  372. if (mode < 1) {
  373. mode = 1;
  374. }
  375. break;
  376. case TEXT('*'):
  377. if (NodePattern) {
  378. if (mode < 3) {
  379. mode = 3;
  380. }
  381. } else {
  382. if (mode < 4) {
  383. mode = 4;
  384. }
  385. }
  386. break;
  387. case TEXT('\\'):
  388. if (NodePattern) {
  389. if (mode < 2) {
  390. mode = 2;
  391. }
  392. }
  393. end = TRUE;
  394. break;
  395. case TEXT('.'):
  396. if (mode < 2) {
  397. mode = 2;
  398. }
  399. end = TRUE;
  400. break;
  401. default:
  402. end = TRUE;
  403. }
  404. if (end) {
  405. break;
  406. }
  407. Source = _tcsinc (Source);
  408. ch = _tcsnextc (Source);
  409. }
  410. if (!ch) {
  411. if ((PatternAfterWack || NodePattern) && (mode == 3)) {
  412. mode = 4;
  413. }
  414. if (mode < 2) {
  415. mode = 2;
  416. }
  417. }
  418. if (FirstChar && (mode == 3)) {
  419. mode = 4;
  420. }
  421. return mode;
  422. }
  423. BOOL
  424. pCopyPatternEx (
  425. IN UINT Mode,
  426. IN PCTSTR *Source,
  427. IN PTSTR *Destination,
  428. IN PUINT CharNr,
  429. IN BOOL NodePattern
  430. )
  431. {
  432. CHARTYPE ch;
  433. BOOL end = FALSE;
  434. INT numChars = 0;
  435. UINT chars;
  436. TCHAR buffer [MAX_PATH] = TEXT("");
  437. ch = (CHARTYPE) _tcsnextc (*Source);
  438. while (ch) {
  439. switch (ch) {
  440. case TEXT('*'):
  441. if (Mode == 1) {
  442. end = TRUE;
  443. break;
  444. }
  445. numChars = -1;
  446. break;
  447. case TEXT('?'):
  448. if (numChars >= 0) {
  449. numChars ++;
  450. }
  451. break;
  452. default:
  453. end = TRUE;
  454. break;
  455. }
  456. if (end) {
  457. break;
  458. }
  459. *Source = _tcsinc (*Source);
  460. ch = (CHARTYPE) _tcsnextc (*Source);
  461. }
  462. // 1->? (if node, no \ or ., if leaf, no .), 2->* (if node, no \ or ., if leaf, no .) 3->* (no \) 4->* (unlimited)
  463. switch (Mode) {
  464. case 1:
  465. if (NodePattern) {
  466. if (numChars > 0) {
  467. wsprintf (buffer, TEXT("?[%d:!(\\,.)]"), numChars);
  468. } else {
  469. wsprintf (buffer, TEXT("?[!(\\,.)]"));
  470. }
  471. } else {
  472. if (numChars > 0) {
  473. wsprintf (buffer, TEXT("?[%d:!(.)]"), numChars);
  474. } else {
  475. wsprintf (buffer, TEXT("?[!(.)]"));
  476. }
  477. }
  478. break;
  479. case 2:
  480. if (NodePattern) {
  481. if (numChars > 0) {
  482. wsprintf (buffer, TEXT("*[%d:!(\\,.)]"), numChars);
  483. } else {
  484. wsprintf (buffer, TEXT("*[!(\\,.)]"));
  485. }
  486. } else {
  487. if (numChars > 0) {
  488. wsprintf (buffer, TEXT("*[%d:!(.)]"), numChars);
  489. } else {
  490. wsprintf (buffer, TEXT("*[!(.)]"));
  491. }
  492. }
  493. break;
  494. case 3:
  495. if (numChars > 0) {
  496. wsprintf (buffer, TEXT("*[%d:!(\\)]"), numChars);
  497. } else {
  498. wsprintf (buffer, TEXT("*[!(\\)]"));
  499. }
  500. break;
  501. case 4:
  502. if (numChars > 0) {
  503. wsprintf (buffer, TEXT("*[%d:]"), numChars);
  504. } else {
  505. wsprintf (buffer, TEXT("*[]"));
  506. }
  507. break;
  508. default:
  509. MYASSERT (FALSE);
  510. }
  511. chars = TcharCount (buffer);
  512. if (CharNr) {
  513. *CharNr += chars;
  514. }
  515. if (Destination && *Destination) {
  516. StringCopy (*Destination, buffer);
  517. *Destination += chars;
  518. }
  519. return TRUE;
  520. }
  521. BOOL
  522. pCopyPattern (
  523. IN PCTSTR *Source,
  524. IN PTSTR *Destination,
  525. IN PUINT CharNr,
  526. IN BOOL NodePattern,
  527. IN BOOL PatternAfterWack,
  528. IN BOOL FirstChar
  529. )
  530. {
  531. // 1->? (if node, no \ or ., if leaf, no .), 2->* (if node, no \ or ., if leaf, no .) 3->* (no \) 4->* (unlimited)
  532. UINT mode = 0;
  533. PTSTR result = NULL;
  534. mode = pGetMode (*Source, NodePattern, PatternAfterWack, FirstChar);
  535. return pCopyPatternEx (mode, Source, Destination, CharNr, NodePattern);
  536. }
  537. BOOL
  538. pFixPattern (
  539. IN PCTSTR Source,
  540. OUT PTSTR Destination, OPTIONAL
  541. OUT PUINT DestinationChars, OPTIONAL
  542. IN BOOL PatternsNotAllowed,
  543. IN BOOL TruncateAtPattern,
  544. IN BOOL NodePattern
  545. )
  546. {
  547. UINT chars = 1;
  548. UINT lastChars = 0;
  549. PTSTR lastWack = NULL;
  550. BOOL end = FALSE;
  551. BOOL result = TRUE;
  552. BOOL patternAfterWack = FALSE;
  553. BOOL firstChar = TRUE;
  554. CHARTYPE ch;
  555. if (Destination) {
  556. *Destination = 0;
  557. }
  558. ch = (CHARTYPE) _tcsnextc (Source);
  559. while (ch) {
  560. switch (ch) {
  561. case TEXT('*'):
  562. case TEXT('?'):
  563. if (TruncateAtPattern) {
  564. if (lastWack) {
  565. *lastWack = 0;
  566. chars = lastChars;
  567. }
  568. end = TRUE;
  569. } else if (PatternsNotAllowed) {
  570. result = FALSE;
  571. Destination = pCopyToDest (Destination, TEXT('^'), &chars);
  572. Destination = pCopyToDest (Destination, ch, &chars);
  573. Source = _tcsinc (Source);
  574. } else {
  575. if (lastWack && (_tcsinc (lastWack) == Destination)) {
  576. patternAfterWack = TRUE;
  577. } else {
  578. patternAfterWack = FALSE;
  579. }
  580. pCopyPattern (&Source, Destination?&Destination:NULL, &chars, NodePattern, patternAfterWack, firstChar);
  581. }
  582. break;
  583. case TEXT('\020'):
  584. case TEXT('<'):
  585. case TEXT('>'):
  586. case TEXT(','):
  587. case TEXT('^'):
  588. Destination = pCopyToDest (Destination, TEXT('^'), &chars);
  589. Destination = pCopyToDest (Destination, ch, &chars);
  590. Source = _tcsinc (Source);
  591. break;
  592. case TEXT('\\'):
  593. if (NodePattern) {
  594. lastWack = Destination;
  595. lastChars = chars;
  596. }
  597. Destination = pCopyToDest (Destination, ch, &chars);
  598. Source = _tcsinc (Source);
  599. break;
  600. case TEXT('.'):
  601. if (!NodePattern) {
  602. lastWack = Destination;
  603. lastChars = chars;
  604. }
  605. Destination = pCopyToDest (Destination, ch, &chars);
  606. Source = _tcsinc (Source);
  607. break;
  608. default:
  609. Destination = pCopyToDest (Destination, ch, &chars);
  610. Source = _tcsinc (Source);
  611. break;
  612. }
  613. firstChar = FALSE;
  614. if (end) {
  615. break;
  616. }
  617. ch = (CHARTYPE) _tcsnextc (Source);
  618. }
  619. if (Destination) {
  620. *Destination = 0;
  621. }
  622. if (DestinationChars) {
  623. *DestinationChars = chars;
  624. }
  625. return result;
  626. }
  627. MIG_OBJECTSTRINGHANDLE
  628. TurnFileStringIntoHandle (
  629. IN PCTSTR String,
  630. IN DWORD Flags
  631. )
  632. /*++
  633. Routine Description:
  634. TurnFileStringIntoHandle converts a file specification from the script
  635. syntax into a cobra object.
  636. Arguments:
  637. String - Specifies the file string in the script syntax.
  638. The string must be in the following format:
  639. <directory>\<file>
  640. Both parts are optional. The Flags member indicates how String
  641. is parsed.
  642. Flags - Specifies zero or more of the following flags:
  643. PFF_NO_PATTERNS_ALLOWED - String cannot contain any wildcard
  644. characters.
  645. PFF_COMPUTE_BASE - Returns the directory portion of the string,
  646. and truncates the directory at the first
  647. wildcard if necessary. Truncation is done
  648. at the backslashes only.
  649. PFF_NO_SUBDIR_PATTERN - Do not include a trailing \*, even if
  650. it was specified in String.
  651. PFF_NO_LEAF_PATTERN - Do not include a * for the leaf when
  652. String does not contain a file name.
  653. If a file name is specified, include it.
  654. PFF_PATTERN_IS_DIR - String does not specify a file name. It
  655. is a directory only. The leaf portion of
  656. the object string will be a *.
  657. PFF_NO_LEAF_AT_ALL - Will return an object string that has a
  658. node only, and no leaf specified at all.
  659. Return Value:
  660. A cobra object handle, or NULL if conversion failed.
  661. --*/
  662. {
  663. PTSTR p;
  664. PTSTR fileCopy = NULL;
  665. MIG_SEGMENTS nodeSegment[2];
  666. MIG_SEGMENTS leafSegment;
  667. MIG_OBJECTSTRINGHANDLE result = NULL;
  668. BOOL tree = FALSE;
  669. PTSTR file = NULL;
  670. UINT nodeCount;
  671. UINT leafCount;
  672. UINT charsInPattern;
  673. BOOL noPatternsAllowed;
  674. BOOL computeBaseNode;
  675. BOOL noSubDirPattern;
  676. BOOL noLeafPattern;
  677. BOOL forceLeafToStar;
  678. PCTSTR node;
  679. PCTSTR leaf = NULL;
  680. PTSTR fixedNode = NULL;
  681. PTSTR fixedLeaf = NULL;
  682. PTSTR tempCopy;
  683. BOOL patternError = FALSE;
  684. noPatternsAllowed = (Flags & PFF_NO_PATTERNS_ALLOWED) == PFF_NO_PATTERNS_ALLOWED;
  685. computeBaseNode = (Flags & PFF_COMPUTE_BASE) == PFF_COMPUTE_BASE;
  686. noSubDirPattern = (Flags & PFF_NO_SUBDIR_PATTERN) == PFF_NO_SUBDIR_PATTERN;
  687. noLeafPattern = (Flags & PFF_NO_LEAF_PATTERN) == PFF_NO_LEAF_PATTERN;
  688. forceLeafToStar = (Flags & PFF_PATTERN_IS_DIR) == PFF_PATTERN_IS_DIR;
  689. //
  690. // Divide pattern into node and leaf
  691. //
  692. tempCopy = DuplicateText (SkipSpace (String));
  693. p = (PTSTR) SkipSpaceR (tempCopy, NULL);
  694. if (p) {
  695. p = _tcsinc (p);
  696. *p = 0;
  697. }
  698. node = tempCopy;
  699. if (!forceLeafToStar) {
  700. p = (PTSTR) FindLastWack (tempCopy);
  701. if (p) {
  702. leaf = SkipSpace (p + 1);
  703. *p = 0;
  704. p = (PTSTR) SkipSpaceR (tempCopy, NULL);
  705. if (p) {
  706. p = _tcsinc (p);
  707. *p = 0;
  708. }
  709. } else {
  710. if (!_tcschr (tempCopy, TEXT(':'))) {
  711. node = NULL;
  712. leaf = tempCopy;
  713. }
  714. }
  715. }
  716. //
  717. // Convert all ? wildcard chars to be compatibile with NT's file system
  718. // Escape all [ characters that follow wildcards
  719. //
  720. if (node) {
  721. p = (PTSTR) GetEndOfString (node);
  722. p = _tcsdec2 (node, p);
  723. if (p) {
  724. if (_tcsnextc (p) == TEXT('*')) {
  725. tree = TRUE;
  726. p = _tcsdec2 (node, p);
  727. if (p && _tcsnextc (p) == TEXT('\\')) {
  728. *p = 0;
  729. } else {
  730. tree = FALSE;
  731. }
  732. }
  733. }
  734. if (!pFixPattern (
  735. node,
  736. NULL,
  737. &charsInPattern,
  738. noPatternsAllowed,
  739. computeBaseNode,
  740. TRUE
  741. )) {
  742. patternError = TRUE;
  743. }
  744. if (charsInPattern) {
  745. fixedNode = AllocText (charsInPattern + 1);
  746. pFixPattern (
  747. node,
  748. fixedNode,
  749. NULL,
  750. noPatternsAllowed,
  751. computeBaseNode,
  752. TRUE
  753. );
  754. }
  755. }
  756. if (leaf && !computeBaseNode) {
  757. if (!pFixPattern (
  758. leaf,
  759. NULL,
  760. &charsInPattern,
  761. noPatternsAllowed,
  762. FALSE,
  763. FALSE
  764. )) {
  765. patternError = TRUE;
  766. }
  767. if (charsInPattern) {
  768. fixedLeaf = AllocText (charsInPattern + 1);
  769. pFixPattern (
  770. leaf,
  771. fixedLeaf,
  772. NULL,
  773. noPatternsAllowed,
  774. FALSE,
  775. FALSE
  776. );
  777. }
  778. }
  779. FreeText (tempCopy);
  780. INVALID_POINTER (tempCopy);
  781. //
  782. // Create the pattern string. Start by preparing the node segments.
  783. //
  784. nodeSegment[0].Segment = fixedNode;
  785. nodeSegment[0].IsPattern = TRUE; // normally FALSE, but because the pattern charset is
  786. // exclusive of the valid filename charset, we allow
  787. // patterns to be in the node
  788. nodeSegment[1].Segment = TEXT("\\*");
  789. nodeSegment[1].IsPattern = TRUE;
  790. if (!fixedNode) {
  791. nodeCount = 0;
  792. } else if (!tree || noSubDirPattern || noPatternsAllowed) {
  793. nodeCount = 1; // just the node, not its subnodes
  794. } else {
  795. nodeCount = 2; // the node and its subnodes
  796. }
  797. //
  798. // Prepare the leaf segments. We want all leaves, a specific leaf, or
  799. // no leaf at all.
  800. //
  801. leafSegment.Segment = fixedLeaf;
  802. leafSegment.IsPattern = TRUE;
  803. leafCount = 1;
  804. MYASSERT (!forceLeafToStar || !fixedLeaf);
  805. if (!fixedLeaf) {
  806. if (noLeafPattern || noPatternsAllowed) {
  807. leafCount = 0;
  808. } else {
  809. leafSegment.Segment = TEXT("*");
  810. }
  811. }
  812. if (nodeCount || leafCount) {
  813. if ((fixedNode && *fixedNode) || (fixedLeaf && *fixedLeaf)) {
  814. result = IsmCreateObjectPattern (
  815. nodeCount ? nodeSegment : NULL,
  816. nodeCount,
  817. leafCount ? &leafSegment : NULL,
  818. leafCount
  819. );
  820. }
  821. }
  822. FreeText (fixedNode);
  823. FreeText (fixedLeaf);
  824. return result;
  825. }
  826. BOOL
  827. pAllocRegistryScriptType (
  828. IN OUT PATTRIB_DATA AttribData
  829. )
  830. {
  831. TCHAR expandBuffer[4096];
  832. MIG_CONTENT objectContent;
  833. DWORD type;
  834. DWORD size;
  835. MULTISZ_ENUM multiSzEnum;
  836. PTSTR ptr;
  837. if (!AttribData) {
  838. SetLastError (ERROR_INVALID_DATA);
  839. return FALSE;
  840. }
  841. // verify that we have some registry
  842. if (!AttribData->ScriptSpecifiedObject) {
  843. SetLastError (ERROR_INVALID_DATA);
  844. return FALSE;
  845. }
  846. // try to create encoded string
  847. AttribData->ObjectTypeId = g_RegType;
  848. AttribData->ObjectName = TurnRegStringIntoHandle (
  849. AttribData->ScriptSpecifiedObject,
  850. FALSE,
  851. NULL
  852. );
  853. if (!AttribData->ObjectName) {
  854. if (GetLastError() == ERROR_SUCCESS) {
  855. SetLastError (ERROR_INVALID_DATA);
  856. }
  857. return FALSE;
  858. }
  859. // try to acqure the object
  860. if (IsmAcquireObject (
  861. AttribData->ObjectTypeId,
  862. AttribData->ObjectName,
  863. &objectContent
  864. )) {
  865. AttribData->ObjectContent = IsmGetMemory (sizeof (MIG_CONTENT));
  866. CopyMemory (AttribData->ObjectContent, &objectContent, sizeof (MIG_CONTENT));
  867. // finally, we want to prepare the return string
  868. if (!AttribData->ObjectContent->ContentInFile &&
  869. (AttribData->ObjectContent->Details.DetailsSize == sizeof (DWORD)) &&
  870. AttribData->ObjectContent->MemoryContent.ContentBytes
  871. ) {
  872. type = *((PDWORD) AttribData->ObjectContent->Details.DetailsData);
  873. switch (type) {
  874. case REG_SZ:
  875. size = SizeOfString ((PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes);
  876. AttribData->ReturnString = (PCTSTR) IsmGetMemory (size);
  877. StringCopy (
  878. (PTSTR) AttribData->ReturnString,
  879. (PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes
  880. );
  881. break;
  882. case REG_EXPAND_SZ:
  883. // we need to expand the content. This will be the return string
  884. AttribData->ReturnString = IsmExpandEnvironmentString (
  885. AttribData->Platform,
  886. S_SYSENVVAR_GROUP,
  887. (PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes,
  888. NULL
  889. );
  890. if (!AttribData->ReturnString) {
  891. AttribData->ReturnString = IsmDuplicateString ((PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes);
  892. }
  893. break;
  894. case REG_MULTI_SZ:
  895. size = SizeOfMultiSz ((PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes);
  896. AttribData->ReturnString = (PCTSTR) IsmGetMemory (size);
  897. ((PTSTR)AttribData->ReturnString) [0] = 0;
  898. if (EnumFirstMultiSz (&multiSzEnum, (PCTSTR) AttribData->ObjectContent->MemoryContent.ContentBytes)) {
  899. do {
  900. StringCat (
  901. (PTSTR)AttribData->ReturnString,
  902. multiSzEnum.CurrentString
  903. );
  904. StringCat (
  905. (PTSTR)AttribData->ReturnString,
  906. TEXT(";")
  907. );
  908. } while (EnumNextMultiSz (&multiSzEnum));
  909. }
  910. break;
  911. case REG_DWORD:
  912. case REG_DWORD_BIG_ENDIAN:
  913. AttribData->ReturnString = (PCTSTR) IsmGetMemory ((sizeof (DWORD) * 2 + 3) * sizeof (TCHAR));
  914. wsprintf (
  915. (PTSTR) AttribData->ReturnString,
  916. TEXT("0x%08X"),
  917. *((PDWORD) AttribData->ObjectContent->MemoryContent.ContentBytes)
  918. );
  919. break;
  920. default:
  921. AttribData->ReturnString = (PCTSTR) IsmGetMemory ((AttribData->ObjectContent->
  922. MemoryContent.ContentSize * 3 *
  923. sizeof (TCHAR)) + sizeof (TCHAR)
  924. );
  925. ptr = (PTSTR) AttribData->ReturnString;
  926. *ptr = 0;
  927. size = 0;
  928. while (size < AttribData->ObjectContent->MemoryContent.ContentSize) {
  929. wsprintf (ptr, TEXT("%02X"), *(AttribData->ObjectContent->MemoryContent.ContentBytes + size));
  930. size ++;
  931. ptr = GetEndOfString (ptr);
  932. if (size < AttribData->ObjectContent->MemoryContent.ContentSize) {
  933. StringCopy (ptr, TEXT(","));
  934. ptr = GetEndOfString (ptr);
  935. }
  936. }
  937. }
  938. } else if (IsmIsObjectHandleNodeOnly (AttribData->ObjectName)) {
  939. //
  940. // Node only case
  941. //
  942. AttribData->ReturnString = (PCTSTR) IsmGetMemory (sizeof (TCHAR));
  943. ptr = (PTSTR) AttribData->ReturnString;
  944. *ptr = 0;
  945. }
  946. }
  947. return TRUE;
  948. }
  949. BOOL
  950. pAllocFileScriptType (
  951. IN OUT PATTRIB_DATA AttribData
  952. )
  953. {
  954. MIG_CONTENT objectContent;
  955. PCTSTR sanitizedPath;
  956. if (!AttribData) {
  957. SetLastError (ERROR_INVALID_DATA);
  958. return FALSE;
  959. }
  960. // verify that we have some registry
  961. if (!AttribData->ScriptSpecifiedObject) {
  962. SetLastError (ERROR_INVALID_DATA);
  963. return FALSE;
  964. }
  965. sanitizedPath = SanitizePath (AttribData->ScriptSpecifiedObject);
  966. // try to create encoded string
  967. AttribData->ObjectTypeId = g_FileType;
  968. AttribData->ObjectName = TurnFileStringIntoHandle (
  969. sanitizedPath,
  970. PFF_NO_LEAF_PATTERN
  971. );
  972. if (!AttribData->ObjectName) {
  973. FreePathString (sanitizedPath);
  974. if (GetLastError() == ERROR_SUCCESS) {
  975. SetLastError (ERROR_INVALID_DATA);
  976. }
  977. return FALSE;
  978. }
  979. // try to acqure the object
  980. if (IsmAcquireObject (
  981. AttribData->ObjectTypeId,
  982. AttribData->ObjectName,
  983. &objectContent
  984. )) {
  985. AttribData->ObjectContent = IsmGetMemory (sizeof (MIG_CONTENT));
  986. CopyMemory (AttribData->ObjectContent, &objectContent, sizeof (MIG_CONTENT));
  987. AttribData->ReturnString = IsmGetMemory (SizeOfString (sanitizedPath));
  988. StringCopy ((PTSTR) AttribData->ReturnString, sanitizedPath);
  989. }
  990. FreePathString (sanitizedPath);
  991. return TRUE;
  992. }
  993. BOOL
  994. pAllocDirectoryScriptType (
  995. IN OUT PATTRIB_DATA AttribData
  996. )
  997. {
  998. MIG_CONTENT objectContent;
  999. PCTSTR sanitizedPath;
  1000. if (!AttribData) {
  1001. SetLastError (ERROR_INVALID_DATA);
  1002. return FALSE;
  1003. }
  1004. // verify that we have some registry
  1005. if (!AttribData->ScriptSpecifiedObject) {
  1006. SetLastError (ERROR_INVALID_DATA);
  1007. return FALSE;
  1008. }
  1009. sanitizedPath = SanitizePath (AttribData->ScriptSpecifiedObject);
  1010. if (!sanitizedPath) {
  1011. SetLastError (ERROR_INVALID_DATA);
  1012. return FALSE;
  1013. }
  1014. // try to create encoded string
  1015. AttribData->ObjectTypeId = g_FileType;
  1016. AttribData->ObjectName = TurnFileStringIntoHandle (
  1017. sanitizedPath,
  1018. PFF_PATTERN_IS_DIR | PFF_NO_LEAF_AT_ALL
  1019. );
  1020. if (!AttribData->ObjectName) {
  1021. FreePathString (sanitizedPath);
  1022. if (GetLastError() == ERROR_SUCCESS) {
  1023. SetLastError (ERROR_INVALID_DATA);
  1024. }
  1025. return FALSE;
  1026. }
  1027. // try to acqure the object
  1028. if (IsmAcquireObject (
  1029. AttribData->ObjectTypeId,
  1030. AttribData->ObjectName,
  1031. &objectContent
  1032. )) {
  1033. AttribData->ObjectContent = IsmGetMemory (sizeof (MIG_CONTENT));
  1034. CopyMemory (AttribData->ObjectContent, &objectContent, sizeof (MIG_CONTENT));
  1035. AttribData->ReturnString = IsmGetMemory (SizeOfString (sanitizedPath));
  1036. StringCopy ((PTSTR) AttribData->ReturnString, sanitizedPath);
  1037. }
  1038. FreePathString (sanitizedPath);
  1039. return TRUE;
  1040. }
  1041. BOOL
  1042. pFreeIsmObjectScriptType (
  1043. IN OUT PATTRIB_DATA AttribData
  1044. )
  1045. {
  1046. if (AttribData->ReturnString) {
  1047. IsmReleaseMemory (AttribData->ReturnString);
  1048. AttribData->ReturnString = NULL;
  1049. }
  1050. AttribData->ObjectTypeId = 0;
  1051. if (AttribData->ObjectName) {
  1052. IsmDestroyObjectHandle (AttribData->ObjectName);
  1053. AttribData->ObjectName = NULL;
  1054. }
  1055. if (AttribData->ObjectContent) {
  1056. IsmReleaseObject (AttribData->ObjectContent);
  1057. IsmReleaseMemory (AttribData->ObjectContent);
  1058. AttribData->ObjectContent = NULL;
  1059. }
  1060. return TRUE;
  1061. }
  1062. BOOL
  1063. pAllocTextScriptType (
  1064. IN OUT PATTRIB_DATA AttribData
  1065. )
  1066. {
  1067. if (!AttribData) {
  1068. SetLastError (ERROR_INVALID_DATA);
  1069. return FALSE;
  1070. }
  1071. // verify that we have some registry
  1072. if (!AttribData->ScriptSpecifiedObject) {
  1073. SetLastError (ERROR_INVALID_DATA);
  1074. return FALSE;
  1075. }
  1076. AttribData->ReturnString = IsmGetMemory (SizeOfString (AttribData->ScriptSpecifiedObject));
  1077. StringCopy ((PTSTR) AttribData->ReturnString, AttribData->ScriptSpecifiedObject);
  1078. return TRUE;
  1079. }
  1080. BOOL
  1081. pFreeTextScriptType (
  1082. IN OUT PATTRIB_DATA AttribData
  1083. )
  1084. {
  1085. if (AttribData->ReturnString) {
  1086. IsmReleaseMemory (AttribData->ReturnString);
  1087. AttribData->ReturnString = NULL;
  1088. }
  1089. return TRUE;
  1090. }
  1091. BOOL
  1092. pAllocSystemScriptType (
  1093. IN OUT PATTRIB_DATA AttribData
  1094. )
  1095. {
  1096. PTSTR specificSection = NULL;
  1097. MIG_OSVERSIONINFO versionInfo;
  1098. UINT tchars;
  1099. BOOL detected = FALSE;
  1100. if (!AttribData) {
  1101. SetLastError (ERROR_INVALID_DATA);
  1102. return FALSE;
  1103. }
  1104. // verify that we have some registry
  1105. if (!AttribData->ScriptSpecifiedObject) {
  1106. SetLastError (ERROR_INVALID_DATA);
  1107. return FALSE;
  1108. }
  1109. if (!IsmGetOsVersionInfo (PLATFORM_SOURCE, &versionInfo)) {
  1110. return FALSE;
  1111. }
  1112. tchars = 1;
  1113. if (versionInfo.OsTypeName) {
  1114. tchars += TcharCount (versionInfo.OsTypeName) + 1;
  1115. }
  1116. if (versionInfo.OsMajorVersionName) {
  1117. tchars += TcharCount (versionInfo.OsMajorVersionName) + 1;
  1118. }
  1119. if (versionInfo.OsMinorVersionName) {
  1120. tchars += TcharCount (versionInfo.OsMinorVersionName);
  1121. }
  1122. specificSection = AllocText (tchars);
  1123. if (!specificSection) {
  1124. return FALSE;
  1125. }
  1126. if (!detected && versionInfo.OsTypeName) {
  1127. wsprintf (
  1128. specificSection,
  1129. TEXT("%s"),
  1130. versionInfo.OsTypeName
  1131. );
  1132. if (StringIMatch (AttribData->ScriptSpecifiedObject, specificSection)) {
  1133. detected = TRUE;
  1134. }
  1135. if (!detected && versionInfo.OsMajorVersionName) {
  1136. wsprintf (
  1137. specificSection,
  1138. TEXT("%s.%s"),
  1139. versionInfo.OsTypeName,
  1140. versionInfo.OsMajorVersionName
  1141. );
  1142. if (StringIMatch (AttribData->ScriptSpecifiedObject, specificSection)) {
  1143. detected = TRUE;
  1144. }
  1145. if (!detected && versionInfo.OsMinorVersionName) {
  1146. wsprintf (
  1147. specificSection,
  1148. TEXT("%s.%s.%s"),
  1149. versionInfo.OsTypeName,
  1150. versionInfo.OsMajorVersionName,
  1151. versionInfo.OsMinorVersionName
  1152. );
  1153. if (StringIMatch (AttribData->ScriptSpecifiedObject, specificSection)) {
  1154. detected = TRUE;
  1155. }
  1156. }
  1157. }
  1158. }
  1159. if (detected) {
  1160. AttribData->ReturnString = IsmGetMemory (SizeOfString (AttribData->ScriptSpecifiedObject));
  1161. StringCopy ((PTSTR) AttribData->ReturnString, AttribData->ScriptSpecifiedObject);
  1162. }
  1163. FreeText (specificSection);
  1164. specificSection = NULL;
  1165. return TRUE;
  1166. }
  1167. BOOL
  1168. pFreeSystemScriptType (
  1169. IN OUT PATTRIB_DATA AttribData
  1170. )
  1171. {
  1172. if (AttribData->ReturnString) {
  1173. IsmReleaseMemory (AttribData->ReturnString);
  1174. AttribData->ReturnString = NULL;
  1175. }
  1176. return TRUE;
  1177. }
  1178. BOOL
  1179. pAllocIniFileScriptType (
  1180. IN OUT PATTRIB_DATA AttribData
  1181. )
  1182. {
  1183. PTSTR fileName = NULL;
  1184. PTSTR sectName = NULL;
  1185. PTSTR keyName = NULL;
  1186. PTSTR charPtr = NULL;
  1187. PTSTR result = NULL;
  1188. DWORD allocatedChars;
  1189. DWORD chars;
  1190. if (!AttribData) {
  1191. SetLastError (ERROR_INVALID_DATA);
  1192. return FALSE;
  1193. }
  1194. // verify that we have something specified
  1195. if (!AttribData->ScriptSpecifiedObject) {
  1196. SetLastError (ERROR_INVALID_DATA);
  1197. return FALSE;
  1198. }
  1199. // Now, let's extract the INI file name, section and key
  1200. fileName = DuplicatePathString (AttribData->ScriptSpecifiedObject, 0);
  1201. if (!fileName) {
  1202. return FALSE;
  1203. }
  1204. charPtr = _tcschr (fileName, TEXT('/'));
  1205. if (charPtr) {
  1206. sectName = _tcsinc (charPtr);
  1207. *charPtr = 0;
  1208. if (sectName) {
  1209. charPtr = _tcschr (sectName, TEXT('/'));
  1210. if (charPtr) {
  1211. keyName = _tcsinc (charPtr);
  1212. *charPtr = 0;
  1213. }
  1214. }
  1215. }
  1216. result = NULL;
  1217. allocatedChars = 256;
  1218. do {
  1219. if (result) {
  1220. FreePathString (result);
  1221. }
  1222. allocatedChars *= 2;
  1223. result = AllocPathString (allocatedChars);
  1224. if (!result) {
  1225. return FALSE;
  1226. }
  1227. chars = GetPrivateProfileString (
  1228. sectName,
  1229. keyName,
  1230. TEXT(""),
  1231. result,
  1232. allocatedChars,
  1233. fileName
  1234. );
  1235. } while (chars >= allocatedChars - 1);
  1236. if (chars) {
  1237. AttribData->ReturnString = IsmGetMemory (SizeOfString (result));
  1238. StringCopy ((PTSTR) AttribData->ReturnString, result);
  1239. FreePathString (result);
  1240. result = NULL;
  1241. return TRUE;
  1242. }
  1243. FreePathString (result);
  1244. result = NULL;
  1245. FreePathString (fileName);
  1246. fileName = NULL;
  1247. return FALSE;
  1248. }
  1249. BOOL
  1250. pFreeIniFileScriptType (
  1251. IN OUT PATTRIB_DATA AttribData
  1252. )
  1253. {
  1254. if (AttribData->ReturnString) {
  1255. IsmReleaseMemory (AttribData->ReturnString);
  1256. AttribData->ReturnString = NULL;
  1257. }
  1258. return TRUE;
  1259. }
  1260. BOOL
  1261. AllocScriptType (
  1262. IN OUT PATTRIB_DATA AttribData CALLER_INITIALIZED
  1263. )
  1264. {
  1265. PTAG_TO_SCRIPTTYPEFN scriptFn = g_TagToScriptTypeFn;
  1266. while (scriptFn->Tag) {
  1267. if (StringIMatch (scriptFn->Tag, AttribData->ScriptSpecifiedType)) {
  1268. break;
  1269. }
  1270. scriptFn ++;
  1271. }
  1272. if (scriptFn->Tag) {
  1273. return (scriptFn->AllocFunction (AttribData));
  1274. } else {
  1275. return FALSE;
  1276. }
  1277. }
  1278. BOOL
  1279. FreeScriptType (
  1280. IN PATTRIB_DATA AttribData ZEROED
  1281. )
  1282. {
  1283. PTAG_TO_SCRIPTTYPEFN scriptFn = g_TagToScriptTypeFn;
  1284. while (scriptFn->Tag) {
  1285. if (StringIMatch (scriptFn->Tag, AttribData->ScriptSpecifiedType)) {
  1286. break;
  1287. }
  1288. scriptFn ++;
  1289. }
  1290. if (scriptFn->Tag) {
  1291. return (scriptFn->FreeFunction (AttribData));
  1292. } else {
  1293. return FALSE;
  1294. }
  1295. }