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.

3267 lines
93 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. flowctrl.c
  5. Abstract:
  6. Implements the control functionality for the ISM. This includes the enumeration manager, transport marshalling
  7. and apply module ordering.
  8. Author:
  9. Marc R. Whitten (marcw) 15-Nov-1999
  10. Revision History:
  11. marcw 1-Dec-1999 Added function level callback prioritization and non-enumerated callbacks.
  12. --*/
  13. //
  14. // Includes
  15. //
  16. #include "pch.h"
  17. #include "ism.h"
  18. #include "ismp.h"
  19. #define DBG_FLOW "FlowCtrl"
  20. //
  21. // Strings
  22. //
  23. #define S_INI_SGMFUNCTIONHIGHPRIORITY TEXT("Source.Gather Function High Priority")
  24. #define S_INI_SGMFUNCTIONLOWPRIORITY TEXT("Source.Gather Function Low Priority")
  25. #define S_INI_DGMFUNCTIONHIGHPRIORITY TEXT("Destination.Gather Function High Priority")
  26. #define S_INI_DGMFUNCTIONLOWPRIORITY TEXT("Destination.Gather Function Low Priority")
  27. //
  28. // Constants
  29. //
  30. #define MINIMUM_FUNCTION_PRIORITY 0xFFFFFFFF
  31. #define MIDDLE_FUNCTION_PRIORITY 0x80000000
  32. #define MAXIMUM_FUNCTION_PRIORITY 0x00000000
  33. #define CALLBEFOREOBJECTENUMERATIONS 0
  34. #define CALLAFTEROBJECTENUMERATIONS 1
  35. //
  36. // Macros
  37. //
  38. #define CALLBACK_ENUMFLAGS_TOP(b) ((PCALLBACK_ENUMFLAGS) ((b)->End > 0 ? ((b)->Buf + (b)->End - sizeof (CALLBACK_ENUMFLAGS)) : NULL))
  39. //
  40. // Types
  41. //
  42. typedef struct {
  43. UINT Level;
  44. BOOL Enabled;
  45. UINT EnableLevel;
  46. DWORD Flags;
  47. } CALLBACK_ENUMFLAGS, *PCALLBACK_ENUMFLAGS;
  48. typedef enum {
  49. CALLBACK_NORMAL = 0x00000001,
  50. CALLBACK_HOOK,
  51. CALLBACK_EXCLUSION,
  52. CALLBACK_PHYSICAL_ENUM,
  53. CALLBACK_PHYSICAL_ACQUIRE
  54. } CALLBACK_TYPE;
  55. typedef struct _TAG_CALLBACKDATA {
  56. //
  57. // Callback Data
  58. //
  59. FARPROC Function;
  60. FARPROC Function2;
  61. UINT MaxLevel;
  62. UINT MinLevel;
  63. PPARSEDPATTERN NodeParsedPattern;
  64. PPARSEDPATTERN ExplodedNodeParsedPattern;
  65. PPARSEDPATTERN LeafParsedPattern;
  66. PPARSEDPATTERN ExplodedLeafParsedPattern;
  67. PCTSTR Pattern;
  68. ULONG_PTR CallbackArg;
  69. CALLBACK_TYPE CallbackType;
  70. //
  71. // Enumeration Control Members
  72. //
  73. GROWBUFFER EnumFlags;
  74. BOOL Done;
  75. BOOL Error;
  76. //
  77. // Prioritization and Identification Members
  78. //
  79. PCTSTR Group;
  80. PCTSTR Identifier;
  81. UINT Priority;
  82. //
  83. // Linkage.
  84. //
  85. struct _TAG_CALLBACKDATA * Next;
  86. struct _TAG_CALLBACKDATA * Prev;
  87. } CALLBACKDATA, *PCALLBACKDATA;
  88. typedef struct _TAG_ENUMDATA {
  89. PCTSTR Pattern;
  90. PPARSEDPATTERN NodeParsedPattern;
  91. PPARSEDPATTERN ExplodedNodeParsedPattern;
  92. PPARSEDPATTERN LeafParsedPattern;
  93. PPARSEDPATTERN ExplodedLeafParsedPattern;
  94. //
  95. // Linkage.
  96. //
  97. struct _TAG_ENUMDATA * Next;
  98. struct _TAG_ENUMDATA * Prev;
  99. } ENUMDATA, *PENUMDATA;
  100. typedef struct {
  101. MIG_OBJECTTYPEID ObjectTypeId;
  102. PCTSTR TypeName;
  103. PCALLBACKDATA PreEnumerationFunctionList;
  104. PCALLBACKDATA PostEnumerationFunctionList;
  105. PCALLBACKDATA FunctionList;
  106. PCALLBACKDATA ExclusionList;
  107. PCALLBACKDATA PhysicalEnumList;
  108. PCALLBACKDATA PhysicalAcquireList;
  109. PENUMDATA FirstEnum;
  110. PENUMDATA LastEnum;
  111. } TYPEENUMINFO, *PTYPEENUMINFO;
  112. typedef BOOL (NONENUMERATEDCALLBACK)(VOID);
  113. typedef NONENUMERATEDCALLBACK *PNONENUMERATEDCALLBACK;
  114. typedef struct {
  115. MIG_OBJECTTYPEID ObjectTypeId;
  116. PMIG_PHYSICALENUMADD AddCallback;
  117. ULONG_PTR AddCallbackArg;
  118. PCTSTR Node;
  119. PCTSTR Leaf;
  120. } ENUMADDCALLBACK, *PENUMADDCALLBACK;
  121. //
  122. // Globals
  123. //
  124. PGROWLIST g_TypeData = NULL;
  125. PGROWLIST g_GlobalTypeData = NULL;
  126. PCALLBACKDATA g_PreEnumerationFunctionList = NULL;
  127. PCALLBACKDATA g_PostEnumerationFunctionList = NULL;
  128. PMHANDLE g_GlobalQueuePool;
  129. PMHANDLE g_UntrackedFlowPool;
  130. PMHANDLE g_CurrentQueuePool;
  131. GROWBUFFER g_EnumerationList = INIT_GROWBUFFER;
  132. GROWLIST g_AcquireList = INIT_GROWLIST;
  133. GROWLIST g_EnumList = INIT_GROWLIST;
  134. GROWLIST g_EnumAddList = INIT_GROWLIST;
  135. #ifdef DEBUG
  136. PCTSTR g_QueueFnName;
  137. #define SETQUEUEFN(x) g_QueueFnName = x
  138. #else
  139. #define SETQUEUEFN(x)
  140. #endif
  141. //
  142. // Macro expansion list
  143. //
  144. // None
  145. //
  146. // Private function prototypes
  147. //
  148. VOID
  149. pAddStaticExclusion (
  150. IN MIG_OBJECTTYPEID ObjectTypeId,
  151. IN MIG_OBJECTSTRINGHANDLE EncodedFullName
  152. );
  153. //
  154. // Macro expansion definition
  155. //
  156. // None
  157. //
  158. // Code
  159. //
  160. BOOL
  161. pInsertCallbackIntoSortedList (
  162. IN PMHANDLE Pool,
  163. IN OUT PCALLBACKDATA * Head,
  164. IN PCALLBACKDATA Data
  165. )
  166. /*++
  167. Routine Description:
  168. pInsertCallback into sorted list.
  169. Arguments:
  170. Pool - Specifies the pool to allocate from
  171. Head - Specifies this head of the callback data list.
  172. Data - Specifies the data to add to the list.
  173. Return Value:
  174. TRUE if the callbackdata was successfully added to the list, FALSE
  175. otherwise.
  176. --*/
  177. {
  178. PCALLBACKDATA cur = *Head;
  179. PCALLBACKDATA last = NULL;
  180. PCALLBACKDATA dataCopy = NULL;
  181. dataCopy = (PCALLBACKDATA) PmGetMemory (Pool, sizeof (CALLBACKDATA));
  182. CopyMemory (dataCopy, Data, sizeof (CALLBACKDATA));
  183. if (!cur || dataCopy->Priority < cur->Priority) {
  184. //
  185. // Add to the head of the list if necessary.
  186. //
  187. dataCopy->Next = cur;
  188. if (cur) {
  189. cur->Prev = dataCopy;
  190. }
  191. *Head = dataCopy;
  192. }
  193. else {
  194. //
  195. // Add inside the list.
  196. // Always goes through the while loop once (see the if above)
  197. //
  198. while (dataCopy->Priority >= cur->Priority) {
  199. last = cur;
  200. if (!cur->Next) {
  201. break;
  202. }
  203. cur = cur->Next;
  204. }
  205. //
  206. // Add immediately after cur
  207. //
  208. dataCopy->Next = last->Next;
  209. last->Next = dataCopy;
  210. dataCopy->Prev = last;
  211. }
  212. return TRUE;
  213. }
  214. BOOL
  215. pRegisterCallback (
  216. IN PMHANDLE Pool,
  217. IN OUT PCALLBACKDATA * FunctionList,
  218. IN FARPROC Callback,
  219. IN FARPROC Callback2,
  220. IN ULONG_PTR CallbackArg,
  221. IN MIG_OBJECTSTRINGHANDLE Pattern, OPTIONAL
  222. IN PCTSTR FunctionId, OPTIONAL
  223. IN CALLBACK_TYPE CallbackType
  224. )
  225. /*++
  226. Routine Description:
  227. pRegisterCallback does the actual work of adding a callback to the
  228. necessary flow control data structures.
  229. Arguments:
  230. Pool - Specifies the pool to allocate from
  231. FunctionList - Specifies the list of callback functions that will be
  232. updated with the new function.
  233. Callback - Specifies the callback function to register
  234. Callback2 - Specifies the second callback function to register
  235. CallbackArg - Specifies a caller-defined value to be passed back on each
  236. enumeration
  237. Pattern - Optionally specifies the pattern that to be associated with
  238. the callback function
  239. FunctionId - Specifies the Function Identifer for the callback. This is used
  240. for function level prioritization.
  241. Return Value:
  242. TRUE if the callback was successfully registered. FALSE otherwise.
  243. --*/
  244. {
  245. CALLBACKDATA data;
  246. INFSTRUCT is = INITINFSTRUCT_PMHANDLE;
  247. PTSTR nodePattern = NULL;
  248. PTSTR leafPattern = NULL;
  249. PCTSTR lowPriorityStr;
  250. PCTSTR highPriorityStr;
  251. BOOL result = TRUE;
  252. MYASSERT (g_CurrentGroup);
  253. //
  254. // Initialize callback data.
  255. //
  256. ZeroMemory (&data, sizeof (CALLBACKDATA));
  257. __try {
  258. data.Function = Callback;
  259. data.Function2 = Callback2;
  260. data.CallbackArg = CallbackArg;
  261. data.Group = PmDuplicateString (Pool, g_CurrentGroup);
  262. data.CallbackType = CallbackType;
  263. if (FunctionId) {
  264. data.Identifier = PmDuplicateString (Pool, FunctionId);
  265. }
  266. //
  267. // Store pattern information (pattern, max level, min level)
  268. //
  269. if (Pattern) {
  270. data.Pattern = PmDuplicateString (Pool, Pattern);
  271. ObsSplitObjectStringEx (Pattern, &nodePattern, &leafPattern, NULL, FALSE);
  272. if (!nodePattern && !leafPattern) {
  273. DEBUGMSG ((DBG_ERROR, "Pattern specified has null node and leaf"));
  274. result = FALSE;
  275. __leave;
  276. }
  277. if (nodePattern) {
  278. GetNodePatternMinMaxLevels (nodePattern, NULL, &data.MinLevel, &data.MaxLevel);
  279. data.NodeParsedPattern = CreateParsedPatternEx (Pool, nodePattern);
  280. if (data.NodeParsedPattern) {
  281. data.ExplodedNodeParsedPattern = ExplodeParsedPatternEx (Pool, data.NodeParsedPattern);
  282. }
  283. ObsFree (nodePattern);
  284. nodePattern = NULL;
  285. } else {
  286. if (data.CallbackType == CALLBACK_NORMAL) {
  287. DEBUGMSG ((DBG_ERROR, "%s: Pattern must specify a node %s", g_QueueFnName, data.Pattern));
  288. result = FALSE;
  289. __leave;
  290. } else {
  291. GetNodePatternMinMaxLevels (TEXT("*"), NULL, &data.MinLevel, &data.MaxLevel);
  292. data.NodeParsedPattern = CreateParsedPatternEx (Pool, TEXT("*"));
  293. data.ExplodedNodeParsedPattern = ExplodeParsedPatternEx (Pool, data.NodeParsedPattern);
  294. DestroyParsedPattern (data.NodeParsedPattern);
  295. data.NodeParsedPattern = NULL;
  296. }
  297. }
  298. if (leafPattern) {
  299. data.LeafParsedPattern = CreateParsedPatternEx (Pool, leafPattern);
  300. if (data.LeafParsedPattern) {
  301. data.ExplodedLeafParsedPattern = ExplodeParsedPatternEx (Pool, data.LeafParsedPattern);
  302. }
  303. ObsFree (leafPattern);
  304. leafPattern = NULL;
  305. }
  306. }
  307. //
  308. // Get the priority for this function.
  309. //
  310. data.Priority = MIDDLE_FUNCTION_PRIORITY;
  311. if (FunctionId) {
  312. if (g_IsmModulePlatformContext == PLATFORM_SOURCE) {
  313. lowPriorityStr = S_INI_SGMFUNCTIONLOWPRIORITY;
  314. highPriorityStr = S_INI_SGMFUNCTIONHIGHPRIORITY;
  315. } else {
  316. lowPriorityStr = S_INI_DGMFUNCTIONLOWPRIORITY;
  317. highPriorityStr = S_INI_DGMFUNCTIONHIGHPRIORITY;
  318. }
  319. if (InfFindFirstLine (g_IsmInf, highPriorityStr, FunctionId, &is)) {
  320. data.Priority = MAXIMUM_FUNCTION_PRIORITY + is.Context.Line;
  321. }
  322. else if (InfFindFirstLine (g_IsmInf, lowPriorityStr, FunctionId, &is)) {
  323. data.Priority = MINIMUM_FUNCTION_PRIORITY - is.Context.Line;
  324. }
  325. InfCleanUpInfStruct (&is);
  326. }
  327. //
  328. // Add the function to the list.
  329. //
  330. pInsertCallbackIntoSortedList (Pool, FunctionList, &data);
  331. }
  332. __finally {
  333. InfCleanUpInfStruct (&is);
  334. if (nodePattern) {
  335. ObsFree (nodePattern);
  336. nodePattern = NULL;
  337. }
  338. if (leafPattern) {
  339. ObsFree (leafPattern);
  340. leafPattern = NULL;
  341. }
  342. if (!result) {
  343. if (data.NodeParsedPattern) {
  344. DestroyParsedPattern (data.NodeParsedPattern);
  345. }
  346. if (data.ExplodedNodeParsedPattern) {
  347. DestroyParsedPattern (data.ExplodedNodeParsedPattern);
  348. }
  349. if (data.LeafParsedPattern) {
  350. DestroyParsedPattern (data.LeafParsedPattern);
  351. }
  352. if (data.ExplodedLeafParsedPattern) {
  353. DestroyParsedPattern (data.ExplodedLeafParsedPattern);
  354. }
  355. ZeroMemory (&data, sizeof (CALLBACKDATA));
  356. }
  357. }
  358. return result;
  359. }
  360. BOOL
  361. pTestContainer (
  362. IN PPARSEDPATTERN NodeContainer,
  363. IN PPARSEDPATTERN NodeContained,
  364. IN PPARSEDPATTERN LeafContainer,
  365. IN PPARSEDPATTERN LeafContained
  366. )
  367. {
  368. MYASSERT (NodeContainer);
  369. MYASSERT (NodeContained);
  370. if ((!NodeContainer) ||
  371. (!NodeContained)
  372. ) {
  373. return FALSE;
  374. }
  375. if (!IsExplodedParsedPatternContainedEx (NodeContainer, NodeContained, FALSE)) {
  376. //they don't match
  377. return FALSE;
  378. }
  379. if (!LeafContained) {
  380. if (LeafContainer) {
  381. // If there is a leaf pattern for container the caller will get nodes
  382. // only if the node pattern has wild chars. So, since we know that the
  383. // contained node pattern is included in the container node pattern
  384. // we just need to see if the container node pattern includes wild chars.
  385. return WildCharsPattern (NodeContainer);
  386. } else {
  387. //both are NULL so...
  388. return TRUE;
  389. }
  390. } else {
  391. if (!LeafContainer) {
  392. // Even if the contained has a leaf pattern, it will get nodes only if
  393. // the node pattern has wild chars. So, since we know that the contained
  394. // node pattern is included in the container node pattern we just need
  395. // to see if the contained node pattern includes wild chars
  396. return WildCharsPattern (NodeContained);
  397. } else {
  398. //return the actual match of non-null parsed patterns
  399. return IsExplodedParsedPatternContainedEx (LeafContainer, LeafContained, TRUE);
  400. }
  401. }
  402. }
  403. BOOL
  404. pTestContainerEx (
  405. IN PPARSEDPATTERN NodeContainer,
  406. IN PPARSEDPATTERN NodeContained,
  407. IN PPARSEDPATTERN LeafContainer,
  408. IN PPARSEDPATTERN LeafContained
  409. )
  410. {
  411. MYASSERT (NodeContainer);
  412. MYASSERT (NodeContained);
  413. if ((!NodeContainer) ||
  414. (!NodeContained)
  415. ) {
  416. return FALSE;
  417. }
  418. if (!DoExplodedParsedPatternsIntersect (NodeContainer, NodeContained)) {
  419. if (!DoExplodedParsedPatternsIntersectEx (NodeContainer, NodeContained, TRUE)) {
  420. return FALSE;
  421. }
  422. }
  423. if (!LeafContained) {
  424. if (LeafContainer) {
  425. // If there is a leaf pattern for container the caller will get nodes
  426. // only if the node pattern has wild chars. So, since we know that the
  427. // contained node pattern is included in the container node pattern
  428. // we just need to see if the container node pattern includes wild chars.
  429. return WildCharsPattern (NodeContainer);
  430. } else {
  431. //both are NULL so...
  432. return TRUE;
  433. }
  434. } else {
  435. if (!LeafContainer) {
  436. // Even if the contained has a leaf pattern, it will get nodes only if
  437. // the node pattern has wild chars. So, since we know that the contained
  438. // node pattern is included in the container node pattern we just need
  439. // to see if the contained node pattern includes wild chars
  440. return WildCharsPattern (NodeContained);
  441. } else {
  442. //return the actual match of non-null parsed patterns
  443. return DoExplodedParsedPatternsIntersect (LeafContainer, LeafContained);
  444. }
  445. }
  446. }
  447. BOOL
  448. pAddEnumeration (
  449. IN PMHANDLE Pool,
  450. IN OUT PTYPEENUMINFO TypeEnumInfo,
  451. IN MIG_OBJECTSTRINGHANDLE ObjectPattern
  452. )
  453. /*++
  454. Routine Description:
  455. pAddEnumeration Adds an enumeration string to the list of enumerations
  456. needed for a given type. Because the flow control module tries to use only
  457. a minimal set of enumerations, the actual enumeration may not be added.
  458. After a successful call to this function, any data needed by the specified
  459. enumeration will be enumerated.
  460. Arguments:
  461. Pool - Specifies the pool to allocate from
  462. TypeEnumInfo - Specifies the type info structure that will receive the new
  463. enumeration data.
  464. ObjectPattern - Specifies the enumeration pattern to add to the type.
  465. Return Value:
  466. TRUE if the pattern was successfully added, FALSE otherwise.
  467. --*/
  468. {
  469. PENUMDATA enumData;
  470. PENUMDATA oldEnumData;
  471. PCTSTR nodePattern = NULL;
  472. PCTSTR leafPattern = NULL;
  473. PPARSEDPATTERN nodeParsedPattern = NULL;
  474. PPARSEDPATTERN explodedNodeParsedPattern = NULL;
  475. PPARSEDPATTERN leafParsedPattern = NULL;
  476. PPARSEDPATTERN explodedLeafParsedPattern = NULL;
  477. //
  478. // Add this to the enumeration list unless its already listed.
  479. //
  480. if (!ObsSplitObjectStringEx (ObjectPattern, &nodePattern, &leafPattern, NULL, FALSE)) {
  481. DEBUGMSG ((DBG_ERROR, "Bad pattern detected in pAddEnumeration: %s", ObjectPattern));
  482. return FALSE;
  483. }
  484. if (nodePattern) {
  485. nodeParsedPattern = CreateParsedPatternEx (Pool, nodePattern);
  486. if (nodeParsedPattern) {
  487. explodedNodeParsedPattern = ExplodeParsedPatternEx (Pool, nodeParsedPattern);
  488. }
  489. ObsFree (nodePattern);
  490. INVALID_POINTER (nodePattern);
  491. }
  492. if (leafPattern) {
  493. leafParsedPattern = CreateParsedPatternEx (Pool, leafPattern);
  494. if (leafParsedPattern) {
  495. explodedLeafParsedPattern = ExplodeParsedPatternEx (Pool, leafParsedPattern);
  496. }
  497. ObsFree (leafPattern);
  498. INVALID_POINTER (leafPattern);
  499. }
  500. enumData = TypeEnumInfo->FirstEnum;
  501. while (enumData) {
  502. if (pTestContainer (enumData->ExplodedNodeParsedPattern, explodedNodeParsedPattern, enumData->ExplodedLeafParsedPattern, explodedLeafParsedPattern)) {
  503. DEBUGMSG ((DBG_FLOW, "Enumeration %s not added. It will be handled during enumeration %s.", ObjectPattern, enumData->Pattern));
  504. break;
  505. }
  506. if (pTestContainer (explodedNodeParsedPattern, enumData->ExplodedNodeParsedPattern, explodedLeafParsedPattern, enumData->ExplodedLeafParsedPattern)) {
  507. DEBUGMSG ((DBG_FLOW, "Enumeration %s will replace enumeration %s.", ObjectPattern, enumData->Pattern));
  508. if (enumData->Prev) {
  509. enumData->Prev->Next = enumData->Next;
  510. }
  511. if (enumData->Next) {
  512. enumData->Next->Prev = enumData->Prev;
  513. }
  514. if (TypeEnumInfo->FirstEnum == enumData) {
  515. TypeEnumInfo->FirstEnum = enumData->Next;
  516. }
  517. if (TypeEnumInfo->LastEnum == enumData) {
  518. TypeEnumInfo->LastEnum = enumData->Prev;
  519. }
  520. PmReleaseMemory (Pool, enumData->Pattern);
  521. DestroyParsedPattern (enumData->ExplodedLeafParsedPattern);
  522. DestroyParsedPattern (enumData->LeafParsedPattern);
  523. DestroyParsedPattern (enumData->ExplodedNodeParsedPattern);
  524. DestroyParsedPattern (enumData->NodeParsedPattern);
  525. oldEnumData = enumData;
  526. enumData = enumData->Next;
  527. PmReleaseMemory (Pool, oldEnumData);
  528. } else {
  529. enumData = enumData->Next;
  530. }
  531. }
  532. if (enumData == NULL) {
  533. DEBUGMSG ((DBG_FLOW, "Adding Enumeration %s to the list of enumerations of type %s.", ObjectPattern, TypeEnumInfo->TypeName));
  534. enumData = (PENUMDATA) PmGetMemory (Pool, sizeof (ENUMDATA));
  535. ZeroMemory (enumData, sizeof (ENUMDATA));
  536. enumData->Pattern = PmDuplicateString (Pool, ObjectPattern);
  537. enumData->NodeParsedPattern = nodeParsedPattern;
  538. enumData->ExplodedNodeParsedPattern = explodedNodeParsedPattern;
  539. enumData->LeafParsedPattern = leafParsedPattern;
  540. enumData->ExplodedLeafParsedPattern = explodedLeafParsedPattern;
  541. if (TypeEnumInfo->LastEnum) {
  542. TypeEnumInfo->LastEnum->Next = enumData;
  543. }
  544. enumData->Prev = TypeEnumInfo->LastEnum;
  545. TypeEnumInfo->LastEnum = enumData;
  546. if (!TypeEnumInfo->FirstEnum) {
  547. TypeEnumInfo->FirstEnum = enumData;
  548. }
  549. } else {
  550. DestroyParsedPattern (explodedLeafParsedPattern);
  551. DestroyParsedPattern (leafParsedPattern);
  552. DestroyParsedPattern (explodedNodeParsedPattern);
  553. DestroyParsedPattern (nodeParsedPattern);
  554. }
  555. return TRUE;
  556. }
  557. PTYPEENUMINFO
  558. pGetTypeEnumInfo (
  559. IN MIG_OBJECTTYPEID ObjectTypeId,
  560. IN BOOL GlobalData
  561. )
  562. /*++
  563. Routine Description:
  564. pGetTypeEnumInfo returns the TypeEnumInfo for a specified type.
  565. Arguments:
  566. ObjectTypeId - Specifies the object type.
  567. GlobalData - Specifies TRUE if the type enum data is global to the whole process,
  568. or FALSE if it is specific to the current enumeration queue.
  569. Return Value:
  570. A TypeEnumInfo structure if one was found, NULL otherwise.
  571. --*/
  572. {
  573. UINT i;
  574. UINT count;
  575. PTYPEENUMINFO rTypeEnumInfo;
  576. PGROWLIST *typeData;
  577. if (GlobalData) {
  578. typeData = &g_GlobalTypeData;
  579. } else {
  580. typeData = &g_TypeData;
  581. }
  582. if (!(*typeData)) {
  583. return NULL;
  584. }
  585. count = GlGetSize (*typeData);
  586. //
  587. // Find the matching type info for this item.
  588. //
  589. for (i = 0; i < count; i++) {
  590. rTypeEnumInfo = (PTYPEENUMINFO) GlGetItem (*typeData, i);
  591. if (rTypeEnumInfo->ObjectTypeId == ObjectTypeId) {
  592. return rTypeEnumInfo;
  593. }
  594. }
  595. return NULL;
  596. }
  597. BOOL
  598. pProcessQueueEnumeration (
  599. IN MIG_OBJECTTYPEID ObjectTypeId,
  600. IN MIG_OBJECTSTRINGHANDLE ObjectPattern,
  601. IN FARPROC Callback,
  602. IN FARPROC Callback2, OPTIONAL
  603. IN ULONG_PTR CallbackArg, OPTIONAL
  604. IN PCTSTR FunctionId, OPTIONAL
  605. IN CALLBACK_TYPE CallbackType
  606. )
  607. /*++
  608. Routine Description:
  609. pProcessQueueEnumeration is used by Source Gather Modules and Destination Gather Modules
  610. in order to register a callback function to be called for a particular object enumeration.
  611. Arguments:
  612. ObjectTypeId - Specifies the object type for the enumeration.
  613. ObjectPattern - Specifies the enumeration pattern to use.
  614. Callback - Specifies the function to callback during the enumeration
  615. Callback2 - Specifies the second function to callback during the enumeration (used
  616. for the free function of physical hooks)
  617. CallbackArg - Specifies a caller-defined value to be passed back on
  618. each enumeration
  619. FunctionId - Specifies the function identifier string, which is used
  620. to prioritize function calls. The function string must
  621. match the priorization string in the control INF file.
  622. GrowEnumPattern - Specifies if the global enumeration pattern should be
  623. grown to include this one. If FALSE, this function just
  624. wants to be called back for all objects matching the
  625. pattern but does not want to force the enumeration of
  626. the pattern.
  627. ExclusionCallback - Specifies TRUE if Callback is an exclusion callback, or
  628. FALSE if Callback is an object enum callback
  629. Return Value:
  630. TRUE if the enumeration was successfully queued, FALSE otherwise.
  631. --*/
  632. {
  633. PTYPEENUMINFO typeEnumInfo;
  634. PCALLBACKDATA * list;
  635. BOOL globalData;
  636. BOOL result = FALSE;
  637. MIG_OBJECTSTRINGHANDLE handle = NULL;
  638. PMHANDLE pool;
  639. __try {
  640. MYASSERT (ObjectTypeId);
  641. if (!ObjectPattern) {
  642. handle = IsmCreateSimpleObjectPattern (NULL, TRUE, NULL, TRUE);
  643. ObjectPattern = handle;
  644. if (!handle) {
  645. MYASSERT (FALSE);
  646. __leave;
  647. }
  648. }
  649. if (CallbackType == CALLBACK_PHYSICAL_ACQUIRE ||
  650. CallbackType == CALLBACK_PHYSICAL_ENUM ||
  651. CallbackType == CALLBACK_EXCLUSION
  652. ) {
  653. globalData = TRUE;
  654. pool = g_GlobalQueuePool;
  655. } else {
  656. globalData = FALSE;
  657. pool = g_CurrentQueuePool;
  658. }
  659. if (!g_CurrentGroup) {
  660. DEBUGMSG ((DBG_ERROR, "%s called outside of ISM-managed callback", g_QueueFnName));
  661. __leave;
  662. }
  663. typeEnumInfo = pGetTypeEnumInfo (ObjectTypeId, globalData);
  664. if (!typeEnumInfo) {
  665. DEBUGMSG ((DBG_ERROR, "%s: %d does not match a known object type.", g_QueueFnName, ObjectTypeId));
  666. __leave;
  667. }
  668. //
  669. // Save away the callback function and associated data.
  670. //
  671. switch (CallbackType) {
  672. case CALLBACK_EXCLUSION:
  673. list = &typeEnumInfo->ExclusionList;
  674. break;
  675. case CALLBACK_PHYSICAL_ENUM:
  676. list = &typeEnumInfo->PhysicalEnumList;
  677. break;
  678. case CALLBACK_PHYSICAL_ACQUIRE:
  679. list = &typeEnumInfo->PhysicalAcquireList;
  680. break;
  681. default:
  682. list = &typeEnumInfo->FunctionList;
  683. break;
  684. }
  685. if (!pRegisterCallback (
  686. pool,
  687. list,
  688. Callback,
  689. Callback2,
  690. CallbackArg,
  691. ObjectPattern,
  692. FunctionId,
  693. CallbackType
  694. )) {
  695. __leave;
  696. }
  697. if (CallbackType == CALLBACK_NORMAL) {
  698. //
  699. // Save the pattern into the object tree and link the callback function with it.
  700. //
  701. if (!pAddEnumeration (pool, typeEnumInfo, ObjectPattern)) {
  702. __leave;
  703. }
  704. }
  705. result = TRUE;
  706. }
  707. __finally {
  708. if (handle) {
  709. IsmDestroyObjectHandle (handle);
  710. }
  711. }
  712. return result;
  713. }
  714. BOOL
  715. IsmProhibitPhysicalEnum (
  716. IN MIG_OBJECTTYPEID ObjectTypeId,
  717. IN MIG_OBJECTSTRINGHANDLE ObjectPattern,
  718. IN PMIG_PHYSICALENUMCHECK EnumCheckCallback, OPTIONAL
  719. IN ULONG_PTR CallbackArg, OPTIONAL
  720. IN PCTSTR FunctionId OPTIONAL
  721. )
  722. {
  723. SETQUEUEFN(TEXT("IsmProhibitPhysicalEnum"));
  724. if (!ObjectPattern) {
  725. DEBUGMSG ((DBG_ERROR, "IsmProhibitPhysicalEnum: ObjectPattern is required"));
  726. return FALSE;
  727. }
  728. return pProcessQueueEnumeration (
  729. ObjectTypeId,
  730. ObjectPattern,
  731. (FARPROC) EnumCheckCallback,
  732. NULL,
  733. CallbackArg,
  734. FunctionId,
  735. CALLBACK_PHYSICAL_ENUM
  736. );
  737. }
  738. BOOL
  739. IsmAddToPhysicalEnum (
  740. IN MIG_OBJECTTYPEID ObjectTypeId,
  741. IN MIG_OBJECTSTRINGHANDLE ObjectBase,
  742. IN PMIG_PHYSICALENUMADD EnumAddCallback,
  743. IN ULONG_PTR CallbackArg OPTIONAL
  744. )
  745. {
  746. PCTSTR newNode = NULL;
  747. PCTSTR newLeaf = NULL;
  748. UINT u;
  749. UINT count;
  750. ENUMADDCALLBACK callbackStruct;
  751. PENUMADDCALLBACK storedStruct;
  752. BOOL result = FALSE;
  753. UINT newTchars;
  754. UINT existTchars;
  755. UINT tchars;
  756. CHARTYPE ch;
  757. if (!ObjectTypeId || !ObjectBase || !EnumAddCallback) {
  758. SetLastError (ERROR_INVALID_PARAMETER);
  759. return FALSE;
  760. }
  761. //
  762. // First test to see if the object base is already listed
  763. //
  764. ObsSplitObjectStringEx (ObjectBase, &newNode, &newLeaf, NULL, TRUE);
  765. if (!newNode) {
  766. DEBUGMSG ((DBG_ERROR, "IsmAddToPhysicalEnum requires a node"));
  767. } else {
  768. count = GlGetSize (&g_EnumAddList);
  769. for (u = 0 ; u < count ; u++) {
  770. storedStruct = (PENUMADDCALLBACK) GlGetItem (&g_EnumAddList, u);
  771. MYASSERT (storedStruct);
  772. if (storedStruct->AddCallback != EnumAddCallback) {
  773. if (StringIMatch (newNode, storedStruct->Node)) {
  774. //
  775. // Node is the same; leaf must be unique
  776. //
  777. if (!newLeaf || !storedStruct->Leaf) {
  778. DEBUGMSG ((DBG_ERROR, "IsmAddToPhysicalEnum requires a unique object for %s", newNode));
  779. break;
  780. }
  781. if (StringIMatch (newLeaf, storedStruct->Leaf)) {
  782. DEBUGMSG ((
  783. DBG_ERROR,
  784. "IsmAddToPhysicalEnum does not have a unique leaf for %s leaf %s",
  785. newNode,
  786. newLeaf
  787. ));
  788. break;
  789. }
  790. } else if (!newLeaf) {
  791. //
  792. // New node cannot be a prefix of an existing node, and vice-versa
  793. //
  794. newTchars = TcharCount (newNode);
  795. existTchars = TcharCount (storedStruct->Node);
  796. tchars = min (newTchars, existTchars);
  797. //
  798. // Compare only when new node might consume stored node
  799. //
  800. if (existTchars == tchars) {
  801. // stored node is shortest; ignore if it has a leaf
  802. if (storedStruct->Leaf) {
  803. continue;
  804. }
  805. }
  806. if (StringIMatchTcharCount (newNode, storedStruct->Node, tchars)) {
  807. //
  808. // Verify the end of the common prefix lands on either a nul or a
  809. // backslash. Otherwise, the prefix isn't common.
  810. //
  811. if (tchars == newTchars) {
  812. ch = (CHARTYPE) _tcsnextc (newNode + tchars);
  813. } else {
  814. ch = (CHARTYPE) _tcsnextc (storedStruct->Node + tchars);
  815. }
  816. if (!ch || ch == TEXT('\\')) {
  817. if (tchars == newTchars) {
  818. DEBUGMSG ((
  819. DBG_ERROR,
  820. "IsmAddToPhysicalEnum: %s is already handled by %s",
  821. newNode,
  822. storedStruct->Node
  823. ));
  824. } else {
  825. DEBUGMSG ((
  826. DBG_ERROR,
  827. "IsmAddToPhysicalEnum: %s is already handled by %s",
  828. storedStruct->Node,
  829. newNode
  830. ));
  831. }
  832. break;
  833. }
  834. }
  835. }
  836. }
  837. }
  838. if (u >= count) {
  839. ZeroMemory (&callbackStruct, sizeof (callbackStruct));
  840. callbackStruct.ObjectTypeId = ObjectTypeId & ~(PLATFORM_MASK);
  841. callbackStruct.Node = PmDuplicateString (g_UntrackedFlowPool, newNode);
  842. callbackStruct.Leaf = newLeaf ? PmDuplicateString (g_UntrackedFlowPool, newLeaf) : NULL;
  843. callbackStruct.AddCallback = EnumAddCallback;
  844. callbackStruct.AddCallbackArg = CallbackArg;
  845. GlAppend (&g_EnumAddList, (PBYTE) &callbackStruct, sizeof (ENUMADDCALLBACK));
  846. result = TRUE;
  847. }
  848. }
  849. ObsFree (newNode);
  850. ObsFree (newLeaf);
  851. return result;
  852. }
  853. BOOL
  854. IsmRegisterPhysicalAcquireHook (
  855. IN MIG_OBJECTTYPEID ObjectTypeId,
  856. IN MIG_OBJECTSTRINGHANDLE ObjectPattern, OPTIONAL
  857. IN PMIG_PHYSICALACQUIREHOOK HookCallback,
  858. IN PMIG_PHYSICALACQUIREFREE FreeCallback, OPTIONAL
  859. IN ULONG_PTR CallbackArg, OPTIONAL
  860. IN PCTSTR FunctionId OPTIONAL
  861. )
  862. {
  863. ObjectTypeId &= ~PLATFORM_MASK;
  864. SETQUEUEFN(TEXT("IsmRegisterPhysicalAcquireHook"));
  865. return pProcessQueueEnumeration (
  866. ObjectTypeId,
  867. ObjectPattern,
  868. (FARPROC) HookCallback,
  869. (FARPROC) FreeCallback,
  870. CallbackArg,
  871. FunctionId,
  872. CALLBACK_PHYSICAL_ACQUIRE
  873. );
  874. }
  875. BOOL
  876. IsmRegisterStaticExclusion (
  877. IN MIG_OBJECTTYPEID ObjectTypeId,
  878. IN MIG_OBJECTSTRINGHANDLE EncodedObjectName
  879. )
  880. {
  881. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  882. pAddStaticExclusion (ObjectTypeId, EncodedObjectName);
  883. return TRUE;
  884. }
  885. UINT
  886. WINAPI
  887. pMakeApplyCallback (
  888. IN PCMIG_OBJECTENUMDATA Data,
  889. IN ULONG_PTR CallerArg
  890. )
  891. {
  892. if (CallerArg & QUEUE_MAKE_APPLY) {
  893. IsmMakeApplyObject (Data->ObjectTypeId, Data->ObjectName);
  894. } else if (CallerArg & QUEUE_MAKE_PERSISTENT) {
  895. IsmMakePersistentObject (Data->ObjectTypeId, Data->ObjectName);
  896. }
  897. if (CallerArg & QUEUE_OVERWRITE_DEST) {
  898. IsmAbandonObjectOnCollision ((Data->ObjectTypeId & ~PLATFORM_MASK)|PLATFORM_DESTINATION, Data->ObjectName);
  899. } else if (CallerArg & QUEUE_DONT_OVERWRITE_DEST) {
  900. IsmAbandonObjectOnCollision ((Data->ObjectTypeId & ~PLATFORM_MASK)|PLATFORM_SOURCE, Data->ObjectName);
  901. }
  902. if (CallerArg & QUEUE_MAKE_NONCRITICAL) {
  903. IsmMakeNonCriticalObject (Data->ObjectTypeId, Data->ObjectName);
  904. }
  905. return CALLBACK_ENUM_CONTINUE;
  906. }
  907. BOOL
  908. IsmQueueEnumeration (
  909. IN MIG_OBJECTTYPEID ObjectTypeId,
  910. IN MIG_OBJECTSTRINGHANDLE ObjectPattern, OPTIONAL
  911. IN PMIG_OBJECTENUMCALLBACK Callback, OPTIONAL
  912. IN ULONG_PTR CallbackArg, OPTIONAL
  913. IN PCTSTR FunctionId OPTIONAL
  914. )
  915. /*++
  916. Routine Description:
  917. IsmQueueEnumeration is used by Source Gather Modules and Destination Gather
  918. Modules in order to register a callback function to be called for a
  919. particular object enumeration.
  920. Arguments:
  921. ObjectTypeId - Specifies the object type for the enumeration.
  922. ObjectPattern - Specifies the enumeration pattern to use. If not specified,
  923. all objects for ObjectTypeId are queued.
  924. Callback - Specifies the function to callback during the enumeration.
  925. If not defined, the built-in ISM callback is used (which
  926. marks the objects as persistent).
  927. CallbackArg - Specifies a caller-defined value to be passed back on
  928. each enumeration. If Callback is NULL, then this argument
  929. specifies zero or more of the following flags:
  930. QUEUE_MAKE_PERSISTENT or QUEUE_MAKE_APPLY (mutually exclusive)
  931. QUEUE_OVERWRITE_DEST or QUEUE_DONT_OVERWRITE_DEST (mutually exclusive)
  932. FunctionId - Specifies the function identifier string, which is used to
  933. prioritize function calls. The function string must match
  934. the priorization string in the control INF file. If
  935. Callback is NULL, then this parameter is forced to the value
  936. "SetDestPriority", "MakePersistent" or "MakeApply" depending
  937. on CallbackArg.
  938. Return Value:
  939. TRUE if the enumeration was successfully queued, FALSE otherwise.
  940. --*/
  941. {
  942. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  943. SETQUEUEFN(TEXT("IsmQueueEnumeration"));
  944. if (!Callback) {
  945. Callback = pMakeApplyCallback;
  946. if (!CallbackArg) {
  947. CallbackArg = QUEUE_MAKE_APPLY;
  948. }
  949. if (CallbackArg & QUEUE_MAKE_APPLY) {
  950. FunctionId = TEXT("MakeApply");
  951. } else if (CallbackArg & QUEUE_MAKE_PERSISTENT) {
  952. FunctionId = TEXT("MakePersistent");
  953. } else {
  954. FunctionId = TEXT("SetDestPriority");
  955. }
  956. }
  957. return pProcessQueueEnumeration (
  958. ObjectTypeId,
  959. ObjectPattern,
  960. (FARPROC) Callback,
  961. NULL,
  962. CallbackArg,
  963. FunctionId,
  964. CALLBACK_NORMAL
  965. );
  966. }
  967. BOOL
  968. IsmHookEnumeration (
  969. IN MIG_OBJECTTYPEID ObjectTypeId,
  970. IN MIG_OBJECTSTRINGHANDLE ObjectPattern,
  971. IN PMIG_OBJECTENUMCALLBACK Callback,
  972. IN ULONG_PTR CallbackArg, OPTIONAL
  973. IN PCTSTR FunctionId OPTIONAL
  974. )
  975. /*++
  976. Routine Description:
  977. IsmHookEnumeration is used by Source Gather Modules and Destination Gather Modules
  978. in order to register a callback function to be called for a particular object enumeration. The
  979. difference to IsmQueueEnumeration is that this function does not expand the
  980. global enumeration pattern.
  981. Arguments:
  982. ObjectTypeId - Specifies the object type for the enumeration.
  983. ObjectPattern - Specifies the enumeration pattern to use. If not specified,
  984. all objects of type ObjectTypeId are hooked.
  985. Callback - Specifies the function to callback during the enumeration
  986. CallbackArg - Specifies a caller-defined value to be passed back on
  987. each enumeration
  988. FunctionId - Specifies the function identifier string, which is used to
  989. prioritize function calls. The function string must match
  990. the priorization string in the control INF file.
  991. Return Value:
  992. TRUE if the enumeration was successfully queued, FALSE otherwise.
  993. --*/
  994. {
  995. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  996. SETQUEUEFN(TEXT("IsmHookEnumeration"));
  997. return pProcessQueueEnumeration (
  998. ObjectTypeId,
  999. ObjectPattern,
  1000. (FARPROC) Callback,
  1001. NULL,
  1002. CallbackArg,
  1003. FunctionId,
  1004. CALLBACK_HOOK
  1005. );
  1006. }
  1007. BOOL
  1008. IsmRegisterDynamicExclusion (
  1009. IN MIG_OBJECTTYPEID ObjectTypeId,
  1010. IN MIG_OBJECTSTRINGHANDLE ObjectPattern, OPTIONAL
  1011. IN PMIG_DYNAMICEXCLUSIONCALLBACK Callback,
  1012. IN ULONG_PTR CallbackArg, OPTIONAL
  1013. IN PCTSTR FunctionId OPTIONAL
  1014. )
  1015. {
  1016. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  1017. SETQUEUEFN(TEXT("IsmRegisterDynamicExclusion"));
  1018. return pProcessQueueEnumeration (
  1019. ObjectTypeId,
  1020. ObjectPattern,
  1021. (FARPROC) Callback,
  1022. NULL,
  1023. CallbackArg,
  1024. FunctionId,
  1025. CALLBACK_EXCLUSION
  1026. );
  1027. }
  1028. BOOL
  1029. pRegisterNonEnumeratedCallback (
  1030. IN FARPROC Callback,
  1031. IN UINT WhenCalled,
  1032. IN PCTSTR FunctionId, OPTIONAL
  1033. IN BOOL PerTypeId,
  1034. IN MIG_OBJECTTYPEID ObjectTypeId
  1035. )
  1036. /*++
  1037. Routine Description:
  1038. IsmRegisterNonEnumeratedCallback is used to register a function to be
  1039. called either before or after the enumeration of data.
  1040. Arguments:
  1041. Callback - Specifies the function to call.
  1042. WhenCalled - Specifies the timing of the non-enumerated callback. Either
  1043. CALLBEFOREOBJECTENUMERATIONS or CALLAFTEROBJECTENUMERATIONS
  1044. FunctionId - Optionally specifies the function identifier string. This
  1045. parameter can be used to add function level prioritization to
  1046. the module.
  1047. PerTypeId - Specifies if the pre or post enumeration callback is per type
  1048. ObjectTypeId - Specifies the object type id if PerTypeId is TRUE
  1049. Return Value:
  1050. TRUE if the function was successfully registered. FALSE otherwise.
  1051. --*/
  1052. {
  1053. PTYPEENUMINFO typeEnumInfo;
  1054. PCALLBACKDATA * list;
  1055. MYASSERT (Callback);
  1056. MYASSERT (WhenCalled == CALLBEFOREOBJECTENUMERATIONS || WhenCalled == CALLAFTEROBJECTENUMERATIONS);
  1057. if (!g_CurrentGroup) {
  1058. DEBUGMSG ((DBG_ERROR, "IsmRegisterNonEnumeratedCallback called outside of ISM-managed callback."));
  1059. return FALSE;
  1060. }
  1061. if (PerTypeId) {
  1062. typeEnumInfo = pGetTypeEnumInfo (ObjectTypeId, FALSE);
  1063. if (!typeEnumInfo) {
  1064. DEBUGMSG ((DBG_ERROR, "IsmRegisterNonEnumeratedCallback: %d does not match a known object type.", ObjectTypeId));
  1065. return FALSE;
  1066. }
  1067. if (WhenCalled == CALLBEFOREOBJECTENUMERATIONS) {
  1068. list = &(typeEnumInfo->PreEnumerationFunctionList);
  1069. }
  1070. else {
  1071. list = &(typeEnumInfo->PostEnumerationFunctionList);
  1072. }
  1073. } else {
  1074. if (WhenCalled == CALLBEFOREOBJECTENUMERATIONS) {
  1075. list = &g_PreEnumerationFunctionList;
  1076. }
  1077. else {
  1078. list = &g_PostEnumerationFunctionList;
  1079. }
  1080. }
  1081. return pRegisterCallback (
  1082. g_CurrentQueuePool,
  1083. list,
  1084. (FARPROC) Callback,
  1085. NULL,
  1086. (ULONG_PTR) 0,
  1087. NULL,
  1088. FunctionId,
  1089. CALLBACK_NORMAL
  1090. );
  1091. }
  1092. BOOL
  1093. IsmRegisterPreEnumerationCallback (
  1094. IN PMIG_PREENUMCALLBACK Callback,
  1095. IN PCTSTR FunctionId OPTIONAL
  1096. )
  1097. {
  1098. return pRegisterNonEnumeratedCallback (
  1099. (FARPROC) Callback,
  1100. CALLBEFOREOBJECTENUMERATIONS,
  1101. FunctionId,
  1102. FALSE,
  1103. 0
  1104. );
  1105. }
  1106. BOOL
  1107. IsmRegisterTypePreEnumerationCallback (
  1108. IN MIG_OBJECTTYPEID ObjectTypeId,
  1109. IN PMIG_PREENUMCALLBACK Callback,
  1110. IN PCTSTR FunctionId OPTIONAL
  1111. )
  1112. {
  1113. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  1114. return pRegisterNonEnumeratedCallback (
  1115. (FARPROC) Callback,
  1116. CALLBEFOREOBJECTENUMERATIONS,
  1117. FunctionId,
  1118. TRUE,
  1119. ObjectTypeId
  1120. );
  1121. }
  1122. BOOL
  1123. IsmRegisterPostEnumerationCallback (
  1124. IN PMIG_POSTENUMCALLBACK Callback,
  1125. IN PCTSTR FunctionId OPTIONAL
  1126. )
  1127. {
  1128. return pRegisterNonEnumeratedCallback (
  1129. (FARPROC) Callback,
  1130. CALLAFTEROBJECTENUMERATIONS,
  1131. FunctionId,
  1132. FALSE,
  1133. 0
  1134. );
  1135. }
  1136. BOOL
  1137. IsmRegisterTypePostEnumerationCallback (
  1138. IN MIG_OBJECTTYPEID ObjectTypeId,
  1139. IN PMIG_POSTENUMCALLBACK Callback,
  1140. IN PCTSTR FunctionId OPTIONAL
  1141. )
  1142. {
  1143. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  1144. return pRegisterNonEnumeratedCallback (
  1145. (FARPROC) Callback,
  1146. CALLAFTEROBJECTENUMERATIONS,
  1147. FunctionId,
  1148. TRUE,
  1149. ObjectTypeId
  1150. );
  1151. }
  1152. VOID
  1153. pCreateFunctionListForPattern (
  1154. IN OUT PGROWLIST List,
  1155. IN PTYPEENUMINFO TypeEnumInfo,
  1156. IN PCTSTR Pattern,
  1157. IN PPARSEDPATTERN ExplodedNodeParsedPattern,
  1158. IN PPARSEDPATTERN ExplodedLeafParsedPattern,
  1159. IN CALLBACK_TYPE CallbackType
  1160. )
  1161. /*++
  1162. Routine Description:
  1163. pCreateFunctionListForPattern enumerates all callback functions for a given
  1164. type and determines if they could be interested in an enumeration keyed off
  1165. of the given pattern. Since we use a minimal list of patterns, at each
  1166. pattern we must come up with the list of callback functions associated with
  1167. patterns contained by our minimal pattern.
  1168. Arguments:
  1169. List - Specifies the growlist where the callback functions are to be
  1170. stored. After the function's return, this list contains all
  1171. callback functions that are needed for the given enumeration
  1172. pattern.
  1173. TypeEnumInfo - Specifies the type to draw potential callback functions from.
  1174. Pattern - Specifies the minimal pattern to that will be used for
  1175. enumeration.
  1176. ExplodedNodeParsedPattern - Specifies the node portion of Pattern, in pre-parsed
  1177. exploded format.
  1178. ExplodedLeafParsedPattern - Specifies the leaf portion of Pattern, in pre-parsed
  1179. exploded format.
  1180. CallbackType - Specifies which type of callback list to use (a CALLBACK_* constant)
  1181. Return Value:
  1182. None.
  1183. --*/
  1184. {
  1185. PCALLBACKDATA data;
  1186. BOOL processHooks = FALSE;
  1187. if (!TypeEnumInfo) {
  1188. return;
  1189. }
  1190. //
  1191. // Loop through all functions for this type, and add functions that fall under the
  1192. // current enumeration pattern.
  1193. //
  1194. switch (CallbackType) {
  1195. case CALLBACK_EXCLUSION:
  1196. data = TypeEnumInfo->ExclusionList;
  1197. break;
  1198. default:
  1199. data = TypeEnumInfo->FunctionList;
  1200. processHooks = TRUE;
  1201. break;
  1202. }
  1203. if (!data) {
  1204. return;
  1205. }
  1206. while (data) {
  1207. if (pTestContainer (
  1208. ExplodedNodeParsedPattern,
  1209. data->ExplodedNodeParsedPattern,
  1210. ExplodedLeafParsedPattern,
  1211. data->ExplodedLeafParsedPattern
  1212. )) {
  1213. GlAppend (List, (PBYTE) data, sizeof (CALLBACKDATA));
  1214. } else if (processHooks) {
  1215. if (data->CallbackType == CALLBACK_HOOK) {
  1216. if (pTestContainerEx (
  1217. data->ExplodedNodeParsedPattern,
  1218. ExplodedNodeParsedPattern,
  1219. data->ExplodedLeafParsedPattern,
  1220. ExplodedLeafParsedPattern
  1221. )) {
  1222. GlAppend (List, (PBYTE) data, sizeof (CALLBACKDATA));
  1223. }
  1224. }
  1225. }
  1226. data = data->Next;
  1227. }
  1228. }
  1229. VOID
  1230. pDestroyFunctionListForPattern (
  1231. IN OUT PGROWLIST List
  1232. )
  1233. /*++
  1234. Routine Description:
  1235. This function simply cleans up the resources associated with a function
  1236. list.
  1237. Arguments:
  1238. List - Specifies the growlist of callbackdata to clean up.
  1239. Return Value:
  1240. None.
  1241. --*/
  1242. {
  1243. UINT i;
  1244. PCALLBACKDATA data;
  1245. UINT count;
  1246. //
  1247. // Clean up enum modification stacks.
  1248. //
  1249. count = GlGetSize (List);
  1250. for (i = 0; i < count; i++) {
  1251. data = (PCALLBACKDATA) GlGetItem (List, i);
  1252. GbFree (&data->EnumFlags);
  1253. }
  1254. //
  1255. // Clean up list itself.
  1256. //
  1257. GlFree (List);
  1258. }
  1259. VOID
  1260. pAddStaticExclusion (
  1261. IN MIG_OBJECTTYPEID ObjectTypeId,
  1262. IN MIG_OBJECTSTRINGHANDLE EncodedFullName
  1263. )
  1264. {
  1265. HASHTABLE exclusionTable;
  1266. if (!EncodedFullName) {
  1267. //
  1268. // Ignore request for bad name
  1269. //
  1270. return;
  1271. }
  1272. ObjectTypeId = ObjectTypeId & (~PLATFORM_MASK);
  1273. exclusionTable = GetTypeExclusionTable (ObjectTypeId);
  1274. if (!exclusionTable) {
  1275. return;
  1276. }
  1277. HtAddString (exclusionTable, EncodedFullName);
  1278. }
  1279. BOOL
  1280. pIsObjectExcluded (
  1281. IN MIG_OBJECTTYPEID ObjectTypeId,
  1282. IN MIG_OBJECTSTRINGHANDLE EncodedFullName
  1283. )
  1284. {
  1285. HASHTABLE exclusionTable;
  1286. if (!EncodedFullName) {
  1287. return FALSE;
  1288. }
  1289. //
  1290. // Check the hash table for an entry
  1291. //
  1292. ObjectTypeId = ObjectTypeId & (~PLATFORM_MASK);
  1293. exclusionTable = GetTypeExclusionTable (ObjectTypeId);
  1294. if (!exclusionTable) {
  1295. return FALSE;
  1296. }
  1297. if (HtFindString (exclusionTable, EncodedFullName)) {
  1298. return TRUE;
  1299. }
  1300. return FALSE;
  1301. }
  1302. BOOL
  1303. pIsObjectNodeExcluded (
  1304. IN MIG_OBJECTTYPEID ObjectTypeId,
  1305. IN PCTSTR NodePattern,
  1306. OUT PBOOL PossiblePatternMatch OPTIONAL
  1307. )
  1308. {
  1309. HASHTABLE exclusionTable;
  1310. HASHTABLE_ENUM e;
  1311. PCTSTR node;
  1312. PTSTR wackedExclusion;
  1313. PCTSTR firstWildcard = NULL;
  1314. PCTSTR wildcard1;
  1315. PCTSTR wildcard2;
  1316. UINT patternStrTchars;
  1317. UINT hashStrTchars;
  1318. BOOL match = FALSE;
  1319. ObjectTypeId = ObjectTypeId & (~PLATFORM_MASK);
  1320. exclusionTable = GetTypeExclusionTable (ObjectTypeId);
  1321. if (!exclusionTable) {
  1322. return FALSE;
  1323. }
  1324. //
  1325. // If NodePattern is a pattern, then PossiblePatternMatch is specified.
  1326. // Otherwise, NodePattern is a specific node.
  1327. //
  1328. if (PossiblePatternMatch) {
  1329. //
  1330. // Computer the length of the non-pattern portion
  1331. //
  1332. *PossiblePatternMatch = FALSE;
  1333. firstWildcard = NULL;
  1334. wildcard1 = ObsFindNonEncodedCharInEncodedString (NodePattern, TEXT('*'));
  1335. wildcard2 = ObsFindNonEncodedCharInEncodedString (NodePattern, TEXT('?'));
  1336. if (wildcard1) {
  1337. firstWildcard = wildcard1;
  1338. }
  1339. if (wildcard2) {
  1340. if ((!firstWildcard) || (firstWildcard > wildcard2)) {
  1341. firstWildcard = wildcard2;
  1342. }
  1343. }
  1344. if (!firstWildcard) {
  1345. firstWildcard = GetEndOfString (NodePattern);
  1346. }
  1347. } else {
  1348. firstWildcard = GetEndOfString (NodePattern);
  1349. }
  1350. //
  1351. // Enumerate all exclusions and check NodePattern against them
  1352. //
  1353. patternStrTchars = (HALF_PTR) (firstWildcard - NodePattern);
  1354. if (EnumFirstHashTableString (&e, exclusionTable)) {
  1355. do {
  1356. if (IsmIsObjectHandleNodeOnly (e.String)) {
  1357. IsmCreateObjectStringsFromHandle (e.String, &node, NULL);
  1358. MYASSERT (node);
  1359. hashStrTchars = TcharCount (node);
  1360. if (hashStrTchars < patternStrTchars) {
  1361. //
  1362. // Require exclusion to be a prefix, ending in a backslash
  1363. //
  1364. wackedExclusion = DuplicatePathString (node, sizeof (TCHAR));
  1365. AppendWack (wackedExclusion);
  1366. if (StringIPrefix (NodePattern, wackedExclusion)) {
  1367. match = TRUE;
  1368. }
  1369. FreePathString (wackedExclusion);
  1370. } else {
  1371. //
  1372. // Require exclusion to match identically
  1373. //
  1374. if (hashStrTchars == patternStrTchars &&
  1375. StringIMatch (NodePattern, e.String)
  1376. ) {
  1377. match = TRUE;
  1378. } else if (PossiblePatternMatch && !match) {
  1379. //
  1380. // We *might* have an exclusion match (we can't tell).
  1381. // If the pattern contains no wacks, then we assume
  1382. // the enumerated node will determine exclusion
  1383. // properly.
  1384. //
  1385. // This could be optimized further by checking if the
  1386. // character set of NodePattern is a subset of the
  1387. // exclusion string.
  1388. //
  1389. if (!_tcschr (NodePattern, TEXT('\\'))) {
  1390. *PossiblePatternMatch = TRUE;
  1391. }
  1392. }
  1393. }
  1394. IsmDestroyObjectString (node);
  1395. }
  1396. } while (!match && EnumNextHashTableString (&e));
  1397. }
  1398. return match;
  1399. }
  1400. BOOL
  1401. pShouldCallGatherCallback (
  1402. IN PMIG_TYPEOBJECTENUM Object,
  1403. IN PCALLBACKDATA Callback
  1404. )
  1405. /*++
  1406. Routine Description:
  1407. This function encapsulates the logic needed to determine wether or not to
  1408. callback the specified callback. This is necessary because patterns
  1409. requested by various Data Gather Modules are collapsed into a minimal set
  1410. of enumeration patterns. Therefore, we only know that a particular callback
  1411. may be interested in the current object. This function is used to make
  1412. sure.
  1413. Arguments:
  1414. Object - Specifies the current object being enumerated.
  1415. Callback - Specifies the callback data to be checked. This may be modified,
  1416. if a previous enumeration change request by the callback has now
  1417. expired.
  1418. Return Value:
  1419. TRUE if the callback should be called, FALSE otherwise.
  1420. --*/
  1421. {
  1422. PCALLBACK_ENUMFLAGS flags;
  1423. BOOL result = FALSE;
  1424. PTSTR tempString;
  1425. if (Object->Level >= Callback->MinLevel && Object->Level <= Callback->MaxLevel ) {
  1426. //
  1427. // Don't call callbacks that have signaled they are finished or that have errored.
  1428. //
  1429. if (Callback->Done || Callback->Error) {
  1430. return FALSE;
  1431. }
  1432. //
  1433. // See if there is a enumeration modification in effect for this callback.
  1434. //
  1435. flags = CALLBACK_ENUMFLAGS_TOP(&Callback->EnumFlags);
  1436. //
  1437. // Remove stale entries in the modification list.
  1438. //
  1439. while (flags) {
  1440. if (Object->IsNode) {
  1441. if (flags->Level > Object->Level) {
  1442. Callback->EnumFlags.End -= sizeof (CALLBACK_ENUMFLAGS);
  1443. flags = CALLBACK_ENUMFLAGS_TOP (&Callback->EnumFlags);
  1444. continue;
  1445. }
  1446. if ((flags->Level == Object->Level) && (flags->Flags == CALLBACK_SKIP_LEAVES)) {
  1447. Callback->EnumFlags.End -= sizeof (CALLBACK_ENUMFLAGS);
  1448. flags = CALLBACK_ENUMFLAGS_TOP (&Callback->EnumFlags);
  1449. continue;
  1450. }
  1451. }
  1452. if (Object->IsLeaf) {
  1453. if (flags->Level > (Object->Level + 1)) {
  1454. Callback->EnumFlags.End -= sizeof (CALLBACK_ENUMFLAGS);
  1455. flags = CALLBACK_ENUMFLAGS_TOP (&Callback->EnumFlags);
  1456. continue;
  1457. }
  1458. }
  1459. break;
  1460. }
  1461. if (flags && (!flags->Enabled) && Object->IsNode && (flags->EnableLevel == Object->Level)) {
  1462. flags->Enabled = TRUE;
  1463. }
  1464. //
  1465. // Check flags to see if we should call this function.
  1466. //
  1467. if (flags) {
  1468. if (flags->Enabled && flags->Flags == CALLBACK_THIS_TREE_ONLY) {
  1469. if (flags->Level == Object->Level) {
  1470. Callback->Done = TRUE;
  1471. return FALSE;
  1472. }
  1473. }
  1474. if (flags->Enabled && flags->Flags == CALLBACK_SKIP_LEAVES) {
  1475. if ((Object->IsLeaf) && (flags->Level == Object->Level + 1)) {
  1476. return FALSE;
  1477. }
  1478. }
  1479. if (flags->Enabled && flags->Flags == CALLBACK_SKIP_NODES) {
  1480. if (flags->Level <= Object->Level){
  1481. return FALSE;
  1482. }
  1483. }
  1484. if (flags->Enabled && flags->Flags == CALLBACK_SKIP_TREE) {
  1485. if (flags->Level <= (Object->IsLeaf?Object->Level+1:Object->Level)){
  1486. return FALSE;
  1487. }
  1488. }
  1489. }
  1490. //
  1491. // If we haven't failed out yet, do a pattern match against the function's requested
  1492. // enumeration.
  1493. //
  1494. result = TRUE;
  1495. if (Object->ObjectNode) {
  1496. if (Callback->NodeParsedPattern) {
  1497. result = TestParsedPattern (Callback->NodeParsedPattern, Object->ObjectNode);
  1498. if (!result) {
  1499. //
  1500. // let's try one more time with a wack at the end
  1501. //
  1502. tempString = JoinText (Object->ObjectNode, TEXT("\\"));
  1503. result = TestParsedPattern (Callback->NodeParsedPattern, tempString);
  1504. FreeText (tempString);
  1505. }
  1506. } else {
  1507. result = Object->ObjectLeaf != NULL;
  1508. }
  1509. }
  1510. if (result && Object->ObjectLeaf) {
  1511. if (Callback->LeafParsedPattern) {
  1512. result = TestParsedPattern (Callback->LeafParsedPattern, Object->ObjectLeaf);
  1513. if (!result &&
  1514. ((Object->ObjectTypeId & (~PLATFORM_MASK)) == MIG_FILE_TYPE) &&
  1515. (_tcschr (Object->ObjectLeaf, TEXT('.')) == NULL)
  1516. ) {
  1517. // let's try one more thing
  1518. tempString = JoinText (Object->ObjectLeaf, TEXT("."));
  1519. result = TestParsedPattern (Callback->LeafParsedPattern, tempString);
  1520. FreeText (tempString);
  1521. }
  1522. }
  1523. }
  1524. }
  1525. return result;
  1526. }
  1527. BOOL
  1528. pProcessCallbackReturnCode (
  1529. IN DWORD ReturnCode,
  1530. IN PMIG_TYPEOBJECTENUM Object,
  1531. IN OUT PCALLBACKDATA Callback
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. This function encapsulates the logic for handling the return code of a
  1536. callback function. Callback functions have the capability to alter the
  1537. behavior of the enumeration with respect to themselves. This function takes
  1538. care of logging those change requests.
  1539. Arguments:
  1540. ReturnCode - Specifies a callback return code.
  1541. Object - Specifies the current object being enumerated.
  1542. Callback - Specifies the callback data structure responsible for the
  1543. return code. May be modified if a change is required by the
  1544. callback.
  1545. Return Value:
  1546. TRUE if the return code was successfully processed, FALSE otherwise.
  1547. --*/
  1548. {
  1549. PCALLBACK_ENUMFLAGS flags;
  1550. if (ReturnCode & CALLBACK_ERROR) {
  1551. //
  1552. // the callback function encountered some error, will never be called again
  1553. //
  1554. Callback->Error = TRUE;
  1555. DEBUGMSG ((DBG_ERROR, "A callback function returned an error while enumerating %s.", Object->ObjectName));
  1556. //
  1557. // NTRAID#NTBUG9-153257-2000/08/01-jimschm Add appropriate error handling here.
  1558. //
  1559. } else if (ReturnCode & CALLBACK_DONE_ENUMERATING) {
  1560. //
  1561. // the callback function is done enumerating, will never be called again
  1562. //
  1563. Callback->Done = TRUE;
  1564. } else if (ReturnCode != CALLBACK_ENUM_CONTINUE) {
  1565. //
  1566. // Save callback enumeration flags into the callback's private stack.
  1567. //
  1568. if (ReturnCode & CALLBACK_THIS_TREE_ONLY) {
  1569. flags = (PCALLBACK_ENUMFLAGS) GbGrow (&Callback->EnumFlags, sizeof(CALLBACK_ENUMFLAGS));
  1570. flags->Level = Object->Level;
  1571. flags->EnableLevel = Object->Level;
  1572. flags->Enabled = FALSE;
  1573. flags->Flags = CALLBACK_THIS_TREE_ONLY;
  1574. }
  1575. if (ReturnCode & CALLBACK_SKIP_NODES) {
  1576. flags = (PCALLBACK_ENUMFLAGS) GbGrow (&Callback->EnumFlags, sizeof(CALLBACK_ENUMFLAGS));
  1577. flags->Level = Object->IsLeaf?Object->Level+1:Object->Level;
  1578. flags->EnableLevel = Object->IsLeaf?Object->Level+1:Object->Level;
  1579. flags->Enabled = FALSE;
  1580. flags->Flags = CALLBACK_SKIP_NODES;
  1581. }
  1582. if (ReturnCode & CALLBACK_SKIP_TREE) {
  1583. flags = (PCALLBACK_ENUMFLAGS) GbGrow (&Callback->EnumFlags, sizeof(CALLBACK_ENUMFLAGS));
  1584. flags->Level = Object->Level + 1;
  1585. flags->EnableLevel = 0;
  1586. flags->Enabled = TRUE;
  1587. flags->Flags = CALLBACK_SKIP_TREE;
  1588. }
  1589. if (ReturnCode & CALLBACK_SKIP_LEAVES) {
  1590. flags = (PCALLBACK_ENUMFLAGS) GbGrow (&Callback->EnumFlags, sizeof(CALLBACK_ENUMFLAGS));
  1591. flags->Level = Object->Level + 1;
  1592. flags->EnableLevel = 0;
  1593. flags->Enabled = TRUE;
  1594. flags->Flags = CALLBACK_SKIP_LEAVES;
  1595. }
  1596. }
  1597. return TRUE;
  1598. }
  1599. BOOL
  1600. pDoSingleEnumeration (
  1601. IN PTYPEENUMINFO GlobalTypeEnumInfo,
  1602. IN PTYPEENUMINFO TypeEnumInfo,
  1603. IN PCTSTR ObjectPattern,
  1604. IN BOOL CallNormalCallbacks,
  1605. IN MIG_PROGRESSSLICEID SliceId OPTIONAL
  1606. )
  1607. /*++
  1608. Routine Description:
  1609. Given a type structure and a pattern, this function runs an enumeration
  1610. based on that pattern, calling all callbacks as needed in that enumeration.
  1611. Arguments:
  1612. GlobalTypeEnumInfo - Specifies the type data for the exclude list. This parameter
  1613. supplies the excluded pattern list.
  1614. TypeEnumInfo - Specifies the type data for the enumeration to be run. This
  1615. parameter supplies the queued pattern lists.
  1616. ObjectPattern - Specifies the pattern for the enumeration.
  1617. CallNormalCallbacks - Specifies TRUE for normal callbacks to be processed,
  1618. or FALSE for hook callbacks to be processed
  1619. SliceId - Specifies the progress bar slice ID, or 0 for no slice. If
  1620. specified, the slice ID will cause ticks to be generated for
  1621. each container at level 3.
  1622. Return Value:
  1623. TRUE if the enumeration was run successfully, FALSE otherwise.
  1624. --*/
  1625. {
  1626. MIG_TYPEOBJECTENUM eObjects;
  1627. GROWLIST funList = INIT_GROWLIST;
  1628. GROWLIST exclFunList = INIT_GROWLIST;
  1629. UINT i;
  1630. PCALLBACKDATA callbackData;
  1631. DWORD rc;
  1632. MIG_OBJECTENUMDATA publicData;
  1633. PTSTR leafPattern = NULL;
  1634. PTSTR nodePattern = NULL;
  1635. PPARSEDPATTERN nodeParsedPattern = NULL;
  1636. PPARSEDPATTERN explodedNodeParsedPattern = NULL;
  1637. PPARSEDPATTERN leafParsedPattern = NULL;
  1638. PPARSEDPATTERN explodedLeafParsedPattern = NULL;
  1639. PMIG_OBJECTENUMCALLBACK obEnumCallback;
  1640. PMIG_DYNAMICEXCLUSIONCALLBACK exclusionCallback;
  1641. UINT size;
  1642. BOOL stop;
  1643. BOOL b;
  1644. BOOL fSkip;
  1645. UINT fIndex;
  1646. BOOL result = TRUE;
  1647. static DWORD ticks;
  1648. static UINT objects;
  1649. BOOL extraExcludeCheck = FALSE;
  1650. MIG_APPINFO appInfo;
  1651. //
  1652. // Is entire pattern excluded?
  1653. //
  1654. ObsSplitObjectStringEx (ObjectPattern, &nodePattern, &leafPattern, NULL, FALSE);
  1655. if (nodePattern) {
  1656. if (pIsObjectNodeExcluded (
  1657. TypeEnumInfo->ObjectTypeId,
  1658. nodePattern,
  1659. &extraExcludeCheck
  1660. )) {
  1661. DEBUGMSG ((DBG_FLOW, "Pattern %s is completely excluded", ObjectPattern));
  1662. ObsFree (nodePattern);
  1663. return TRUE;
  1664. }
  1665. }
  1666. //
  1667. // Prepare parsed patterns for speed
  1668. //
  1669. if (nodePattern) {
  1670. nodeParsedPattern = CreateParsedPatternEx (g_CurrentQueuePool, nodePattern);
  1671. if (nodeParsedPattern) {
  1672. explodedNodeParsedPattern = ExplodeParsedPatternEx (g_CurrentQueuePool, nodeParsedPattern);
  1673. }
  1674. ObsFree (nodePattern);
  1675. INVALID_POINTER (nodePattern);
  1676. }
  1677. if (leafPattern) {
  1678. leafParsedPattern = CreateParsedPatternEx (g_CurrentQueuePool, leafPattern);
  1679. if (leafParsedPattern) {
  1680. explodedLeafParsedPattern = ExplodeParsedPatternEx (g_CurrentQueuePool, leafParsedPattern);
  1681. }
  1682. ObsFree (leafPattern);
  1683. INVALID_POINTER (leafPattern);
  1684. }
  1685. //
  1686. // Perform enumeration
  1687. //
  1688. if (EnumFirstObjectOfType (&eObjects, TypeEnumInfo->ObjectTypeId, ObjectPattern, NODE_LEVEL_MAX)) {
  1689. DEBUGMSG ((DBG_FLOW, "Enumerating objects of type %s with pattern %s.", TypeEnumInfo->TypeName, ObjectPattern));
  1690. //
  1691. // Get list of functions that want things from this particular enumeration.
  1692. //
  1693. pCreateFunctionListForPattern (
  1694. &funList,
  1695. TypeEnumInfo,
  1696. ObjectPattern,
  1697. explodedNodeParsedPattern,
  1698. explodedLeafParsedPattern,
  1699. CALLBACK_NORMAL
  1700. );
  1701. pCreateFunctionListForPattern (
  1702. &exclFunList,
  1703. GlobalTypeEnumInfo,
  1704. ObjectPattern,
  1705. explodedNodeParsedPattern,
  1706. explodedLeafParsedPattern,
  1707. CALLBACK_EXCLUSION
  1708. );
  1709. MYASSERT ((!CallNormalCallbacks) || GlGetSize (&funList));
  1710. do {
  1711. //
  1712. // Should enumeration of this object be skipped?
  1713. //
  1714. objects++;
  1715. LOG ((LOG_STATUS, (PCSTR) MSG_OBJECT_STATUS, objects, eObjects.NativeObjectName));
  1716. if (!eObjects.ObjectLeaf) {
  1717. // send our status to the app, but only for nodes to keep it fast
  1718. ZeroMemory (&appInfo, sizeof (MIG_APPINFO));
  1719. appInfo.Phase = g_CurrentPhase;
  1720. appInfo.SubPhase = 0;
  1721. appInfo.ObjectTypeId = (eObjects.ObjectTypeId & (~PLATFORM_MASK));
  1722. appInfo.ObjectName = eObjects.ObjectName;
  1723. IsmSendMessageToApp (ISMMESSAGE_APP_INFO, (ULONG_PTR) (&appInfo));
  1724. }
  1725. //
  1726. // Is this object at level 3? If so, tick the progress bar.
  1727. //
  1728. if (g_ProgressBarFn) {
  1729. if (SliceId && !eObjects.ObjectLeaf && eObjects.SubLevel <= 3) {
  1730. IsmTickProgressBar (SliceId, 1);
  1731. }
  1732. }
  1733. if (extraExcludeCheck && eObjects.ObjectNode) {
  1734. if (pIsObjectNodeExcluded (
  1735. TypeEnumInfo->ObjectTypeId,
  1736. eObjects.ObjectNode,
  1737. NULL
  1738. )) {
  1739. DEBUGMSG ((DBG_FLOW, "Node %s is completely excluded", ObjectPattern));
  1740. AbortCurrentNodeEnum (&eObjects);
  1741. continue;
  1742. }
  1743. }
  1744. if (pIsObjectExcluded (eObjects.ObjectTypeId, eObjects.ObjectName)) {
  1745. DEBUGMSG ((DBG_FLOW, "Object %s is excluded", eObjects.ObjectName));
  1746. //
  1747. // If leaf is empty, abort enum of this node
  1748. //
  1749. if (!eObjects.ObjectLeaf) {
  1750. AbortCurrentNodeEnum (&eObjects);
  1751. }
  1752. continue;
  1753. }
  1754. if (eObjects.ObjectLeaf) {
  1755. b = pIsObjectExcluded (
  1756. eObjects.ObjectTypeId,
  1757. ObsGetNodeLeafDivider (eObjects.ObjectName)
  1758. );
  1759. if (b) {
  1760. DEBUGMSG ((DBG_FLOW, "Leaf %s is excluded", eObjects.ObjectLeaf));
  1761. continue;
  1762. }
  1763. }
  1764. //
  1765. // Call all dynamic exclusion functions
  1766. //
  1767. stop = FALSE;
  1768. size = GlGetSize (&exclFunList);
  1769. for (i = 0; i < size ; i++) {
  1770. callbackData = (PCALLBACKDATA) GlGetItem (&exclFunList, i);
  1771. if (pShouldCallGatherCallback (&eObjects, callbackData)) {
  1772. //
  1773. // Call the callback function
  1774. //
  1775. MYASSERT (!g_CurrentGroup);
  1776. g_CurrentGroup = callbackData->Group;
  1777. exclusionCallback = (PMIG_DYNAMICEXCLUSIONCALLBACK) callbackData->Function;
  1778. stop = exclusionCallback (
  1779. eObjects.ObjectTypeId,
  1780. eObjects.ObjectName,
  1781. callbackData->CallbackArg
  1782. );
  1783. g_CurrentGroup = NULL;
  1784. if (stop) {
  1785. break;
  1786. }
  1787. }
  1788. }
  1789. if (stop) {
  1790. DEBUGMSG ((
  1791. DBG_FLOW,
  1792. "Object %s is dynamically excluded",
  1793. eObjects.ObjectName
  1794. ));
  1795. continue;
  1796. }
  1797. //
  1798. // Check if the user wants to cancel. If yes, fail with an error.
  1799. //
  1800. if (IsmCheckCancel()) {
  1801. AbortObjectOfTypeEnum (&eObjects);
  1802. SetLastError (ERROR_CANCELLED);
  1803. result = FALSE;
  1804. break;
  1805. }
  1806. //
  1807. // Cycle through each of the list of functions looking for any that care about the current data.
  1808. //
  1809. size = GlGetSize (&funList);
  1810. g_EnumerationList.End = 0;
  1811. for (i = 0; i < size ; i++) {
  1812. callbackData = (PCALLBACKDATA) GlGetItem (&funList, i);
  1813. if (CallNormalCallbacks || (callbackData->CallbackType == CALLBACK_HOOK)) {
  1814. if (pShouldCallGatherCallback (&eObjects, callbackData)) {
  1815. fSkip = FALSE;
  1816. if (g_EnumerationList.End) {
  1817. fIndex = 0;
  1818. while (fIndex < g_EnumerationList.End) {
  1819. if (*((ULONG_PTR *)(g_EnumerationList.Buf + fIndex)) == (ULONG_PTR)callbackData->Function) {
  1820. fSkip = TRUE;
  1821. }
  1822. fIndex += sizeof (callbackData->Function);
  1823. if (*((ULONG_PTR *)(g_EnumerationList.Buf + fIndex)) != (ULONG_PTR)callbackData->CallbackArg) {
  1824. fSkip = FALSE;
  1825. }
  1826. fIndex += sizeof (callbackData->CallbackArg);
  1827. if (fSkip) {
  1828. break;
  1829. }
  1830. }
  1831. }
  1832. if (!fSkip) {
  1833. CopyMemory (
  1834. GbGrow (&g_EnumerationList, sizeof (callbackData->Function)),
  1835. &(callbackData->Function),
  1836. sizeof (callbackData->Function)
  1837. );
  1838. CopyMemory (
  1839. GbGrow (&g_EnumerationList, sizeof (callbackData->CallbackArg)),
  1840. &(callbackData->CallbackArg),
  1841. sizeof (callbackData->CallbackArg)
  1842. );
  1843. //
  1844. // Copy the enumeration info to the public structure
  1845. //
  1846. publicData.ObjectTypeId = TypeEnumInfo->ObjectTypeId;
  1847. publicData.ObjectName = eObjects.ObjectName;
  1848. publicData.NativeObjectName = eObjects.NativeObjectName;
  1849. publicData.ObjectNode = eObjects.ObjectNode;
  1850. publicData.ObjectLeaf = eObjects.ObjectLeaf;
  1851. publicData.Level = eObjects.Level;
  1852. publicData.SubLevel = eObjects.SubLevel;
  1853. publicData.IsLeaf = eObjects.IsLeaf;
  1854. publicData.IsNode = eObjects.IsNode;
  1855. publicData.Details.DetailsSize = eObjects.Details.DetailsSize;
  1856. publicData.Details.DetailsData = eObjects.Details.DetailsData;
  1857. //
  1858. // Call the callback function
  1859. //
  1860. MYASSERT (!g_CurrentGroup);
  1861. g_CurrentGroup = callbackData->Group;
  1862. obEnumCallback = (PMIG_OBJECTENUMCALLBACK) callbackData->Function;
  1863. rc = obEnumCallback (&publicData, callbackData->CallbackArg);
  1864. g_CurrentGroup = NULL;
  1865. if (rc != CALLBACK_ENUM_CONTINUE) {
  1866. //
  1867. // Callback wants to make some sort of modification to its enumeration.
  1868. //
  1869. pProcessCallbackReturnCode (rc, &eObjects, callbackData);
  1870. }
  1871. }
  1872. }
  1873. }
  1874. }
  1875. } while (EnumNextObjectOfType (&eObjects));
  1876. //
  1877. // Clean up function list.
  1878. //
  1879. pDestroyFunctionListForPattern (&funList);
  1880. pDestroyFunctionListForPattern (&exclFunList);
  1881. }
  1882. ELSE_DEBUGMSG ((DBG_FLOW, "No objects found matching enumeration pattern %s.", ObjectPattern));
  1883. DestroyParsedPattern (explodedLeafParsedPattern);
  1884. DestroyParsedPattern (leafParsedPattern);
  1885. DestroyParsedPattern (explodedNodeParsedPattern);
  1886. DestroyParsedPattern (nodeParsedPattern);
  1887. return result;
  1888. }
  1889. VOID
  1890. pCreatePhysicalTypeCallbackList (
  1891. IN MIG_OBJECTTYPEID ObjectTypeId,
  1892. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  1893. IN CALLBACK_TYPE CallbackType,
  1894. IN OUT PGROWLIST List
  1895. )
  1896. {
  1897. PTYPEENUMINFO typeEnumInfo;
  1898. PCTSTR node;
  1899. PCTSTR leaf;
  1900. PCALLBACKDATA callbackData;
  1901. BOOL callFn;
  1902. //
  1903. // Test object against all patterns of the type
  1904. //
  1905. typeEnumInfo = pGetTypeEnumInfo (ObjectTypeId & (~PLATFORM_MASK), TRUE);
  1906. if (!typeEnumInfo) {
  1907. return;
  1908. }
  1909. ObsSplitObjectStringEx (ObjectName, &node, &leaf, NULL, TRUE);
  1910. if (!node && !leaf) {
  1911. return;
  1912. }
  1913. switch (CallbackType) {
  1914. case CALLBACK_PHYSICAL_ENUM:
  1915. callbackData = typeEnumInfo->PhysicalEnumList;
  1916. break;
  1917. case CALLBACK_PHYSICAL_ACQUIRE:
  1918. callbackData = typeEnumInfo->PhysicalAcquireList;
  1919. break;
  1920. default:
  1921. MYASSERT (FALSE);
  1922. return;
  1923. }
  1924. while (callbackData) {
  1925. MYASSERT (callbackData->NodeParsedPattern);
  1926. if (!node || TestParsedPattern (callbackData->NodeParsedPattern, node)) {
  1927. if (callbackData->LeafParsedPattern && leaf) {
  1928. callFn = TestParsedPattern (callbackData->LeafParsedPattern, leaf);
  1929. } else if (leaf && !callbackData->LeafParsedPattern) {
  1930. callFn = FALSE;
  1931. } else {
  1932. callFn = TRUE;
  1933. }
  1934. if (callFn) {
  1935. GlAppend (List, (PBYTE) callbackData, sizeof (CALLBACKDATA));
  1936. }
  1937. }
  1938. callbackData = callbackData->Next;
  1939. }
  1940. ObsFree (node);
  1941. ObsFree (leaf);
  1942. }
  1943. BOOL
  1944. ExecutePhysicalAcquireCallbacks (
  1945. IN MIG_OBJECTTYPEID ObjectTypeId,
  1946. IN MIG_OBJECTSTRINGHANDLE ObjectName,
  1947. IN PMIG_CONTENT Content, OPTIONAL
  1948. IN MIG_CONTENTTYPE ContentType,
  1949. IN UINT MemoryContentLimit,
  1950. OUT PMIG_CONTENT *NewContent
  1951. )
  1952. {
  1953. UINT count;
  1954. UINT u;
  1955. PCALLBACKDATA callbackData;
  1956. PMIG_PHYSICALACQUIREFREE acquireFree = NULL;
  1957. PMIG_PHYSICALACQUIREHOOK acquireHook;
  1958. PMIG_CONTENT updatedContent;
  1959. BOOL result = TRUE;
  1960. PMIG_CONTENT currentContent;
  1961. pCreatePhysicalTypeCallbackList (
  1962. ObjectTypeId,
  1963. ObjectName,
  1964. CALLBACK_PHYSICAL_ACQUIRE,
  1965. &g_AcquireList
  1966. );
  1967. count = GlGetSize (&g_AcquireList);
  1968. currentContent = Content;
  1969. for (u = 0 ; u < count ; u++) {
  1970. //
  1971. // Call this function
  1972. //
  1973. callbackData = (PCALLBACKDATA) GlGetItem (&g_AcquireList, u);
  1974. acquireHook = (PMIG_PHYSICALACQUIREHOOK) callbackData->Function;
  1975. if (acquireHook) {
  1976. updatedContent = NULL;
  1977. if (!acquireHook (
  1978. ObjectName,
  1979. currentContent,
  1980. ContentType,
  1981. MemoryContentLimit,
  1982. &updatedContent,
  1983. FALSE,
  1984. callbackData->CallbackArg
  1985. )) {
  1986. //
  1987. // Hook says "don't acquire"
  1988. //
  1989. result = FALSE;
  1990. }
  1991. if (!result || updatedContent) {
  1992. if (currentContent != Content) {
  1993. //
  1994. // Free previous hook content change
  1995. //
  1996. if (acquireFree) {
  1997. acquireFree (currentContent);
  1998. acquireFree = NULL;
  1999. }
  2000. currentContent = NULL;
  2001. }
  2002. if (updatedContent) {
  2003. //
  2004. // Hook provided replacement content
  2005. //
  2006. currentContent = updatedContent;
  2007. acquireFree = (PMIG_PHYSICALACQUIREFREE) callbackData->Function2;
  2008. } else {
  2009. break; // don't acquire -- we can stop now
  2010. }
  2011. }
  2012. }
  2013. }
  2014. if (currentContent && acquireFree) {
  2015. currentContent->IsmHandle = acquireFree;
  2016. }
  2017. *NewContent = currentContent != Content ? currentContent : NULL;
  2018. GlReset (&g_AcquireList);
  2019. return result;
  2020. }
  2021. BOOL
  2022. FreeViaAcquirePhysicalCallback (
  2023. IN PMIG_CONTENT Content
  2024. )
  2025. {
  2026. PMIG_PHYSICALACQUIREFREE acquireFree;
  2027. if (!Content->IsmHandle) {
  2028. return FALSE;
  2029. }
  2030. acquireFree = (PMIG_PHYSICALACQUIREFREE) Content->IsmHandle;
  2031. if (acquireFree) {
  2032. acquireFree (Content);
  2033. }
  2034. return TRUE;
  2035. }
  2036. BOOL
  2037. ExecutePhysicalEnumCheckCallbacks (
  2038. IN PMIG_TYPEOBJECTENUM ObjectEnum
  2039. )
  2040. {
  2041. UINT count;
  2042. UINT u;
  2043. PCALLBACKDATA callbackData;
  2044. PMIG_PHYSICALENUMCHECK enumCheck;
  2045. BOOL result = TRUE;
  2046. pCreatePhysicalTypeCallbackList (
  2047. ObjectEnum->ObjectTypeId,
  2048. ObjectEnum->ObjectName,
  2049. CALLBACK_PHYSICAL_ENUM,
  2050. &g_EnumList
  2051. );
  2052. count = GlGetSize (&g_EnumList);
  2053. for (u = 0 ; u < count ; u++) {
  2054. //
  2055. // Call this function
  2056. //
  2057. callbackData = (PCALLBACKDATA) GlGetItem (&g_EnumList, u);
  2058. enumCheck = (PMIG_PHYSICALENUMCHECK) callbackData->Function;
  2059. if (enumCheck) {
  2060. if (!enumCheck (ObjectEnum, callbackData->CallbackArg)) {
  2061. //
  2062. // Hook says "skip"
  2063. //
  2064. result = FALSE;
  2065. break;
  2066. }
  2067. } else {
  2068. //
  2069. // No callback means "skip"
  2070. //
  2071. result = FALSE;
  2072. break;
  2073. }
  2074. }
  2075. GlReset (&g_EnumList);
  2076. return result;
  2077. }
  2078. BOOL
  2079. ExecutePhysicalEnumAddCallbacks (
  2080. IN OUT PMIG_TYPEOBJECTENUM ObjectEnum,
  2081. IN MIG_OBJECTSTRINGHANDLE Pattern,
  2082. IN MIG_PARSEDPATTERN ParsedPattern,
  2083. IN OUT PUINT CurrentCallback
  2084. )
  2085. {
  2086. BOOL result = FALSE;
  2087. BOOL done;
  2088. PENUMADDCALLBACK callback;
  2089. MIG_OBJECTTYPEID objectTypeId;
  2090. objectTypeId = ObjectEnum->ObjectTypeId & ~(PLATFORM_MASK);
  2091. do {
  2092. done = TRUE;
  2093. if (GlGetSize (&g_EnumAddList) > *CurrentCallback) {
  2094. callback = (PENUMADDCALLBACK) GlGetItem (&g_EnumAddList, *CurrentCallback);
  2095. MYASSERT (callback);
  2096. MYASSERT (callback->AddCallback);
  2097. if (callback->ObjectTypeId != objectTypeId) {
  2098. result = FALSE;
  2099. } else {
  2100. result = callback->AddCallback (ObjectEnum, Pattern, ParsedPattern, callback->AddCallbackArg, FALSE);
  2101. }
  2102. if (!result) {
  2103. *CurrentCallback += 1;
  2104. done = FALSE;
  2105. }
  2106. }
  2107. } while (!done);
  2108. return result;
  2109. }
  2110. VOID
  2111. AbortPhysicalEnumCallback (
  2112. IN PMIG_TYPEOBJECTENUM ObjectEnum, ZEROED
  2113. IN UINT CurrentCallback
  2114. )
  2115. {
  2116. PENUMADDCALLBACK callback;
  2117. if (GlGetSize (&g_EnumAddList) > CurrentCallback) {
  2118. callback = (PENUMADDCALLBACK) GlGetItem (&g_EnumAddList, CurrentCallback);
  2119. MYASSERT (callback);
  2120. MYASSERT (callback->AddCallback);
  2121. callback->AddCallback (ObjectEnum, NULL, NULL, callback->AddCallbackArg, TRUE);
  2122. }
  2123. ZeroMemory (ObjectEnum, sizeof (MIG_TYPEOBJECTENUM));
  2124. }
  2125. UINT
  2126. pEstimateSingleEnumerationTicks (
  2127. IN PTYPEENUMINFO TypeEnumInfo,
  2128. IN PCTSTR ObjectPattern
  2129. )
  2130. /*++
  2131. Routine Description:
  2132. Given a type structure and a pattern, this function runs an enumeration
  2133. based on that pattern, counting all the containers 3 levels deep. This
  2134. is a quick approximation of how much work there is to do.
  2135. Arguments:
  2136. TypeEnumInfo - Specifies the type data for the enumeration to be run.
  2137. ObjectPattern - Specifies the pattern for the enumeration.
  2138. Return Value:
  2139. The number of containers exactly 3 levels deep in the object pattern.
  2140. --*/
  2141. {
  2142. MIG_TYPEOBJECTENUM eObjects;
  2143. PTSTR nodePattern = NULL;
  2144. UINT ticks = 0;
  2145. MIG_OBJECTSTRINGHANDLE nodeOnlyPattern;
  2146. ObsSplitObjectStringEx (ObjectPattern, &nodePattern, NULL, NULL, FALSE);
  2147. if (nodePattern) {
  2148. nodeOnlyPattern = ObsBuildEncodedObjectStringEx (nodePattern, NULL, FALSE);
  2149. ObsFree (nodePattern);
  2150. INVALID_POINTER (nodePattern);
  2151. } else {
  2152. return 0;
  2153. }
  2154. if (EnumFirstObjectOfType (&eObjects, TypeEnumInfo->ObjectTypeId, nodeOnlyPattern, 3)) {
  2155. DEBUGMSG ((DBG_FLOW, "Estimating number of objects of type %s with pattern %s.", TypeEnumInfo->TypeName, nodeOnlyPattern));
  2156. do {
  2157. if (eObjects.SubLevel <= 3) {
  2158. ticks++;
  2159. }
  2160. } while (EnumNextObjectOfType (&eObjects));
  2161. }
  2162. ELSE_DEBUGMSG ((DBG_FLOW, "No objects found matching enumeration pattern %s.", nodeOnlyPattern));
  2163. ObsFree (nodeOnlyPattern);
  2164. return ticks;
  2165. }
  2166. BOOL
  2167. pCallNonEnumeratedCallbacks (
  2168. IN PCALLBACKDATA FunctionList
  2169. )
  2170. /*++
  2171. Routine Description:
  2172. This function simply takes the provided list of CALLBACKDATA and for each
  2173. function, calls it as a non-enumerated callback.
  2174. Arguments:
  2175. FunctionList - Specifies the list of functions to call.
  2176. Return Value:
  2177. TRUE if all functions were called successfully. FALSE otherwise.
  2178. --*/
  2179. {
  2180. PCALLBACKDATA cur;
  2181. BOOL rc;
  2182. cur = FunctionList;
  2183. while (cur) {
  2184. MYASSERT (!g_CurrentGroup);
  2185. g_CurrentGroup = cur->Group;
  2186. rc = ((PNONENUMERATEDCALLBACK) cur->Function) ();
  2187. if (!rc) {
  2188. DEBUGMSG ((
  2189. DBG_FLOW,
  2190. "Group %s returned an error while calling its NonEnumerated Callback with id %s.",
  2191. g_CurrentGroup,
  2192. cur->Identifier ? cur->Identifier : TEXT("<Unidentified Function>")
  2193. ));
  2194. }
  2195. g_CurrentGroup = NULL;
  2196. cur = cur->Next;
  2197. }
  2198. return TRUE;
  2199. }
  2200. UINT
  2201. EstimateAllObjectEnumerations (
  2202. MIG_PROGRESSSLICEID SliceId,
  2203. BOOL PreEstimate
  2204. )
  2205. /*++
  2206. Routine Description:
  2207. EstimateAllObjectEnumerations computes a tick estimate for all enumerations
  2208. that have been requested by Data Gather Modules (by calling
  2209. IsmQueueEnumeration).
  2210. The function loops through all known types and for each needed enumeration
  2211. of that type, then calls down to a worker function to call to perform the
  2212. actual enumeration.
  2213. Arguments:
  2214. None.
  2215. Return Value:
  2216. TRUE if enumerations were completed successfully. FALSE otherwise.
  2217. --*/
  2218. {
  2219. PTYPEENUMINFO typeEnumInfo;
  2220. MIG_OBJECTTYPEID typeId;
  2221. PENUMDATA enumData;
  2222. MIG_OBJECTTYPEIDENUM objTypeIdEnum;
  2223. UINT ticks = 0;
  2224. if (g_CurrentGroup) {
  2225. DEBUGMSG ((DBG_ERROR, "EstimateAllObjectEnumerations cannot be called during another callback"));
  2226. return 0;
  2227. }
  2228. if (!g_ProgressBarFn) {
  2229. //
  2230. // No need to estimate; no progress bar callback
  2231. //
  2232. return 0;
  2233. }
  2234. //
  2235. // Initialize type data with all known types. Note that we require
  2236. // the type manager to have been initialized before we are.
  2237. //
  2238. if (!IsmEnumFirstObjectTypeId (&objTypeIdEnum)) {
  2239. DEBUGMSG ((DBG_ERROR, "EstimateAllObjectEnumerations: No known types to enumerate"));
  2240. return 0;
  2241. }
  2242. do {
  2243. typeId = objTypeIdEnum.ObjectTypeId;
  2244. if (g_IsmModulePlatformContext == PLATFORM_CURRENT) {
  2245. typeId |= g_IsmCurrentPlatform;
  2246. } else {
  2247. typeId |= g_IsmModulePlatformContext;
  2248. }
  2249. typeEnumInfo = pGetTypeEnumInfo (typeId, FALSE);
  2250. //
  2251. // For each enumeration of this type, call the enumeration worker function
  2252. //
  2253. enumData = typeEnumInfo->FirstEnum;
  2254. while (enumData) {
  2255. if (PreEstimate) {
  2256. ticks ++;
  2257. } else {
  2258. ticks += pEstimateSingleEnumerationTicks (typeEnumInfo, enumData->Pattern);
  2259. }
  2260. if (SliceId) {
  2261. IsmTickProgressBar (SliceId, 1);
  2262. }
  2263. enumData = enumData->Next;
  2264. }
  2265. } while (IsmEnumNextObjectTypeId (&objTypeIdEnum));
  2266. return ticks;
  2267. }
  2268. BOOL
  2269. DoAllObjectEnumerations (
  2270. IN MIG_PROGRESSSLICEID SliceId
  2271. )
  2272. /*++
  2273. Routine Description:
  2274. DoAllObjectEnumerations is responsible for processing all enumerations that
  2275. have been requested by Data Gather Modules (by calling
  2276. IsmQueueEnumeration).
  2277. The function:
  2278. (1) Calls Pre EnumerationFunctions
  2279. (2) Loops through all known types and for each needed enumeration of that type,
  2280. calls down to a worker function to call to perform the actual enumeration.
  2281. (3) Calls Post Enumeration Functions
  2282. Arguments:
  2283. None.
  2284. Return Value:
  2285. TRUE if enumerations were completed successfully. FALSE otherwise.
  2286. --*/
  2287. {
  2288. PTYPEENUMINFO globalTypeEnumInfo;
  2289. PTYPEENUMINFO typeEnumInfo;
  2290. MIG_OBJECTTYPEID typeId;
  2291. PENUMDATA enumData;
  2292. MIG_OBJECTTYPEIDENUM objTypeIdEnum;
  2293. BOOL result = TRUE;
  2294. if (g_CurrentGroup) {
  2295. DEBUGMSG ((DBG_ERROR, "DoAllObjectEnumerations cannot be called during another callback"));
  2296. return FALSE;
  2297. }
  2298. //
  2299. // Call any Pre-ObjectEnumeration functions.
  2300. //
  2301. pCallNonEnumeratedCallbacks (g_PreEnumerationFunctionList);
  2302. //
  2303. // Initialize type data with all known types. Note that we require
  2304. // type type manager to have been initialized before we are.
  2305. //
  2306. if (!IsmEnumFirstObjectTypeId (&objTypeIdEnum)) {
  2307. DEBUGMSG ((DBG_ERROR, "DoAllObjectEnumerations: No known types to enumerate"));
  2308. return FALSE;
  2309. }
  2310. do {
  2311. typeId = objTypeIdEnum.ObjectTypeId;
  2312. if (g_IsmModulePlatformContext == PLATFORM_CURRENT) {
  2313. typeId |= g_IsmCurrentPlatform;
  2314. } else {
  2315. typeId |= g_IsmModulePlatformContext;
  2316. }
  2317. globalTypeEnumInfo = pGetTypeEnumInfo (typeId, TRUE);
  2318. typeEnumInfo = pGetTypeEnumInfo (typeId, FALSE);
  2319. pCallNonEnumeratedCallbacks (typeEnumInfo->PreEnumerationFunctionList);
  2320. //
  2321. // For each enumeration of this type, call the enumeration worker function
  2322. //
  2323. enumData = typeEnumInfo->FirstEnum;
  2324. while (enumData && result) {
  2325. result = pDoSingleEnumeration (
  2326. globalTypeEnumInfo,
  2327. typeEnumInfo,
  2328. enumData->Pattern,
  2329. TRUE,
  2330. SliceId
  2331. );
  2332. enumData = enumData->Next;
  2333. }
  2334. if (result) {
  2335. result = pCallNonEnumeratedCallbacks (typeEnumInfo->PostEnumerationFunctionList);
  2336. }
  2337. } while (IsmEnumNextObjectTypeId (&objTypeIdEnum) && result);
  2338. //
  2339. // Call any Post-ObjectEnumeration functions.
  2340. //
  2341. if (result) {
  2342. result = pCallNonEnumeratedCallbacks (g_PostEnumerationFunctionList);
  2343. }
  2344. return result;
  2345. }
  2346. VOID
  2347. IsmExecuteHooks (
  2348. IN MIG_OBJECTTYPEID ObjectTypeId,
  2349. IN MIG_OBJECTSTRINGHANDLE ObjectName
  2350. )
  2351. {
  2352. PTYPEENUMINFO globalTypeEnumInfo;
  2353. PTYPEENUMINFO typeEnumInfo;
  2354. PENUMDATA enumData;
  2355. PCTSTR oldCurrentGroup;
  2356. PCTSTR node = NULL;
  2357. PCTSTR leaf = NULL;
  2358. PCTSTR tempString;
  2359. BOOL result;
  2360. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  2361. globalTypeEnumInfo = pGetTypeEnumInfo (ObjectTypeId, TRUE);
  2362. typeEnumInfo = pGetTypeEnumInfo (ObjectTypeId, FALSE);
  2363. if (!globalTypeEnumInfo || !typeEnumInfo) {
  2364. SetLastError (ERROR_INVALID_PARAMETER);
  2365. return;
  2366. }
  2367. enumData = typeEnumInfo->FirstEnum;
  2368. if (!ObsSplitObjectStringEx (ObjectName, &node, &leaf, NULL, TRUE)) {
  2369. DEBUGMSG ((DBG_ERROR, "Bad encoded object detected in IsmExecuteHooks: %s", ObjectName));
  2370. return;
  2371. }
  2372. while (enumData) {
  2373. result = TestParsedPattern (enumData->NodeParsedPattern, node);
  2374. if (!result) {
  2375. //
  2376. // let's try one more time with a wack at the end
  2377. //
  2378. tempString = JoinText (node, TEXT("\\"));
  2379. result = TestParsedPattern (enumData->NodeParsedPattern, tempString);
  2380. FreeText (tempString);
  2381. }
  2382. if (result && leaf) {
  2383. if (!enumData->LeafParsedPattern) {
  2384. result = FALSE;
  2385. } else {
  2386. result = TestParsedPattern (enumData->LeafParsedPattern, leaf);
  2387. if (!result &&
  2388. ((ObjectTypeId & (~PLATFORM_MASK)) == MIG_FILE_TYPE) &&
  2389. (_tcschr (leaf, TEXT('.')) == NULL)
  2390. ) {
  2391. // let's try one more thing
  2392. tempString = JoinText (leaf, TEXT("."));
  2393. result = TestParsedPattern (enumData->LeafParsedPattern, tempString);
  2394. FreeText (tempString);
  2395. }
  2396. }
  2397. }
  2398. if (result) {
  2399. DEBUGMSG ((DBG_FLOW, "IsmExecuteHooks request for an object that was or will be enumerated: %s", ObjectName));
  2400. break;
  2401. }
  2402. enumData = enumData->Next;
  2403. }
  2404. ObsFree (node);
  2405. ObsFree (leaf);
  2406. oldCurrentGroup = g_CurrentGroup;
  2407. g_CurrentGroup = NULL;
  2408. pDoSingleEnumeration (globalTypeEnumInfo, typeEnumInfo, ObjectName, FALSE, 0);
  2409. g_CurrentGroup = oldCurrentGroup;
  2410. SetLastError (ERROR_SUCCESS);
  2411. }
  2412. BOOL
  2413. InitializeFlowControl (
  2414. VOID
  2415. )
  2416. /*++
  2417. Routine Description:
  2418. InitializeFlowControl is called to ready the flow control unit for work.
  2419. This function takes care of initialization of basic resources needed by the
  2420. flow control unit.
  2421. Flow control is dependent upon the type manager module and can only be
  2422. initialized after type manager intialization is completed.
  2423. Arguments:
  2424. None.
  2425. Return Value:
  2426. TRUE if flow control was able to successfully initialize, FALSE otherwise.
  2427. --*/
  2428. {
  2429. g_GlobalQueuePool = PmCreateNamedPool ("Global Queue Pool");
  2430. g_UntrackedFlowPool = PmCreatePool();
  2431. PmDisableTracking (g_UntrackedFlowPool);
  2432. g_CurrentQueuePool = PmCreateNamedPoolEx ("Current Queue Pool", 32768);
  2433. return TRUE;
  2434. }
  2435. VOID
  2436. pAddTypeToEnumerationEnvironment (
  2437. IN PMHANDLE Pool,
  2438. IN PGROWLIST *TypeData,
  2439. IN MIG_OBJECTTYPEID TypeId
  2440. )
  2441. {
  2442. TYPEENUMINFO data;
  2443. ZeroMemory (&data, sizeof (TYPEENUMINFO));
  2444. data.ObjectTypeId = TypeId | g_IsmModulePlatformContext;
  2445. data.TypeName = PmDuplicateString (Pool, GetObjectTypeName (TypeId));
  2446. GlAppend (*TypeData, (PBYTE) &data, sizeof (TYPEENUMINFO));
  2447. }
  2448. VOID
  2449. AddTypeToGlobalEnumerationEnvironment (
  2450. IN MIG_OBJECTTYPEID TypeId
  2451. )
  2452. {
  2453. pAddTypeToEnumerationEnvironment (g_GlobalQueuePool, &g_GlobalTypeData, TypeId);
  2454. }
  2455. BOOL
  2456. PrepareEnumerationEnvironment (
  2457. BOOL GlobalEnv
  2458. )
  2459. {
  2460. MIG_OBJECTTYPEID typeId;
  2461. PGROWLIST *typeData;
  2462. PMHANDLE pool;
  2463. MIG_OBJECTTYPEIDENUM objTypeIdEnum;
  2464. if (GlobalEnv) {
  2465. typeData = &g_GlobalTypeData;
  2466. pool = g_GlobalQueuePool;
  2467. } else {
  2468. typeData = &g_TypeData;
  2469. pool = g_CurrentQueuePool;
  2470. }
  2471. *typeData = (PGROWLIST) PmGetMemory (pool, sizeof (GROWLIST));
  2472. ZeroMemory (*typeData, sizeof (GROWLIST));
  2473. //
  2474. // Initialize type data with all known types. For global types, we expect
  2475. // this list to be empty.
  2476. //
  2477. if (IsmEnumFirstObjectTypeId (&objTypeIdEnum)) {
  2478. do {
  2479. typeId = objTypeIdEnum.ObjectTypeId;
  2480. pAddTypeToEnumerationEnvironment (pool, typeData, typeId);
  2481. } while (IsmEnumNextObjectTypeId (&objTypeIdEnum));
  2482. }
  2483. return TRUE;
  2484. }
  2485. BOOL
  2486. ClearEnumerationEnvironment (
  2487. IN BOOL GlobalData
  2488. )
  2489. {
  2490. PGROWLIST *typeData;
  2491. if (GlobalData) {
  2492. typeData = &g_GlobalTypeData;
  2493. } else {
  2494. typeData = &g_TypeData;
  2495. }
  2496. if (*typeData) {
  2497. //
  2498. // Clean up the grow lists, but forget about the rest because
  2499. // it all was allocated from the queue pool
  2500. //
  2501. GlFree (*typeData);
  2502. *typeData = NULL;
  2503. }
  2504. g_PreEnumerationFunctionList = NULL;
  2505. g_PostEnumerationFunctionList = NULL;
  2506. if (GlobalData) {
  2507. PmEmptyPool (g_GlobalQueuePool);
  2508. } else {
  2509. PmEmptyPool (g_CurrentQueuePool);
  2510. }
  2511. return TRUE;
  2512. }
  2513. VOID
  2514. TerminateFlowControl (
  2515. VOID
  2516. )
  2517. /*++
  2518. Routine Description:
  2519. TerminateFlowControl should be called when flow control services are no
  2520. longer needed. This function ensures that flow control resources are freed.
  2521. Arguments:
  2522. None.
  2523. Return Value:
  2524. None.
  2525. --*/
  2526. {
  2527. GbFree (&g_EnumerationList);
  2528. PmEmptyPool (g_CurrentQueuePool);
  2529. PmDestroyPool (g_CurrentQueuePool);
  2530. g_CurrentQueuePool = NULL;
  2531. PmEmptyPool (g_GlobalQueuePool);
  2532. PmDestroyPool (g_GlobalQueuePool);
  2533. g_GlobalQueuePool = NULL;
  2534. PmEmptyPool (g_UntrackedFlowPool);
  2535. PmDestroyPool (g_UntrackedFlowPool);
  2536. g_UntrackedFlowPool = NULL;
  2537. GlFree (&g_AcquireList);
  2538. GlFree (&g_EnumList);
  2539. GlFree (&g_EnumAddList);
  2540. }