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.

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