Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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