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.

997 lines
20 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. exclist.c
  5. Abstract:
  6. Implements a set of APIs to manage exclusion lists of objects
  7. of various well-known types.
  8. Author:
  9. Ovidiu Temereanca (ovidiut) 23-Nov-1999
  10. Revision History:
  11. <alias> <date> <comments>
  12. --*/
  13. #include "pch.h"
  14. //
  15. // Includes
  16. //
  17. // None
  18. #define DBG_EXCLIST "ExcList"
  19. //
  20. // Strings
  21. //
  22. #define S_EXCLUSIONLIST "ExcList"
  23. //
  24. // Constants
  25. //
  26. // None
  27. //
  28. // Macros
  29. //
  30. #define pAllocateMemory(Size) PmGetMemory (g_ElPool,Size)
  31. #define pFreeMemory(Buffer) if (Buffer) PmReleaseMemory (g_ElPool, (PVOID)Buffer)
  32. //
  33. // Types
  34. //
  35. typedef struct {
  36. DWORD TypeId;
  37. PCSTR TypeName;
  38. } EXCLISTPROPS, *PEXCLISTPROPS;
  39. //
  40. // Globals
  41. //
  42. PMHANDLE g_ElPool;
  43. GROWLIST* g_ElTypeLists;
  44. //
  45. // Macro expansion list
  46. //
  47. // Defined in exclist.h
  48. //
  49. // Private function prototypes
  50. //
  51. // None
  52. //
  53. // Macro expansion definition
  54. //
  55. #define DEFMAC(TypeId,TypeName) TypeId, TypeName,
  56. EXCLISTPROPS g_ExcListProps [] = {
  57. EXCLUSIONLIST_TYPES /* , */
  58. ELT_LAST, NULL
  59. };
  60. #undef DEFMAC
  61. //
  62. // Code
  63. //
  64. BOOL
  65. ElInitialize (
  66. VOID
  67. )
  68. /*++
  69. Routine Description:
  70. ElInitialize initializes this library.
  71. Arguments:
  72. none
  73. Return Value:
  74. TRUE if the init was successful.
  75. FALSE if not. GetLastError() returns extended error info.
  76. --*/
  77. {
  78. MYASSERT (!g_ElPool);
  79. g_ElPool = PmCreateNamedPool (S_EXCLUSIONLIST);
  80. if (!g_ElPool) {
  81. return FALSE;
  82. }
  83. MYASSERT (!g_ElTypeLists);
  84. g_ElTypeLists = pAllocateMemory (ELT_LAST * DWSIZEOF (GROWLIST));
  85. MYASSERT (g_ElTypeLists);
  86. ZeroMemory (g_ElTypeLists, ELT_LAST * DWSIZEOF (GROWLIST));
  87. return TRUE;
  88. }
  89. /*++
  90. Routine Description:
  91. ElTerminate is called to free resources used by this lib.
  92. Arguments:
  93. none
  94. Return Value:
  95. none
  96. --*/
  97. VOID
  98. ElTerminateA (
  99. VOID
  100. )
  101. {
  102. ElRemoveAllA ();
  103. if (g_ElTypeLists) {
  104. pFreeMemory (g_ElTypeLists);
  105. g_ElTypeLists = NULL;
  106. }
  107. if (g_ElPool) {
  108. PmDestroyPool (g_ElPool);
  109. g_ElPool = NULL;
  110. }
  111. }
  112. VOID
  113. ElTerminateW (
  114. VOID
  115. )
  116. {
  117. ElRemoveAllW ();
  118. if (g_ElTypeLists) {
  119. pFreeMemory (g_ElTypeLists);
  120. g_ElTypeLists = NULL;
  121. }
  122. if (g_ElPool) {
  123. PmDestroyPool (g_ElPool);
  124. g_ElPool = NULL;
  125. }
  126. }
  127. /*++
  128. Routine Description:
  129. ElGetTypeId returns the TypeId of a type given by name
  130. Arguments:
  131. TypeName - Specifies the name
  132. Return Value:
  133. One of DWORD enumeration values
  134. --*/
  135. DWORD
  136. ElGetTypeId (
  137. IN PCSTR TypeName
  138. )
  139. {
  140. UINT u;
  141. if (TypeName) {
  142. for (u = 0; g_ExcListProps[u].TypeName; u++) {
  143. if (StringIMatchA (g_ExcListProps[u].TypeName, TypeName)) {
  144. return g_ExcListProps[u].TypeId;
  145. }
  146. }
  147. }
  148. return ELT_LAST;
  149. }
  150. /*++
  151. Routine Description:
  152. ElGetTypeName returns the type name of a type given by TypeId
  153. Arguments:
  154. TypeId - Specifies the ID
  155. Return Value:
  156. A pointer to one of the known type names or NULL if TypeId is unknown
  157. --*/
  158. PCSTR
  159. ElGetTypeName (
  160. IN DWORD TypeId
  161. )
  162. {
  163. MYASSERT (TypeId < ELT_LAST);
  164. if (TypeId >= ELT_LAST) {
  165. return NULL;
  166. }
  167. return g_ExcListProps[TypeId].TypeName;
  168. }
  169. /*++
  170. Routine Description:
  171. ElAdd adds the given object of the given type to the exclusion list. The object
  172. is first parsed so that the decision if a given string matches this pattern is faster.
  173. Arguments:
  174. ObjectType - Specifies the object type
  175. ObjectName - Specifies the object pattern string
  176. Return Value:
  177. TRUE if the string pattern was successfully parsed and added to the list
  178. --*/
  179. BOOL
  180. ElAddA (
  181. IN DWORD ObjectType,
  182. IN PCSTR ObjectName
  183. )
  184. {
  185. POBSPARSEDPATTERNA pp;
  186. MYASSERT (ObjectType < ELT_LAST);
  187. if (ObjectType >= ELT_LAST) {
  188. return FALSE;
  189. }
  190. MYASSERT (ObjectName);
  191. //
  192. // add each object in its own type list
  193. //
  194. pp = ObsCreateParsedPatternExA (NULL, ObjectName, ObjectType == ELT_FILE);
  195. if (!pp) {
  196. DEBUGMSGA ((
  197. DBG_EXCLIST,
  198. "ElAddA: Bad ObjectName: %s (type %s)",
  199. ObjectName,
  200. ElGetTypeName (ObjectType)
  201. ));
  202. return FALSE;
  203. }
  204. //
  205. // add the pointer to the list
  206. //
  207. GlAppend (&g_ElTypeLists[ObjectType], (PBYTE)&pp, DWSIZEOF (pp));
  208. DEBUGMSGA ((
  209. DBG_EXCLIST,
  210. "ElAddA: Added excluded %s as type %s",
  211. ObjectName,
  212. ElGetTypeName (ObjectType)
  213. ));
  214. return TRUE;
  215. }
  216. BOOL
  217. ElAddW (
  218. IN DWORD ObjectType,
  219. IN PCWSTR ObjectName
  220. )
  221. {
  222. POBSPARSEDPATTERNW pp;
  223. MYASSERT (ObjectType < ELT_LAST);
  224. if (ObjectType >= ELT_LAST) {
  225. return FALSE;
  226. }
  227. MYASSERT (ObjectName);
  228. //
  229. // add each object in its own type list
  230. //
  231. pp = ObsCreateParsedPatternExW (NULL, ObjectName, ObjectType == ELT_FILE);
  232. if (!pp) {
  233. DEBUGMSGW ((
  234. DBG_EXCLIST,
  235. "ElAddW: Bad ObjectName: %s (type %hs)",
  236. ObjectName,
  237. ElGetTypeName (ObjectType)
  238. ));
  239. return FALSE;
  240. }
  241. //
  242. // add the pointer to the list
  243. //
  244. GlAppend (&g_ElTypeLists[ObjectType], (PBYTE)&pp, DWSIZEOF (pp));
  245. DEBUGMSGW ((
  246. DBG_EXCLIST,
  247. "ElAddW: Added excluded %s as type %hs",
  248. ObjectName,
  249. ElGetTypeName (ObjectType)
  250. ));
  251. return TRUE;
  252. }
  253. /*++
  254. Routine Description:
  255. ElRemoveAll removes all object patterns from the exclusion list.
  256. Arguments:
  257. none
  258. Return Value:
  259. none
  260. --*/
  261. VOID
  262. ElRemoveAllA (
  263. VOID
  264. )
  265. {
  266. PGROWLIST gl;
  267. UINT u;
  268. UINT i;
  269. if (g_ElTypeLists) {
  270. for (u = 0; u < ELT_LAST; u++) {
  271. gl = &g_ElTypeLists[u];
  272. for (i = GlGetSize (gl); i > 0; i--) {
  273. ObsDestroyParsedPatternA (*(POBSPARSEDPATTERNA*) GlGetItem (gl, i - 1));
  274. GlDeleteItem (gl, i - 1);
  275. }
  276. GlFree (gl);
  277. }
  278. ZeroMemory (g_ElTypeLists, ELT_LAST * DWSIZEOF (GROWLIST));
  279. }
  280. }
  281. VOID
  282. ElRemoveAllW (
  283. VOID
  284. )
  285. {
  286. PGROWLIST gl;
  287. UINT u;
  288. UINT i;
  289. if (g_ElTypeLists) {
  290. for (u = 0; u < ELT_LAST; u++) {
  291. gl = &g_ElTypeLists[u];
  292. for (i = GlGetSize (gl); i > 0; i--) {
  293. ObsDestroyParsedPatternW (*(POBSPARSEDPATTERNW*) GlGetItem (gl, i - 1));
  294. GlDeleteItem (gl, i - 1);
  295. }
  296. GlFree (gl);
  297. }
  298. ZeroMemory (g_ElTypeLists, ELT_LAST * DWSIZEOF (GROWLIST));
  299. }
  300. }
  301. /*++
  302. Routine Description:
  303. ElIsExcluded decides if the given object string is excluded (if it matches one of the
  304. patterns added previously).
  305. Arguments:
  306. ObjectType - Specifies the object type
  307. Object - Specifies the object string
  308. Return Value:
  309. TRUE if the string is excluded
  310. --*/
  311. BOOL
  312. ElIsExcludedA (
  313. IN DWORD ObjectType,
  314. IN PCSTR Object
  315. )
  316. {
  317. PGROWLIST gl;
  318. POBSPARSEDPATTERNA pp;
  319. UINT i;
  320. PSTR node;
  321. PSTR leaf;
  322. BOOL b = FALSE;
  323. MYASSERT (ObjectType < ELT_LAST);
  324. if (ObjectType >= ELT_LAST) {
  325. return FALSE;
  326. }
  327. MYASSERT (Object);
  328. if (!Object) {
  329. return FALSE;
  330. }
  331. //
  332. // lookup each object in its own type list
  333. //
  334. gl = &g_ElTypeLists[ObjectType];
  335. if (!ObsSplitObjectStringExA (Object, &node, &leaf, g_ElPool, FALSE)) {
  336. DEBUGMSGA ((DBG_EXCLIST, "ElIsExcludedA: invalid Object: \"%s\"", Object));
  337. return FALSE;
  338. }
  339. for (i = GlGetSize (gl); i > 0; i--) {
  340. pp = *(POBSPARSEDPATTERNA*) GlGetItem (gl, i - 1);
  341. //
  342. // if stored pattern doesn't contain a node,
  343. // that means "any node matches"
  344. //
  345. if (pp->NodePattern && !node) {
  346. continue;
  347. }
  348. if (!pp->LeafPattern && leaf || pp->LeafPattern && !leaf) {
  349. continue;
  350. }
  351. if (leaf) {
  352. MYASSERT (pp->LeafPattern);
  353. if (!TestParsedPatternA (pp->LeafPattern, leaf)) {
  354. continue;
  355. }
  356. }
  357. if (pp->NodePattern && !TestParsedPatternA (pp->NodePattern, node)) {
  358. continue;
  359. }
  360. //
  361. // the patterns match!
  362. //
  363. b = TRUE;
  364. break;
  365. }
  366. pFreeMemory (node);
  367. pFreeMemory (leaf);
  368. return b;
  369. }
  370. BOOL
  371. ElIsExcludedW (
  372. IN DWORD ObjectType,
  373. IN PCWSTR Object
  374. )
  375. {
  376. PGROWLIST gl;
  377. POBSPARSEDPATTERNW pp;
  378. UINT i;
  379. PWSTR node;
  380. PWSTR leaf;
  381. BOOL b = FALSE;
  382. MYASSERT (ObjectType < ELT_LAST);
  383. if (ObjectType >= ELT_LAST) {
  384. return FALSE;
  385. }
  386. MYASSERT (Object);
  387. if (!Object) {
  388. return FALSE;
  389. }
  390. //
  391. // lookup each object in its own type list
  392. //
  393. gl = &g_ElTypeLists[ObjectType];
  394. if (!ObsSplitObjectStringExW (Object, &node, &leaf, g_ElPool, FALSE)) {
  395. DEBUGMSGW ((DBG_EXCLIST, "ElIsExcludedW: invalid Object: \"%s\"", Object));
  396. return FALSE;
  397. }
  398. for (i = GlGetSize (gl); i > 0; i--) {
  399. pp = *(POBSPARSEDPATTERNW*) GlGetItem (gl, i - 1);
  400. //
  401. // if stored pattern doesn't contain a node,
  402. // that means "any node matches"
  403. //
  404. if (pp->NodePattern && !node) {
  405. continue;
  406. }
  407. if (!pp->LeafPattern && leaf || pp->LeafPattern && !leaf) {
  408. continue;
  409. }
  410. if (leaf) {
  411. MYASSERT (pp->LeafPattern);
  412. if (!TestParsedPatternW (pp->LeafPattern, leaf)) {
  413. continue;
  414. }
  415. }
  416. if (pp->NodePattern && !TestParsedPatternW (pp->NodePattern, node)) {
  417. continue;
  418. }
  419. //
  420. // the patterns match!
  421. //
  422. b = TRUE;
  423. break;
  424. }
  425. pFreeMemory (node);
  426. pFreeMemory (leaf);
  427. return b;
  428. }
  429. /*++
  430. Routine Description:
  431. ElIsExcluded2 decides if the object given by its 2 components is excluded
  432. (if it matches one of the patterns added previously).
  433. Arguments:
  434. ObjectType - Specifies the object type
  435. Node - Specifies the node part of the object
  436. Leaf - Specifies the leaf part of the object; optional
  437. Return Value:
  438. TRUE if the string is excluded
  439. --*/
  440. BOOL
  441. ElIsExcluded2A (
  442. IN DWORD ObjectType,
  443. IN PCSTR Node, OPTIONAL
  444. IN PCSTR Leaf OPTIONAL
  445. )
  446. {
  447. PGROWLIST gl;
  448. POBSPARSEDPATTERNA pp;
  449. UINT i;
  450. //
  451. // validate params
  452. //
  453. MYASSERT (ObjectType < ELT_LAST);
  454. if (ObjectType >= ELT_LAST) {
  455. return FALSE;
  456. }
  457. gl = &g_ElTypeLists[ObjectType];
  458. for (i = GlGetSize (gl); i > 0; i--) {
  459. pp = *(POBSPARSEDPATTERNA*) GlGetItem (gl, i - 1);
  460. //
  461. // if stored pattern doesn't contain a node,
  462. // that means "any node matches"
  463. //
  464. if (pp->NodePattern && !Node) {
  465. continue;
  466. }
  467. if (!pp->LeafPattern && Leaf || pp->LeafPattern && !Leaf) {
  468. continue;
  469. }
  470. if (Leaf) {
  471. MYASSERT (pp->LeafPattern);
  472. if (!TestParsedPatternA (pp->LeafPattern, Leaf)) {
  473. continue;
  474. }
  475. }
  476. if (pp->NodePattern && !TestParsedPatternA (pp->NodePattern, Node)) {
  477. continue;
  478. }
  479. //
  480. // the patterns match!
  481. //
  482. return TRUE;
  483. }
  484. return FALSE;
  485. }
  486. BOOL
  487. ElIsExcluded2W (
  488. IN DWORD ObjectType,
  489. IN PCWSTR Node, OPTIONAL
  490. IN PCWSTR Leaf OPTIONAL
  491. )
  492. {
  493. PGROWLIST gl;
  494. POBSPARSEDPATTERNW pp;
  495. UINT i;
  496. //
  497. // validate params
  498. //
  499. MYASSERT (ObjectType < ELT_LAST);
  500. if (ObjectType >= ELT_LAST) {
  501. return FALSE;
  502. }
  503. gl = &g_ElTypeLists[ObjectType];
  504. for (i = GlGetSize (gl); i > 0; i--) {
  505. pp = *(POBSPARSEDPATTERNW*) GlGetItem (gl, i - 1);
  506. //
  507. // if stored pattern doesn't contain a node,
  508. // that means "any node matches"
  509. //
  510. if (pp->NodePattern && !Node) {
  511. continue;
  512. }
  513. if (!pp->LeafPattern && Leaf || pp->LeafPattern && !Leaf) {
  514. continue;
  515. }
  516. if (Leaf) {
  517. MYASSERT (pp->LeafPattern);
  518. if (!TestParsedPatternW (pp->LeafPattern, Leaf)) {
  519. continue;
  520. }
  521. }
  522. if (pp->NodePattern && !TestParsedPatternW (pp->NodePattern, Node)) {
  523. continue;
  524. }
  525. //
  526. // the patterns match!
  527. //
  528. return TRUE;
  529. }
  530. return FALSE;
  531. }
  532. /*++
  533. Routine Description:
  534. ElIsTreeExcluded2 decides if the object given by its 2 components and representing the
  535. whole tree beneath it (as a root) is excluded; i.e. if any child of the given object
  536. is excluded
  537. Arguments:
  538. ObjectType - Specifies the object type
  539. Root - Specifies the root of the tree
  540. LeafPattern - Specifies the leaf pattern to be used for this decision; optional;
  541. if NULL, no leaf pattern matching will be attempted
  542. Return Value:
  543. TRUE if the tree is excluded, given the leaf pattern
  544. --*/
  545. BOOL
  546. ElIsTreeExcluded2A (
  547. IN DWORD ObjectType,
  548. IN PCSTR Root,
  549. IN PCSTR LeafPattern OPTIONAL
  550. )
  551. {
  552. PGROWLIST gl;
  553. UINT i;
  554. POBSPARSEDPATTERNA pp;
  555. PCSTR subTreePattern;
  556. PPARSEDPATTERNA stpp;
  557. PPARSEDPATTERNA lpp;
  558. BOOL b;
  559. MYASSERT (ObjectType < ELT_LAST);
  560. if (ObjectType >= ELT_LAST) {
  561. return FALSE;
  562. }
  563. MYASSERT (Root);
  564. if (!Root) {
  565. return FALSE;
  566. }
  567. gl = &g_ElTypeLists[ObjectType];
  568. if (GlGetSize (gl) == 0) {
  569. return FALSE;
  570. }
  571. if (LeafPattern) {
  572. lpp = CreateParsedPatternA (LeafPattern);
  573. if (!lpp) {
  574. DEBUGMSGA ((DBG_EXCLIST, "ElIsTreeExcluded2A: invalid LeafPattern: %s", LeafPattern));
  575. return FALSE;
  576. }
  577. } else {
  578. lpp = NULL;
  579. }
  580. //
  581. // look if Root ends with "\*"
  582. //
  583. subTreePattern = FindLastWackA (Root);
  584. if (!subTreePattern || subTreePattern[1] != '*' || subTreePattern[2] != 0) {
  585. subTreePattern = JoinPathsInPoolExA ((g_ElPool, Root, "*", NULL));
  586. } else {
  587. subTreePattern = Root;
  588. }
  589. b = FALSE;
  590. stpp = CreateParsedPatternA (subTreePattern);
  591. if (stpp) {
  592. for (i = GlGetSize (gl); i > 0; i--) {
  593. pp = *(POBSPARSEDPATTERNA*) GlGetItem (gl, i - 1);
  594. if (!pp->LeafPattern && LeafPattern || pp->LeafPattern && !LeafPattern) {
  595. continue;
  596. }
  597. if (LeafPattern) {
  598. MYASSERT (pp->LeafPattern);
  599. if (!PatternIncludesPatternA (pp->LeafPattern, lpp)) {
  600. continue;
  601. }
  602. }
  603. if (!PatternIncludesPatternA (pp->NodePattern, stpp)) {
  604. continue;
  605. }
  606. //
  607. // the patterns match!
  608. //
  609. b = TRUE;
  610. break;
  611. }
  612. DestroyParsedPatternA (stpp);
  613. }
  614. ELSE_DEBUGMSGA ((DBG_EXCLIST, "ElIsTreeExcluded2A: invalid Root: %s", Root));
  615. if (subTreePattern != Root) {
  616. pFreeMemory (subTreePattern);
  617. }
  618. if (lpp) {
  619. DestroyParsedPatternA (lpp);
  620. }
  621. return b;
  622. }
  623. BOOL
  624. ElIsTreeExcluded2W (
  625. IN DWORD ObjectType,
  626. IN PCWSTR Root,
  627. IN PCWSTR LeafPattern OPTIONAL
  628. )
  629. {
  630. PGROWLIST gl;
  631. UINT i;
  632. POBSPARSEDPATTERNW pp;
  633. PCWSTR subTreePattern;
  634. PPARSEDPATTERNW stpp;
  635. PPARSEDPATTERNW lpp;
  636. BOOL b;
  637. MYASSERT (ObjectType < ELT_LAST);
  638. if (ObjectType >= ELT_LAST) {
  639. return FALSE;
  640. }
  641. MYASSERT (Root);
  642. if (!Root) {
  643. return FALSE;
  644. }
  645. gl = &g_ElTypeLists[ObjectType];
  646. if (GlGetSize (gl) == 0) {
  647. return FALSE;
  648. }
  649. if (LeafPattern) {
  650. lpp = CreateParsedPatternW (LeafPattern);
  651. if (!lpp) {
  652. DEBUGMSGW ((DBG_EXCLIST, "ElIsTreeExcluded2W: invalid LeafPattern: %s", LeafPattern));
  653. return FALSE;
  654. }
  655. } else {
  656. lpp = NULL;
  657. }
  658. //
  659. // look if Root ends with "\*"
  660. //
  661. subTreePattern = FindLastWackW (Root);
  662. if (!subTreePattern || subTreePattern[1] != L'*' || subTreePattern[2] != 0) {
  663. subTreePattern = JoinPathsInPoolExW ((g_ElPool, Root, L"*", NULL));
  664. } else {
  665. subTreePattern = Root;
  666. }
  667. b = FALSE;
  668. stpp = CreateParsedPatternW (subTreePattern);
  669. if (stpp) {
  670. for (i = GlGetSize (gl); i > 0; i--) {
  671. pp = *(POBSPARSEDPATTERNW*) GlGetItem (gl, i - 1);
  672. if (!pp->LeafPattern && LeafPattern || pp->LeafPattern && !LeafPattern) {
  673. continue;
  674. }
  675. if (LeafPattern) {
  676. MYASSERT (pp->LeafPattern);
  677. if (!PatternIncludesPatternW (pp->LeafPattern, lpp)) {
  678. continue;
  679. }
  680. }
  681. if (!PatternIncludesPatternW (pp->NodePattern, stpp)) {
  682. continue;
  683. }
  684. //
  685. // the patterns match!
  686. //
  687. b = TRUE;
  688. break;
  689. }
  690. DestroyParsedPatternW (stpp);
  691. }
  692. ELSE_DEBUGMSGW ((DBG_EXCLIST, "ElIsTreeExcluded2W: invalid Root: %s", Root));
  693. if (subTreePattern != Root) {
  694. pFreeMemory (subTreePattern);
  695. }
  696. if (lpp) {
  697. DestroyParsedPatternW (lpp);
  698. }
  699. return b;
  700. }
  701. /*++
  702. Routine Description:
  703. ElIsObsPatternExcluded decides if the object given by its parsed pattern is excluded;
  704. i.e. if any object matching this pattern is excluded
  705. Arguments:
  706. ObjectType - Specifies the object type
  707. Pattern - Specifies the parsed pattern to be used for this decision
  708. Return Value:
  709. TRUE if the object is excluded
  710. --*/
  711. BOOL
  712. ElIsObsPatternExcludedA (
  713. IN DWORD ObjectType,
  714. IN POBSPARSEDPATTERNA Pattern
  715. )
  716. {
  717. PGROWLIST gl;
  718. UINT i;
  719. MYASSERT (ObjectType < ELT_LAST);
  720. if (ObjectType >= ELT_LAST) {
  721. return FALSE;
  722. }
  723. MYASSERT (Pattern);
  724. if (!Pattern) {
  725. return FALSE;
  726. }
  727. gl = &g_ElTypeLists[ObjectType];
  728. for (i = GlGetSize (gl); i > 0; i--) {
  729. if (ObsPatternIncludesPatternA (*(POBSPARSEDPATTERNA*) GlGetItem (gl, i - 1), Pattern)) {
  730. return TRUE;
  731. }
  732. }
  733. return FALSE;
  734. }
  735. BOOL
  736. ElIsObsPatternExcludedW (
  737. IN DWORD ObjectType,
  738. IN POBSPARSEDPATTERNW Pattern
  739. )
  740. {
  741. PGROWLIST gl;
  742. UINT i;
  743. MYASSERT (ObjectType < ELT_LAST);
  744. if (ObjectType >= ELT_LAST) {
  745. return FALSE;
  746. }
  747. MYASSERT (Pattern);
  748. if (!Pattern) {
  749. return FALSE;
  750. }
  751. gl = &g_ElTypeLists[ObjectType];
  752. for (i = GlGetSize (gl); i > 0; i--) {
  753. if (ObsPatternIncludesPatternW (*(POBSPARSEDPATTERNW*) GlGetItem (gl, i - 1), Pattern)) {
  754. return TRUE;
  755. }
  756. }
  757. return FALSE;
  758. }