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.

1819 lines
44 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. objstr.c
  5. Abstract:
  6. Implements a set of APIs to handle the string representation of nodes/leafs of a tree
  7. Author:
  8. 03-Jan-2000 Ovidiu Temereanca (ovidiut) - File creation.
  9. Revision History:
  10. <alias> <date> <comments>
  11. --*/
  12. /*
  13. +-------+
  14. | root1 | Level 1
  15. +-------+
  16. / \
  17. / \
  18. +---------+ (-------)
  19. | node1 | ( leaf1 ) Level 2
  20. +---------+ (-------)
  21. / | \ \__________
  22. / | \ \
  23. +-------+ +-------+ (-------) (-------)
  24. | node2 | | node3 | ( leaf2 ) ( leaf3 ) Level 3
  25. +-------+ +-------+ (-------) (-------)
  26. / \
  27. / \
  28. +-------+ (-------)
  29. | node4 | ( leaf4 ) Level 4
  30. +-------+ (-------)
  31. / \
  32. / \
  33. (-------) (-------)
  34. ( leaf5 ) ( leaf6 ) Level 5
  35. (-------) (-------)
  36. The string representation of some tree elements above:
  37. root1
  38. root1 <leaf1>
  39. root1\node1
  40. root1\node1 <leaf2>
  41. root1\node1 <leaf3>
  42. */
  43. #include "pch.h"
  44. //
  45. // Includes
  46. //
  47. // None
  48. #define DBG_OBJSTR "ObjStr"
  49. //
  50. // Strings
  51. //
  52. #define S_OBJSTR "ObjStr"
  53. //
  54. // Constants
  55. //
  56. #define OBJSTR_LEAF_HEADA '<'
  57. #define OBJSTR_LEAF_HEADW L'<'
  58. #define OBJSTR_LEAF_TAILA '>'
  59. #define OBJSTR_LEAF_TAILW L'>'
  60. #define OBJSTR_SEPARATORA ' '
  61. #define OBJSTR_SEPARATORW L' '
  62. //
  63. // Macros
  64. //
  65. #define pObjStrAllocateMemory(Size) PmGetMemory (g_ObjStrPool, Size)
  66. #define pObjStrFreeMemory(Buffer) if (/*lint --e(774)*/Buffer) PmReleaseMemory (g_ObjStrPool, Buffer)
  67. //
  68. // Types
  69. //
  70. // None
  71. //
  72. // Globals
  73. //
  74. PMHANDLE g_ObjStrPool;
  75. //
  76. // Macro expansion list
  77. //
  78. // None
  79. //
  80. // Private function prototypes
  81. //
  82. // None
  83. //
  84. // Macro expansion definition
  85. //
  86. // None
  87. //
  88. // Code
  89. //
  90. BOOL
  91. ObsInitialize (
  92. VOID
  93. )
  94. /*++
  95. Routine Description:
  96. ObsInitialize initializes this library.
  97. Arguments:
  98. none
  99. Return Value:
  100. TRUE if the init was successful.
  101. FALSE if not. GetLastError() returns extended error info.
  102. --*/
  103. {
  104. g_ObjStrPool = PmCreateNamedPool (S_OBJSTR);
  105. return g_ObjStrPool != NULL;
  106. }
  107. VOID
  108. ObsTerminate (
  109. VOID
  110. )
  111. /*++
  112. Routine Description:
  113. ObsTerminate is called to free resources used by this lib.
  114. Arguments:
  115. none
  116. Return Value:
  117. none
  118. --*/
  119. {
  120. if (g_ObjStrPool) {
  121. PmDestroyPool (g_ObjStrPool);
  122. g_ObjStrPool = NULL;
  123. }
  124. }
  125. /*++
  126. Routine Description:
  127. pExtractStringAB is a private function that creates a new string in the given pool,
  128. using a source string and a limit to copy up to.
  129. Arguments:
  130. Start - Specifies the source string
  131. End - Specifies the point to copy up to (excluding it), within the same string
  132. Pool - Specifies the pool to use for allocation
  133. Return Value:
  134. A pointer to the newly created string
  135. --*/
  136. PSTR
  137. pExtractStringABA (
  138. IN PCSTR Start,
  139. IN PCSTR End,
  140. IN PMHANDLE Pool
  141. )
  142. {
  143. PSTR p;
  144. p = PmGetMemory (Pool, (DWORD)(End - Start + 1) * DWSIZEOF (CHAR));
  145. StringCopyABA (p, Start, End);
  146. return p;
  147. }
  148. PWSTR
  149. pExtractStringABW (
  150. IN PCWSTR Start,
  151. IN PCWSTR End,
  152. IN PMHANDLE Pool
  153. )
  154. {
  155. PWSTR p;
  156. p = PmGetMemory (Pool, (DWORD)(End - Start + 1) * DWSIZEOF (WCHAR));
  157. StringCopyABW (p, Start, End);
  158. return p;
  159. }
  160. /*++
  161. Routine Description:
  162. ObsFree frees the given object from the private pool
  163. Arguments:
  164. EncodedObject - Specifies the source string
  165. End - Specifies the point to copy up to (excluding it), within the same string
  166. Pool - Specifies the pool to use for allocation
  167. Return Value:
  168. A pointer to the newly created string
  169. --*/
  170. VOID
  171. ObsFreeA (
  172. IN PCSTR EncodedObject
  173. )
  174. {
  175. pObjStrFreeMemory ((PVOID)EncodedObject);
  176. }
  177. VOID
  178. ObsFreeW (
  179. IN PCWSTR EncodedObject
  180. )
  181. {
  182. pObjStrFreeMemory ((PVOID)EncodedObject);
  183. }
  184. BOOL
  185. ObsEncodeStringA (
  186. PSTR Destination,
  187. PCSTR Source
  188. )
  189. {
  190. MBCHAR ch;
  191. while (*Source) {
  192. ch = _mbsnextc (Source);
  193. if (_mbschr (EscapedCharsA, ch)) {
  194. *Destination = '^';
  195. Destination ++;
  196. }
  197. // now copy the multibyte character
  198. if (IsLeadByte (*Source)) {
  199. *Destination = *Source;
  200. Destination ++;
  201. Source ++;
  202. }
  203. *Destination = *Source;
  204. Destination ++;
  205. Source ++;
  206. }
  207. *Destination = 0;
  208. return TRUE;
  209. }
  210. BOOL
  211. ObsEncodeStringW (
  212. PWSTR Destination,
  213. PCWSTR Source
  214. )
  215. {
  216. while (*Source) {
  217. if (wcschr (EscapedCharsW, *Source)) {
  218. *Destination = L'^';
  219. Destination ++;
  220. }
  221. *Destination = *Source;
  222. Destination ++;
  223. Source ++;
  224. }
  225. *Destination = 0;
  226. return TRUE;
  227. }
  228. BOOL
  229. ObsDecodeStringA (
  230. PSTR Destination,
  231. PCSTR Source
  232. )
  233. {
  234. BOOL escaping = FALSE;
  235. while (*Source) {
  236. if ((_mbsnextc (Source) == '^') && (!escaping)) {
  237. escaping = TRUE;
  238. Source ++;
  239. } else {
  240. escaping = FALSE;
  241. // now copy the multibyte character
  242. if (IsLeadByte (*Source)) {
  243. *Destination = *Source;
  244. Destination ++;
  245. Source ++;
  246. }
  247. *Destination = *Source;
  248. Destination ++;
  249. Source ++;
  250. }
  251. }
  252. *Destination = 0;
  253. return TRUE;
  254. }
  255. BOOL
  256. ObsDecodeStringW (
  257. PWSTR Destination,
  258. PCWSTR Source
  259. )
  260. {
  261. BOOL escaping = FALSE;
  262. while (*Source) {
  263. if ((*Source == L'^') && (!escaping)) {
  264. escaping = TRUE;
  265. Source ++;
  266. } else {
  267. escaping = FALSE;
  268. *Destination = *Source;
  269. Destination ++;
  270. Source ++;
  271. }
  272. }
  273. *Destination = 0;
  274. return TRUE;
  275. }
  276. /*++
  277. Routine Description:
  278. ObsSplitObjectStringEx splits the given encoded object into components: node and
  279. leaf. Strings are allocated from the given pool
  280. Arguments:
  281. EncodedObject - Specifies the source object string
  282. DecodedNode - Receives the decoded node part; optional
  283. DecodedLeaf - Receives the decoded leaf part; optional
  284. Pool - Specifies the pool to use for allocation; optional; if not specified,
  285. the module pool will be used and ObsFree needs to be called for them
  286. to be freed
  287. Return Value:
  288. TRUE if the source object has a legal format and it has been split into components
  289. --*/
  290. BOOL
  291. ObsSplitObjectStringExA (
  292. IN PCSTR EncodedObject,
  293. OUT PSTR* DecodedNode, OPTIONAL
  294. OUT PSTR* DecodedLeaf, OPTIONAL
  295. IN PMHANDLE Pool, OPTIONAL
  296. IN BOOL DecodeStrings
  297. )
  298. {
  299. PCSTR p;
  300. PCSTR q;
  301. PCSTR nodeTerm;
  302. PSTR leaf = NULL;
  303. PCSTR lastWack = NULL;
  304. PCSTR lastStar = NULL;
  305. MYASSERT (EncodedObject);
  306. if (!EncodedObject) {
  307. return FALSE;
  308. }
  309. if (!Pool) {
  310. Pool = g_ObjStrPool;
  311. }
  312. p = EncodedObject;
  313. if (*p == '\\') {
  314. //
  315. // must be UNC format; check for syntax
  316. //
  317. p++;
  318. if (*p != '\\') {
  319. DEBUGMSGA ((
  320. DBG_OBJSTR,
  321. "ObsSplitObjectStringExA: relative paths not supported: %s",
  322. EncodedObject
  323. ));
  324. return FALSE;
  325. }
  326. }
  327. while (*p && *p != OBJSTR_LEAF_HEADA) {
  328. if (*p == OBJSTR_SEPARATORA) {
  329. q = p + 1;
  330. while (*q == OBJSTR_SEPARATORA) {
  331. q++;
  332. }
  333. if (*q == 0 || *q == OBJSTR_LEAF_HEADA) {
  334. break;
  335. }
  336. p = q;
  337. }
  338. if (*p == '\\') {
  339. if ((UBINT)p == (UBINT)lastWack + 1) {
  340. //
  341. // two wacks in a row? no way
  342. //
  343. DEBUGMSGA ((
  344. DBG_OBJSTR,
  345. "ObsSplitObjectStringExA: Bad EncodedObject: %s",
  346. EncodedObject
  347. ));
  348. return FALSE;
  349. }
  350. lastWack = p;
  351. } else if (*p == '*') {
  352. lastStar = p;
  353. }
  354. p = CharNextA (p);
  355. }
  356. if (p == EncodedObject) {
  357. DEBUGMSGA ((
  358. DBG_OBJSTR,
  359. "ObsSplitObjectStringExA: Bad EncodedObject: %s",
  360. EncodedObject
  361. ));
  362. return FALSE;
  363. }
  364. if (lastWack && lastWack + 1 == p && lastStar && lastStar + 1 != lastWack) {
  365. nodeTerm = lastWack;
  366. } else {
  367. nodeTerm = p;
  368. }
  369. while (*p == OBJSTR_SEPARATORA) {
  370. //
  371. // *p is one byte wide
  372. //
  373. p++;
  374. }
  375. if (*p) {
  376. if (*p != OBJSTR_LEAF_HEADA) {
  377. //
  378. // wrong start
  379. //
  380. DEBUGMSGA ((
  381. DBG_OBJSTR,
  382. "ObsSplitObjectStringExA: Bad EncodedObject: %s",
  383. EncodedObject
  384. ));
  385. return FALSE;
  386. }
  387. q = p + 1;
  388. while (*q != OBJSTR_LEAF_TAILA) {
  389. if (*q == 0) {
  390. //
  391. // incorrectly terminated
  392. //
  393. DEBUGMSGA ((
  394. DBG_OBJSTR,
  395. "ObsSplitObjectStringExA: Bad EncodedObject: %s",
  396. EncodedObject
  397. ));
  398. return FALSE;
  399. }
  400. q = CharNextA (q);
  401. }
  402. if (*(q + 1) != 0) {
  403. //
  404. // must end after the terminating char
  405. //
  406. DEBUGMSGA ((
  407. DBG_OBJSTR,
  408. "ObsSplitObjectStringExA: Bad EncodedObject: \"%s\"; chars after the leaf",
  409. EncodedObject
  410. ));
  411. return FALSE;
  412. }
  413. if (DecodedLeaf) {
  414. leaf = pExtractStringABA (p + 1, q, Pool);
  415. if (DecodeStrings) {
  416. //
  417. // decode chars
  418. //
  419. ObsDecodeStringA (leaf, leaf);
  420. }
  421. }
  422. }
  423. if (DecodedLeaf) {
  424. *DecodedLeaf = leaf;
  425. }
  426. if (DecodedNode) {
  427. *DecodedNode = pExtractStringABA (EncodedObject, nodeTerm, Pool);
  428. if (DecodeStrings) {
  429. //
  430. // decode chars
  431. //
  432. ObsDecodeStringA (*DecodedNode, *DecodedNode);
  433. }
  434. }
  435. return TRUE;
  436. }
  437. BOOL
  438. ObsSplitObjectStringExW (
  439. IN PCWSTR EncodedObject,
  440. OUT PWSTR* DecodedNode, OPTIONAL
  441. OUT PWSTR* DecodedLeaf, OPTIONAL
  442. IN PMHANDLE Pool, OPTIONAL
  443. IN BOOL DecodeStrings
  444. )
  445. {
  446. PCWSTR p;
  447. PCWSTR q;
  448. PCWSTR nodeTerm;
  449. PWSTR leaf = NULL;
  450. PCWSTR lastWack = NULL;
  451. PCWSTR lastStar = NULL;
  452. MYASSERT (EncodedObject);
  453. if (!EncodedObject) {
  454. return FALSE;
  455. }
  456. if (!Pool) {
  457. Pool = g_ObjStrPool;
  458. }
  459. p = EncodedObject;
  460. if (*p == L'\\') {
  461. //
  462. // must be UNC format; check for syntax
  463. //
  464. p++;
  465. if (*p != L'\\') {
  466. DEBUGMSGW ((
  467. DBG_OBJSTR,
  468. "ObsSplitObjectStringExW: relative paths not supported: %s",
  469. EncodedObject
  470. ));
  471. return FALSE;
  472. }
  473. }
  474. while (*p && *p != OBJSTR_LEAF_HEADW) {
  475. if (*p == OBJSTR_SEPARATORW) {
  476. q = p + 1;
  477. while (*q == OBJSTR_SEPARATORW) {
  478. q++;
  479. }
  480. if (*q == 0 || *q == OBJSTR_LEAF_HEADW) {
  481. break;
  482. }
  483. p = q;
  484. }
  485. if (*p == L'\\') {
  486. if ((UBINT)p == (UBINT)lastWack + 1) {
  487. //
  488. // two wacks in a row? no way
  489. //
  490. DEBUGMSGW ((
  491. DBG_OBJSTR,
  492. "ObsSplitObjectStringExW: Bad EncodedObject: %s",
  493. EncodedObject
  494. ));
  495. return FALSE;
  496. }
  497. lastWack = p;
  498. } else if (*p == L'*') {
  499. lastStar = p;
  500. }
  501. p++;
  502. }
  503. if (p == EncodedObject) {
  504. DEBUGMSGW ((
  505. DBG_OBJSTR,
  506. "ObsSplitObjectStringExW: Bad EncodedObject: %s",
  507. EncodedObject
  508. ));
  509. return FALSE;
  510. }
  511. if (lastWack && lastWack + 1 == p && lastStar && lastStar + 1 != lastWack) {
  512. nodeTerm = lastWack;
  513. } else {
  514. nodeTerm = p;
  515. }
  516. while (*p == OBJSTR_SEPARATORW) {
  517. //
  518. // *p is one WCHAR wide
  519. //
  520. p++;
  521. }
  522. if (*p) {
  523. if (*p != OBJSTR_LEAF_HEADW) {
  524. //
  525. // wrong start
  526. //
  527. DEBUGMSGW ((
  528. DBG_OBJSTR,
  529. "ObsSplitObjectStringExW: Bad EncodedObject: %s",
  530. EncodedObject
  531. ));
  532. return FALSE;
  533. }
  534. q = p + 1;
  535. while (*q != OBJSTR_LEAF_TAILW) {
  536. if (*q == 0) {
  537. //
  538. // incorrectly terminated
  539. //
  540. DEBUGMSGW ((
  541. DBG_OBJSTR,
  542. "ObsSplitObjectStringExW: Bad EncodedObject: %s",
  543. EncodedObject
  544. ));
  545. return FALSE;
  546. }
  547. q++;
  548. }
  549. if (*(q + 1) != 0) {
  550. //
  551. // must end after the terminating char
  552. //
  553. DEBUGMSGW ((
  554. DBG_OBJSTR,
  555. "ObsSplitObjectStringExW: Bad EncodedObject: \"%s\"; chars after the leaf",
  556. EncodedObject
  557. ));
  558. return FALSE;
  559. }
  560. if (DecodedLeaf) {
  561. leaf = pExtractStringABW (p + 1, q, Pool);
  562. if (DecodeStrings) {
  563. //
  564. // decode chars
  565. //
  566. ObsDecodeStringW (leaf, leaf);
  567. }
  568. }
  569. }
  570. if (DecodedLeaf) {
  571. *DecodedLeaf = leaf;
  572. }
  573. if (DecodedNode) {
  574. *DecodedNode = pExtractStringABW (EncodedObject, nodeTerm, Pool);
  575. if (DecodeStrings) {
  576. //
  577. // decode chars
  578. //
  579. ObsDecodeStringW (*DecodedNode, *DecodedNode);
  580. }
  581. }
  582. return TRUE;
  583. }
  584. /*++
  585. Routine Description:
  586. ObsBuildEncodedObjectStringEx builds an encoded object from components: node and
  587. leaf. The string is allocated from the module's pool
  588. Arguments:
  589. DecodedNode - Specifies the decoded node part
  590. DecodedLeaf - Specifies the decoded leaf part; optional
  591. EncodeObject - Specifies TRUE if the resulting object needs to be encoded using
  592. encoding rules
  593. Return Value:
  594. Pointer to the newly created object string
  595. --*/
  596. PSTR
  597. ObsBuildEncodedObjectStringExA (
  598. IN PCSTR DecodedNode,
  599. IN PCSTR DecodedLeaf, OPTIONAL
  600. IN BOOL EncodeObject
  601. )
  602. {
  603. PSTR encodedNode;
  604. PSTR encodedLeaf;
  605. PSTR encodedString;
  606. MYASSERT (DecodedNode);
  607. if (!DecodedNode) {
  608. return NULL;
  609. }
  610. //
  611. // at most, one byte char will be expanded to 4 bytes (4 times)
  612. //
  613. if (EncodeObject) {
  614. encodedNode = pObjStrAllocateMemory (4 * ByteCountA (DecodedNode) + DWSIZEOF(CHAR));
  615. ObsEncodeStringA (encodedNode, DecodedNode);
  616. } else {
  617. encodedNode = DuplicateTextExA (g_ObjStrPool, DecodedNode, 0, NULL);
  618. }
  619. if (!DecodedLeaf) {
  620. return encodedNode;
  621. }
  622. if (EncodeObject) {
  623. encodedLeaf = pObjStrAllocateMemory (4 * ByteCountA (DecodedLeaf) + DWSIZEOF(CHAR));
  624. ObsEncodeStringA (encodedLeaf, DecodedLeaf);
  625. } else {
  626. encodedLeaf = DuplicateTextExA (g_ObjStrPool, DecodedLeaf, 0, NULL);
  627. }
  628. //
  629. // preferred format: %1 <%2> %1 - Node, %2 - Leaf
  630. //
  631. encodedString = pObjStrAllocateMemory (
  632. ByteCountA (encodedNode) +
  633. DWSIZEOF (" <>") +
  634. ByteCountA (encodedLeaf)
  635. );
  636. wsprintfA (
  637. encodedString,
  638. "%s %c%s%c",
  639. encodedNode,
  640. OBJSTR_LEAF_HEADA,
  641. encodedLeaf,
  642. OBJSTR_LEAF_TAILA
  643. );
  644. pObjStrFreeMemory (encodedNode);
  645. pObjStrFreeMemory (encodedLeaf);
  646. return encodedString;
  647. }
  648. PWSTR
  649. ObsBuildEncodedObjectStringExW (
  650. IN PCWSTR DecodedNode,
  651. IN PCWSTR DecodedLeaf, OPTIONAL
  652. IN BOOL EncodeObject
  653. )
  654. {
  655. PWSTR encodedNode;
  656. PWSTR encodedLeaf;
  657. PWSTR encodedString;
  658. MYASSERT (DecodedNode);
  659. if (!DecodedNode) {
  660. return NULL;
  661. }
  662. //
  663. // at most, one wide char will be expanded to 4 wide chars (4 times)
  664. //
  665. if (EncodeObject) {
  666. encodedNode = pObjStrAllocateMemory (4 * ByteCountW (DecodedNode) + DWSIZEOF(WCHAR));
  667. ObsEncodeStringW (encodedNode, DecodedNode);
  668. } else {
  669. encodedNode = DuplicateTextExW (g_ObjStrPool, DecodedNode, 0, NULL);
  670. }
  671. if (!DecodedLeaf) {
  672. return encodedNode;
  673. }
  674. if (EncodeObject) {
  675. encodedLeaf = pObjStrAllocateMemory (4 * ByteCountW (DecodedLeaf) + DWSIZEOF(WCHAR));
  676. ObsEncodeStringW (encodedLeaf, DecodedLeaf);
  677. } else {
  678. encodedLeaf = DuplicateTextExW (g_ObjStrPool, DecodedLeaf, 0, NULL);
  679. }
  680. //
  681. // preferred format: %1 <%2> %1 - Node, %2 - Leaf
  682. //
  683. encodedString = pObjStrAllocateMemory (
  684. ByteCountW (encodedNode) +
  685. DWSIZEOF (L" <>") +
  686. ByteCountW (encodedLeaf)
  687. );
  688. wsprintfW (
  689. encodedString,
  690. L"%s %c%s%c",
  691. encodedNode,
  692. OBJSTR_LEAF_HEADW,
  693. encodedLeaf,
  694. OBJSTR_LEAF_TAILW
  695. );
  696. pObjStrFreeMemory (encodedNode);
  697. pObjStrFreeMemory (encodedLeaf);
  698. return encodedString;
  699. }
  700. /*++
  701. Routine Description:
  702. ObsCreateParsedPatternEx parses the given object into an internal format for quick
  703. pattern matching
  704. Arguments:
  705. EncodedObject - Specifies the source object string
  706. Return Value:
  707. A pointer to the newly created structure or NULL if the object was invalid
  708. --*/
  709. POBSPARSEDPATTERNA
  710. ObsCreateParsedPatternExA (
  711. IN PCSTR EncodedObject,
  712. IN BOOL MakePrimaryRootEndWithWack
  713. )
  714. {
  715. POBSPARSEDPATTERNA ospp;
  716. PSTR decodedNode;
  717. PSTR decodedLeaf;
  718. PCSTR p;
  719. PCSTR root;
  720. MYASSERT (EncodedObject);
  721. if (!ObsSplitObjectStringExA (EncodedObject, &decodedNode, &decodedLeaf, NULL, FALSE)) {
  722. return NULL;
  723. }
  724. ospp = pObjStrAllocateMemory (DWSIZEOF(OBSPARSEDPATTERNA));
  725. ZeroMemory (ospp, DWSIZEOF(OBSPARSEDPATTERNA));
  726. ospp->MaxSubLevel = NODE_LEVEL_MAX;
  727. MYASSERT (decodedNode);
  728. if (!GetNodePatternMinMaxLevelsA (decodedNode, decodedNode, &ospp->MinNodeLevel, &ospp->MaxNodeLevel)) {
  729. pObjStrFreeMemory (decodedNode);
  730. pObjStrFreeMemory (decodedLeaf);
  731. pObjStrFreeMemory (ospp);
  732. return NULL;
  733. }
  734. MYASSERT (ospp->MinNodeLevel > 0 && ospp->MaxNodeLevel >= ospp->MinNodeLevel);
  735. if (ospp->MaxNodeLevel != NODE_LEVEL_MAX) {
  736. ospp->MaxSubLevel = ospp->MaxNodeLevel - ospp->MinNodeLevel;
  737. }
  738. ospp->NodePattern = CreateParsedPatternA (decodedNode);
  739. if (!ospp->NodePattern) {
  740. DEBUGMSGA ((
  741. DBG_OBJSTR,
  742. "ObsCreateParsedPatternExA: Bad EncodedObject: %s",
  743. EncodedObject
  744. ));
  745. pObjStrFreeMemory (decodedNode);
  746. pObjStrFreeMemory (decodedLeaf);
  747. pObjStrFreeMemory (ospp);
  748. return NULL;
  749. }
  750. if (ospp->NodePattern->PatternCount > 1) {
  751. DEBUGMSGA ((
  752. DBG_OBJSTR,
  753. "ObsCreateParsedPatternExA: Bad EncodedObject (multiple patterns specified): %s",
  754. EncodedObject
  755. ));
  756. DestroyParsedPatternA (ospp->NodePattern);
  757. pObjStrFreeMemory (decodedNode);
  758. pObjStrFreeMemory (decodedLeaf);
  759. pObjStrFreeMemory (ospp);
  760. return NULL;
  761. }
  762. root = ParsedPatternGetRootA (ospp->NodePattern);
  763. if (root) {
  764. //
  765. // extract the real root part
  766. //
  767. if (ParsedPatternIsExactMatchA (ospp->NodePattern)) {
  768. ospp->Flags |= OBSPF_EXACTNODE;
  769. ospp->ExactRoot = DuplicateTextExA (g_ObjStrPool, root, 0, NULL);
  770. ospp->ExactRootBytes = ByteCountA (root);
  771. ospp->MaxSubLevel = 0;
  772. } else {
  773. p = FindLastWackA (root);
  774. if (p) {
  775. //
  776. // exact root specified
  777. // if the last wack is actually the last character or is followed by star(s),
  778. // optimize the matching by setting some flags
  779. //
  780. if (*(p + 1) == 0) {
  781. if (ParsedPatternIsRootPlusStarA (ospp->NodePattern)) {
  782. ospp->Flags |= OBSPF_NODEISROOTPLUSSTAR;
  783. }
  784. }
  785. if (MakePrimaryRootEndWithWack && *root != '\\') {
  786. //
  787. // see if this is really the primary root
  788. //
  789. if (p == _mbschr (root, '\\')) {
  790. //
  791. // include it in the string
  792. //
  793. p++;
  794. }
  795. }
  796. ospp->ExactRoot = pExtractStringABA (root, p, g_ObjStrPool);
  797. ospp->ExactRootBytes = (DWORD)((PBYTE)p - (PBYTE)root);
  798. }
  799. }
  800. } else if (ParsedPatternIsOptionalA (ospp->NodePattern)) {
  801. ospp->Flags |= OBSPF_OPTIONALNODE;
  802. }
  803. if (decodedLeaf) {
  804. if (*decodedLeaf) {
  805. ospp->LeafPattern = CreateParsedPatternA (decodedLeaf);
  806. if (!ospp->LeafPattern) {
  807. DEBUGMSGA ((
  808. DBG_OBJSTR,
  809. "ObsCreateParsedPatternExA: Bad EncodedObject: %s",
  810. EncodedObject
  811. ));
  812. DestroyParsedPatternA (ospp->NodePattern);
  813. pObjStrFreeMemory (ospp->ExactRoot);
  814. pObjStrFreeMemory (decodedNode);
  815. pObjStrFreeMemory (decodedLeaf);
  816. pObjStrFreeMemory (ospp);
  817. return NULL;
  818. }
  819. if (ospp->LeafPattern->PatternCount > 1) {
  820. DEBUGMSGA ((
  821. DBG_OBJSTR,
  822. "ObsCreateParsedPatternExA: Bad EncodedObject (multiple patterns specified): %s",
  823. EncodedObject
  824. ));
  825. DestroyParsedPatternA (ospp->NodePattern);
  826. DestroyParsedPatternA (ospp->LeafPattern);
  827. pObjStrFreeMemory (ospp->ExactRoot);
  828. pObjStrFreeMemory (decodedNode);
  829. pObjStrFreeMemory (decodedLeaf);
  830. pObjStrFreeMemory (ospp);
  831. return NULL;
  832. }
  833. if (ParsedPatternIsOptionalA (ospp->LeafPattern)) {
  834. ospp->Flags |= OBSPF_OPTIONALLEAF;
  835. } else if (ParsedPatternIsExactMatchA (ospp->LeafPattern)) {
  836. ospp->Flags |= OBSPF_EXACTLEAF;
  837. }
  838. } else {
  839. //
  840. // accept empty string for leaf
  841. //
  842. ospp->Flags |= OBSPF_EXACTLEAF;
  843. }
  844. ospp->Leaf = DuplicateTextExA (g_ObjStrPool, decodedLeaf, 0, NULL);
  845. } else {
  846. ospp->Flags |= OBSPF_NOLEAF;
  847. }
  848. pObjStrFreeMemory (decodedNode);
  849. pObjStrFreeMemory (decodedLeaf);
  850. return ospp;
  851. }
  852. POBSPARSEDPATTERNW
  853. ObsCreateParsedPatternExW (
  854. IN PCWSTR EncodedObject,
  855. IN BOOL MakePrimaryRootEndWithWack
  856. )
  857. {
  858. POBSPARSEDPATTERNW ospp;
  859. PWSTR decodedNode;
  860. PWSTR decodedLeaf;
  861. PCWSTR p;
  862. PCWSTR root;
  863. MYASSERT (EncodedObject);
  864. if (!ObsSplitObjectStringExW (EncodedObject, &decodedNode, &decodedLeaf, NULL, FALSE)) {
  865. return NULL;
  866. }
  867. ospp = pObjStrAllocateMemory (DWSIZEOF(OBSPARSEDPATTERNW));
  868. ZeroMemory (ospp, DWSIZEOF(OBSPARSEDPATTERNW));
  869. ospp->MaxSubLevel = NODE_LEVEL_MAX;
  870. MYASSERT (decodedNode);
  871. if (!GetNodePatternMinMaxLevelsW (decodedNode, decodedNode, &ospp->MinNodeLevel, &ospp->MaxNodeLevel)) {
  872. pObjStrFreeMemory (decodedNode);
  873. pObjStrFreeMemory (decodedLeaf);
  874. pObjStrFreeMemory (ospp);
  875. return NULL;
  876. }
  877. MYASSERT (ospp->MinNodeLevel > 0 && ospp->MaxNodeLevel >= ospp->MinNodeLevel);
  878. if (ospp->MaxNodeLevel != NODE_LEVEL_MAX) {
  879. ospp->MaxSubLevel = ospp->MaxNodeLevel - ospp->MinNodeLevel;
  880. }
  881. ospp->NodePattern = CreateParsedPatternW (decodedNode);
  882. if (!ospp->NodePattern) {
  883. DEBUGMSGW ((
  884. DBG_OBJSTR,
  885. "ObsCreateParsedPatternExW: Bad EncodedObject: %s",
  886. EncodedObject
  887. ));
  888. pObjStrFreeMemory (decodedNode);
  889. pObjStrFreeMemory (decodedLeaf);
  890. pObjStrFreeMemory (ospp);
  891. return NULL;
  892. }
  893. if (ospp->NodePattern->PatternCount > 1) {
  894. DEBUGMSGW ((
  895. DBG_OBJSTR,
  896. "ObsCreateParsedPatternExW: Bad EncodedObject (multiple patterns specified): %s",
  897. EncodedObject
  898. ));
  899. DestroyParsedPatternW (ospp->NodePattern);
  900. pObjStrFreeMemory (decodedNode);
  901. pObjStrFreeMemory (decodedLeaf);
  902. pObjStrFreeMemory (ospp);
  903. return NULL;
  904. }
  905. root = ParsedPatternGetRootW (ospp->NodePattern);
  906. if (root) {
  907. //
  908. // extract the real root part
  909. //
  910. if (ParsedPatternIsExactMatchW (ospp->NodePattern)) {
  911. ospp->Flags |= OBSPF_EXACTNODE;
  912. ospp->ExactRoot = DuplicateTextExW (g_ObjStrPool, root, 0, NULL);
  913. ospp->ExactRootBytes = ByteCountW (root);
  914. ospp->MaxSubLevel = 0;
  915. } else {
  916. p = FindLastWackW (root);
  917. if (p) {
  918. //
  919. // exact root specified
  920. // if the last wack is actually the last character or is followed by star(s),
  921. // optimize the matching by setting some flags
  922. //
  923. if (*(p + 1) == 0) {
  924. if (ParsedPatternIsRootPlusStarW (ospp->NodePattern)) {
  925. ospp->Flags |= OBSPF_NODEISROOTPLUSSTAR;
  926. }
  927. }
  928. if (MakePrimaryRootEndWithWack && *root != L'\\') {
  929. //
  930. // see if this is really the primary root
  931. //
  932. if (p == wcschr (root, L'\\')) {
  933. //
  934. // include it in the string
  935. //
  936. p++;
  937. }
  938. }
  939. ospp->ExactRoot = pExtractStringABW (root, p, g_ObjStrPool);
  940. ospp->ExactRootBytes = (DWORD)((PBYTE)p - (PBYTE)root);
  941. }
  942. }
  943. } else if (ParsedPatternIsOptionalW (ospp->NodePattern)) {
  944. ospp->Flags |= OBSPF_OPTIONALNODE;
  945. }
  946. if (decodedLeaf) {
  947. if (*decodedLeaf) {
  948. ospp->LeafPattern = CreateParsedPatternW (decodedLeaf);
  949. if (!ospp->LeafPattern) {
  950. DEBUGMSGW ((
  951. DBG_OBJSTR,
  952. "ObsCreateParsedPatternExW: Bad EncodedObject: %s",
  953. EncodedObject
  954. ));
  955. DestroyParsedPatternW (ospp->NodePattern);
  956. pObjStrFreeMemory (ospp->ExactRoot);
  957. pObjStrFreeMemory (decodedNode);
  958. pObjStrFreeMemory (decodedLeaf);
  959. pObjStrFreeMemory (ospp);
  960. return NULL;
  961. }
  962. if (ospp->LeafPattern->PatternCount > 1) {
  963. DEBUGMSGW ((
  964. DBG_OBJSTR,
  965. "ObsCreateParsedPatternExW: Bad EncodedObject (multiple patterns specified): %s",
  966. EncodedObject
  967. ));
  968. DestroyParsedPatternW (ospp->NodePattern);
  969. DestroyParsedPatternW (ospp->LeafPattern);
  970. pObjStrFreeMemory (ospp->ExactRoot);
  971. pObjStrFreeMemory (decodedNode);
  972. pObjStrFreeMemory (decodedLeaf);
  973. pObjStrFreeMemory (ospp);
  974. return NULL;
  975. }
  976. if (ParsedPatternIsOptionalW (ospp->LeafPattern)) {
  977. ospp->Flags |= OBSPF_OPTIONALLEAF;
  978. } else if (ParsedPatternIsExactMatchW (ospp->LeafPattern)) {
  979. ospp->Flags |= OBSPF_EXACTLEAF;
  980. }
  981. } else {
  982. //
  983. // accept empty string for leaf
  984. //
  985. ospp->Flags |= OBSPF_EXACTLEAF;
  986. }
  987. ospp->Leaf = DuplicateTextExW (g_ObjStrPool, decodedLeaf, 0, NULL);
  988. } else {
  989. ospp->Flags |= OBSPF_NOLEAF;
  990. }
  991. pObjStrFreeMemory (decodedNode);
  992. pObjStrFreeMemory (decodedLeaf);
  993. return ospp;
  994. }
  995. /*++
  996. Routine Description:
  997. ObsDestroyParsedPattern destroys the given structure, freeing resources
  998. Arguments:
  999. ParsedPattern - Specifies the parsed pattern structure
  1000. Return Value:
  1001. none
  1002. --*/
  1003. VOID
  1004. ObsDestroyParsedPatternA (
  1005. IN POBSPARSEDPATTERNA ParsedPattern
  1006. )
  1007. {
  1008. if (ParsedPattern) {
  1009. if (ParsedPattern->NodePattern) {
  1010. DestroyParsedPatternA (ParsedPattern->NodePattern);
  1011. }
  1012. if (ParsedPattern->LeafPattern) {
  1013. DestroyParsedPatternA (ParsedPattern->LeafPattern);
  1014. }
  1015. if (ParsedPattern->Leaf) {
  1016. FreeTextExA (g_ObjStrPool, ParsedPattern->Leaf);
  1017. }
  1018. pObjStrFreeMemory (ParsedPattern->ExactRoot);
  1019. pObjStrFreeMemory (ParsedPattern);
  1020. }
  1021. }
  1022. VOID
  1023. ObsDestroyParsedPatternW (
  1024. IN POBSPARSEDPATTERNW ParsedPattern
  1025. )
  1026. {
  1027. if (ParsedPattern) {
  1028. if (ParsedPattern->NodePattern) {
  1029. DestroyParsedPatternW (ParsedPattern->NodePattern);
  1030. }
  1031. if (ParsedPattern->LeafPattern) {
  1032. DestroyParsedPatternW (ParsedPattern->LeafPattern);
  1033. }
  1034. if (ParsedPattern->Leaf) {
  1035. FreeTextExW (g_ObjStrPool, ParsedPattern->Leaf);
  1036. }
  1037. pObjStrFreeMemory (ParsedPattern->ExactRoot);
  1038. pObjStrFreeMemory (ParsedPattern);
  1039. }
  1040. }
  1041. /*++
  1042. Routine Description:
  1043. ObsParsedPatternMatch tests the given object against a parsed pattern
  1044. Arguments:
  1045. ParsedPattern - Specifies the parsed pattern structure
  1046. EncodedObject - Specifies the object string to test against the pattern
  1047. Return Value:
  1048. TRUE if the string matches the pattern
  1049. --*/
  1050. BOOL
  1051. ObsParsedPatternMatchA (
  1052. IN POBSPARSEDPATTERNA ParsedPattern,
  1053. IN PCSTR EncodedObject
  1054. )
  1055. {
  1056. PSTR decodedNode;
  1057. PSTR decodedLeaf;
  1058. BOOL b;
  1059. if (!ObsSplitObjectStringExA (EncodedObject, &decodedNode, &decodedLeaf, NULL, FALSE)) {
  1060. return FALSE;
  1061. }
  1062. b = ObsParsedPatternMatchExA (ParsedPattern, decodedNode, decodedLeaf);
  1063. pObjStrFreeMemory (decodedNode);
  1064. pObjStrFreeMemory (decodedLeaf);
  1065. return b;
  1066. }
  1067. BOOL
  1068. ObsParsedPatternMatchW (
  1069. IN POBSPARSEDPATTERNW ParsedPattern,
  1070. IN PCWSTR EncodedObject
  1071. )
  1072. {
  1073. PWSTR decodedNode;
  1074. PWSTR decodedLeaf;
  1075. BOOL b;
  1076. if (!ObsSplitObjectStringExW (EncodedObject, &decodedNode, &decodedLeaf, NULL, FALSE)) {
  1077. return FALSE;
  1078. }
  1079. b = ObsParsedPatternMatchExW (ParsedPattern, decodedNode, decodedLeaf);
  1080. pObjStrFreeMemory (decodedNode);
  1081. pObjStrFreeMemory (decodedLeaf);
  1082. return b;
  1083. }
  1084. /*++
  1085. Routine Description:
  1086. ObsParsedPatternMatchEx tests the given object, given by its components,
  1087. against a parsed pattern
  1088. Arguments:
  1089. ParsedPattern - Specifies the parsed pattern structure
  1090. Node - Specifies the node part of the object string to test against the pattern
  1091. Leaf - Specifies the leaf part of the object string to test against the pattern
  1092. Return Value:
  1093. TRUE if the string components match the pattern
  1094. --*/
  1095. BOOL
  1096. ObsParsedPatternMatchExA (
  1097. IN POBSPARSEDPATTERNA ParsedPattern,
  1098. IN PCSTR Node,
  1099. IN PCSTR Leaf OPTIONAL
  1100. )
  1101. {
  1102. MYASSERT (Node && ParsedPattern->NodePattern);
  1103. if (!(Node && ParsedPattern->NodePattern)) {
  1104. return FALSE;
  1105. }
  1106. if ((ParsedPattern->Flags & OBSPF_NOLEAF) && Leaf ||
  1107. !(ParsedPattern->Flags & OBSPF_NOLEAF) && !Leaf
  1108. ) {
  1109. return FALSE;
  1110. }
  1111. if (!TestParsedPatternA (ParsedPattern->NodePattern, Node)) {
  1112. return FALSE;
  1113. }
  1114. return !Leaf || TestParsedPatternA (ParsedPattern->LeafPattern, Leaf);
  1115. }
  1116. BOOL
  1117. ObsParsedPatternMatchExW (
  1118. IN POBSPARSEDPATTERNW ParsedPattern,
  1119. IN PCWSTR Node, OPTIONAL
  1120. IN PCWSTR Leaf OPTIONAL
  1121. )
  1122. {
  1123. MYASSERT (Node && ParsedPattern->NodePattern);
  1124. if (!(Node && ParsedPattern->NodePattern)) {
  1125. return FALSE;
  1126. }
  1127. if ((ParsedPattern->Flags & OBSPF_NOLEAF) && Leaf ||
  1128. !(ParsedPattern->Flags & OBSPF_NOLEAF) && !Leaf
  1129. ) {
  1130. return FALSE;
  1131. }
  1132. if (!TestParsedPatternW (ParsedPattern->NodePattern, Node)) {
  1133. return FALSE;
  1134. }
  1135. return !Leaf || TestParsedPatternW (ParsedPattern->LeafPattern, Leaf);
  1136. }
  1137. /*++
  1138. Routine Description:
  1139. ObsPatternMatch tests an object string against a pattern object string
  1140. Arguments:
  1141. ParsedPattern - Specifies the parsed pattern structure
  1142. Node - Specifies the node part of the object string to test against the pattern
  1143. Leaf - Specifies the leaf part of the object string to test against the pattern
  1144. Return Value:
  1145. TRUE if the string components match the pattern
  1146. --*/
  1147. BOOL
  1148. ObsPatternMatchA (
  1149. IN PCSTR ObjectPattern,
  1150. IN PCSTR ObjectStr
  1151. )
  1152. {
  1153. PSTR opNode;
  1154. PSTR opLeaf;
  1155. PSTR osNode;
  1156. PSTR osLeaf;
  1157. BOOL b = FALSE;
  1158. if (ObsSplitObjectStringExA (ObjectPattern, &opNode, &opLeaf, NULL, FALSE)) {
  1159. if (ObsSplitObjectStringExA (ObjectStr, &osNode, &osLeaf, NULL, TRUE)) {
  1160. if (opNode) {
  1161. if (osNode) {
  1162. b = IsPatternMatchExABA (opNode, osNode, GetEndOfStringA (osNode));
  1163. } else {
  1164. b = FALSE;
  1165. }
  1166. } else {
  1167. if (osNode) {
  1168. b = FALSE;
  1169. } else {
  1170. b = TRUE;
  1171. }
  1172. }
  1173. if (b) {
  1174. if (opLeaf) {
  1175. if (osLeaf) {
  1176. b = IsPatternMatchExABA (opLeaf, osLeaf, GetEndOfStringA (osLeaf));
  1177. } else {
  1178. b = TRUE;
  1179. }
  1180. } else {
  1181. if (osLeaf) {
  1182. b = FALSE;
  1183. } else {
  1184. b = TRUE;
  1185. }
  1186. }
  1187. }
  1188. pObjStrFreeMemory (osNode);
  1189. pObjStrFreeMemory (osLeaf);
  1190. }
  1191. ELSE_DEBUGMSGA ((DBG_OBJSTR, "ObsPatternMatchA: bad ObjectStr: %s", ObjectStr));
  1192. pObjStrFreeMemory (opNode);
  1193. pObjStrFreeMemory (opLeaf);
  1194. }
  1195. ELSE_DEBUGMSGA ((DBG_OBJSTR, "ObsPatternMatchA: bad ObjectPattern: %s", ObjectPattern));
  1196. return b;
  1197. }
  1198. BOOL
  1199. ObsPatternMatchW (
  1200. IN PCWSTR ObjectPattern,
  1201. IN PCWSTR ObjectStr
  1202. )
  1203. {
  1204. PWSTR opNode;
  1205. PWSTR opLeaf;
  1206. PWSTR osNode;
  1207. PWSTR osLeaf;
  1208. BOOL b = FALSE;
  1209. if (ObsSplitObjectStringExW (ObjectPattern, &opNode, &opLeaf, NULL, FALSE)) {
  1210. if (ObsSplitObjectStringExW (ObjectStr, &osNode, &osLeaf, NULL, FALSE)) {
  1211. if (opNode) {
  1212. if (osNode) {
  1213. b = IsPatternMatchExABW (opNode, osNode, GetEndOfStringW (osNode));
  1214. } else {
  1215. b = FALSE;
  1216. }
  1217. } else {
  1218. if (osNode) {
  1219. b = FALSE;
  1220. } else {
  1221. b = TRUE;
  1222. }
  1223. }
  1224. if (b) {
  1225. if (opLeaf) {
  1226. if (osLeaf) {
  1227. b = IsPatternMatchExABW (opLeaf, osLeaf, GetEndOfStringW (osLeaf));
  1228. } else {
  1229. b = FALSE;
  1230. }
  1231. } else {
  1232. if (osLeaf) {
  1233. b = FALSE;
  1234. } else {
  1235. b = TRUE;
  1236. }
  1237. }
  1238. }
  1239. pObjStrFreeMemory (osNode);
  1240. pObjStrFreeMemory (osLeaf);
  1241. }
  1242. ELSE_DEBUGMSGW ((DBG_OBJSTR, "ObsPatternMatchW: bad ObjectStr: %s", ObjectStr));
  1243. pObjStrFreeMemory (opNode);
  1244. pObjStrFreeMemory (opLeaf);
  1245. }
  1246. ELSE_DEBUGMSGW ((DBG_OBJSTR, "ObsPatternMatchW: bad ObjectPattern: %s", ObjectPattern));
  1247. return b;
  1248. }
  1249. /*++
  1250. Routine Description:
  1251. ObsIsPatternContained compares two patterns to see if one of them is
  1252. included in the other. Both patterns may contain any of the following
  1253. expressions:
  1254. Arguments:
  1255. Container - Specifies the container pattern
  1256. Contained - Specifies the contained pattern
  1257. Return Value:
  1258. TRUE if Contained is contained in Container
  1259. --*/
  1260. BOOL
  1261. ObsIsPatternContainedA (
  1262. IN PCSTR Container,
  1263. IN PCSTR Contained
  1264. )
  1265. {
  1266. PSTR opNode;
  1267. PSTR opLeaf;
  1268. PSTR osNode;
  1269. PSTR osLeaf;
  1270. BOOL b = FALSE;
  1271. if (ObsSplitObjectStringExA (Container, &opNode, &opLeaf, NULL, FALSE)) {
  1272. if (ObsSplitObjectStringExA (Contained, &osNode, &osLeaf, NULL, FALSE)) {
  1273. if (opNode) {
  1274. if (osNode) {
  1275. b = IsPatternContainedExA (opNode, osNode);
  1276. } else {
  1277. b = FALSE;
  1278. }
  1279. } else {
  1280. if (osNode) {
  1281. b = FALSE;
  1282. } else {
  1283. b = TRUE;
  1284. }
  1285. }
  1286. if (b) {
  1287. if (opLeaf) {
  1288. if (osLeaf) {
  1289. b = IsPatternContainedExA (opLeaf, osLeaf);
  1290. } else {
  1291. b = TRUE;
  1292. }
  1293. } else {
  1294. if (osLeaf) {
  1295. b = FALSE;
  1296. } else {
  1297. b = TRUE;
  1298. }
  1299. }
  1300. }
  1301. pObjStrFreeMemory (osNode);
  1302. pObjStrFreeMemory (osLeaf);
  1303. }
  1304. ELSE_DEBUGMSGA ((DBG_OBJSTR, "ObsIsPatternContainedA: bad Contained string: %s", Contained));
  1305. pObjStrFreeMemory (opNode);
  1306. pObjStrFreeMemory (opLeaf);
  1307. }
  1308. ELSE_DEBUGMSGA ((DBG_OBJSTR, "ObsIsPatternContainedA: bad Container string: %s", Container));
  1309. return b;
  1310. }
  1311. BOOL
  1312. ObsIsPatternContainedW (
  1313. IN PCWSTR Container,
  1314. IN PCWSTR Contained
  1315. )
  1316. {
  1317. PWSTR opNode;
  1318. PWSTR opLeaf;
  1319. PWSTR osNode;
  1320. PWSTR osLeaf;
  1321. BOOL b = FALSE;
  1322. if (ObsSplitObjectStringExW (Container, &opNode, &opLeaf, NULL, FALSE)) {
  1323. if (ObsSplitObjectStringExW (Contained, &osNode, &osLeaf, NULL, FALSE)) {
  1324. if (opNode) {
  1325. if (osNode) {
  1326. b = IsPatternContainedExW (opNode, osNode);
  1327. } else {
  1328. b = FALSE;
  1329. }
  1330. } else {
  1331. if (osNode) {
  1332. b = FALSE;
  1333. } else {
  1334. b = TRUE;
  1335. }
  1336. }
  1337. if (b) {
  1338. if (opLeaf) {
  1339. if (osLeaf) {
  1340. b = IsPatternContainedExW (opLeaf, osLeaf);
  1341. } else {
  1342. b = TRUE;
  1343. }
  1344. } else {
  1345. if (osLeaf) {
  1346. b = FALSE;
  1347. } else {
  1348. b = TRUE;
  1349. }
  1350. }
  1351. }
  1352. pObjStrFreeMemory (osNode);
  1353. pObjStrFreeMemory (osLeaf);
  1354. }
  1355. ELSE_DEBUGMSGW ((DBG_OBJSTR, "ObsIsPatternContainedW: bad Contained string: %s", Contained));
  1356. pObjStrFreeMemory (opNode);
  1357. pObjStrFreeMemory (opLeaf);
  1358. }
  1359. ELSE_DEBUGMSGW ((DBG_OBJSTR, "ObsIsPatternContainedW: bad Container string: %s", Container));
  1360. return b;
  1361. }
  1362. /*++
  1363. Routine Description:
  1364. ObsGetPatternLevels gets the minimum and maximum levels of a string that would
  1365. match the given pattern.
  1366. Arguments:
  1367. ObjectPattern - Specifies the pattern
  1368. MinLevel - Receives the minimum possible level; the root has level 1
  1369. MaxLevel - Receives the maximum possible level; the root has level 1
  1370. Return Value:
  1371. TRUE if the pattern was correct and computing was done; FALSE otherwise
  1372. --*/
  1373. BOOL
  1374. ObsGetPatternLevelsA (
  1375. IN PCSTR ObjectPattern,
  1376. OUT PDWORD MinLevel, OPTIONAL
  1377. OUT PDWORD MaxLevel OPTIONAL
  1378. )
  1379. {
  1380. PSTR decodedNode;
  1381. PSTR decodedLeaf;
  1382. BOOL b;
  1383. if (!ObsSplitObjectStringExA (ObjectPattern, &decodedNode, &decodedLeaf, NULL, FALSE)) {
  1384. return FALSE;
  1385. }
  1386. if (decodedNode) {
  1387. b = GetNodePatternMinMaxLevelsA (decodedNode, decodedNode, MinLevel, MaxLevel);
  1388. } else {
  1389. b = FALSE;
  1390. }
  1391. pObjStrFreeMemory (decodedNode);
  1392. pObjStrFreeMemory (decodedLeaf);
  1393. return b;
  1394. }
  1395. BOOL
  1396. ObsGetPatternLevelsW (
  1397. IN PCWSTR ObjectPattern,
  1398. OUT PDWORD MinLevel,
  1399. OUT PDWORD MaxLevel
  1400. )
  1401. {
  1402. PWSTR decodedNode;
  1403. PWSTR decodedLeaf;
  1404. BOOL b;
  1405. if (!ObsSplitObjectStringExW (ObjectPattern, &decodedNode, &decodedLeaf, NULL, FALSE)) {
  1406. return FALSE;
  1407. }
  1408. if (decodedNode) {
  1409. b = GetNodePatternMinMaxLevelsW (decodedNode, decodedNode, MinLevel, MaxLevel);
  1410. } else {
  1411. b = FALSE;
  1412. }
  1413. pObjStrFreeMemory (decodedNode);
  1414. pObjStrFreeMemory (decodedLeaf);
  1415. return b;
  1416. }
  1417. /*++
  1418. Routine Description:
  1419. ObsPatternIncludesPattern decides if a given pattern includes another pattern,
  1420. meaning that any string that would match the second will match the first.
  1421. Arguments:
  1422. IncludingPattern - Specifies the first parsed pattern
  1423. IncludedPattern - Specifies the second parsed pattern
  1424. Return Value:
  1425. TRUE if the first pattern includes the second
  1426. --*/
  1427. BOOL
  1428. ObsPatternIncludesPatternA (
  1429. IN POBSPARSEDPATTERNA IncludingPattern,
  1430. IN POBSPARSEDPATTERNA IncludedPattern
  1431. )
  1432. {
  1433. MYASSERT (IncludingPattern->NodePattern && IncludedPattern->NodePattern);
  1434. if (!(IncludingPattern->NodePattern && IncludedPattern->NodePattern)) {
  1435. return FALSE;
  1436. }
  1437. if (IncludingPattern->MinNodeLevel > IncludedPattern->MinNodeLevel ||
  1438. IncludingPattern->MaxNodeLevel < IncludedPattern->MaxNodeLevel
  1439. ) {
  1440. return FALSE;
  1441. }
  1442. if (!PatternIncludesPatternA (IncludingPattern->NodePattern, IncludedPattern->NodePattern)) {
  1443. return FALSE;
  1444. }
  1445. if (IncludingPattern->LeafPattern) {
  1446. if (!IncludedPattern->LeafPattern) {
  1447. return FALSE;
  1448. }
  1449. if (!PatternIncludesPatternA (IncludingPattern->LeafPattern, IncludedPattern->LeafPattern)) {
  1450. return FALSE;
  1451. }
  1452. } else {
  1453. if (IncludedPattern->LeafPattern) {
  1454. return FALSE;
  1455. }
  1456. }
  1457. return TRUE;
  1458. }
  1459. BOOL
  1460. ObsPatternIncludesPatternW (
  1461. IN POBSPARSEDPATTERNW IncludingPattern,
  1462. IN POBSPARSEDPATTERNW IncludedPattern
  1463. )
  1464. {
  1465. MYASSERT (IncludingPattern->NodePattern && IncludedPattern->NodePattern);
  1466. if (!(IncludingPattern->NodePattern && IncludedPattern->NodePattern)) {
  1467. return FALSE;
  1468. }
  1469. if (IncludingPattern->MinNodeLevel > IncludedPattern->MinNodeLevel ||
  1470. IncludingPattern->MaxNodeLevel < IncludedPattern->MaxNodeLevel
  1471. ) {
  1472. return FALSE;
  1473. }
  1474. if (!PatternIncludesPatternW (IncludingPattern->NodePattern, IncludedPattern->NodePattern)) {
  1475. return FALSE;
  1476. }
  1477. if (IncludingPattern->LeafPattern) {
  1478. if (!IncludedPattern->LeafPattern) {
  1479. return FALSE;
  1480. }
  1481. if (!PatternIncludesPatternW (IncludingPattern->LeafPattern, IncludedPattern->LeafPattern)) {
  1482. return FALSE;
  1483. }
  1484. } else {
  1485. if (IncludedPattern->LeafPattern) {
  1486. return FALSE;
  1487. }
  1488. }
  1489. return TRUE;
  1490. }