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.

1680 lines
37 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. attrib.c
  5. Abstract:
  6. Implements the attribute interface for the ISM. Attributes are caller-defined
  7. flags that are associated with objects, for purposes of understanding and
  8. organizing state.
  9. Author:
  10. Jim Schmidt (jimschm) 01-Feb-2000
  11. Revision History:
  12. <alias> <date> <comments>
  13. --*/
  14. //
  15. // Includes
  16. //
  17. #include "pch.h"
  18. #include "ism.h"
  19. #include "ismp.h"
  20. #define DBG_ATTRIB "Attrib"
  21. //
  22. // Strings
  23. //
  24. #define S_PERSISTENT_ATTRIBUTE TEXT("$PERSISTENT")
  25. #define S_APPLY_ATTRIBUTE TEXT("$APPLY")
  26. #define S_ABANDONED_ATTRIBUTE TEXT("$ABANDONED")
  27. #define S_NONCRITICAL_ATTRIBUTE TEXT("$NONCRITICAL")
  28. //
  29. // Constants
  30. //
  31. // None
  32. //
  33. // Macros
  34. //
  35. // None
  36. //
  37. // Types
  38. //
  39. typedef struct {
  40. PUINT LinkageList;
  41. UINT Count;
  42. UINT Index;
  43. } OBJECTATTRIBUTE_HANDLE, *POBJECTATTRIBUTE_HANDLE;
  44. typedef struct {
  45. PUINT LinkageList;
  46. UINT Count;
  47. UINT Index;
  48. PCTSTR ObjectFromMemdb;
  49. } OBJECTWITHATTRIBUTE_HANDLE, *POBJECTWITHATTRIBUTE_HANDLE;
  50. //
  51. // Globals
  52. //
  53. MIG_ATTRIBUTEID g_PersistentAttributeId = 0;
  54. MIG_ATTRIBUTEID g_ApplyAttributeId = 0;
  55. MIG_ATTRIBUTEID g_AbandonedAttributeId = 0;
  56. MIG_ATTRIBUTEID g_NonCriticalAttributeId = 0;
  57. //
  58. // Macro expansion list
  59. //
  60. // None
  61. //
  62. // Private function prototypes
  63. //
  64. // None
  65. //
  66. // Macro expansion definition
  67. //
  68. // None
  69. //
  70. // Code
  71. //
  72. PCTSTR
  73. pGetAttributeNameForDebugMsg (
  74. IN MIG_ATTRIBUTEID AttributeId
  75. )
  76. {
  77. static TCHAR name[256];
  78. if (!IsmGetAttributeName (AttributeId, name, ARRAYSIZE(name), NULL, NULL, NULL)) {
  79. StringCopy (name, TEXT("<invalid attribute>"));
  80. }
  81. return name;
  82. }
  83. PCTSTR
  84. pAttributePathFromId (
  85. IN MIG_ATTRIBUTEID AttributeId
  86. )
  87. {
  88. return MemDbGetKeyFromHandle ((UINT) AttributeId, 0);
  89. }
  90. PCTSTR
  91. pAttributePathFromName (
  92. IN PCTSTR AttributeName
  93. )
  94. {
  95. return JoinPaths (TEXT("Attrib"), AttributeName);
  96. }
  97. MIG_ATTRIBUTEID
  98. IsmRegisterAttribute (
  99. IN PCTSTR AttributeName,
  100. IN BOOL Private
  101. )
  102. /*++
  103. Routine Description:
  104. IsmRegisterAttribute creates a public or private attribute and returns the
  105. ID to the caller. If the attribute already exists, then the existing ID is
  106. returned to the caller.
  107. Arguments:
  108. AttribName - Specifies the attribute name to register.
  109. Private - Specifies TRUE if the attribute is owned by the calling module
  110. only, or FALSE if it is shared by all modules. If TRUE is
  111. specified, the caller must be in an ISM callback function.
  112. Return Value:
  113. The ID of the attribute, or 0 if the registration failed.
  114. --*/
  115. {
  116. PCTSTR attribPath;
  117. PCTSTR decoratedName;
  118. UINT offset;
  119. if (!g_CurrentGroup && Private) {
  120. DEBUGMSG ((DBG_ERROR, "IsmRegisterAttribute called for private attribute outside of ISM-managed context"));
  121. return 0;
  122. }
  123. if (!IsValidCNameWithDots (AttributeName)) {
  124. DEBUGMSG ((DBG_ERROR, "attribute name \"%s\" is illegal", AttributeName));
  125. return 0;
  126. }
  127. #ifdef DEBUG
  128. if (Private && !IsValidCName (g_CurrentGroup)) {
  129. DEBUGMSG ((DBG_ERROR, "group name \"%s\" is illegal", g_CurrentGroup));
  130. return 0;
  131. }
  132. #endif
  133. if (Private) {
  134. decoratedName = JoinTextEx (NULL, g_CurrentGroup, AttributeName, TEXT(":"), 0, NULL);
  135. } else {
  136. decoratedName = JoinTextEx (NULL, S_COMMON, AttributeName, TEXT(":"), 0, NULL);
  137. }
  138. attribPath = pAttributePathFromName (decoratedName);
  139. FreeText (decoratedName);
  140. if (!MarkGroupIds (attribPath)) {
  141. DEBUGMSG ((
  142. DBG_ERROR,
  143. "%s conflicts with previously registered attribute",
  144. attribPath
  145. ));
  146. FreePathString (attribPath);
  147. return 0;
  148. }
  149. offset = MemDbSetKey (attribPath);
  150. FreePathString (attribPath);
  151. if (!offset) {
  152. EngineError ();
  153. return 0;
  154. }
  155. return (MIG_ATTRIBUTEID) offset;
  156. }
  157. BOOL
  158. RegisterInternalAttributes (
  159. VOID
  160. )
  161. {
  162. PCTSTR attribPath;
  163. PCTSTR decoratedName;
  164. UINT offset;
  165. decoratedName = JoinTextEx (NULL, S_COMMON, S_PERSISTENT_ATTRIBUTE, TEXT(":"), 0, NULL);
  166. attribPath = pAttributePathFromName (decoratedName);
  167. FreeText (decoratedName);
  168. if (!MarkGroupIds (attribPath)) {
  169. DEBUGMSG ((
  170. DBG_ERROR,
  171. "%s conflicts with previously registered attribute",
  172. attribPath
  173. ));
  174. FreePathString (attribPath);
  175. return 0;
  176. }
  177. offset = MemDbSetKey (attribPath);
  178. FreePathString (attribPath);
  179. if (!offset) {
  180. EngineError ();
  181. return FALSE;
  182. }
  183. g_PersistentAttributeId = (MIG_ATTRIBUTEID) offset;
  184. decoratedName = JoinTextEx (NULL, S_COMMON, S_APPLY_ATTRIBUTE, TEXT(":"), 0, NULL);
  185. attribPath = pAttributePathFromName (decoratedName);
  186. FreeText (decoratedName);
  187. if (!MarkGroupIds (attribPath)) {
  188. DEBUGMSG ((
  189. DBG_ERROR,
  190. "%s conflicts with previously registered attribute",
  191. attribPath
  192. ));
  193. FreePathString (attribPath);
  194. return 0;
  195. }
  196. offset = MemDbSetKey (attribPath);
  197. FreePathString (attribPath);
  198. if (!offset) {
  199. EngineError ();
  200. return FALSE;
  201. }
  202. g_ApplyAttributeId = (MIG_ATTRIBUTEID) offset;
  203. decoratedName = JoinTextEx (NULL, S_COMMON, S_ABANDONED_ATTRIBUTE, TEXT(":"), 0, NULL);
  204. attribPath = pAttributePathFromName (decoratedName);
  205. FreeText (decoratedName);
  206. if (!MarkGroupIds (attribPath)) {
  207. DEBUGMSG ((
  208. DBG_ERROR,
  209. "%s conflicts with previously registered attribute",
  210. attribPath
  211. ));
  212. FreePathString (attribPath);
  213. return 0;
  214. }
  215. offset = MemDbSetKey (attribPath);
  216. FreePathString (attribPath);
  217. if (!offset) {
  218. EngineError ();
  219. return FALSE;
  220. }
  221. g_AbandonedAttributeId = (MIG_ATTRIBUTEID) offset;
  222. decoratedName = JoinTextEx (NULL, S_COMMON, S_NONCRITICAL_ATTRIBUTE, TEXT(":"), 0, NULL);
  223. attribPath = pAttributePathFromName (decoratedName);
  224. FreeText (decoratedName);
  225. if (!MarkGroupIds (attribPath)) {
  226. DEBUGMSG ((
  227. DBG_ERROR,
  228. "%s conflicts with previously registered attribute",
  229. attribPath
  230. ));
  231. FreePathString (attribPath);
  232. return 0;
  233. }
  234. offset = MemDbSetKey (attribPath);
  235. FreePathString (attribPath);
  236. if (!offset) {
  237. EngineError ();
  238. return FALSE;
  239. }
  240. g_NonCriticalAttributeId = (MIG_ATTRIBUTEID) offset;
  241. return TRUE;
  242. }
  243. BOOL
  244. IsmGetAttributeName (
  245. IN MIG_ATTRIBUTEID AttributeId,
  246. OUT PTSTR AttributeName, OPTIONAL
  247. IN UINT AttributeNameBufChars,
  248. OUT PBOOL Private, OPTIONAL
  249. OUT PBOOL BelongsToMe, OPTIONAL
  250. OUT PUINT ObjectReferences OPTIONAL
  251. )
  252. /*++
  253. Routine Description:
  254. IsmGetAttributeName obtains the attribute text name from a numeric ID. It
  255. also identifies private and owned attributes.
  256. Arguments:
  257. AttributeId - Specifies the attribute ID to look up.
  258. AttributeName - Receives the attribute name. The name is filled for
  259. all valid AttributeId values, even when the return
  260. value is FALSE.
  261. AttributeNameBufChars - Specifies the number of TCHARs that AttributeName
  262. can hold, including the nul terminator.
  263. Private - Receives TRUE if the attribute is private, or FALSE
  264. if it is public.
  265. BelongsToMe - Receives TRUE if the attribute is private and
  266. belongs to the caller, FALSE otherwise.
  267. ObjectReferences - Receives the number of objects that reference the
  268. attribute
  269. Return Value:
  270. TRUE if the attribute is public, or if the attribute is private and belongs to
  271. the caller.
  272. FALSE if the attribute is private and belongs to someone else. AttributeName,
  273. Private and BelongsToMe are valid in this case.
  274. FALSE if AttributeId is not valid. Attributename, Private and BelongsToMe are
  275. not modified in this case. Do not use this function to test if AttributeId
  276. is valid or not.
  277. --*/
  278. {
  279. PCTSTR attribPath = NULL;
  280. PCTSTR start;
  281. PTSTR p, q;
  282. BOOL privateAttribute = FALSE;
  283. BOOL groupMatch = FALSE;
  284. BOOL result = FALSE;
  285. UINT references;
  286. PUINT linkageList;
  287. __try {
  288. //
  289. // Get the attribute path from memdb, then parse it for group and name
  290. //
  291. attribPath = pAttributePathFromId (AttributeId);
  292. if (!attribPath) {
  293. __leave;
  294. }
  295. p = _tcschr (attribPath, TEXT('\\'));
  296. if (!p) {
  297. __leave;
  298. }
  299. start = _tcsinc (p);
  300. p = _tcschr (start, TEXT(':'));
  301. if (!p) {
  302. __leave;
  303. }
  304. q = _tcsinc (p);
  305. *p = 0;
  306. if (StringIMatch (start, S_COMMON)) {
  307. //
  308. // This attribute is a global attribute.
  309. //
  310. privateAttribute = FALSE;
  311. groupMatch = TRUE;
  312. } else if (g_CurrentGroup) {
  313. //
  314. // This attribute is private. Check if it is ours.
  315. //
  316. privateAttribute = TRUE;
  317. if (StringIMatch (start, g_CurrentGroup)) {
  318. groupMatch = TRUE;
  319. } else {
  320. groupMatch = FALSE;
  321. }
  322. } else {
  323. //
  324. // This is a private attribute, but the caller is not
  325. // a module that can own attributes.
  326. //
  327. DEBUGMSG ((DBG_WARNING, "IsmGetAttributeName: Caller cannot own private attributes"));
  328. }
  329. //
  330. // Copy the name to the buffer, update outbound BOOLs, set result
  331. //
  332. if (AttributeName && AttributeNameBufChars >= sizeof (TCHAR)) {
  333. StringCopyByteCount (AttributeName, q, AttributeNameBufChars * sizeof (TCHAR));
  334. }
  335. if (Private) {
  336. *Private = privateAttribute;
  337. }
  338. if (BelongsToMe) {
  339. *BelongsToMe = privateAttribute && groupMatch;
  340. }
  341. if (ObjectReferences) {
  342. linkageList = MemDbGetDoubleLinkageArrayByKeyHandle (
  343. AttributeId,
  344. ATTRIBUTE_INDEX,
  345. &references
  346. );
  347. references /= SIZEOF(KEYHANDLE);
  348. if (linkageList) {
  349. MemDbReleaseMemory (linkageList);
  350. INVALID_POINTER (linkageList);
  351. } else {
  352. references = 0;
  353. }
  354. *ObjectReferences = references;
  355. }
  356. if (groupMatch) {
  357. result = TRUE;
  358. }
  359. }
  360. __finally {
  361. if (attribPath) { //lint !e774
  362. MemDbReleaseMemory (attribPath);
  363. attribPath = NULL;
  364. }
  365. }
  366. return result;
  367. }
  368. MIG_ATTRIBUTEID
  369. IsmGetAttributeGroup (
  370. IN MIG_ATTRIBUTEID AttributeId
  371. )
  372. {
  373. return (MIG_ATTRIBUTEID) GetGroupOfId ((KEYHANDLE) AttributeId);
  374. }
  375. BOOL
  376. pSetAttributeOnObjectId (
  377. IN MIG_OBJECTID ObjectId,
  378. IN MIG_ATTRIBUTEID AttributeId,
  379. IN BOOL QueryOnly
  380. )
  381. {
  382. BOOL result = FALSE;
  383. __try {
  384. //
  385. // Test if object is locked, then if not locked, add linkage
  386. //
  387. if (TestLock (ObjectId, (KEYHANDLE) AttributeId)) {
  388. SetLastError (ERROR_LOCKED);
  389. DEBUGMSG ((
  390. DBG_WARNING,
  391. "Can't set attribute %s on %s because of lock",
  392. pGetAttributeNameForDebugMsg (AttributeId),
  393. GetObjectNameForDebugMsg (ObjectId)
  394. ));
  395. __leave;
  396. }
  397. if (QueryOnly) {
  398. result = TRUE;
  399. __leave;
  400. }
  401. result = MemDbAddDoubleLinkageByKeyHandle (
  402. ObjectId,
  403. AttributeId,
  404. ATTRIBUTE_INDEX
  405. );
  406. if (!result) {
  407. EngineError ();
  408. }
  409. }
  410. __finally {
  411. }
  412. return result;
  413. }
  414. BOOL
  415. pSetAttributeGroup (
  416. IN KEYHANDLE AttributeId,
  417. IN BOOL FirstPass,
  418. IN ULONG_PTR Arg
  419. )
  420. {
  421. MYASSERT (IsItemId (AttributeId));
  422. return pSetAttributeOnObjectId (
  423. (MIG_OBJECTID) Arg,
  424. (MIG_ATTRIBUTEID) AttributeId,
  425. FirstPass
  426. );
  427. }
  428. BOOL
  429. IsmSetAttributeOnObjectId (
  430. IN MIG_OBJECTID ObjectId,
  431. IN MIG_ATTRIBUTEID AttributeId
  432. )
  433. {
  434. RECURSERETURN rc;
  435. //
  436. // If AttributeId is a group, set all attribs in the group
  437. //
  438. rc = RecurseForGroupItems (
  439. AttributeId,
  440. pSetAttributeGroup,
  441. (ULONG_PTR) ObjectId,
  442. FALSE,
  443. FALSE
  444. );
  445. if (rc == RECURSE_FAIL) {
  446. return FALSE;
  447. } else if (rc == RECURSE_SUCCESS) {
  448. return TRUE;
  449. }
  450. MYASSERT (rc == RECURSE_NOT_NEEDED);
  451. return pSetAttributeOnObjectId (ObjectId, AttributeId, FALSE);
  452. }
  453. BOOL
  454. IsmSetAttributeOnObject (
  455. IN MIG_OBJECTTYPEID ObjectTypeId,
  456. IN ENCODEDSTRHANDLE EncodedObjectName,
  457. IN MIG_ATTRIBUTEID AttributeId
  458. )
  459. {
  460. MIG_OBJECTID objectId;
  461. BOOL result = FALSE;
  462. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  463. objectId = GetObjectIdForModification (ObjectTypeId, EncodedObjectName);
  464. if (objectId) {
  465. result = IsmSetAttributeOnObjectId (objectId, AttributeId);
  466. }
  467. return result;
  468. }
  469. BOOL
  470. IsmMakePersistentObjectId (
  471. IN MIG_OBJECTID ObjectId
  472. )
  473. {
  474. MIG_OBJECTTYPEID objectTypeId;
  475. BOOL result;
  476. if (IsmIsPersistentObjectId (ObjectId)) {
  477. return TRUE;
  478. }
  479. result = pSetAttributeOnObjectId (ObjectId, g_PersistentAttributeId, FALSE);
  480. if (result) {
  481. g_TotalObjects.PersistentObjects ++;
  482. result = MemDbGetValueByHandle (ObjectId, &objectTypeId);
  483. if (result) {
  484. if ((objectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE) {
  485. g_SourceObjects.PersistentObjects ++;
  486. } else {
  487. g_DestinationObjects.PersistentObjects ++;
  488. }
  489. IncrementPersistentObjectCount (objectTypeId);
  490. }
  491. result = TRUE;
  492. }
  493. return result;
  494. }
  495. BOOL
  496. IsmMakePersistentObject (
  497. IN MIG_OBJECTTYPEID ObjectTypeId,
  498. IN ENCODEDSTRHANDLE EncodedObjectName
  499. )
  500. {
  501. MIG_OBJECTID objectId;
  502. BOOL result = FALSE;
  503. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  504. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, FALSE);
  505. if (objectId) {
  506. result = IsmMakePersistentObjectId (objectId);
  507. }
  508. return result;
  509. }
  510. BOOL
  511. IsmMakeApplyObjectId (
  512. IN MIG_OBJECTID ObjectId
  513. )
  514. {
  515. MIG_OBJECTTYPEID objectTypeId;
  516. BOOL result;
  517. if (IsmIsApplyObjectId (ObjectId)) {
  518. return TRUE;
  519. }
  520. if (!IsmMakePersistentObjectId (ObjectId)) {
  521. return FALSE;
  522. }
  523. result = pSetAttributeOnObjectId (ObjectId, g_ApplyAttributeId, FALSE);
  524. if (result) {
  525. g_TotalObjects.ApplyObjects ++;
  526. result = MemDbGetValueByHandle (ObjectId, &objectTypeId);
  527. if (result) {
  528. if ((objectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE) {
  529. g_SourceObjects.ApplyObjects ++;
  530. } else {
  531. g_DestinationObjects.ApplyObjects ++;
  532. }
  533. IncrementApplyObjectCount (objectTypeId);
  534. }
  535. result = TRUE;
  536. }
  537. return result;
  538. }
  539. BOOL
  540. IsmMakeApplyObject (
  541. IN MIG_OBJECTTYPEID ObjectTypeId,
  542. IN ENCODEDSTRHANDLE EncodedObjectName
  543. )
  544. {
  545. MIG_OBJECTID objectId;
  546. BOOL result = FALSE;
  547. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  548. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, FALSE);
  549. if (objectId) {
  550. result = IsmMakeApplyObjectId (objectId);
  551. }
  552. return result;
  553. }
  554. BOOL
  555. IsmAbandonObjectIdOnCollision (
  556. IN MIG_OBJECTID ObjectId
  557. )
  558. {
  559. BOOL result;
  560. if (IsmIsObjectIdAbandonedOnCollision (ObjectId)) {
  561. return TRUE;
  562. }
  563. result = pSetAttributeOnObjectId (ObjectId, g_AbandonedAttributeId, FALSE);
  564. return result;
  565. }
  566. BOOL
  567. IsmAbandonObjectOnCollision (
  568. IN MIG_OBJECTTYPEID ObjectTypeId,
  569. IN ENCODEDSTRHANDLE EncodedObjectName
  570. )
  571. {
  572. MIG_OBJECTID objectId;
  573. BOOL result = FALSE;
  574. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  575. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, FALSE);
  576. if (objectId) {
  577. result = IsmAbandonObjectIdOnCollision (objectId);
  578. }
  579. return result;
  580. }
  581. BOOL
  582. IsmMakeNonCriticalObjectId (
  583. IN MIG_OBJECTID ObjectId
  584. )
  585. {
  586. if (IsmIsNonCriticalObjectId (ObjectId)) {
  587. return TRUE;
  588. }
  589. return pSetAttributeOnObjectId (ObjectId, g_NonCriticalAttributeId, FALSE);
  590. }
  591. BOOL
  592. IsmMakeNonCriticalObject (
  593. IN MIG_OBJECTTYPEID ObjectTypeId,
  594. IN ENCODEDSTRHANDLE EncodedObjectName
  595. )
  596. {
  597. MIG_OBJECTID objectId;
  598. BOOL result = FALSE;
  599. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  600. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, FALSE);
  601. if (objectId) {
  602. result = IsmMakeNonCriticalObjectId (objectId);
  603. }
  604. return result;
  605. }
  606. VOID
  607. IsmLockAttribute (
  608. IN MIG_OBJECTID ObjectId,
  609. IN MIG_ATTRIBUTEID AttributeId
  610. )
  611. {
  612. LockHandle (ObjectId, (KEYHANDLE) AttributeId);
  613. }
  614. BOOL
  615. pClearAttributeOnObjectId (
  616. IN MIG_OBJECTID ObjectId,
  617. IN MIG_ATTRIBUTEID AttributeId,
  618. IN BOOL QueryOnly
  619. )
  620. {
  621. PCTSTR groupKey = NULL;
  622. PCTSTR enumKey = NULL;
  623. BOOL result = FALSE;
  624. __try {
  625. if (TestLock (ObjectId, (KEYHANDLE) AttributeId)) {
  626. SetLastError (ERROR_LOCKED);
  627. DEBUGMSG ((
  628. DBG_ERROR,
  629. "Can't clear attribute %s on %s because of lock",
  630. pGetAttributeNameForDebugMsg (AttributeId),
  631. GetObjectNameForDebugMsg (ObjectId)
  632. ));
  633. __leave;
  634. }
  635. if (QueryOnly) {
  636. result = TRUE;
  637. __leave;
  638. }
  639. result = MemDbDeleteDoubleLinkageByKeyHandle (
  640. ObjectId,
  641. AttributeId,
  642. ATTRIBUTE_INDEX
  643. );
  644. }
  645. __finally {
  646. if (groupKey) {
  647. MemDbReleaseMemory (groupKey);
  648. INVALID_POINTER (groupKey);
  649. }
  650. if (enumKey) {
  651. FreeText (enumKey);
  652. INVALID_POINTER (enumKey);
  653. }
  654. }
  655. return result;
  656. }
  657. BOOL
  658. pClearAttributeGroup (
  659. IN KEYHANDLE AttributeId,
  660. IN BOOL FirstPass,
  661. IN ULONG_PTR Arg
  662. )
  663. {
  664. return pClearAttributeOnObjectId (
  665. (MIG_OBJECTID) Arg,
  666. (MIG_ATTRIBUTEID) AttributeId,
  667. FirstPass
  668. );
  669. }
  670. BOOL
  671. IsmClearAttributeOnObjectId (
  672. IN MIG_OBJECTID ObjectId,
  673. IN MIG_ATTRIBUTEID AttributeId
  674. )
  675. {
  676. RECURSERETURN rc;
  677. //
  678. // If AttributeId is a group, set all attribs in the group
  679. //
  680. rc = RecurseForGroupItems (
  681. AttributeId,
  682. pClearAttributeGroup,
  683. (ULONG_PTR) ObjectId,
  684. FALSE,
  685. FALSE
  686. );
  687. if (rc == RECURSE_FAIL) {
  688. return FALSE;
  689. } else if (rc == RECURSE_SUCCESS) {
  690. return TRUE;
  691. }
  692. MYASSERT (rc == RECURSE_NOT_NEEDED);
  693. return pClearAttributeOnObjectId (ObjectId, AttributeId, FALSE);
  694. }
  695. BOOL
  696. IsmClearAttributeOnObject (
  697. IN MIG_OBJECTTYPEID ObjectTypeId,
  698. IN ENCODEDSTRHANDLE EncodedObjectName,
  699. IN MIG_ATTRIBUTEID AttributeId
  700. )
  701. {
  702. MIG_OBJECTID objectId;
  703. BOOL result = FALSE;
  704. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  705. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  706. if (objectId) {
  707. result = IsmClearAttributeOnObjectId (objectId, AttributeId);
  708. }
  709. return result;
  710. }
  711. BOOL
  712. IsmClearPersistenceOnObjectId (
  713. IN MIG_OBJECTID ObjectId
  714. )
  715. {
  716. MIG_OBJECTTYPEID objectTypeId;
  717. BOOL result;
  718. if (!IsmIsPersistentObjectId (ObjectId)) {
  719. return TRUE;
  720. }
  721. if (!IsmClearApplyOnObjectId (ObjectId)) {
  722. return FALSE;
  723. }
  724. result = pClearAttributeOnObjectId (ObjectId, g_PersistentAttributeId, FALSE);
  725. if (result) {
  726. g_TotalObjects.PersistentObjects --;
  727. result = MemDbGetValueByHandle (ObjectId, &objectTypeId);
  728. if (result) {
  729. if ((objectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE) {
  730. g_SourceObjects.PersistentObjects --;
  731. } else {
  732. g_DestinationObjects.PersistentObjects --;
  733. }
  734. DecrementPersistentObjectCount (objectTypeId);
  735. }
  736. result = TRUE;
  737. }
  738. return result;
  739. }
  740. BOOL
  741. IsmClearPersistenceOnObject (
  742. IN MIG_OBJECTTYPEID ObjectTypeId,
  743. IN ENCODEDSTRHANDLE EncodedObjectName
  744. )
  745. {
  746. MIG_OBJECTID objectId;
  747. BOOL result = FALSE;
  748. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  749. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  750. if (objectId) {
  751. result = IsmClearPersistenceOnObjectId (objectId);
  752. }
  753. return result;
  754. }
  755. BOOL
  756. IsmClearApplyOnObjectId (
  757. IN MIG_OBJECTID ObjectId
  758. )
  759. {
  760. MIG_OBJECTTYPEID objectTypeId;
  761. BOOL result;
  762. if (!IsmIsApplyObjectId (ObjectId)) {
  763. return TRUE;
  764. }
  765. result = pClearAttributeOnObjectId (ObjectId, g_ApplyAttributeId, FALSE);
  766. if (result) {
  767. g_TotalObjects.ApplyObjects --;
  768. result = MemDbGetValueByHandle (ObjectId, &objectTypeId);
  769. if (result) {
  770. if ((objectTypeId & PLATFORM_MASK) == PLATFORM_SOURCE) {
  771. g_SourceObjects.ApplyObjects --;
  772. } else {
  773. g_DestinationObjects.ApplyObjects --;
  774. }
  775. DecrementApplyObjectCount (objectTypeId);
  776. }
  777. result = TRUE;
  778. }
  779. return result;
  780. }
  781. BOOL
  782. IsmClearApplyOnObject (
  783. IN MIG_OBJECTTYPEID ObjectTypeId,
  784. IN ENCODEDSTRHANDLE EncodedObjectName
  785. )
  786. {
  787. MIG_OBJECTID objectId;
  788. BOOL result = FALSE;
  789. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  790. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  791. if (objectId) {
  792. result = IsmClearApplyOnObjectId (objectId);
  793. }
  794. return result;
  795. }
  796. BOOL
  797. IsmClearAbandonObjectIdOnCollision (
  798. IN MIG_OBJECTID ObjectId
  799. )
  800. {
  801. BOOL result;
  802. if (!IsmIsObjectIdAbandonedOnCollision (ObjectId)) {
  803. return TRUE;
  804. }
  805. result = pClearAttributeOnObjectId (ObjectId, g_AbandonedAttributeId, FALSE);
  806. return result;
  807. }
  808. BOOL
  809. IsmClearAbandonObjectOnCollision (
  810. IN MIG_OBJECTTYPEID ObjectTypeId,
  811. IN ENCODEDSTRHANDLE EncodedObjectName
  812. )
  813. {
  814. MIG_OBJECTID objectId;
  815. BOOL result = FALSE;
  816. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  817. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  818. if (objectId) {
  819. result = IsmClearAbandonObjectIdOnCollision (objectId);
  820. }
  821. return result;
  822. }
  823. BOOL
  824. IsmClearNonCriticalFlagOnObjectId (
  825. IN MIG_OBJECTID ObjectId
  826. )
  827. {
  828. if (!IsmIsNonCriticalObjectId (ObjectId)) {
  829. return TRUE;
  830. }
  831. return pClearAttributeOnObjectId (ObjectId, g_NonCriticalAttributeId, FALSE);
  832. }
  833. BOOL
  834. IsmClearNonCriticalFlagOnObject (
  835. IN MIG_OBJECTTYPEID ObjectTypeId,
  836. IN ENCODEDSTRHANDLE EncodedObjectName
  837. )
  838. {
  839. MIG_OBJECTID objectId;
  840. BOOL result = FALSE;
  841. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  842. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  843. if (objectId) {
  844. result = IsmClearNonCriticalFlagOnObjectId (objectId);
  845. }
  846. return result;
  847. }
  848. BOOL
  849. pIsAttributeSetOnObjectId (
  850. IN MIG_OBJECTID ObjectId,
  851. IN MIG_ATTRIBUTEID AttributeId
  852. )
  853. {
  854. return MemDbTestDoubleLinkageByKeyHandle (
  855. ObjectId,
  856. AttributeId,
  857. ATTRIBUTE_INDEX
  858. );
  859. }
  860. BOOL
  861. pQueryAttributeGroup (
  862. IN KEYHANDLE AttributeId,
  863. IN BOOL FirstPass,
  864. IN ULONG_PTR Arg
  865. )
  866. {
  867. return pIsAttributeSetOnObjectId (
  868. (MIG_OBJECTID) Arg,
  869. (MIG_ATTRIBUTEID) AttributeId
  870. );
  871. }
  872. BOOL
  873. IsmIsAttributeSetOnObjectId (
  874. IN MIG_OBJECTID ObjectId,
  875. IN MIG_ATTRIBUTEID AttributeId
  876. )
  877. {
  878. RECURSERETURN rc;
  879. //
  880. // If AttributeId is a group, query all properties in the group
  881. //
  882. rc = RecurseForGroupItems (
  883. AttributeId,
  884. pQueryAttributeGroup,
  885. (ULONG_PTR) ObjectId,
  886. TRUE,
  887. TRUE
  888. );
  889. if (rc == RECURSE_FAIL) {
  890. return FALSE;
  891. } else if (rc == RECURSE_SUCCESS) {
  892. return TRUE;
  893. }
  894. MYASSERT (rc == RECURSE_NOT_NEEDED);
  895. return pIsAttributeSetOnObjectId (ObjectId, AttributeId);
  896. }
  897. BOOL
  898. IsmIsAttributeSetOnObject (
  899. IN MIG_OBJECTTYPEID ObjectTypeId,
  900. IN ENCODEDSTRHANDLE EncodedObjectName,
  901. IN MIG_ATTRIBUTEID AttributeId
  902. )
  903. {
  904. MIG_OBJECTID objectId;
  905. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  906. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  907. if (objectId) {
  908. return IsmIsAttributeSetOnObjectId (objectId, AttributeId);
  909. }
  910. return FALSE;
  911. }
  912. BOOL
  913. IsmIsPersistentObjectId (
  914. IN MIG_OBJECTID ObjectId
  915. )
  916. {
  917. return pIsAttributeSetOnObjectId (ObjectId, g_PersistentAttributeId);
  918. }
  919. BOOL
  920. IsmIsPersistentObject (
  921. IN MIG_OBJECTTYPEID ObjectTypeId,
  922. IN ENCODEDSTRHANDLE EncodedObjectName
  923. )
  924. {
  925. MIG_OBJECTID objectId;
  926. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  927. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  928. if (objectId) {
  929. return IsmIsPersistentObjectId (objectId);
  930. }
  931. return FALSE;
  932. }
  933. BOOL
  934. IsmIsApplyObjectId (
  935. IN MIG_OBJECTID ObjectId
  936. )
  937. {
  938. return pIsAttributeSetOnObjectId (ObjectId, g_ApplyAttributeId);
  939. }
  940. BOOL
  941. IsmIsApplyObject (
  942. IN MIG_OBJECTTYPEID ObjectTypeId,
  943. IN ENCODEDSTRHANDLE EncodedObjectName
  944. )
  945. {
  946. MIG_OBJECTID objectId;
  947. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  948. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  949. if (objectId) {
  950. return IsmIsApplyObjectId (objectId);
  951. }
  952. return FALSE;
  953. }
  954. BOOL
  955. IsmIsObjectIdAbandonedOnCollision (
  956. IN MIG_OBJECTID ObjectId
  957. )
  958. {
  959. return pIsAttributeSetOnObjectId (ObjectId, g_AbandonedAttributeId);
  960. }
  961. BOOL
  962. IsmIsObjectAbandonedOnCollision (
  963. IN MIG_OBJECTTYPEID ObjectTypeId,
  964. IN ENCODEDSTRHANDLE EncodedObjectName
  965. )
  966. {
  967. MIG_OBJECTID objectId;
  968. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  969. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  970. if (objectId) {
  971. return IsmIsObjectIdAbandonedOnCollision (objectId);
  972. }
  973. return FALSE;
  974. }
  975. BOOL
  976. IsmIsNonCriticalObjectId (
  977. IN MIG_OBJECTID ObjectId
  978. )
  979. {
  980. return pIsAttributeSetOnObjectId (ObjectId, g_NonCriticalAttributeId);
  981. }
  982. BOOL
  983. IsmIsNonCriticalObject (
  984. IN MIG_OBJECTTYPEID ObjectTypeId,
  985. IN ENCODEDSTRHANDLE EncodedObjectName
  986. )
  987. {
  988. MIG_OBJECTID objectId;
  989. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  990. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  991. if (objectId) {
  992. return IsmIsNonCriticalObjectId (objectId);
  993. }
  994. return FALSE;
  995. }
  996. BOOL
  997. IsmEnumFirstObjectAttributeById (
  998. OUT PMIG_OBJECTATTRIBUTE_ENUM EnumPtr,
  999. IN MIG_OBJECTID ObjectId
  1000. )
  1001. {
  1002. POBJECTATTRIBUTE_HANDLE handle;
  1003. BOOL result = TRUE;
  1004. ZeroMemory (EnumPtr, sizeof (MIG_OBJECTATTRIBUTE_ENUM));
  1005. EnumPtr->Handle = MemAllocZeroed (sizeof (OBJECTATTRIBUTE_HANDLE));
  1006. handle = (POBJECTATTRIBUTE_HANDLE) EnumPtr->Handle;
  1007. handle->LinkageList = MemDbGetDoubleLinkageArrayByKeyHandle (
  1008. ObjectId,
  1009. ATTRIBUTE_INDEX,
  1010. &handle->Count
  1011. );
  1012. handle->Count = handle->Count / SIZEOF(KEYHANDLE);
  1013. if (!handle->LinkageList || !handle->Count) {
  1014. IsmAbortObjectAttributeEnum (EnumPtr);
  1015. result = FALSE;
  1016. } else {
  1017. result = IsmEnumNextObjectAttribute (EnumPtr);
  1018. }
  1019. return result;
  1020. }
  1021. BOOL
  1022. IsmEnumFirstObjectAttribute (
  1023. OUT PMIG_OBJECTATTRIBUTE_ENUM EnumPtr,
  1024. IN MIG_OBJECTTYPEID ObjectTypeId,
  1025. IN ENCODEDSTRHANDLE EncodedObjectName
  1026. )
  1027. {
  1028. MIG_OBJECTID objectId;
  1029. ObjectTypeId = FixEnumerationObjectTypeId (ObjectTypeId);
  1030. objectId = IsmGetObjectIdFromName (ObjectTypeId, EncodedObjectName, TRUE);
  1031. if (objectId) {
  1032. return IsmEnumFirstObjectAttributeById (EnumPtr, objectId);
  1033. }
  1034. return FALSE;
  1035. }
  1036. BOOL
  1037. IsmEnumNextObjectAttribute (
  1038. IN OUT PMIG_OBJECTATTRIBUTE_ENUM EnumPtr
  1039. )
  1040. {
  1041. POBJECTATTRIBUTE_HANDLE handle;
  1042. BOOL result = FALSE;
  1043. BOOL mine;
  1044. handle = (POBJECTATTRIBUTE_HANDLE) EnumPtr->Handle;
  1045. if (!handle) {
  1046. return FALSE;
  1047. }
  1048. do {
  1049. MYASSERT (!result);
  1050. //
  1051. // Check if we hit the end
  1052. //
  1053. if (handle->Index >= handle->Count) {
  1054. break;
  1055. }
  1056. //
  1057. // Return the next attribute
  1058. //
  1059. EnumPtr->AttributeId = (MIG_ATTRIBUTEID) handle->LinkageList[handle->Index];
  1060. handle->Index++;
  1061. result = IsmGetAttributeName (
  1062. EnumPtr->AttributeId,
  1063. NULL,
  1064. 0,
  1065. &EnumPtr->Private,
  1066. &mine,
  1067. NULL
  1068. );
  1069. //
  1070. // Continue when the attribute is not owned by the caller
  1071. //
  1072. if (result && EnumPtr->Private && !mine) {
  1073. result = FALSE;
  1074. }
  1075. //
  1076. // Continue when we are talking about reserved persistent/apply attribute
  1077. //
  1078. if (result) {
  1079. if (EnumPtr->AttributeId == g_PersistentAttributeId ||
  1080. EnumPtr->AttributeId == g_ApplyAttributeId ||
  1081. EnumPtr->AttributeId == g_AbandonedAttributeId ||
  1082. EnumPtr->AttributeId == g_NonCriticalAttributeId
  1083. ) {
  1084. result = FALSE;
  1085. }
  1086. }
  1087. } while (!result);
  1088. if (!result) {
  1089. IsmAbortObjectAttributeEnum (EnumPtr);
  1090. }
  1091. return result;
  1092. }
  1093. VOID
  1094. IsmAbortObjectAttributeEnum (
  1095. IN OUT PMIG_OBJECTATTRIBUTE_ENUM EnumPtr
  1096. )
  1097. {
  1098. POBJECTATTRIBUTE_HANDLE handle;
  1099. if (EnumPtr->Handle) {
  1100. handle = (POBJECTATTRIBUTE_HANDLE) EnumPtr->Handle;
  1101. if (handle->LinkageList) {
  1102. MemDbReleaseMemory (handle->LinkageList);
  1103. INVALID_POINTER (handle->LinkageList);
  1104. }
  1105. MemFree (g_hHeap, 0, EnumPtr->Handle);
  1106. INVALID_POINTER (EnumPtr->Handle);
  1107. }
  1108. ZeroMemory (EnumPtr, sizeof (MIG_OBJECTATTRIBUTE_ENUM));
  1109. }
  1110. BOOL
  1111. IsmEnumFirstObjectWithAttribute (
  1112. OUT PMIG_OBJECTWITHATTRIBUTE_ENUM EnumPtr,
  1113. IN MIG_ATTRIBUTEID AttributeId
  1114. )
  1115. {
  1116. POBJECTWITHATTRIBUTE_HANDLE handle;
  1117. BOOL result = FALSE;
  1118. __try {
  1119. if (!IsItemId ((KEYHANDLE) AttributeId)) {
  1120. DEBUGMSG ((DBG_ERROR, "IsmEnumFirstObjectWithAttribute: invalid attribute id"));
  1121. __leave;
  1122. }
  1123. ZeroMemory (EnumPtr, sizeof (MIG_OBJECTWITHATTRIBUTE_ENUM));
  1124. EnumPtr->Handle = MemAllocZeroed (sizeof (OBJECTWITHATTRIBUTE_HANDLE));
  1125. handle = (POBJECTWITHATTRIBUTE_HANDLE) EnumPtr->Handle;
  1126. handle->LinkageList = MemDbGetDoubleLinkageArrayByKeyHandle (
  1127. AttributeId,
  1128. ATTRIBUTE_INDEX,
  1129. &handle->Count
  1130. );
  1131. handle->Count = handle->Count / SIZEOF(KEYHANDLE);
  1132. if (!handle->LinkageList || !handle->Count) {
  1133. IsmAbortObjectWithAttributeEnum (EnumPtr);
  1134. __leave;
  1135. } else {
  1136. result = IsmEnumNextObjectWithAttribute (EnumPtr);
  1137. }
  1138. }
  1139. __finally {
  1140. }
  1141. return result;
  1142. }
  1143. BOOL
  1144. IsmEnumNextObjectWithAttribute (
  1145. IN OUT PMIG_OBJECTWITHATTRIBUTE_ENUM EnumPtr
  1146. )
  1147. {
  1148. POBJECTWITHATTRIBUTE_HANDLE handle;
  1149. PCTSTR objectPath = NULL;
  1150. BOOL result = FALSE;
  1151. PTSTR p;
  1152. __try {
  1153. handle = (POBJECTWITHATTRIBUTE_HANDLE) EnumPtr->Handle;
  1154. if (!handle) {
  1155. __leave;
  1156. }
  1157. do {
  1158. //
  1159. // Check if enum is done
  1160. //
  1161. if (handle->Index >= handle->Count) {
  1162. break;
  1163. }
  1164. //
  1165. // Get the next object id from the linkage list
  1166. //
  1167. EnumPtr->ObjectId = handle->LinkageList[handle->Index];
  1168. handle->Index++;
  1169. if (handle->ObjectFromMemdb) {
  1170. MemDbReleaseMemory (handle->ObjectFromMemdb);
  1171. INVALID_POINTER (handle->ObjectFromMemdb);
  1172. }
  1173. handle->ObjectFromMemdb = MemDbGetKeyFromHandle ((KEYHANDLE) EnumPtr->ObjectId, 0);
  1174. if (!handle->ObjectFromMemdb) {
  1175. MYASSERT (FALSE); // this error shouldn't happen -- but don't give up
  1176. continue;
  1177. }
  1178. //
  1179. // Turn the object id into a name
  1180. //
  1181. p = _tcschr (handle->ObjectFromMemdb, TEXT('\\'));
  1182. if (p) {
  1183. result = TRUE;
  1184. EnumPtr->ObjectName = _tcsinc (p);
  1185. *p = 0;
  1186. EnumPtr->ObjectTypeId = GetObjectTypeId (handle->ObjectFromMemdb);
  1187. }
  1188. } while (!result);
  1189. }
  1190. __finally {
  1191. }
  1192. if (!result) {
  1193. IsmAbortObjectWithAttributeEnum (EnumPtr);
  1194. }
  1195. return result;
  1196. }
  1197. VOID
  1198. IsmAbortObjectWithAttributeEnum (
  1199. IN PMIG_OBJECTWITHATTRIBUTE_ENUM EnumPtr
  1200. )
  1201. {
  1202. POBJECTWITHATTRIBUTE_HANDLE handle;
  1203. if (EnumPtr->Handle) {
  1204. handle = (POBJECTWITHATTRIBUTE_HANDLE) EnumPtr->Handle;
  1205. if (handle->ObjectFromMemdb) {
  1206. MemDbReleaseMemory (handle->ObjectFromMemdb);
  1207. INVALID_POINTER (handle->ObjectFromMemdb);
  1208. }
  1209. if (handle->LinkageList) {
  1210. MemDbReleaseMemory (handle->LinkageList);
  1211. INVALID_POINTER (handle->LinkageList);
  1212. }
  1213. FreeAlloc (EnumPtr->Handle);
  1214. INVALID_POINTER (EnumPtr->Handle);
  1215. }
  1216. ZeroMemory (EnumPtr, sizeof (MIG_OBJECTWITHATTRIBUTE_ENUM));
  1217. }
  1218. BOOL
  1219. IsmEnumFirstPersistentObject (
  1220. OUT PMIG_OBJECTWITHATTRIBUTE_ENUM EnumPtr
  1221. )
  1222. {
  1223. return IsmEnumFirstObjectWithAttribute (EnumPtr, g_PersistentAttributeId);
  1224. }
  1225. BOOL
  1226. IsmEnumNextPersistentObject (
  1227. IN OUT PMIG_OBJECTWITHATTRIBUTE_ENUM EnumPtr
  1228. )
  1229. {
  1230. return IsmEnumNextObjectWithAttribute (EnumPtr);
  1231. }
  1232. VOID
  1233. IsmAbortPersistentObjectEnum (
  1234. IN PMIG_OBJECTWITHATTRIBUTE_ENUM EnumPtr
  1235. )
  1236. {
  1237. IsmAbortObjectWithAttributeEnum (EnumPtr);
  1238. }
  1239. BOOL
  1240. IsmEnumFirstApplyObject (
  1241. OUT PMIG_OBJECTWITHATTRIBUTE_ENUM EnumPtr
  1242. )
  1243. {
  1244. return IsmEnumFirstObjectWithAttribute (EnumPtr, g_ApplyAttributeId);
  1245. }
  1246. BOOL
  1247. IsmEnumNextApplyObject (
  1248. IN OUT PMIG_OBJECTWITHATTRIBUTE_ENUM EnumPtr
  1249. )
  1250. {
  1251. return IsmEnumNextObjectWithAttribute (EnumPtr);
  1252. }
  1253. VOID
  1254. IsmAbortApplyObjectEnum (
  1255. IN PMIG_OBJECTWITHATTRIBUTE_ENUM EnumPtr
  1256. )
  1257. {
  1258. IsmAbortObjectWithAttributeEnum (EnumPtr);
  1259. }