Windows NT 4.0 source code leak
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.

1052 lines
31 KiB

4 years ago
  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. obref.c
  5. Abstract:
  6. Object open API
  7. Author:
  8. Steve Wood (stevewo) 31-Mar-1989
  9. Revision History:
  10. --*/
  11. #include "obp.h"
  12. extern POBJECT_TYPE PspProcessType;
  13. extern POBJECT_TYPE PspThreadType;
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(PAGE,ObGetObjectPointerCount)
  16. #pragma alloc_text(PAGE,ObOpenObjectByName)
  17. #pragma alloc_text(PAGE,ObOpenObjectByPointer)
  18. #pragma alloc_text(PAGE,ObReferenceObjectByName)
  19. #pragma alloc_text(PAGE,ObpRemoveObjectRoutine)
  20. #pragma alloc_text(PAGE,ObpDeleteNameCheck)
  21. #endif
  22. ULONG
  23. ObGetObjectPointerCount(
  24. IN PVOID Object
  25. )
  26. /*++
  27. Routine Description:
  28. This routine returns the current pointer count for a specified object.
  29. Arguments:
  30. Object - Pointer to the object whose pointer count is to be returned.
  31. Return Value:
  32. The current pointer count for the specified object is returned.
  33. Note:
  34. This function cannot be made a macro, since fields in the thread object
  35. move from release to release, so this must remain a full function.
  36. --*/
  37. {
  38. PAGED_CODE();
  39. //
  40. // Simply return the current pointer count for the object.
  41. //
  42. return OBJECT_TO_OBJECT_HEADER( Object )->PointerCount;
  43. }
  44. NTSTATUS
  45. ObOpenObjectByName(
  46. IN POBJECT_ATTRIBUTES ObjectAttributes,
  47. IN POBJECT_TYPE ObjectType OPTIONAL,
  48. IN KPROCESSOR_MODE AccessMode,
  49. IN OUT PACCESS_STATE AccessState OPTIONAL,
  50. IN ACCESS_MASK DesiredAccess OPTIONAL,
  51. IN OUT PVOID ParseContext OPTIONAL,
  52. OUT PHANDLE Handle
  53. )
  54. /*++
  55. Routine Description:
  56. This function opens an object with full access validation and auditing.
  57. Soon after entering we capture the SubjectContext for the caller. This
  58. context must remain captured until auditing is complete, and passed to
  59. any routine that may have to do access checking or auditing.
  60. Arguments:
  61. ObjectAttributes - Supplies a pointer to the object attributes.
  62. ObjectType - Supplies an optional pointer to the object type descriptor.
  63. AccessMode - Supplies the processor mode of the access.
  64. AccessState - Supplies an optional pointer to the current access status
  65. describing already granted access types, the privileges used to get
  66. them, and any access types yet to be granted.
  67. DesiredAcess - Supplies the desired access to the object.
  68. ParseContext - Supplies an optional pointer to parse context.
  69. Handle - Supplies a pointer to a variable that receives the handle value.
  70. Return Value:
  71. If the object is successfully opened, then a handle for the object is
  72. created and a success status is returned. Otherwise, an error status is
  73. returned.
  74. --*/
  75. {
  76. NTSTATUS Status;
  77. NTSTATUS HandleStatus;
  78. PVOID ExistingObject;
  79. HANDLE NewHandle;
  80. BOOLEAN DirectoryLocked;
  81. OB_OPEN_REASON OpenReason;
  82. POBJECT_HEADER ObjectHeader;
  83. OBJECT_CREATE_INFORMATION ObjectCreateInfo;
  84. UNICODE_STRING CapturedObjectName;
  85. ACCESS_STATE LocalAccessState;
  86. AUX_ACCESS_DATA AuxData;
  87. PGENERIC_MAPPING GenericMapping;
  88. PAGED_CODE();
  89. ObpValidateIrql("ObOpenObjectByName");
  90. //
  91. // If the object attributes are not specified, then return an error.
  92. //
  93. *Handle = NULL;
  94. if (!ARGUMENT_PRESENT(ObjectAttributes)) {
  95. Status = STATUS_INVALID_PARAMETER;
  96. } else {
  97. //
  98. // Capture the object creation information.
  99. //
  100. Status = ObpCaptureObjectCreateInformation(ObjectType,
  101. AccessMode,
  102. ObjectAttributes,
  103. &CapturedObjectName,
  104. &ObjectCreateInfo,
  105. TRUE);
  106. //
  107. // If the object creation information is successfully captured,
  108. // then generate the access state.
  109. //
  110. if (NT_SUCCESS(Status)) {
  111. if (!ARGUMENT_PRESENT(AccessState)) {
  112. //
  113. // If an object type descriptor is specified, then use
  114. // associated generic mapping. Otherwise, use no generic
  115. // mapping.
  116. //
  117. GenericMapping = NULL;
  118. if (ARGUMENT_PRESENT(ObjectType)) {
  119. GenericMapping = &ObjectType->TypeInfo.GenericMapping;
  120. }
  121. AccessState = &LocalAccessState;
  122. Status = SeCreateAccessState(&LocalAccessState,
  123. &AuxData,
  124. DesiredAccess,
  125. GenericMapping);
  126. if (!NT_SUCCESS(Status)) {
  127. goto FreeCreateInfo;
  128. }
  129. }
  130. //
  131. // If there is a security descriptor specified in the object
  132. // attributes, then capture it in the access state.
  133. //
  134. if (ObjectCreateInfo.SecurityDescriptor != NULL) {
  135. AccessState->SecurityDescriptor = ObjectCreateInfo.SecurityDescriptor;
  136. }
  137. //
  138. // Validate the access state.
  139. //
  140. Status = ObpValidateAccessMask(AccessState);
  141. //
  142. // If the access state is valid, then lookup the object by
  143. // name.
  144. //
  145. if (NT_SUCCESS(Status)) {
  146. Status = ObpLookupObjectName(ObjectCreateInfo.RootDirectory,
  147. &CapturedObjectName,
  148. ObjectCreateInfo.Attributes,
  149. ObjectType,
  150. AccessMode,
  151. ParseContext,
  152. ObjectCreateInfo.SecurityQos,
  153. NULL,
  154. AccessState,
  155. &DirectoryLocked,
  156. &ExistingObject);
  157. //
  158. // If the object was successfully looked up, then attempt
  159. // to create or open a handle.
  160. //
  161. if (NT_SUCCESS(Status)) {
  162. ObjectHeader = OBJECT_TO_OBJECT_HEADER(ExistingObject);
  163. //
  164. // If the object is being created, then the operation
  165. // must be a open-if operation. Otherwise, a handle to
  166. // an object is being opened.
  167. //
  168. if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) {
  169. OpenReason = ObCreateHandle;
  170. if (ObjectHeader->ObjectCreateInfo != NULL) {
  171. ObpFreeObjectCreateInformation(ObjectHeader->ObjectCreateInfo);
  172. ObjectHeader->ObjectCreateInfo = NULL;
  173. }
  174. } else {
  175. OpenReason = ObOpenHandle;
  176. }
  177. //
  178. // If any of the object attributes are invalid, then
  179. // return an error status.
  180. //
  181. if (ObjectHeader->Type->TypeInfo.InvalidAttributes & ObjectCreateInfo.Attributes) {
  182. Status = STATUS_INVALID_PARAMETER;
  183. if (DirectoryLocked) {
  184. ObpLeaveRootDirectoryMutex();
  185. }
  186. } else {
  187. //
  188. // The status returned by the object lookup routine
  189. // must be returned if the creation of a handle is
  190. // successful. Otherwise, the handle creation status
  191. // is returned.
  192. //
  193. HandleStatus = ObpCreateHandle(OpenReason,
  194. ExistingObject,
  195. ObjectType,
  196. AccessState,
  197. 0,
  198. ObjectCreateInfo.Attributes,
  199. DirectoryLocked,
  200. AccessMode,
  201. (PVOID *)NULL,
  202. &NewHandle);
  203. if (!NT_SUCCESS(HandleStatus)) {
  204. ObDereferenceObject(ExistingObject);
  205. Status = HandleStatus;
  206. } else {
  207. *Handle = NewHandle;
  208. }
  209. }
  210. } else {
  211. if (DirectoryLocked) {
  212. ObpLeaveRootDirectoryMutex();
  213. }
  214. }
  215. }
  216. //
  217. // If the access state was generated, then delete the access
  218. // state.
  219. //
  220. if (AccessState == &LocalAccessState) {
  221. SeDeleteAccessState(AccessState);
  222. }
  223. //
  224. // Free the create information.
  225. //
  226. FreeCreateInfo:
  227. ObpReleaseObjectCreateInformation(&ObjectCreateInfo);
  228. if (CapturedObjectName.Buffer != NULL) {
  229. ObpFreeObjectNameBuffer(&CapturedObjectName);
  230. }
  231. }
  232. }
  233. return Status;
  234. }
  235. NTSTATUS
  236. ObOpenObjectByPointer(
  237. IN PVOID Object,
  238. IN ULONG HandleAttributes,
  239. IN PACCESS_STATE PassedAccessState OPTIONAL,
  240. IN ACCESS_MASK DesiredAccess,
  241. IN POBJECT_TYPE ObjectType OPTIONAL,
  242. IN KPROCESSOR_MODE AccessMode,
  243. OUT PHANDLE Handle
  244. )
  245. {
  246. NTSTATUS Status;
  247. HANDLE NewHandle;
  248. POBJECT_HEADER ObjectHeader;
  249. ACCESS_STATE LocalAccessState;
  250. PACCESS_STATE AccessState = NULL;
  251. AUX_ACCESS_DATA AuxData;
  252. PAGED_CODE();
  253. ObpValidateIrql( "ObOpenObjectByPointer" );
  254. Status = ObReferenceObjectByPointer( Object,
  255. 0,
  256. ObjectType,
  257. AccessMode
  258. );
  259. if (NT_SUCCESS( Status )) {
  260. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  261. if (!ARGUMENT_PRESENT( PassedAccessState )) {
  262. Status = SeCreateAccessState( &LocalAccessState,
  263. &AuxData,
  264. DesiredAccess,
  265. &ObjectHeader->Type->TypeInfo.GenericMapping
  266. );
  267. if (!NT_SUCCESS( Status )) {
  268. ObDereferenceObject( Object );
  269. return(Status);
  270. }
  271. AccessState = &LocalAccessState;
  272. } else {
  273. AccessState = PassedAccessState;
  274. }
  275. if (ObjectHeader->Type->TypeInfo.InvalidAttributes & HandleAttributes) {
  276. if (AccessState == &LocalAccessState) {
  277. SeDeleteAccessState( AccessState );
  278. }
  279. ObDereferenceObject( Object );
  280. return( STATUS_INVALID_PARAMETER );
  281. }
  282. Status = ObpCreateHandle( ObOpenHandle,
  283. Object,
  284. ObjectType,
  285. AccessState,
  286. 0,
  287. HandleAttributes,
  288. FALSE,
  289. AccessMode,
  290. (PVOID *)NULL,
  291. &NewHandle
  292. );
  293. if (!NT_SUCCESS( Status )) {
  294. ObDereferenceObject( Object );
  295. }
  296. }
  297. if (NT_SUCCESS( Status )) {
  298. *Handle = NewHandle;
  299. }
  300. else {
  301. *Handle = NULL;
  302. }
  303. if (AccessState == &LocalAccessState) {
  304. SeDeleteAccessState( AccessState );
  305. }
  306. return( Status );
  307. }
  308. NTSTATUS
  309. ObReferenceObjectByHandle(
  310. IN HANDLE Handle,
  311. IN ACCESS_MASK DesiredAccess,
  312. IN POBJECT_TYPE ObjectType OPTIONAL,
  313. IN KPROCESSOR_MODE AccessMode,
  314. OUT PVOID *Object,
  315. OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
  316. )
  317. {
  318. ACCESS_MASK GrantedAccess;
  319. PHANDLE_ENTRY HandleEntry;
  320. PHANDLE_TABLE HandleTable;
  321. POBJECT_HEADER ObjectHeader;
  322. POBJECT_TABLE_ENTRY ObjectTableEntry;
  323. PEPROCESS Process;
  324. NTSTATUS Status;
  325. PHANDLE_ENTRY TableBound;
  326. PHANDLE_ENTRY TableEntries;
  327. ULONG TableIndex;
  328. PETHREAD Thread;
  329. ObpValidateIrql("ObReferenceObjectByHandle");
  330. //
  331. // If the handle value is greater than or equal to zero, then the handle
  332. // is an index into a handle table. Otherwise, the handle is a builtin
  333. // handle value.
  334. //
  335. if ((LONG)Handle >= 0) {
  336. //
  337. // Lock the current process object handle table and translate the
  338. // specified handle to an object table index.
  339. //
  340. HandleTable = ObpGetObjectTable();
  341. ASSERT(HandleTable != NULL);
  342. ExLockHandleTableShared(HandleTable);
  343. //
  344. // If the object table index is less than the number of entires in
  345. // the handle table, then get the contents of the handle table entry.
  346. //
  347. TableIndex = HANDLE_TO_INDEX(OBJ_HANDLE_TO_HANDLE_INDEX(Handle));
  348. TableBound = HandleTable->TableBound;
  349. TableEntries = HandleTable->TableEntries;
  350. if (TableIndex < (ULONG)(TableBound - TableEntries)) {
  351. HandleEntry = &TableEntries[TableIndex];
  352. //
  353. // If the handle table entry is not free, then compute the address
  354. // of the object header.
  355. //
  356. if (ExIsEntryUsed(TableEntries, TableBound, HandleEntry)) {
  357. //
  358. // If the object type matches the specified object type or the
  359. // the specified objec type is NULL, then determine whether
  360. // access to the object is allowed.
  361. //
  362. ObjectTableEntry = (POBJECT_TABLE_ENTRY)HandleEntry;
  363. ObjectHeader = (POBJECT_HEADER)(ObjectTableEntry->Attributes & ~OBJ_HANDLE_ATTRIBUTES);
  364. if ((ObjectHeader->Type == ObjectType) || (ObjectType == NULL)) {
  365. #if i386 && !FPO
  366. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  367. if ((AccessMode != KernelMode) ||
  368. ARGUMENT_PRESENT(HandleInformation)) {
  369. GrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );
  370. }
  371. } else
  372. #endif // i386 && !FPO
  373. GrantedAccess = ObjectTableEntry->GrantedAccess;
  374. if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
  375. (AccessMode == KernelMode)) {
  376. //
  377. // Access to the object is allowed. Return the handle
  378. // information is requested, increment the object
  379. // pointer count, unlock the handle table and return
  380. // a success status.
  381. //
  382. if (ARGUMENT_PRESENT(HandleInformation)) {
  383. HandleInformation->GrantedAccess = GrantedAccess;
  384. HandleInformation->HandleAttributes = ObjectTableEntry->Attributes & OBJ_HANDLE_ATTRIBUTES;
  385. }
  386. ObpIncrPointerCount(ObjectHeader);
  387. *Object = &ObjectHeader->Body;
  388. ExUnlockHandleTableShared(HandleTable);
  389. return STATUS_SUCCESS;
  390. } else {
  391. Status = STATUS_ACCESS_DENIED;
  392. }
  393. } else {
  394. Status = STATUS_OBJECT_TYPE_MISMATCH;
  395. }
  396. } else {
  397. Status = STATUS_INVALID_HANDLE;
  398. }
  399. } else {
  400. Status = STATUS_INVALID_HANDLE;
  401. }
  402. ExUnlockHandleTableShared(HandleTable);
  403. //
  404. // If the handle is equal to the current process handle and the object
  405. // type is NULL or type process, then attempt to translate a handle to
  406. // the current process. Otherwise, check if the handle is the current
  407. // thread handle.
  408. //
  409. } else if (Handle == NtCurrentProcess()) {
  410. if ((ObjectType == PsProcessType) || (ObjectType == NULL)) {
  411. Process = PsGetCurrentProcess();
  412. GrantedAccess = Process->GrantedAccess;
  413. if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
  414. (AccessMode == KernelMode)) {
  415. ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process);
  416. if (ARGUMENT_PRESENT(HandleInformation)) {
  417. HandleInformation->GrantedAccess = GrantedAccess;
  418. HandleInformation->HandleAttributes = 0;
  419. }
  420. ObpIncrPointerCount(ObjectHeader);
  421. *Object = Process;
  422. return STATUS_SUCCESS;
  423. } else {
  424. Status = STATUS_ACCESS_DENIED;
  425. }
  426. } else {
  427. Status = STATUS_OBJECT_TYPE_MISMATCH;
  428. }
  429. //
  430. // If the handle is equal to the current thread handle and the object
  431. // type is NULL or type thread, then attempt to translate a handle to
  432. // the current thread. Otherwise, the handle cannot be translated and
  433. // return the appropriate error status.
  434. //
  435. } else if (Handle == NtCurrentThread()) {
  436. if ((ObjectType == PsThreadType) || (ObjectType == NULL)) {
  437. Thread = PsGetCurrentThread();
  438. GrantedAccess = Thread->GrantedAccess;
  439. if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
  440. (AccessMode == KernelMode)) {
  441. ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread);
  442. if (ARGUMENT_PRESENT(HandleInformation)) {
  443. HandleInformation->GrantedAccess = GrantedAccess;
  444. HandleInformation->HandleAttributes = 0;
  445. }
  446. ObpIncrPointerCount(ObjectHeader);
  447. *Object = Thread;
  448. return STATUS_SUCCESS;
  449. } else {
  450. Status = STATUS_ACCESS_DENIED;
  451. }
  452. } else {
  453. Status = STATUS_OBJECT_TYPE_MISMATCH;
  454. }
  455. } else {
  456. Status = STATUS_INVALID_HANDLE;
  457. }
  458. //
  459. // No handle translation is possible. Set the object address to NULL
  460. // and return an error status.
  461. //
  462. *Object = NULL;
  463. return Status;
  464. }
  465. NTSTATUS
  466. ObReferenceObjectByName(
  467. IN PUNICODE_STRING ObjectName,
  468. IN ULONG Attributes,
  469. IN PACCESS_STATE AccessState OPTIONAL,
  470. IN ACCESS_MASK DesiredAccess OPTIONAL,
  471. IN POBJECT_TYPE ObjectType,
  472. IN KPROCESSOR_MODE AccessMode,
  473. IN OUT PVOID ParseContext OPTIONAL,
  474. OUT PVOID *Object
  475. )
  476. {
  477. UNICODE_STRING CapturedObjectName;
  478. BOOLEAN DirectoryLocked;
  479. PVOID ExistingObject;
  480. ACCESS_STATE LocalAccessState;
  481. AUX_ACCESS_DATA AuxData;
  482. NTSTATUS Status;
  483. PAGED_CODE();
  484. ObpValidateIrql("ObReferenceObjectByName");
  485. //
  486. // If the object name descriptor is not specified, or the object name
  487. // length is zero, then the object name is invalid.
  488. //
  489. if ((ObjectName == NULL) || (ObjectName->Length == 0)) {
  490. Status = STATUS_OBJECT_NAME_INVALID;
  491. } else {
  492. //
  493. // Capture the object name.
  494. //
  495. Status = ObpCaptureObjectName(AccessMode,
  496. ObjectName,
  497. &CapturedObjectName,
  498. TRUE);
  499. if (NT_SUCCESS(Status)) {
  500. //
  501. // If the access state is not specified, then create the access
  502. // state.
  503. //
  504. if (!ARGUMENT_PRESENT(AccessState)) {
  505. AccessState = &LocalAccessState;
  506. Status = SeCreateAccessState(&LocalAccessState,
  507. &AuxData,
  508. DesiredAccess,
  509. &ObjectType->TypeInfo.GenericMapping);
  510. if (!NT_SUCCESS(Status)) {
  511. goto FreeBuffer;
  512. }
  513. }
  514. //
  515. // Lookup object by name.
  516. //
  517. Status = ObpLookupObjectName(NULL,
  518. &CapturedObjectName,
  519. Attributes,
  520. ObjectType,
  521. AccessMode,
  522. ParseContext,
  523. NULL,
  524. NULL,
  525. AccessState,
  526. &DirectoryLocked,
  527. &ExistingObject);
  528. //
  529. // If the directory is returned locked, then unlock it.
  530. //
  531. if (DirectoryLocked) {
  532. ObpLeaveRootDirectoryMutex();
  533. }
  534. //
  535. // If the lookup was successful, then return the existing
  536. // object is access is allowed. Otherwise, return NULL.
  537. //
  538. *Object = NULL;
  539. if (NT_SUCCESS(Status)) {
  540. if (ObpCheckObjectReference(ExistingObject,
  541. AccessState,
  542. FALSE,
  543. AccessMode,
  544. &Status)) {
  545. *Object = ExistingObject;
  546. }
  547. }
  548. //
  549. // If the access state was generated, then delete the access
  550. // state.
  551. //
  552. if (AccessState == &LocalAccessState) {
  553. SeDeleteAccessState(AccessState);
  554. }
  555. //
  556. // Free the object name buffer.
  557. //
  558. FreeBuffer:
  559. ObpFreeObjectNameBuffer(&CapturedObjectName);
  560. }
  561. }
  562. return Status;
  563. }
  564. VOID
  565. FASTCALL
  566. ObfReferenceObject(
  567. IN PVOID Object
  568. )
  569. /*++
  570. Routine Description:
  571. This function increments the reference count for an object.
  572. N.B. This function should be used to increment the reference count
  573. when the accessing mode is kernel or the objct type is known.
  574. Arguments:
  575. Object - Supplies a pointer to the object whose reference count is
  576. incremented.
  577. Return Value:
  578. None.
  579. --*/
  580. {
  581. POBJECT_HEADER ObjectHeader;
  582. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  583. ObpIncrPointerCount( ObjectHeader );
  584. return;
  585. }
  586. NTSTATUS
  587. ObReferenceObjectByPointer(
  588. IN PVOID Object,
  589. IN ACCESS_MASK DesiredAccess,
  590. IN POBJECT_TYPE ObjectType,
  591. IN KPROCESSOR_MODE AccessMode
  592. )
  593. {
  594. POBJECT_HEADER ObjectHeader;
  595. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  596. if ((ObjectHeader->Type != ObjectType) && (AccessMode != KernelMode ||
  597. ObjectType == ObpSymbolicLinkObjectType
  598. )
  599. ) {
  600. return( STATUS_OBJECT_TYPE_MISMATCH );
  601. }
  602. ObpIncrPointerCount( ObjectHeader );
  603. return( STATUS_SUCCESS );
  604. }
  605. BOOLEAN ObpRemoveQueueActive;
  606. VOID
  607. FASTCALL
  608. ObfDereferenceObject(
  609. IN PVOID Object
  610. )
  611. {
  612. POBJECT_HEADER ObjectHeader;
  613. POBJECT_TYPE ObjectType;
  614. KIRQL OldIrql;
  615. BOOLEAN StartWorkerThread;
  616. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  617. if (ObpDecrPointerCountWithResult( ObjectHeader )) {
  618. OldIrql = KeGetCurrentIrql();
  619. ObjectType = ObjectHeader->Type;
  620. ASSERT(ObjectHeader->HandleCount == 0);
  621. if ((OldIrql == PASSIVE_LEVEL) ||
  622. ((OldIrql == APC_LEVEL) &&
  623. ((ObjectType != NULL) && (ObjectType->TypeInfo.PoolType != NonPagedPool)))) {
  624. //
  625. // Delete the object now.
  626. //
  627. ObpRemoveObjectRoutine( Object );
  628. return;
  629. }
  630. else {
  631. //
  632. // Objects can't be deleted from an IRQL above APC_LEVEL.
  633. // Nonpaged objects can't be deleted from APC_LEVEL.
  634. // So queue the delete operation.
  635. //
  636. ASSERT((ObjectHeader->Type == NULL) || (ObjectHeader->Type->TypeInfo.PoolType == NonPagedPool));
  637. ExAcquireSpinLock( &ObpLock, &OldIrql );
  638. InsertTailList( &ObpRemoveObjectQueue, &ObjectHeader->Entry );
  639. if (!ObpRemoveQueueActive) {
  640. ObpRemoveQueueActive = TRUE;
  641. StartWorkerThread = TRUE;
  642. }
  643. else {
  644. StartWorkerThread = FALSE;
  645. }
  646. #if 0
  647. if (StartWorkerThread) {
  648. KdPrint(( "OB: %08x Starting ObpProcessRemoveObjectQueue thread.\n", Object ));
  649. }
  650. else {
  651. KdPrint(( "OB: %08x Queued to ObpProcessRemoveObjectQueue thread.\n", Object ));
  652. }
  653. #endif // 1
  654. ExReleaseSpinLock( &ObpLock, OldIrql );
  655. if (StartWorkerThread) {
  656. ExInitializeWorkItem( &ObpRemoveObjectWorkItem,
  657. ObpProcessRemoveObjectQueue,
  658. NULL
  659. );
  660. ExQueueWorkItem( &ObpRemoveObjectWorkItem, CriticalWorkQueue );
  661. }
  662. }
  663. }
  664. return;
  665. }
  666. VOID
  667. ObpProcessRemoveObjectQueue(
  668. PVOID Parameter
  669. )
  670. {
  671. PLIST_ENTRY Entry;
  672. POBJECT_HEADER ObjectHeader;
  673. KIRQL OldIrql;
  674. ExAcquireSpinLock( &ObpLock, &OldIrql );
  675. while (!IsListEmpty( &ObpRemoveObjectQueue )) {
  676. Entry = RemoveHeadList( &ObpRemoveObjectQueue );
  677. ExReleaseSpinLock( &ObpLock, OldIrql );
  678. ObjectHeader = CONTAINING_RECORD( Entry,
  679. OBJECT_HEADER,
  680. Entry
  681. );
  682. ObpRemoveObjectRoutine( &ObjectHeader->Body );
  683. ExAcquireSpinLock( &ObpLock, &OldIrql );
  684. }
  685. ObpRemoveQueueActive = FALSE;
  686. ExReleaseSpinLock( &ObpLock, OldIrql );
  687. return;
  688. }
  689. VOID
  690. ObpRemoveObjectRoutine(
  691. PVOID Object
  692. )
  693. {
  694. NTSTATUS Status;
  695. POBJECT_HEADER ObjectHeader;
  696. POBJECT_TYPE ObjectType;
  697. POBJECT_HEADER_CREATOR_INFO CreatorInfo;
  698. POBJECT_HEADER_NAME_INFO NameInfo;
  699. PAGED_CODE();
  700. ObpValidateIrql( "ObpRemoveObjectRoutine" );
  701. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  702. ObjectType = ObjectHeader->Type;
  703. CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader );
  704. NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
  705. ObpEnterObjectTypeMutex( ObjectType );
  706. if (CreatorInfo != NULL && !IsListEmpty( &CreatorInfo->TypeList )) {
  707. RemoveEntryList( &CreatorInfo->TypeList );
  708. }
  709. if (NameInfo != NULL && NameInfo->Name.Buffer != NULL) {
  710. ExFreePool( NameInfo->Name.Buffer );
  711. NameInfo->Name.Buffer = NULL;
  712. NameInfo->Name.Length = 0;
  713. NameInfo->Name.MaximumLength = 0;
  714. }
  715. ObpLeaveObjectTypeMutex( ObjectType );
  716. //
  717. // Security descriptor deletion must precede the
  718. // call to the object's DeleteProcedure.
  719. //
  720. if (ObjectHeader->SecurityDescriptor != NULL) {
  721. KIRQL SaveIrql;
  722. ObpBeginTypeSpecificCallOut( SaveIrql );
  723. Status = (ObjectType->TypeInfo.SecurityProcedure)( Object,
  724. DeleteSecurityDescriptor,
  725. NULL, NULL, NULL,
  726. &ObjectHeader->SecurityDescriptor,
  727. 0, NULL
  728. );
  729. ObpEndTypeSpecificCallOut( SaveIrql, "Security", ObjectType, Object );
  730. }
  731. if (ObjectType->TypeInfo.DeleteProcedure) {
  732. KIRQL SaveIrql;
  733. ObpBeginTypeSpecificCallOut( SaveIrql );
  734. (*(ObjectType->TypeInfo.DeleteProcedure))( Object );
  735. ObpEndTypeSpecificCallOut( SaveIrql, "Delete", ObjectType, Object );
  736. }
  737. ObpFreeObject( Object );
  738. }
  739. VOID
  740. ObpDeleteNameCheck(
  741. IN PVOID Object,
  742. IN BOOLEAN TypeMutexHeld
  743. )
  744. {
  745. POBJECT_HEADER ObjectHeader;
  746. POBJECT_TYPE ObjectType;
  747. POBJECT_HEADER_NAME_INFO NameInfo;
  748. PVOID DirObject;
  749. PAGED_CODE();
  750. ObpValidateIrql( "ObpDeleteNameCheck" );
  751. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  752. NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
  753. ObjectType = ObjectHeader->Type;
  754. if (!TypeMutexHeld) {
  755. ObpEnterObjectTypeMutex( ObjectType );
  756. }
  757. if (ObjectHeader->HandleCount == 0 &&
  758. NameInfo != NULL &&
  759. NameInfo->Name.Length != 0 &&
  760. !(ObjectHeader->Flags & OB_FLAG_PERMANENT_OBJECT)
  761. ) {
  762. ObpLeaveObjectTypeMutex( ObjectType );
  763. ObpEnterRootDirectoryMutex();
  764. DirObject = NULL;
  765. if (Object == ObpLookupDirectoryEntry( NameInfo->Directory,
  766. &NameInfo->Name,
  767. 0
  768. )
  769. ) {
  770. ObpEnterObjectTypeMutex( ObjectType );
  771. if (ObjectHeader->HandleCount == 0) {
  772. KIRQL SaveIrql;
  773. ObpDeleteDirectoryEntry( NameInfo->Directory );
  774. ObpBeginTypeSpecificCallOut( SaveIrql );
  775. (ObjectType->TypeInfo.SecurityProcedure)(
  776. Object,
  777. DeleteSecurityDescriptor,
  778. NULL,
  779. NULL,
  780. NULL,
  781. &ObjectHeader->SecurityDescriptor,
  782. ObjectType->TypeInfo.PoolType,
  783. NULL
  784. );
  785. ObpEndTypeSpecificCallOut( SaveIrql, "Security", ObjectType, Object );
  786. ExFreePool( NameInfo->Name.Buffer );
  787. NameInfo->Name.Buffer = NULL;
  788. NameInfo->Name.Length = 0;
  789. NameInfo->Name.MaximumLength = 0;
  790. DirObject = NameInfo->Directory;
  791. NameInfo->Directory = NULL;
  792. }
  793. ObpLeaveObjectTypeMutex( ObjectType );
  794. }
  795. ObpLeaveRootDirectoryMutex();
  796. if (DirObject != NULL) {
  797. ObDereferenceObject( DirObject );
  798. ObDereferenceObject( Object );
  799. }
  800. }
  801. else {
  802. ObpLeaveObjectTypeMutex( ObjectType );
  803. }
  804. }
  805. //
  806. // Thunks to support standard call callers
  807. //
  808. #ifdef ObDereferenceObject
  809. #undef ObDereferenceObject
  810. #endif
  811. VOID
  812. ObDereferenceObject(
  813. IN PVOID Object
  814. )
  815. {
  816. ObfDereferenceObject (Object) ;
  817. }