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.

1343 lines
31 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. objmgr.c
  5. Abstract:
  6. Object Manager object management routines for the NT Cluster Service
  7. Author:
  8. Rod Gamache (rodga) 13-Mar-1996
  9. Revision History:
  10. --*/
  11. #include "omp.h"
  12. //
  13. // Global data defined by this module
  14. //
  15. //
  16. // The Object Type table and lock.
  17. //
  18. POM_OBJECT_TYPE OmpObjectTypeTable[ObjectTypeMax] = {0};
  19. CRITICAL_SECTION OmpObjectTypeLock;
  20. #if OM_TRACE_REF
  21. LIST_ENTRY gDeadListHead;
  22. #endif
  23. //
  24. // Functions local to this module
  25. //
  26. #if OM_TRACE_OBJREF
  27. DWORDLONG *OmpMatchRef = NULL;
  28. VOID
  29. OmpReferenceHeader(
  30. POM_HEADER pOmHeader
  31. )
  32. {
  33. InterlockedIncrement(&(pOmHeader)->RefCount);
  34. if (&(pOmHeader)->Body == OmpMatchRef) {
  35. ClRtlLogPrint(LOG_CRITICAL,
  36. "[OM] Referencing %1!lx! - new ref %2!d!\n",
  37. OmpMatchRef,
  38. (pOmHeader)->RefCount);
  39. }
  40. }
  41. DWORD
  42. OmpDereferenceHeader(
  43. IN POM_HEADER Header
  44. )
  45. {
  46. if (&Header->Body == OmpMatchRef) {
  47. ClRtlLogPrint(LOG_CRITICAL,
  48. "[OM] Dereferencing %1!lx! - old ref %2!d!\n",
  49. OmpMatchRef,
  50. Header->RefCount);
  51. }
  52. return(InterlockedDecrement(&Header->RefCount) == 0);
  53. }
  54. #endif
  55. DWORD
  56. WINAPI
  57. OmCreateType(
  58. IN OBJECT_TYPE ObjectType,
  59. IN POM_OBJECT_TYPE_INITIALIZE ObjectTypeInitialize
  60. )
  61. /*++
  62. Routine Description:
  63. This routine creates an object of the type specified. This merely
  64. allocates an object type structure, and inserts a pointer to this
  65. structure into the OmpObjectTypeTable.
  66. Arguments:
  67. ObjectType - The Object Type being created.
  68. ObjectTypeIntialize - The initialization info.
  69. Returns:
  70. ERROR_SUCCESS if the request is successful.
  71. A Win32 error code on failure.
  72. --*/
  73. {
  74. POM_OBJECT_TYPE objType;
  75. DWORD objTypeSize;
  76. CL_ASSERT( ObjectType < ObjectTypeMax );
  77. CL_ASSERT( ARGUMENT_PRESENT(ObjectTypeInitialize) );
  78. CL_ASSERT( ObjectTypeInitialize->ObjectSize );
  79. //
  80. // Take out a lock, just in case there can be multiple threads.
  81. //
  82. EnterCriticalSection( &OmpObjectTypeLock );
  83. //
  84. // Check if this ObjectType is already allocated.
  85. //
  86. if ( OmpObjectTypeTable[ObjectType] != NULL ) {
  87. LeaveCriticalSection( &OmpObjectTypeLock );
  88. return(ERROR_OBJECT_ALREADY_EXISTS);
  89. }
  90. //
  91. // Allocate an object type block, plus its name.
  92. //
  93. objTypeSize = (sizeof(OM_OBJECT_TYPE) + sizeof(DWORDLONG)) &
  94. ~sizeof(DWORDLONG);
  95. objType = LocalAlloc(LMEM_ZEROINIT, objTypeSize +
  96. ((lstrlenW(ObjectTypeInitialize->Name) + 1) *
  97. sizeof(WCHAR)));
  98. if ( objType == NULL ) {
  99. LeaveCriticalSection( &OmpObjectTypeLock );
  100. return(ERROR_NOT_ENOUGH_MEMORY);
  101. }
  102. //
  103. // Init the object type block.
  104. //
  105. InitializeListHead(&objType->ListHead);
  106. InitializeListHead(&objType->CallbackListHead);
  107. InitializeCriticalSection(&objType->CriticalSection);
  108. objType->Type = ObjectType;
  109. objType->ObjectSize = ObjectTypeInitialize->ObjectSize;
  110. objType->Signature = ObjectTypeInitialize->Signature;
  111. objType->DeleteObjectMethod = ObjectTypeInitialize->DeleteObjectMethod;
  112. objType->Name = (LPWSTR)((PCHAR)objType + objTypeSize);
  113. lstrcpyW(objType->Name, ObjectTypeInitialize->Name);
  114. OmpObjectTypeTable[ObjectType] = objType;
  115. LeaveCriticalSection( &OmpObjectTypeLock );
  116. OmpLogPrint( L"OTCREATE \"%1!ws!\"\n", objType->Name );
  117. return(ERROR_SUCCESS);
  118. } // OmCreateType
  119. PVOID
  120. WINAPI
  121. OmCreateObject(
  122. IN OBJECT_TYPE ObjectType,
  123. IN LPCWSTR ObjectId,
  124. IN LPCWSTR ObjectName OPTIONAL,
  125. OUT PBOOL Created OPTIONAL
  126. )
  127. /*++
  128. Routine Description:
  129. This routine creates an object of the type specified or opens an
  130. object if one of the same Id already exists. If the object is created
  131. its reference count is 1. If it is not create, then the reference count
  132. of the object is incremented.
  133. Arguments:
  134. ObjectType - The type of object being created.
  135. ObjectId - The Id string for the object to find/create.
  136. ObjectName - The name to set for the object if found or created.
  137. Created - If present, returns TRUE if the object was created, returns
  138. FALSE otherwise.
  139. Returns:
  140. A pointer to the created/opened object on success.
  141. A NULL on failure - use GetLastError to get the error code.
  142. --*/
  143. {
  144. DWORD status;
  145. PVOID object;
  146. PVOID tmpObject = NULL;
  147. LPWSTR objectName = NULL;
  148. POM_HEADER objHeader;
  149. POM_OBJECT_TYPE objType;
  150. DWORD objSize;
  151. CL_ASSERT( ObjectType < ObjectTypeMax );
  152. CL_ASSERT( OmpObjectTypeTable[ObjectType] );
  153. //
  154. // Get our Object Type block.
  155. //
  156. objType = OmpObjectTypeTable[ObjectType];
  157. //
  158. // Calculate size of this object (round it to a DWORDLONG).
  159. // Note: we don't subtract the DWORDLONG Body for rounding purposes.
  160. //
  161. objSize = (sizeof(OM_HEADER) + objType->ObjectSize) & ~sizeof(DWORDLONG);
  162. EnterCriticalSection( &objType->CriticalSection );
  163. //
  164. // Try to open the object first
  165. //
  166. object = OmReferenceObjectById( ObjectType, ObjectId );
  167. if ( object != NULL ) {
  168. status = ERROR_SUCCESS;
  169. if ( ARGUMENT_PRESENT(ObjectName) ) {
  170. //
  171. // Set the new ObjectName.
  172. //
  173. status = OmSetObjectName( object, ObjectName );
  174. //
  175. // If we failed, then return NULL.
  176. //
  177. if ( status != ERROR_SUCCESS ) {
  178. OmDereferenceObject( object );
  179. object = NULL;
  180. }
  181. }
  182. LeaveCriticalSection( &objType->CriticalSection );
  183. if ( ARGUMENT_PRESENT(Created) ) {
  184. *Created = FALSE;
  185. }
  186. SetLastError( status );
  187. return(object);
  188. }
  189. //
  190. // Attempt to allocate the object, plus its Id string.
  191. //
  192. objHeader = LocalAlloc(LMEM_ZEROINIT, objSize +
  193. ((lstrlenW(ObjectId) + 1) * sizeof(WCHAR)));
  194. if ( objHeader == NULL ) {
  195. LeaveCriticalSection( &objType->CriticalSection );
  196. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  197. return(NULL);
  198. }
  199. if ( ARGUMENT_PRESENT(ObjectName) ) {
  200. //
  201. // Make sure ObjectName is unique.
  202. //
  203. tmpObject = OmReferenceObjectByName( ObjectType, ObjectName );
  204. if ( tmpObject != NULL ) {
  205. LeaveCriticalSection( &objType->CriticalSection );
  206. LocalFree( objHeader );
  207. SetLastError(ERROR_OBJECT_ALREADY_EXISTS);
  208. return(NULL);
  209. }
  210. objectName = LocalAlloc(LMEM_ZEROINIT,
  211. (lstrlenW(ObjectName) + 1) * sizeof(WCHAR));
  212. if ( objectName == NULL ) {
  213. LeaveCriticalSection( &objType->CriticalSection );
  214. LocalFree( objHeader );
  215. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  216. return(NULL);
  217. }
  218. lstrcpyW( objectName, ObjectName );
  219. }
  220. //
  221. // Initialize the object.
  222. //
  223. InitializeListHead(&objHeader->ListEntry);
  224. objHeader->Signature = objType->Signature;
  225. objHeader->RefCount = 1;
  226. objHeader->ObjectType = objType;
  227. objHeader->Name = objectName;
  228. InitializeListHead(&objHeader->CbListHead);
  229. //
  230. // The Id string goes after the object header and body.
  231. //
  232. objHeader->Id = (LPWSTR)((PCHAR)objHeader + objSize);
  233. lstrcpyW(objHeader->Id, ObjectId);
  234. //
  235. // Tell the caller that we had to create this object.
  236. //
  237. if ( ARGUMENT_PRESENT(Created) ) {
  238. *Created = TRUE;
  239. }
  240. #if OM_TRACE_REF
  241. //SS: all objects are added to the dead list on creation
  242. // they are removed when the refcount goes to zero
  243. InitializeListHead(&objHeader->DeadListEntry);
  244. InsertTailList( &gDeadListHead, &objHeader->DeadListEntry );
  245. #endif
  246. LeaveCriticalSection( &objType->CriticalSection );
  247. OmpLogPrint(L"OBCREATE \"%1!ws!\" \"%2!ws!\" \"%3!ws!\"\n",
  248. objType->Name,
  249. ObjectId,
  250. ObjectName == NULL ? L"" : ObjectName);
  251. return(&objHeader->Body);
  252. } // OmCreateObject
  253. DWORD
  254. WINAPI
  255. OmInsertObject(
  256. IN PVOID Object
  257. )
  258. /*++
  259. Routine Description:
  260. This routine inserts an object into the object's list.
  261. Arguments:
  262. Object - A pointer to the object to be inserted into its object type list.
  263. Returns:
  264. ERROR_SUCCESS - if the request was successful.
  265. ERROR_OBJECT_ALREADY_EXISTS if this object is already in the list.
  266. --*/
  267. {
  268. POM_HEADER objHeader;
  269. POM_HEADER otherHeader;
  270. POM_OBJECT_TYPE objType;
  271. //
  272. // Get our Object Header.
  273. //
  274. objHeader = OmpObjectToHeader( Object );
  275. //
  276. // Get our Object Type block.
  277. //
  278. objType = objHeader->ObjectType;
  279. //
  280. // Now perform the insertion, but first check to see if someone else
  281. // snuck in ahead of us and inserted another object of the same name.
  282. //
  283. EnterCriticalSection( &objType->CriticalSection );
  284. CL_ASSERT( !(objHeader->Flags & OM_FLAG_OBJECT_INSERTED) );
  285. otherHeader = OmpFindIdInList( &objType->ListHead, objHeader->Id );
  286. if ( otherHeader != NULL ) {
  287. // We loose!
  288. LeaveCriticalSection( &objType->CriticalSection );
  289. return(ERROR_OBJECT_ALREADY_EXISTS);
  290. }
  291. //
  292. // We generate the enumeration key for this object, and we must insert
  293. // the object at the tail of the list, so the list is ordered by EnumKey.
  294. // By definition, this entry must go at the end of the list.
  295. //
  296. objHeader->EnumKey = ++objType->EnumKey;
  297. CL_ASSERT( objHeader->EnumKey > 0 );
  298. InsertTailList( &objType->ListHead, &objHeader->ListEntry );
  299. objHeader->Flags |= OM_FLAG_OBJECT_INSERTED;
  300. LeaveCriticalSection( &objType->CriticalSection );
  301. return(ERROR_SUCCESS);
  302. } // OmInsertObject
  303. DWORD
  304. WINAPI
  305. OmRemoveObject(
  306. IN PVOID Object
  307. )
  308. /*++
  309. Routine Description:
  310. This routine removes an object from its object's list.
  311. Arguments:
  312. Object - A pointer to the object to be removed from its object type list.
  313. Returns:
  314. ERROR_SUCCESS if the request is successful.
  315. ERROR_RESOURCE_NOT_FOUND if the object is not in any list.
  316. --*/
  317. {
  318. POM_HEADER objHeader;
  319. POM_OBJECT_TYPE objType;
  320. //
  321. // Get our Object Header.
  322. //
  323. objHeader = OmpObjectToHeader( Object );
  324. //
  325. // Get our Object Type block.
  326. //
  327. objType = objHeader->ObjectType;
  328. //
  329. // Now perform the removal.
  330. //
  331. EnterCriticalSection( &objType->CriticalSection );
  332. if ( !(objHeader->Flags & OM_FLAG_OBJECT_INSERTED) ) {
  333. LeaveCriticalSection( &objType->CriticalSection );
  334. return(ERROR_RESOURCE_NOT_FOUND);
  335. }
  336. RemoveEntryList( &objHeader->ListEntry );
  337. objHeader->Flags &= ~OM_FLAG_OBJECT_INSERTED;
  338. //
  339. // log while the lock is held so we don't lose our pointers
  340. //
  341. OmpLogPrint(L"OBDELETE \"%1!ws!\" \"%2!ws!\" \"%3!ws!\"\n",
  342. objType->Name,
  343. objHeader->Id,
  344. objHeader->Name == NULL ? L"" : objHeader->Name);
  345. LeaveCriticalSection( &objType->CriticalSection );
  346. return(ERROR_SUCCESS);
  347. } // OmRemoveObject
  348. PVOID
  349. WINAPI
  350. OmpReferenceObjectById(
  351. IN OBJECT_TYPE ObjectType,
  352. IN LPCWSTR Id
  353. )
  354. /*++
  355. Routine Description:
  356. This routine opens an object of the name and type specified. It also
  357. increments the reference count on the object.
  358. Arguments:
  359. ObjectType - The Object Type to open.
  360. Id - The Id string of the object to open.
  361. Returns:
  362. A pointer to the object on success.
  363. NULL on error.
  364. --*/
  365. {
  366. DWORD status;
  367. POM_OBJECT_TYPE objType;
  368. POM_HEADER objHeader;
  369. CL_ASSERT( ObjectType < ObjectTypeMax );
  370. CL_ASSERT( OmpObjectTypeTable[ObjectType] );
  371. //
  372. // Get our Object Type block.
  373. //
  374. objType = OmpObjectTypeTable[ObjectType];
  375. EnterCriticalSection( &objType->CriticalSection );
  376. //
  377. // Get the Object's header
  378. //
  379. objHeader = OmpFindIdInList( &objType->ListHead, Id );
  380. if ( objHeader == NULL ) {
  381. LeaveCriticalSection( &objType->CriticalSection );
  382. return(NULL);
  383. }
  384. #if OM_TRACE_REF
  385. OmReferenceObject(&objHeader->Body);
  386. #else
  387. OmpReferenceHeader( objHeader );
  388. #endif
  389. LeaveCriticalSection( &objType->CriticalSection );
  390. return(&objHeader->Body);
  391. } // OmpReferenceObjectById
  392. PVOID
  393. WINAPI
  394. OmpReferenceObjectByName(
  395. IN OBJECT_TYPE ObjectType,
  396. IN LPCWSTR Name
  397. )
  398. /*++
  399. Routine Description:
  400. This routine opens an object of the name and type specified. It also
  401. increments the reference count on the object.
  402. Arguments:
  403. ObjectType - The Object Type to open.
  404. Name - The name of the object to open.
  405. Returns:
  406. A pointer to the object on success.
  407. NULL on error.
  408. --*/
  409. {
  410. DWORD status;
  411. POM_OBJECT_TYPE objType;
  412. POM_HEADER objHeader;
  413. CL_ASSERT( ObjectType < ObjectTypeMax );
  414. CL_ASSERT( OmpObjectTypeTable[ObjectType] );
  415. //
  416. // Get our Object Type block.
  417. //
  418. objType = OmpObjectTypeTable[ObjectType];
  419. EnterCriticalSection( &objType->CriticalSection );
  420. //
  421. // Get the Object's header
  422. //
  423. objHeader = OmpFindNameInList( &objType->ListHead, Name );
  424. if ( objHeader == NULL ) {
  425. LeaveCriticalSection( &objType->CriticalSection );
  426. return(NULL);
  427. }
  428. #if OM_TRACE_REF
  429. OmReferenceObject(&objHeader->Body);
  430. #else
  431. OmpReferenceHeader( objHeader );
  432. #endif
  433. LeaveCriticalSection( &objType->CriticalSection );
  434. return(&objHeader->Body);
  435. } // OmReferenceObjectByName
  436. DWORD
  437. WINAPI
  438. OmCountObjects(
  439. IN OBJECT_TYPE ObjectType,
  440. OUT LPDWORD NumberOfObjects
  441. )
  442. /*++
  443. Routine Description:
  444. Returns the count of the number of objects of a particular type
  445. which exist in the database at this time.
  446. Arguments:
  447. ObjectType - The object type to count.
  448. NumberOfObjects - On output, contains the number of objects of the
  449. specified type in the database.
  450. Return Value:
  451. ERROR_SUCCESS - if the request is successful.
  452. A Win32 error if the request fails.
  453. --*/
  454. {
  455. POM_OBJECT_TYPE objType;
  456. PLIST_ENTRY listEntry;
  457. DWORD objectCount = 0;
  458. CL_ASSERT( ObjectType < ObjectTypeMax );
  459. objType = OmpObjectTypeTable[ObjectType];
  460. if ( !objType ) {
  461. return(ERROR_RESOURCE_NOT_FOUND);
  462. }
  463. EnterCriticalSection(&objType->CriticalSection);
  464. for ( listEntry = objType->ListHead.Flink;
  465. listEntry != &(objType->ListHead);
  466. listEntry = listEntry->Flink
  467. )
  468. {
  469. objectCount++;
  470. }
  471. LeaveCriticalSection(&objType->CriticalSection);
  472. *NumberOfObjects = objectCount;
  473. return(ERROR_SUCCESS);
  474. } // OmCountObjects
  475. DWORD
  476. WINAPI
  477. OmEnumObjects(
  478. IN OBJECT_TYPE ObjectType,
  479. IN OM_ENUM_OBJECT_ROUTINE EnumerationRoutine,
  480. IN PVOID Context1,
  481. IN PVOID Context2
  482. )
  483. /*++
  484. Routine Description:
  485. Enumerates all objects of the specified type.
  486. Arguments:
  487. ObjectType - The object type to enumerate.
  488. EnumerationRoutine - Supplies the enumeration routine to be
  489. called for each object.
  490. Context1 - Supplies a context pointer to be passed to the
  491. enumeration routine.
  492. Context2 - Supplies a second context pointer to be passed to the
  493. enumeration routine.
  494. Return Value:
  495. ERROR_SUCCESS - if the request is successful.
  496. A Win32 error if the request fails.
  497. --*/
  498. {
  499. POM_OBJECT_TYPE objType;
  500. POM_HEADER objHeader;
  501. PLIST_ENTRY listEntry;
  502. DWORD enumKey = 0;
  503. CL_ASSERT( ObjectType < ObjectTypeMax );
  504. objType = OmpObjectTypeTable[ObjectType];
  505. if ( !objType ) {
  506. return(ERROR_RESOURCE_NOT_FOUND);
  507. }
  508. //
  509. // Enumeration is a little tricky. First, we have to allow for multiple
  510. // entries in the enumeration list to be removed as a side effect of the
  511. // callout. Second, we have to allow the list lock to be released so the
  512. // first issue can be handled. We'll use a sort order key to remember where
  513. // we are in the enumeration and pick up from the next highest value.
  514. //
  515. while ( TRUE ) {
  516. EnterCriticalSection(&objType->CriticalSection);
  517. //
  518. // Skip to next entry to process in list.
  519. // We can treat this like an entry only after verifying it is not the
  520. // ListHeader.
  521. //
  522. listEntry = objType->ListHead.Flink;
  523. objHeader = CONTAINING_RECORD( listEntry, OM_HEADER, ListEntry );
  524. while ( listEntry != &objType->ListHead &&
  525. objHeader->EnumKey <= enumKey ) {
  526. listEntry = listEntry->Flink;
  527. objHeader = CONTAINING_RECORD( listEntry, OM_HEADER, ListEntry );
  528. }
  529. //
  530. // Save the enumeration key for next iteration.
  531. //
  532. enumKey = objHeader->EnumKey;
  533. //if it is a valid object, increment the reference count
  534. // so that it is not deleted while the call out is being
  535. // made
  536. if ( listEntry != &objType->ListHead ) {
  537. OmReferenceObject(&objHeader->Body);
  538. }
  539. //
  540. // Drop the lock to return or call out.
  541. //
  542. LeaveCriticalSection(&objType->CriticalSection);
  543. if ( listEntry == &objType->ListHead ) {
  544. return(ERROR_SUCCESS);
  545. }
  546. if (!(EnumerationRoutine)(Context1,
  547. Context2,
  548. &objHeader->Body,
  549. objHeader->Id)) {
  550. OmDereferenceObject(&objHeader->Body);
  551. break;
  552. }
  553. OmDereferenceObject(&objHeader->Body);
  554. }
  555. return(ERROR_SUCCESS);
  556. } // OmEnumObject
  557. VOID
  558. OmpDereferenceObject(
  559. IN PVOID Object
  560. )
  561. /*++
  562. Routine Description:
  563. This routine dereferences an object. If the reference count goes to
  564. zero, then the object is deallocated.
  565. Arguments:
  566. Object - A pointer to the object to be dereferenced.
  567. Returns:
  568. None
  569. --*/
  570. {
  571. DWORD status;
  572. POM_HEADER objHeader;
  573. POM_OBJECT_TYPE objType;
  574. objHeader = OmpObjectToHeader( Object );
  575. objType = objHeader->ObjectType;
  576. CL_ASSERT( objHeader->RefCount != 0xfeeefeee );
  577. CL_ASSERT( objHeader->RefCount > 0 );
  578. if ( OmpDereferenceHeader(objHeader) ) {
  579. //
  580. // The reference count has gone to zero. Acquire the
  581. // lock, remove the object from the list, and perform
  582. // cleanup.
  583. //
  584. EnterCriticalSection( &objType->CriticalSection );
  585. //
  586. // Check the ref count again, to close the race condition between
  587. // open/create and this routine.
  588. //
  589. if ( objHeader->RefCount == 0 ) {
  590. //
  591. // If the object hasn't been previously removed from it's
  592. // object type list, then remove it now.
  593. //
  594. if ( objHeader->Flags & OM_FLAG_OBJECT_INSERTED ) {
  595. RemoveEntryList( &objHeader->ListEntry );
  596. objHeader->Flags &= ~OM_FLAG_OBJECT_INSERTED;
  597. }
  598. //
  599. // Call the object type's delete method (if present).
  600. //
  601. if ( ARGUMENT_PRESENT( objType->DeleteObjectMethod ) ) {
  602. (objType->DeleteObjectMethod)( &objHeader->Body );
  603. }
  604. objHeader->Signature = 'rFmO';
  605. #if OM_TRACE_REF
  606. RemoveEntryList(&objHeader->DeadListEntry);
  607. #endif
  608. if ( objHeader->Name != NULL ) {
  609. ClRtlLogPrint(LOG_NOISE,
  610. "[OM] Deleting object %1!ws! (%2!ws!)\n",
  611. objHeader->Name,
  612. objHeader->Id);
  613. LocalFree( objHeader->Name );
  614. } else {
  615. ClRtlLogPrint(LOG_NOISE,
  616. "[OM] Deleting object %1!ws!\n",
  617. objHeader->Id);
  618. }
  619. LocalFree( objHeader );
  620. }
  621. LeaveCriticalSection( &objType->CriticalSection );
  622. }
  623. } // OmpDereferenceObject
  624. DWORD
  625. WINAPI
  626. OmSetObjectName(
  627. IN PVOID Object,
  628. IN LPCWSTR ObjectName
  629. )
  630. /*++
  631. Routine Description:
  632. Set the object name for an object. If the ObjectName already exists on a
  633. different object, then this call will fail.
  634. Arguments:
  635. Object - A pointer to the object to set its name.
  636. ObjectName - The name to set for the object.
  637. Return Value:
  638. ERROR_SUCCESS if successful.
  639. A Win32 error code on failure.
  640. --*/
  641. {
  642. DWORD status = ERROR_SUCCESS;
  643. PVOID object = NULL;
  644. LPWSTR objectName;
  645. POM_HEADER objHeader;
  646. POM_OBJECT_TYPE objType;
  647. //
  648. // Make sure object name is valid (not empty)
  649. //
  650. if (ObjectName[0] == '\0')
  651. {
  652. status = ERROR_INVALID_NAME;
  653. goto FnExit;
  654. }
  655. objHeader = OmpObjectToHeader( Object );
  656. objType = objHeader->ObjectType;
  657. EnterCriticalSection( &objType->CriticalSection );
  658. //
  659. // Make sure ObjectName is unique.
  660. //
  661. object = OmReferenceObjectByName( objType->Type, ObjectName );
  662. if ( object != NULL )
  663. {
  664. //
  665. // If our's is the other object, then nothing to do. Otherwise,
  666. // there is a duplicate.
  667. //
  668. if ( object != Object )
  669. {
  670. status = ERROR_OBJECT_ALREADY_EXISTS;
  671. goto FnUnlock;
  672. }
  673. }
  674. else
  675. {
  676. //
  677. // No other object with the new name, then set the new name.
  678. //
  679. objectName = LocalAlloc(LMEM_ZEROINIT,
  680. (lstrlenW(ObjectName) + 1) * sizeof(WCHAR));
  681. if ( objectName == NULL ) {
  682. status = ERROR_NOT_ENOUGH_MEMORY;
  683. } else {
  684. if ( objHeader->Name != NULL ) {
  685. LocalFree( objHeader->Name );
  686. }
  687. objHeader->Name = objectName;
  688. lstrcpyW( objectName, ObjectName );
  689. OmpLogPrint(L"OBRENAME \"%1!ws!\" \"%2!ws!\" \"%3!ws!\"\n",
  690. objType->Name,
  691. objHeader->Id,
  692. ObjectName);
  693. }
  694. }
  695. FnUnlock:
  696. LeaveCriticalSection( &objType->CriticalSection );
  697. FnExit:
  698. if (object)
  699. {
  700. OmDereferenceObject(object);
  701. }
  702. return(status);
  703. } // OmSetObjectName
  704. DWORD
  705. WINAPI
  706. OmRegisterTypeNotify(
  707. IN OBJECT_TYPE ObjectType,
  708. IN PVOID pContext,
  709. IN DWORD dwNotifyMask,
  710. IN OM_OBJECT_NOTIFYCB pfnObjNotifyCb
  711. )
  712. /*++
  713. Routine Description:
  714. Registers a callback to be called by the FM on object state changes.
  715. Arguments:
  716. ObjectType - The object type that notifications should be delivered for.
  717. pContext - A pointer to context information that is passed back into the callback.
  718. dwNotifyMask - The type of notifications that should be delivered
  719. pfnObjNotifyCb - a pointer to the callback.
  720. Return Value:
  721. ERROR_SUCCESS if successful.
  722. A Win32 error code on failure.
  723. --*/
  724. {
  725. DWORD dwError = ERROR_SUCCESS;
  726. POM_HEADER pObjHeader;
  727. POM_OBJECT_TYPE pObjType;
  728. POM_NOTIFY_RECORD pNotifyRec;
  729. if ( !pfnObjNotifyCb ) {
  730. return(ERROR_INVALID_PARAMETER);
  731. }
  732. pObjType = OmpObjectTypeTable[ObjectType];
  733. //
  734. // The object type lock is used to serialize callbacks. This
  735. // is so that callees do not deadlock if they are waiting on
  736. // another thread that needs to enumerate objects.
  737. //
  738. EnterCriticalSection( &OmpObjectTypeLock );
  739. //
  740. // First, check if the same notification is being registered twice!
  741. // If so, then just change the notification mask and context.
  742. //
  743. pNotifyRec = OmpFindNotifyCbInList( &pObjType->CallbackListHead,
  744. pfnObjNotifyCb);
  745. if ( !pNotifyRec ) {
  746. pNotifyRec = (POM_NOTIFY_RECORD) LocalAlloc(LMEM_FIXED,sizeof(OM_NOTIFY_RECORD));
  747. if ( !pNotifyRec ) {
  748. dwError = ERROR_NOT_ENOUGH_MEMORY;
  749. CsInconsistencyHalt(dwError);
  750. goto FnExit;
  751. }
  752. pNotifyRec->pfnObjNotifyCb = pfnObjNotifyCb;
  753. //insert the notification record at the tail
  754. InsertTailList(&pObjType->CallbackListHead, &pNotifyRec->ListEntry);
  755. }
  756. pNotifyRec->dwNotifyMask = dwNotifyMask;
  757. pNotifyRec->pContext = pContext;
  758. FnExit:
  759. LeaveCriticalSection( &OmpObjectTypeLock );
  760. return(dwError);
  761. } // OmRegisterTypeNotify
  762. DWORD
  763. WINAPI
  764. OmRegisterNotify(
  765. IN PVOID pObject,
  766. IN PVOID pContext,
  767. IN DWORD dwNotifyMask,
  768. IN OM_OBJECT_NOTIFYCB pfnObjNotifyCb
  769. )
  770. /*++
  771. Routine Description:
  772. Registers a callback to be called by the FM on object state changes.
  773. Arguments:
  774. pObject - A pointer to the object to set its name.
  775. pContext - A pointer to context information that is passed back into the callback.
  776. dwNotifyMask - The name to set for the object.
  777. pfnObjNotifyCb - a pointer to the callback.
  778. Return Value:
  779. ERROR_SUCCESS if successful.
  780. A Win32 error code on failure.
  781. --*/
  782. {
  783. DWORD dwError = ERROR_SUCCESS;
  784. POM_HEADER pObjHeader;
  785. POM_OBJECT_TYPE pObjType;
  786. POM_NOTIFY_RECORD pNotifyRec;
  787. if ( !pfnObjNotifyCb ) {
  788. return(ERROR_INVALID_PARAMETER);
  789. }
  790. pObjHeader = OmpObjectToHeader( pObject );
  791. pObjType = pObjHeader->ObjectType;
  792. EnterCriticalSection( &OmpObjectTypeLock );
  793. //
  794. // First, check if the same notification is being registered twice!
  795. // If so, then just change the notification mask and context.
  796. //
  797. pNotifyRec = OmpFindNotifyCbInList(&pObjHeader->CbListHead, pfnObjNotifyCb);
  798. if ( !pNotifyRec ) {
  799. pNotifyRec = (POM_NOTIFY_RECORD) LocalAlloc(LMEM_FIXED,sizeof(OM_NOTIFY_RECORD));
  800. if ( !pNotifyRec ) {
  801. dwError = ERROR_NOT_ENOUGH_MEMORY;
  802. CsInconsistencyHalt(dwError);
  803. goto FnExit;
  804. }
  805. pNotifyRec->pfnObjNotifyCb = pfnObjNotifyCb;
  806. //insert the notification record at the tail
  807. InsertTailList(&pObjHeader->CbListHead, &pNotifyRec->ListEntry);
  808. }
  809. pNotifyRec->dwNotifyMask = dwNotifyMask;
  810. pNotifyRec->pContext = pContext;
  811. FnExit:
  812. LeaveCriticalSection( &OmpObjectTypeLock );
  813. return(dwError);
  814. } // OmRegisterNotify
  815. DWORD
  816. WINAPI
  817. OmDeregisterNotify(
  818. IN PVOID pObject,
  819. IN OM_OBJECT_NOTIFYCB pfnObjNotifyCb
  820. )
  821. /*++
  822. Routine Description:
  823. Removes the callback registed with the object.
  824. Arguments:
  825. pObject - A pointer to the object to set its name.
  826. pfnObjNotifyCb - a pointer to the callback.
  827. Return Value:
  828. ERROR_SUCCESS if successful.
  829. A Win32 error code on failure.
  830. --*/
  831. {
  832. DWORD dwError = ERROR_SUCCESS;
  833. POM_HEADER pObjHeader;
  834. POM_OBJECT_TYPE pObjType;
  835. POM_NOTIFY_RECORD pNotifyRec;
  836. if ( !pfnObjNotifyCb ) {
  837. return(ERROR_INVALID_PARAMETER);
  838. }
  839. pObjHeader = OmpObjectToHeader( pObject );
  840. //SS: we use the same crit section for list manipulations
  841. pObjType = pObjHeader->ObjectType;
  842. //
  843. // The object type lock is used to serialize callbacks. This
  844. // is so that callees do not deadlock if they are waiting on
  845. // another thread that needs to enumerate objects.
  846. //
  847. EnterCriticalSection( &OmpObjectTypeLock );
  848. pNotifyRec = OmpFindNotifyCbInList(&pObjHeader->CbListHead, pfnObjNotifyCb);
  849. if (!pNotifyRec) {
  850. ClRtlLogPrint(LOG_UNUSUAL,
  851. "[OM] OmRegisterNotify: OmpFindNotifyCbInList failed for 0x%1!08lx!\r\n",
  852. pfnObjNotifyCb);
  853. dwError = ERROR_INVALID_PARAMETER;
  854. CL_LOGFAILURE(dwError);
  855. goto FnExit;
  856. }
  857. RemoveEntryList(&pNotifyRec->ListEntry);
  858. FnExit:
  859. LeaveCriticalSection( &OmpObjectTypeLock );
  860. return(dwError);
  861. } // OmRegisterNotify
  862. DWORD
  863. WINAPI
  864. OmNotifyCb(
  865. IN PVOID pObject,
  866. IN DWORD dwNotification
  867. )
  868. /*++
  869. Routine Description:
  870. The callback registered with the quorum resource object.
  871. Arguments:
  872. pContext - The resource whose call back list will be traversed.
  873. dwNotification - The notification to be passed to the callback.
  874. Return Value:
  875. ERROR_SUCCESS if successful.
  876. A Win32 error code on failure.
  877. --*/
  878. {
  879. POM_HEADER pObjHeader;
  880. POM_OBJECT_TYPE pObjType;
  881. PLIST_ENTRY ListEntry;
  882. DWORD dwError=ERROR_SUCCESS;
  883. POM_NOTIFY_RECORD pNotifyRecList = NULL;
  884. DWORD dwCount;
  885. DWORD i;
  886. CL_ASSERT(pObject);
  887. //get the callback list
  888. pObjHeader = OmpObjectToHeader(pObject);
  889. pObjType = pObjHeader->ObjectType;
  890. //will walk the list of callbacks, do allow more registrations
  891. EnterCriticalSection(&OmpObjectTypeLock);
  892. dwError = OmpGetCbList(pObject, &pNotifyRecList, &dwCount);
  893. LeaveCriticalSection(&OmpObjectTypeLock);
  894. for (i=0; i < dwCount; i++)
  895. {
  896. if (pNotifyRecList[i].dwNotifyMask & dwNotification) {
  897. (pNotifyRecList[i].pfnObjNotifyCb)(pNotifyRecList[i].pContext,
  898. pObject,
  899. dwNotification);
  900. }
  901. }
  902. LocalFree(pNotifyRecList);
  903. return(dwError);
  904. }
  905. DWORD OmpGetCbList(
  906. IN PVOID pObject,
  907. OUT POM_NOTIFY_RECORD *ppNotifyRecList,
  908. OUT LPDWORD pdwCount
  909. )
  910. {
  911. DWORD status = ERROR_SUCCESS;
  912. POM_NOTIFY_RECORD pNotifyRecList;
  913. POM_NOTIFY_RECORD pNotifyRec;
  914. DWORD dwAllocated;
  915. PLIST_ENTRY ListEntry;
  916. DWORD dwRetrySize=1;
  917. POM_HEADER pObjHeader;
  918. POM_OBJECT_TYPE pObjType;
  919. DWORD i = 0;
  920. *ppNotifyRecList = NULL;
  921. *pdwCount = 0;
  922. Retry:
  923. dwAllocated = ENUM_GROW_SIZE * dwRetrySize;
  924. pObjHeader = OmpObjectToHeader(pObject);
  925. pObjType = pObjHeader->ObjectType;
  926. pNotifyRecList = LocalAlloc(LMEM_FIXED, sizeof(OM_NOTIFY_RECORD) * ENUM_GROW_SIZE);
  927. if ( pNotifyRecList == NULL ) {
  928. status = ERROR_NOT_ENOUGH_MEMORY;
  929. goto FnExit;
  930. }
  931. ZeroMemory( pNotifyRecList, sizeof(OM_NOTIFY_RECORD) * ENUM_GROW_SIZE );
  932. //
  933. // First notify any type-specific callbacks
  934. //
  935. ListEntry = pObjType->CallbackListHead.Flink;
  936. while (ListEntry != &pObjType->CallbackListHead) {
  937. pNotifyRec = CONTAINING_RECORD(ListEntry,
  938. OM_NOTIFY_RECORD,
  939. ListEntry);
  940. if (i < dwAllocated)
  941. {
  942. CopyMemory(&pNotifyRecList[i++], pNotifyRec, sizeof(OM_NOTIFY_RECORD));
  943. }
  944. else
  945. {
  946. LocalFree(pNotifyRecList);
  947. dwRetrySize++;
  948. goto Retry;
  949. }
  950. ListEntry = ListEntry->Flink;
  951. }
  952. //
  953. // Next notify any resource-specific callbacks
  954. //
  955. ListEntry = pObjHeader->CbListHead.Flink;
  956. while (ListEntry != &(pObjHeader->CbListHead)) {
  957. pNotifyRec = CONTAINING_RECORD(ListEntry, OM_NOTIFY_RECORD, ListEntry);
  958. if (i < dwAllocated)
  959. {
  960. CopyMemory(&pNotifyRecList[i++], pNotifyRec, sizeof(OM_NOTIFY_RECORD));
  961. }
  962. else
  963. {
  964. LocalFree(pNotifyRecList);
  965. dwRetrySize++;
  966. goto Retry;
  967. }
  968. ListEntry = ListEntry->Flink;
  969. }
  970. FnExit:
  971. *ppNotifyRecList = pNotifyRecList;
  972. *pdwCount = i;
  973. return(status);
  974. }