Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2947 lines
76 KiB

  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. #undef ObReferenceObjectByHandle
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text(INIT,ObpInitStackTrace)
  15. #pragma alloc_text(PAGE,ObOpenObjectByName)
  16. #pragma alloc_text(PAGE,ObOpenObjectByPointer)
  17. #pragma alloc_text(PAGE,ObReferenceObjectByHandle)
  18. #pragma alloc_text(PAGE,ObpReferenceProcessObjectByHandle)
  19. #pragma alloc_text(PAGE,ObReferenceObjectByName)
  20. #pragma alloc_text(PAGE,ObReferenceFileObjectForWrite)
  21. #pragma alloc_text(PAGE,ObpProcessRemoveObjectQueue)
  22. #pragma alloc_text(PAGE,ObpRemoveObjectRoutine)
  23. #pragma alloc_text(PAGE,ObpDeleteNameCheck)
  24. #pragma alloc_text(PAGE,ObpAuditObjectAccess)
  25. #pragma alloc_text(PAGE,ObIsObjectDeletionInline)
  26. #pragma alloc_text(PAGE,ObAuditObjectAccess)
  27. #endif
  28. //
  29. //
  30. // Stack Trace code
  31. //
  32. //
  33. ULONG ObpTraceNoDeregister = 0;
  34. WCHAR ObpTracePoolTagsBuffer[128] = { 0 };
  35. ULONG ObpTracePoolTagsLength = sizeof(ObpTracePoolTagsBuffer);
  36. ULONG ObpTracePoolTags[16];
  37. BOOLEAN ObpTraceEnabled = FALSE;
  38. #ifdef POOL_TAGGING
  39. #define OBTRACE_OBJECTBUCKETS 401 // # of buckets in the object hash table (a prime)
  40. #define OBTRACE_STACKS 14747 // max # of unique stack traces (a prime)
  41. #define OBTRACE_STACKSPEROBJECT 32768 // max number of object references
  42. #define OBTRACE_TRACEDEPTH 16 // depth of stack traces
  43. //
  44. // The constants below are used by the !obtrace debugger extension
  45. //
  46. const ObpObjectBuckets = OBTRACE_OBJECTBUCKETS;
  47. const ObpMaxStacks = OBTRACE_STACKS;
  48. const ObpStacksPerObject = OBTRACE_STACKSPEROBJECT;
  49. const ObpTraceDepth = OBTRACE_TRACEDEPTH;
  50. //
  51. // Object reference stacktrace structure
  52. //
  53. typedef struct _OBJECT_REF_TRACE {
  54. PVOID StackTrace[OBTRACE_TRACEDEPTH];
  55. } OBJECT_REF_TRACE, *POBJECT_REF_TRACE;
  56. typedef struct _OBJECT_REF_STACK_INFO {
  57. USHORT Sequence;
  58. USHORT Index;
  59. } OBJECT_REF_STACK_INFO, *POBJECT_REF_STACK_INFO;
  60. //
  61. // Object reference info structure
  62. //
  63. typedef struct _OBJECT_REF_INFO {
  64. POBJECT_HEADER ObjectHeader;
  65. PVOID NextRef;
  66. UCHAR ImageFileName[16];
  67. ULONG NextPos;
  68. OBJECT_REF_STACK_INFO StackInfo[OBTRACE_STACKSPEROBJECT];
  69. } OBJECT_REF_INFO, *POBJECT_REF_INFO;
  70. //
  71. // The stack hash table, and the object hash table
  72. //
  73. OBJECT_REF_TRACE *ObpStackTable = NULL;
  74. POBJECT_REF_INFO *ObpObjectTable = NULL;
  75. //
  76. // Some statistics
  77. //
  78. ULONG ObpNumStackTraces;
  79. ULONG ObpNumTracedObjects;
  80. ULONG ObpStackSequence;
  81. //
  82. // Spin lock for object tracing
  83. //
  84. KSPIN_LOCK ObpStackTraceLock;
  85. #define OBTRACE_HASHOBJECT(x) (((((ULONG)(ULONG_PTR)(&(x)->Body)) >> 4) & 0xfffff) % OBTRACE_OBJECTBUCKETS)
  86. POBJECT_REF_INFO
  87. ObpGetObjectRefInfo (
  88. POBJECT_HEADER ObjectHeader
  89. )
  90. /*++
  91. Routine Description:
  92. This routine returns a pointer to the OBJECT_REF_INFO for the
  93. specified object, or NULL, if it doesn't exist.
  94. Arguments:
  95. ObjectHeader - Pointer to the object header
  96. Return Value:
  97. The pointer to a OBJECT_REF_INFO object for the specified object.
  98. --*/
  99. {
  100. POBJECT_REF_INFO ObjectRefInfo = ObpObjectTable[OBTRACE_HASHOBJECT(ObjectHeader)];
  101. while (ObjectRefInfo && ObjectRefInfo->ObjectHeader != ObjectHeader) {
  102. ObjectRefInfo = (POBJECT_REF_INFO)ObjectRefInfo->NextRef;
  103. }
  104. return ObjectRefInfo;
  105. }
  106. ULONG
  107. ObpGetTraceIndex (
  108. POBJECT_REF_TRACE Trace
  109. )
  110. /*++
  111. Routine Description:
  112. This routine returns the index of 'Trace' in the stack
  113. trace hash table (ObpStackTable). If Trace does not exist
  114. in the table, it is added, and the new index is returned.
  115. Arguments:
  116. Trace - Pointer to a stack trace to find in the table
  117. Return Value:
  118. The index of Trace in ObpStackTable
  119. --*/
  120. {
  121. ULONG_PTR Value = 0;
  122. ULONG Index;
  123. PUSHORT Key;
  124. ULONG Hash;
  125. //
  126. // Determine the hash value for the stack trace
  127. //
  128. Key = (PUSHORT)Trace->StackTrace;
  129. for (Index = 0; Index < sizeof(Trace->StackTrace) / sizeof(*Key); Index += 2) {
  130. Value += Key[Index] ^ Key[Index + 1];
  131. }
  132. Hash = ((ULONG)Value) % OBTRACE_STACKS;
  133. //
  134. // Look up the trace at that index (linear probing)
  135. //
  136. while (ObpStackTable[Hash].StackTrace[0] != NULL &&
  137. RtlCompareMemory(&ObpStackTable[Hash], Trace, sizeof(OBJECT_REF_TRACE)) != sizeof(OBJECT_REF_TRACE)) {
  138. Hash = (Hash + 1) % OBTRACE_STACKS;
  139. if (Hash == ((ULONG)Value) % OBTRACE_STACKS) {
  140. return OBTRACE_STACKS;
  141. }
  142. }
  143. //
  144. // If the trace doesn't already exist in the table, add it.
  145. //
  146. if (ObpStackTable[Hash].StackTrace[0] == NULL) {
  147. RtlCopyMemory(&ObpStackTable[Hash], Trace, sizeof(OBJECT_REF_TRACE));
  148. ObpNumStackTraces++;
  149. }
  150. return Hash;
  151. }
  152. VOID
  153. ObpInitStackTrace()
  154. /*++
  155. Routine Description:
  156. Initialize the ob ref/deref stack-tracing code.
  157. Arguments:
  158. Return Value:
  159. --*/
  160. {
  161. ULONG i,j;
  162. KeInitializeSpinLock( &ObpStackTraceLock );
  163. RtlZeroMemory(ObpTracePoolTags, sizeof(ObpTracePoolTags));
  164. ObpStackSequence = 0;
  165. ObpNumStackTraces = 0;
  166. ObpNumTracedObjects = 0;
  167. ObpTraceEnabled = FALSE;
  168. //
  169. // Loop through the ObpTracePoolTagsBuffer string, and convert it to
  170. // an array of pool tags.
  171. //
  172. // The string should be in the form "Tag1;Tag2;Tag3; ..."
  173. //
  174. for (i = 0; i < sizeof(ObpTracePoolTags) / sizeof(ULONG); i++) {
  175. for (j = 0; j < 4; j++) {
  176. ObpTracePoolTags[i] = (ObpTracePoolTags[i] << 8) | ObpTracePoolTagsBuffer[5*i+(3-j)];
  177. }
  178. }
  179. //
  180. // If object tracing was turned on via the registry key, then we
  181. // need to allocate memory for the tables. If the memory allocations
  182. // fail, we turn off tracing by clearing the pool tag array.
  183. //
  184. if (ObpTracePoolTags[0] != 0) {
  185. ObpStackTable = ExAllocatePoolWithTag( NonPagedPool,
  186. OBTRACE_STACKS * sizeof(OBJECT_REF_TRACE),
  187. 'TSbO' );
  188. if (ObpStackTable != NULL) {
  189. RtlZeroMemory(ObpStackTable, OBTRACE_STACKS * sizeof(OBJECT_REF_TRACE));
  190. ObpObjectTable = ExAllocatePoolWithTag( NonPagedPool,
  191. OBTRACE_OBJECTBUCKETS * sizeof(POBJECT_REF_INFO),
  192. 'TSbO' );
  193. if (ObpObjectTable != NULL) {
  194. RtlZeroMemory(ObpObjectTable, OBTRACE_OBJECTBUCKETS * sizeof(POBJECT_REF_INFO));
  195. ObpTraceEnabled = TRUE;
  196. } else {
  197. ExFreePoolWithTag( ObpStackTable, 'TSbO' );
  198. ObpStackTable = NULL;
  199. RtlZeroMemory(ObpTracePoolTags, sizeof(ObpTracePoolTags));
  200. }
  201. } else {
  202. RtlZeroMemory(ObpTracePoolTags, sizeof(ObpTracePoolTags));
  203. }
  204. }
  205. }
  206. BOOLEAN
  207. ObpIsObjectTraced (
  208. POBJECT_HEADER ObjectHeader
  209. )
  210. /*++
  211. Routine Description:
  212. This routine determines if an object should have its references
  213. and dereferences traced.
  214. Arguments:
  215. ObjectHeader - The object to check
  216. Return Value:
  217. TRUE, if the object should be traced, and FALSE, otherwise
  218. --*/
  219. {
  220. ULONG i;
  221. if (ObjectHeader != NULL) {
  222. //
  223. // Loop through the ObpTracePoolTags array, and return true if
  224. // the object type key matches one of them.
  225. //
  226. for (i = 0; i < sizeof(ObpTracePoolTags) / sizeof(ULONG); i++) {
  227. if (ObjectHeader->Type->Key == ObpTracePoolTags[i]) {
  228. return TRUE;
  229. }
  230. }
  231. }
  232. return FALSE;
  233. }
  234. VOID
  235. ObpRegisterObject (
  236. POBJECT_HEADER ObjectHeader
  237. )
  238. /*++
  239. Routine Description:
  240. This routine is called once for each object that is created.
  241. It determines if the object should be traced, and if so, adds
  242. it to the hash table.
  243. Arguments:
  244. ObjectHeader - The object to register
  245. Return Value:
  246. --*/
  247. {
  248. KIRQL OldIrql;
  249. POBJECT_REF_INFO ObjectRefInfo = NULL;
  250. //
  251. // Are we tracing this object?
  252. //
  253. if (ObpIsObjectTraced( ObjectHeader )) {
  254. ExAcquireSpinLock( &ObpStackTraceLock, &OldIrql );
  255. ObjectRefInfo = ObpGetObjectRefInfo(ObjectHeader);
  256. if (ObjectRefInfo == NULL) {
  257. //
  258. // Allocate a new OBJECT_REF_INFO for the object
  259. //
  260. ObjectRefInfo = ExAllocatePoolWithTag( NonPagedPool,
  261. sizeof(OBJECT_REF_INFO),
  262. 'TSbO' );
  263. if (ObjectRefInfo != NULL) {
  264. //
  265. // Place the object into the hash table (at the beginning of the bucket)
  266. //
  267. ObjectRefInfo->NextRef = ObpObjectTable[OBTRACE_HASHOBJECT(ObjectHeader)];
  268. ObpObjectTable[OBTRACE_HASHOBJECT(ObjectHeader)] = ObjectRefInfo;
  269. } else {
  270. DbgPrint( "ObpRegisterObject - ExAllocatePoolWithTag failed.\n" );
  271. }
  272. }
  273. if (ObjectRefInfo != NULL) {
  274. ObpNumTracedObjects++;
  275. //
  276. // Initialize the OBJECT_REF_INFO
  277. //
  278. ObjectRefInfo->ObjectHeader = ObjectHeader;
  279. RtlCopyMemory( ObjectRefInfo->ImageFileName,
  280. PsGetCurrentProcess()->ImageFileName,
  281. sizeof(ObjectRefInfo->ImageFileName) );
  282. ObjectRefInfo->NextPos = 0;
  283. RtlZeroMemory( ObjectRefInfo->StackInfo,
  284. sizeof(ObjectRefInfo->StackInfo) );
  285. }
  286. ExReleaseSpinLock( &ObpStackTraceLock, OldIrql );
  287. }
  288. }
  289. VOID
  290. ObpDeregisterObject (
  291. POBJECT_HEADER ObjectHeader
  292. )
  293. /*++
  294. Routine Description:
  295. This routine is called once for each object that is deleted.
  296. It determines if the object is traced, and if so, deletes
  297. it from the hash table.
  298. Arguments:
  299. ObjectHeader - The object to deregister
  300. Return Value:
  301. --*/
  302. {
  303. KIRQL OldIrql;
  304. POBJECT_REF_INFO ObjectRefInfo = NULL;
  305. //
  306. // Are we tracing this object?
  307. //
  308. if (ObpIsObjectTraced( ObjectHeader )) {
  309. ExAcquireSpinLock( &ObpStackTraceLock, &OldIrql );
  310. ObjectRefInfo = ObpObjectTable[OBTRACE_HASHOBJECT(ObjectHeader)];
  311. if (ObjectRefInfo != NULL) {
  312. //
  313. // Remove the entry from the list
  314. //
  315. if (ObjectRefInfo->ObjectHeader == ObjectHeader) {
  316. ObpObjectTable[OBTRACE_HASHOBJECT(ObjectHeader)] = ObjectRefInfo->NextRef;
  317. } else {
  318. POBJECT_REF_INFO PrevObjectRefInfo;
  319. do {
  320. PrevObjectRefInfo = ObjectRefInfo;
  321. ObjectRefInfo = ObjectRefInfo->NextRef;
  322. } while (ObjectRefInfo && (ObjectRefInfo->ObjectHeader != ObjectHeader));
  323. if (ObjectRefInfo && (ObjectRefInfo->ObjectHeader == ObjectHeader)) {
  324. PrevObjectRefInfo->NextRef = ObjectRefInfo->NextRef;
  325. }
  326. }
  327. }
  328. //
  329. // Free the object we just removed from the list
  330. //
  331. if (ObjectRefInfo != NULL) {
  332. ExFreePoolWithTag( ObjectRefInfo, 'TSbO' );
  333. }
  334. ExReleaseSpinLock( &ObpStackTraceLock, OldIrql );
  335. }
  336. }
  337. VOID
  338. ObpPushStackInfo (
  339. POBJECT_HEADER ObjectHeader,
  340. BOOLEAN IsRef
  341. )
  342. /*++
  343. Routine Description:
  344. This routine is called each time an object is referenced or
  345. dereferenced. It determines if the object is traced, and if
  346. so, adds the necessary trace to the object reference info.
  347. Arguments:
  348. ObjectHeader - The object to trace.
  349. IsRef - TRUE if this is a ref, FALSE if a deref
  350. Return Value:
  351. --*/
  352. {
  353. KIRQL OldIrql;
  354. POBJECT_REF_INFO ObjectInfo;
  355. //
  356. // Are we tracing this object?
  357. //
  358. if (ObpIsObjectTraced( ObjectHeader )) {
  359. ExAcquireSpinLock( &ObpStackTraceLock, &OldIrql );
  360. ObjectInfo = ObpGetObjectRefInfo( ObjectHeader );
  361. if (ObjectInfo) {
  362. OBJECT_REF_TRACE Stack = { 0 };
  363. ULONG StackIndex;
  364. ULONG CapturedTraces;
  365. //
  366. // Capture the stack trace
  367. //
  368. CapturedTraces = RtlCaptureStackBackTrace( 1, OBTRACE_TRACEDEPTH, Stack.StackTrace, &StackIndex );
  369. if (CapturedTraces >= 1) {
  370. //
  371. // Get the table index for the trace
  372. //
  373. StackIndex = ObpGetTraceIndex( &Stack );
  374. if (StackIndex < OBTRACE_STACKS) {
  375. //
  376. // Add new reference info to the object
  377. //
  378. if (ObjectInfo->NextPos < OBTRACE_STACKSPEROBJECT) {
  379. ObjectInfo->StackInfo[ObjectInfo->NextPos].Index = (USHORT)StackIndex | (IsRef ? 0x8000 : 0);
  380. ObpStackSequence++;
  381. ObjectInfo->StackInfo[ObjectInfo->NextPos].Sequence = (USHORT)ObpStackSequence;
  382. ObjectInfo->NextPos++;
  383. }
  384. } else {
  385. DbgPrint( "ObpPushStackInfo -- ObpStackTable overflow!\n" );
  386. }
  387. }
  388. }
  389. ExReleaseSpinLock( &ObpStackTraceLock, OldIrql );
  390. }
  391. }
  392. #endif //POOL_TAGGING
  393. //
  394. //
  395. // End Stack trace code
  396. //
  397. typedef struct _OB_TEMP_BUFFER {
  398. ACCESS_STATE LocalAccessState;
  399. OBJECT_CREATE_INFORMATION ObjectCreateInfo;
  400. OBP_LOOKUP_CONTEXT LookupContext;
  401. AUX_ACCESS_DATA AuxData;
  402. } OB_TEMP_BUFFER, *POB_TEMP_BUFFER;
  403. NTSTATUS
  404. ObOpenObjectByName (
  405. IN POBJECT_ATTRIBUTES ObjectAttributes,
  406. IN POBJECT_TYPE ObjectType OPTIONAL,
  407. IN KPROCESSOR_MODE AccessMode,
  408. IN OUT PACCESS_STATE AccessState OPTIONAL,
  409. IN ACCESS_MASK DesiredAccess OPTIONAL,
  410. IN OUT PVOID ParseContext OPTIONAL,
  411. OUT PHANDLE Handle
  412. )
  413. /*++
  414. Routine Description:
  415. This function opens an object with full access validation and auditing.
  416. Soon after entering we capture the SubjectContext for the caller. This
  417. context must remain captured until auditing is complete, and passed to
  418. any routine that may have to do access checking or auditing.
  419. Arguments:
  420. ObjectAttributes - Supplies a pointer to the object attributes.
  421. ObjectType - Supplies an optional pointer to the object type descriptor.
  422. AccessMode - Supplies the processor mode of the access.
  423. AccessState - Supplies an optional pointer to the current access status
  424. describing already granted access types, the privileges used to get
  425. them, and any access types yet to be granted.
  426. DesiredAcess - Supplies the desired access to the object.
  427. ParseContext - Supplies an optional pointer to parse context.
  428. Handle - Supplies a pointer to a variable that receives the handle value.
  429. Return Value:
  430. If the object is successfully opened, then a handle for the object is
  431. created and a success status is returned. Otherwise, an error status is
  432. returned.
  433. --*/
  434. {
  435. NTSTATUS Status;
  436. NTSTATUS HandleStatus;
  437. PVOID ExistingObject;
  438. HANDLE NewHandle;
  439. OB_OPEN_REASON OpenReason;
  440. POBJECT_HEADER ObjectHeader;
  441. UNICODE_STRING CapturedObjectName;
  442. PGENERIC_MAPPING GenericMapping;
  443. PAGED_CODE();
  444. ObpValidateIrql("ObOpenObjectByName");
  445. //
  446. // If the object attributes are not specified, then return an error.
  447. //
  448. *Handle = NULL;
  449. if (!ARGUMENT_PRESENT(ObjectAttributes)) {
  450. Status = STATUS_INVALID_PARAMETER;
  451. } else {
  452. POB_TEMP_BUFFER TempBuffer;
  453. TempBuffer = ExAllocatePoolWithTag( NonPagedPool,
  454. sizeof(OB_TEMP_BUFFER),
  455. 'tSbO'
  456. );
  457. if (TempBuffer == NULL) {
  458. return STATUS_INSUFFICIENT_RESOURCES;
  459. }
  460. //
  461. // Capture the object creation information.
  462. //
  463. Status = ObpCaptureObjectCreateInformation( ObjectType,
  464. AccessMode,
  465. AccessMode,
  466. ObjectAttributes,
  467. &CapturedObjectName,
  468. &TempBuffer->ObjectCreateInfo,
  469. TRUE );
  470. //
  471. // If the object creation information is successfully captured,
  472. // then generate the access state.
  473. //
  474. if (NT_SUCCESS(Status)) {
  475. if (!ARGUMENT_PRESENT(AccessState)) {
  476. //
  477. // If an object type descriptor is specified, then use
  478. // associated generic mapping. Otherwise, use no generic
  479. // mapping.
  480. //
  481. GenericMapping = NULL;
  482. if (ARGUMENT_PRESENT(ObjectType)) {
  483. GenericMapping = &ObjectType->TypeInfo.GenericMapping;
  484. }
  485. AccessState = &TempBuffer->LocalAccessState;
  486. Status = SeCreateAccessState( &TempBuffer->LocalAccessState,
  487. &TempBuffer->AuxData,
  488. DesiredAccess,
  489. GenericMapping );
  490. if (!NT_SUCCESS(Status)) {
  491. goto FreeCreateInfo;
  492. }
  493. }
  494. //
  495. // If there is a security descriptor specified in the object
  496. // attributes, then capture it in the access state.
  497. //
  498. if (TempBuffer->ObjectCreateInfo.SecurityDescriptor != NULL) {
  499. AccessState->SecurityDescriptor = TempBuffer->ObjectCreateInfo.SecurityDescriptor;
  500. }
  501. //
  502. // Validate the access state.
  503. //
  504. Status = ObpValidateAccessMask(AccessState);
  505. //
  506. // If the access state is valid, then lookup the object by
  507. // name.
  508. //
  509. if (NT_SUCCESS(Status)) {
  510. Status = ObpLookupObjectName( TempBuffer->ObjectCreateInfo.RootDirectory,
  511. &CapturedObjectName,
  512. TempBuffer->ObjectCreateInfo.Attributes,
  513. ObjectType,
  514. AccessMode,
  515. ParseContext,
  516. TempBuffer->ObjectCreateInfo.SecurityQos,
  517. NULL,
  518. AccessState,
  519. &TempBuffer->LookupContext,
  520. &ExistingObject );
  521. //
  522. // If the object was successfully looked up, then attempt
  523. // to create or open a handle.
  524. //
  525. if (NT_SUCCESS(Status)) {
  526. ObjectHeader = OBJECT_TO_OBJECT_HEADER(ExistingObject);
  527. //
  528. // If the object is being created, then the operation
  529. // must be a open-if operation. Otherwise, a handle to
  530. // an object is being opened.
  531. //
  532. if (ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) {
  533. OpenReason = ObCreateHandle;
  534. if (ObjectHeader->ObjectCreateInfo != NULL) {
  535. ObpFreeObjectCreateInformation(ObjectHeader->ObjectCreateInfo);
  536. ObjectHeader->ObjectCreateInfo = NULL;
  537. }
  538. } else {
  539. OpenReason = ObOpenHandle;
  540. }
  541. //
  542. // If any of the object attributes are invalid, then
  543. // return an error status.
  544. //
  545. if (ObjectHeader->Type->TypeInfo.InvalidAttributes & TempBuffer->ObjectCreateInfo.Attributes) {
  546. Status = STATUS_INVALID_PARAMETER;
  547. ObpReleaseLookupContext( &TempBuffer->LookupContext );
  548. } else {
  549. //
  550. // The status returned by the object lookup routine
  551. // must be returned if the creation of a handle is
  552. // successful. Otherwise, the handle creation status
  553. // is returned.
  554. //
  555. HandleStatus = ObpCreateHandle( OpenReason,
  556. ExistingObject,
  557. ObjectType,
  558. AccessState,
  559. 0,
  560. TempBuffer->ObjectCreateInfo.Attributes,
  561. &TempBuffer->LookupContext,
  562. AccessMode,
  563. (PVOID *)NULL,
  564. &NewHandle );
  565. if (!NT_SUCCESS(HandleStatus)) {
  566. ObDereferenceObject(ExistingObject);
  567. Status = HandleStatus;
  568. } else {
  569. *Handle = NewHandle;
  570. }
  571. }
  572. } else {
  573. ObpReleaseLookupContext( &TempBuffer->LookupContext );
  574. }
  575. }
  576. //
  577. // If the access state was generated, then delete the access
  578. // state.
  579. //
  580. if (AccessState == &TempBuffer->LocalAccessState) {
  581. SeDeleteAccessState(AccessState);
  582. }
  583. //
  584. // Free the create information.
  585. //
  586. FreeCreateInfo:
  587. ObpReleaseObjectCreateInformation(&TempBuffer->ObjectCreateInfo);
  588. if (CapturedObjectName.Buffer != NULL) {
  589. ObpFreeObjectNameBuffer(&CapturedObjectName);
  590. }
  591. }
  592. ExFreePool(TempBuffer);
  593. }
  594. return Status;
  595. }
  596. NTSTATUS
  597. ObOpenObjectByPointer (
  598. IN PVOID Object,
  599. IN ULONG HandleAttributes,
  600. IN PACCESS_STATE PassedAccessState OPTIONAL,
  601. IN ACCESS_MASK DesiredAccess,
  602. IN POBJECT_TYPE ObjectType,
  603. IN KPROCESSOR_MODE AccessMode,
  604. OUT PHANDLE Handle
  605. )
  606. /*++
  607. Routine Description:
  608. This routine opens an object referenced by a pointer.
  609. Arguments:
  610. Object - A pointer to the object being opened.
  611. HandleAttributes - The desired attributes for the handle, such
  612. as OBJ_INHERIT, OBJ_PERMANENT, OBJ_EXCLUSIVE, OBJ_CASE_INSENSITIVE,
  613. OBJ_OPENIF, and OBJ_OPENLINK
  614. PassedAccessState - Supplies an optional pointer to the current access
  615. status describing already granted access types, the privileges used
  616. to get them, and any access types yet to be granted.
  617. DesiredAcess - Supplies the desired access to the object.
  618. ObjectType - Supplies the type of the object being opened
  619. AccessMode - Supplies the processor mode of the access.
  620. Handle - Supplies a pointer to a variable that receives the handle value.
  621. Return Value:
  622. An appropriate NTSTATUS value
  623. --*/
  624. {
  625. NTSTATUS Status;
  626. HANDLE NewHandle = (HANDLE)-1;
  627. POBJECT_HEADER ObjectHeader;
  628. ACCESS_STATE LocalAccessState;
  629. PACCESS_STATE AccessState = NULL;
  630. AUX_ACCESS_DATA AuxData;
  631. PAGED_CODE();
  632. ObpValidateIrql( "ObOpenObjectByPointer" );
  633. //
  634. // First increment the pointer count for the object. This routine
  635. // also checks the object types
  636. //
  637. Status = ObReferenceObjectByPointer( Object,
  638. 0,
  639. ObjectType,
  640. AccessMode );
  641. if (NT_SUCCESS( Status )) {
  642. //
  643. // Get the object header for the input object body
  644. //
  645. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  646. //
  647. // If the caller did not pass in an access state then
  648. // we will create a new one based on the desired access
  649. // and the object types generic mapping
  650. //
  651. if (!ARGUMENT_PRESENT( PassedAccessState )) {
  652. Status = SeCreateAccessState( &LocalAccessState,
  653. &AuxData,
  654. DesiredAccess,
  655. &ObjectHeader->Type->TypeInfo.GenericMapping );
  656. if (!NT_SUCCESS( Status )) {
  657. ObDereferenceObject( Object );
  658. return(Status);
  659. }
  660. AccessState = &LocalAccessState;
  661. //
  662. // Otherwise the caller did specify an access state so
  663. // we use the one passed in.
  664. //
  665. } else {
  666. AccessState = PassedAccessState;
  667. }
  668. //
  669. // Make sure the caller is asking for handle attributes that are
  670. // valid for the given object type
  671. //
  672. if (ObjectHeader->Type->TypeInfo.InvalidAttributes & HandleAttributes) {
  673. if (AccessState == &LocalAccessState) {
  674. SeDeleteAccessState( AccessState );
  675. }
  676. ObDereferenceObject( Object );
  677. return( STATUS_INVALID_PARAMETER );
  678. }
  679. //
  680. // We've referenced the object and have an access state to give
  681. // the new handle so now create a new handle for the object.
  682. //
  683. Status = ObpCreateHandle( ObOpenHandle,
  684. Object,
  685. ObjectType,
  686. AccessState,
  687. 0,
  688. HandleAttributes,
  689. NULL,
  690. AccessMode,
  691. (PVOID *)NULL,
  692. &NewHandle );
  693. if (!NT_SUCCESS( Status )) {
  694. ObDereferenceObject( Object );
  695. }
  696. }
  697. //
  698. // If we successfully opened by object and created a new handle
  699. // then set the output variable correctly
  700. //
  701. if (NT_SUCCESS( Status )) {
  702. *Handle = NewHandle;
  703. } else {
  704. *Handle = NULL;
  705. }
  706. //
  707. // Check if we used our own access state and now need to cleanup
  708. //
  709. if (AccessState == &LocalAccessState) {
  710. SeDeleteAccessState( AccessState );
  711. }
  712. //
  713. // And return to our caller
  714. //
  715. return( Status );
  716. }
  717. NTSTATUS
  718. ObReferenceObjectByHandle (
  719. IN HANDLE Handle,
  720. IN ACCESS_MASK DesiredAccess,
  721. IN POBJECT_TYPE ObjectType OPTIONAL,
  722. IN KPROCESSOR_MODE AccessMode,
  723. OUT PVOID *Object,
  724. OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL
  725. )
  726. /*++
  727. Routine Description:
  728. Given a handle to an object this routine returns a pointer
  729. to the body of the object with proper ref counts
  730. Arguments:
  731. Handle - Supplies a handle to the object being referenced. It can
  732. also be the result of NtCurrentProcess or NtCurrentThread
  733. DesiredAccess - Supplies the access being requested by the caller
  734. ObjectType - Optionally supplies the type of the object we
  735. are expecting
  736. AccessMode - Supplies the processor mode of the access
  737. Object - Receives a pointer to the object body if the operation
  738. is successful
  739. HandleInformation - Optionally receives information regarding the
  740. input handle.
  741. Return Value:
  742. An appropriate NTSTATUS value
  743. --*/
  744. {
  745. ACCESS_MASK GrantedAccess;
  746. PHANDLE_TABLE HandleTable;
  747. POBJECT_HEADER ObjectHeader;
  748. PHANDLE_TABLE_ENTRY ObjectTableEntry;
  749. PEPROCESS Process;
  750. NTSTATUS Status;
  751. PETHREAD Thread;
  752. ObpValidateIrql("ObReferenceObjectByHandle");
  753. Thread = PsGetCurrentThread ();
  754. *Object = NULL;
  755. //
  756. // Check is this handle is a kernel handle or one of the two builtin pseudo handles
  757. //
  758. if ((LONG)(ULONG_PTR) Handle < 0) {
  759. //
  760. // If the handle is equal to the current process handle and the object
  761. // type is NULL or type process, then attempt to translate a handle to
  762. // the current process. Otherwise, check if the handle is the current
  763. // thread handle.
  764. //
  765. if (Handle == NtCurrentProcess()) {
  766. if ((ObjectType == PsProcessType) || (ObjectType == NULL)) {
  767. Process = PsGetCurrentProcessByThread(Thread);
  768. GrantedAccess = Process->GrantedAccess;
  769. if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
  770. (AccessMode == KernelMode)) {
  771. ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process);
  772. if (ARGUMENT_PRESENT(HandleInformation)) {
  773. HandleInformation->GrantedAccess = GrantedAccess;
  774. HandleInformation->HandleAttributes = 0;
  775. }
  776. ObpIncrPointerCount(ObjectHeader);
  777. *Object = Process;
  778. ASSERT( *Object != NULL );
  779. Status = STATUS_SUCCESS;
  780. } else {
  781. Status = STATUS_ACCESS_DENIED;
  782. }
  783. } else {
  784. Status = STATUS_OBJECT_TYPE_MISMATCH;
  785. }
  786. return Status;
  787. //
  788. // If the handle is equal to the current thread handle and the object
  789. // type is NULL or type thread, then attempt to translate a handle to
  790. // the current thread. Otherwise, the we'll try and translate the
  791. // handle
  792. //
  793. } else if (Handle == NtCurrentThread()) {
  794. if ((ObjectType == PsThreadType) || (ObjectType == NULL)) {
  795. GrantedAccess = Thread->GrantedAccess;
  796. if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
  797. (AccessMode == KernelMode)) {
  798. ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread);
  799. if (ARGUMENT_PRESENT(HandleInformation)) {
  800. HandleInformation->GrantedAccess = GrantedAccess;
  801. HandleInformation->HandleAttributes = 0;
  802. }
  803. ObpIncrPointerCount(ObjectHeader);
  804. *Object = Thread;
  805. ASSERT( *Object != NULL );
  806. Status = STATUS_SUCCESS;
  807. } else {
  808. Status = STATUS_ACCESS_DENIED;
  809. }
  810. } else {
  811. Status = STATUS_OBJECT_TYPE_MISMATCH;
  812. }
  813. return Status;
  814. } else if (AccessMode == KernelMode) {
  815. //
  816. // Make the handle look like a regular handle
  817. //
  818. Handle = DecodeKernelHandle( Handle );
  819. //
  820. // The global kernel handle table
  821. //
  822. HandleTable = ObpKernelHandleTable;
  823. } else {
  824. //
  825. // The previous mode was user for this kernel handle value. Reject it here.
  826. //
  827. return STATUS_INVALID_HANDLE;
  828. }
  829. } else {
  830. HandleTable = PsGetCurrentProcessByThread(Thread)->ObjectTable;
  831. }
  832. ASSERT(HandleTable != NULL);
  833. //
  834. // Protect this thread from being suspended while we hold the handle table entry lock
  835. //
  836. KeEnterCriticalRegionThread(&Thread->Tcb);
  837. //
  838. // Translate the specified handle to an object table index.
  839. //
  840. ObjectTableEntry = ExMapHandleToPointerEx ( HandleTable, Handle, AccessMode );
  841. //
  842. // Make sure the object table entry really does exist
  843. //
  844. if (ObjectTableEntry != NULL) {
  845. ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
  846. if ((ObjectHeader->Type == ObjectType) || (ObjectType == NULL)) {
  847. #if i386
  848. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  849. GrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );
  850. } else {
  851. GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
  852. }
  853. #else
  854. GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
  855. #endif // i386
  856. if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
  857. (AccessMode == KernelMode)) {
  858. PHANDLE_TABLE_ENTRY_INFO ObjectInfo;
  859. ObjectInfo = ExGetHandleInfo(HandleTable, Handle, TRUE);
  860. //
  861. // Access to the object is allowed. Return the handle
  862. // information is requested, increment the object
  863. // pointer count, unlock the handle table and return
  864. // a success status.
  865. //
  866. // Note that this is the only successful return path
  867. // out of this routine if the user did not specify
  868. // the current process or current thread in the input
  869. // handle.
  870. //
  871. if (ARGUMENT_PRESENT(HandleInformation)) {
  872. HandleInformation->GrantedAccess = GrantedAccess;
  873. HandleInformation->HandleAttributes = ObpGetHandleAttributes(ObjectTableEntry);
  874. }
  875. //
  876. // If this object was audited when it was opened, it may
  877. // be necessary to generate an audit now. Check the audit
  878. // mask that was saved when the handle was created.
  879. //
  880. // It is safe to do this check in a non-atomic fashion,
  881. // because bits will never be added to this mask once it is
  882. // created.
  883. //
  884. if ( (ObjectTableEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE) &&
  885. (ObjectInfo != NULL) &&
  886. (ObjectInfo->AuditMask != 0) &&
  887. (DesiredAccess != 0) &&
  888. (AccessMode != KernelMode)) {
  889. ObpAuditObjectAccess( Handle, ObjectInfo, &ObjectHeader->Type->Name, DesiredAccess );
  890. }
  891. ObpIncrPointerCount(ObjectHeader);
  892. ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry );
  893. KeLeaveCriticalRegionThread(&Thread->Tcb);
  894. *Object = &ObjectHeader->Body;
  895. ASSERT( *Object != NULL );
  896. return STATUS_SUCCESS;
  897. } else {
  898. Status = STATUS_ACCESS_DENIED;
  899. }
  900. } else {
  901. Status = STATUS_OBJECT_TYPE_MISMATCH;
  902. }
  903. ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry );
  904. } else {
  905. Status = STATUS_INVALID_HANDLE;
  906. }
  907. KeLeaveCriticalRegionThread(&Thread->Tcb);
  908. return Status;
  909. }
  910. NTSTATUS
  911. ObpReferenceProcessObjectByHandle (
  912. IN HANDLE Handle,
  913. IN PEPROCESS Process,
  914. IN PHANDLE_TABLE HandleTable,
  915. IN KPROCESSOR_MODE AccessMode,
  916. OUT PVOID *Object,
  917. OUT POBJECT_HANDLE_INFORMATION HandleInformation,
  918. OUT PACCESS_MASK AuditMask
  919. )
  920. /*++
  921. Routine Description:
  922. Given a handle to an object a process and its handle table
  923. this routine returns a pointer to the body of the object with
  924. proper ref counts
  925. Arguments:
  926. Handle - Supplies a handle to the object being referenced. It can
  927. also be the result of NtCurrentProcess or NtCurrentThread
  928. Process - Process that the handle should be referenced from.
  929. HandleTable - Handle table of target process
  930. AccessMode - Supplies the processor mode of the access
  931. Object - Receives a pointer to the object body if the operation
  932. is successful
  933. HandleInformation - receives information regarding the
  934. input handle.
  935. AuditMask - Pointer to any audit mask associated with the handle.
  936. Return Value:
  937. An appropriate NTSTATUS value
  938. --*/
  939. {
  940. ACCESS_MASK GrantedAccess;
  941. POBJECT_HEADER ObjectHeader;
  942. PHANDLE_TABLE_ENTRY ObjectTableEntry;
  943. NTSTATUS Status;
  944. PETHREAD Thread;
  945. PHANDLE_TABLE_ENTRY_INFO ObjectInfo;
  946. ObpValidateIrql("ObReferenceObjectByHandle");
  947. Thread = PsGetCurrentThread ();
  948. *Object = NULL;
  949. //
  950. // Check is this handle is a kernel handle or one of the two builtin pseudo handles
  951. //
  952. if ((LONG)(ULONG_PTR) Handle < 0) {
  953. //
  954. // If the handle is equal to the current process handle and the object
  955. // type is NULL or type process, then attempt to translate a handle to
  956. // the current process. Otherwise, check if the handle is the current
  957. // thread handle.
  958. //
  959. if (Handle == NtCurrentProcess()) {
  960. GrantedAccess = Process->GrantedAccess;
  961. ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process);
  962. HandleInformation->GrantedAccess = GrantedAccess;
  963. HandleInformation->HandleAttributes = 0;
  964. *AuditMask = 0;
  965. ObpIncrPointerCount(ObjectHeader);
  966. *Object = Process;
  967. ASSERT( *Object != NULL );
  968. Status = STATUS_SUCCESS;
  969. return Status;
  970. //
  971. // If the handle is equal to the current thread handle and the object
  972. // type is NULL or type thread, then attempt to translate a handle to
  973. // the current thread. Otherwise, the we'll try and translate the
  974. // handle
  975. //
  976. } else if (Handle == NtCurrentThread()) {
  977. GrantedAccess = Thread->GrantedAccess;
  978. ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread);
  979. HandleInformation->GrantedAccess = GrantedAccess;
  980. HandleInformation->HandleAttributes = 0;
  981. *AuditMask = 0;
  982. ObpIncrPointerCount(ObjectHeader);
  983. *Object = Thread;
  984. ASSERT( *Object != NULL );
  985. Status = STATUS_SUCCESS;
  986. return Status;
  987. } else if (AccessMode == KernelMode) {
  988. //
  989. // Make the handle look like a regular handle
  990. //
  991. Handle = DecodeKernelHandle( Handle );
  992. //
  993. // The global kernel handle table
  994. //
  995. HandleTable = ObpKernelHandleTable;
  996. } else {
  997. //
  998. // The previous mode was user for this kernel handle value. Reject it here.
  999. //
  1000. return STATUS_INVALID_HANDLE;
  1001. }
  1002. }
  1003. ASSERT(HandleTable != NULL);
  1004. //
  1005. // Protect this thread from being suspended while we hold the handle table entry lock
  1006. //
  1007. KeEnterCriticalRegionThread(&Thread->Tcb);
  1008. //
  1009. // Translate the specified handle to an object table index.
  1010. //
  1011. ObjectTableEntry = ExMapHandleToPointer ( HandleTable, Handle );
  1012. //
  1013. // Make sure the object table entry really does exist
  1014. //
  1015. if (ObjectTableEntry != NULL) {
  1016. ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
  1017. #if i386
  1018. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  1019. GrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );
  1020. } else {
  1021. GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
  1022. }
  1023. #else
  1024. GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
  1025. #endif // i386
  1026. ObjectInfo = ExGetHandleInfo(HandleTable, Handle, TRUE);
  1027. //
  1028. // Return the handle information, increment the object
  1029. // pointer count, unlock the handle table and return
  1030. // a success status.
  1031. //
  1032. // Note that this is the only successful return path
  1033. // out of this routine if the user did not specify
  1034. // the current process or current thread in the input
  1035. // handle.
  1036. //
  1037. HandleInformation->GrantedAccess = GrantedAccess;
  1038. HandleInformation->HandleAttributes = ObpGetHandleAttributes(ObjectTableEntry);
  1039. //
  1040. // Return handle audit information to the caller
  1041. //
  1042. if (ObjectInfo != NULL) {
  1043. *AuditMask = ObjectInfo->AuditMask;
  1044. } else {
  1045. *AuditMask = 0;
  1046. }
  1047. ObpIncrPointerCount(ObjectHeader);
  1048. ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry );
  1049. KeLeaveCriticalRegionThread(&Thread->Tcb);
  1050. *Object = &ObjectHeader->Body;
  1051. ASSERT( *Object != NULL );
  1052. return STATUS_SUCCESS;
  1053. } else {
  1054. Status = STATUS_INVALID_HANDLE;
  1055. }
  1056. KeLeaveCriticalRegionThread(&Thread->Tcb);
  1057. return Status;
  1058. }
  1059. NTSTATUS
  1060. ObReferenceFileObjectForWrite(
  1061. IN HANDLE Handle,
  1062. IN KPROCESSOR_MODE AccessMode,
  1063. OUT PVOID *FileObject,
  1064. OUT POBJECT_HANDLE_INFORMATION HandleInformation
  1065. )
  1066. /*++
  1067. Routine Description:
  1068. Given a handle to a file object this routine returns a pointer
  1069. to the body of the object with proper ref counts and auditing. This
  1070. routine is meant to solve a very particular handle reference issue with
  1071. file object access auditing. Do not call this unless you understand exactly
  1072. what you are doing.
  1073. Arguments:
  1074. Handle - Supplies a handle to the IoFileObjectType being referenced.
  1075. AccessMode - Supplies the processor mode of the access
  1076. FileObject - Receives a pointer to the object body if the operation
  1077. is successful
  1078. HandleInformation - receives information regarding the input handle.
  1079. Return Value:
  1080. An appropriate NTSTATUS value
  1081. --*/
  1082. {
  1083. ACCESS_MASK GrantedAccess;
  1084. ACCESS_MASK DesiredAccess;
  1085. PHANDLE_TABLE HandleTable;
  1086. POBJECT_HEADER ObjectHeader;
  1087. PHANDLE_TABLE_ENTRY ObjectTableEntry;
  1088. NTSTATUS Status;
  1089. PETHREAD Thread;
  1090. PHANDLE_TABLE_ENTRY_INFO ObjectInfo;
  1091. ObpValidateIrql("ObReferenceFileObjectForWrite");
  1092. Thread = PsGetCurrentThread ();
  1093. //
  1094. // Check is this handle is a kernel handle
  1095. //
  1096. if ((LONG)(ULONG_PTR) Handle < 0) {
  1097. if ((AccessMode == KernelMode) && (Handle != NtCurrentProcess()) && (Handle != NtCurrentThread())) {
  1098. //
  1099. // Make the handle look like a regular handle
  1100. //
  1101. Handle = DecodeKernelHandle( Handle );
  1102. //
  1103. // The global kernel handle table
  1104. //
  1105. HandleTable = ObpKernelHandleTable;
  1106. } else {
  1107. //
  1108. // The previous mode was user for this kernel handle value, or it was a builtin handle. Reject it here.
  1109. //
  1110. return STATUS_INVALID_HANDLE;
  1111. }
  1112. } else {
  1113. HandleTable = PsGetCurrentProcessByThread(Thread)->ObjectTable;
  1114. }
  1115. ASSERT(HandleTable != NULL);
  1116. //
  1117. // Protect this thread from being suspended while we hold the handle table entry lock
  1118. //
  1119. KeEnterCriticalRegionThread(&Thread->Tcb);
  1120. //
  1121. // Translate the specified handle to an object table index.
  1122. //
  1123. ObjectTableEntry = ExMapHandleToPointerEx ( HandleTable, Handle, AccessMode );
  1124. //
  1125. // Make sure the object table entry really does exist
  1126. //
  1127. if (ObjectTableEntry != NULL) {
  1128. ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
  1129. if (NT_SUCCESS(IoComputeDesiredAccessFileObject((PFILE_OBJECT)&ObjectHeader->Body, (PNTSTATUS)&DesiredAccess))) {
  1130. #if i386
  1131. if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
  1132. GrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );
  1133. } else {
  1134. GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
  1135. }
  1136. #else
  1137. GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
  1138. #endif // i386
  1139. ObjectInfo = ExGetHandleInfo(HandleTable, Handle, TRUE);
  1140. //
  1141. // Access to the object is allowed. Return the handle
  1142. // information, increment the object pointer count,
  1143. // compute correct access, audit, unlock the handle
  1144. // table and return a success status.
  1145. //
  1146. // Note that this is the only successful return path
  1147. // out of this routine.
  1148. //
  1149. HandleInformation->GrantedAccess = GrantedAccess;
  1150. HandleInformation->HandleAttributes = ObpGetHandleAttributes(ObjectTableEntry);
  1151. //
  1152. // Check to ensure that the caller has either WRITE_DATA or APPEND_DATA
  1153. // access to the file. If not, cleanup and return an access denied
  1154. // error status value. Note that if this is a pipe then the APPEND_DATA
  1155. // access check may not be made since this access code is overlaid with
  1156. // CREATE_PIPE_INSTANCE access.
  1157. //
  1158. if (SeComputeGrantedAccesses( GrantedAccess, DesiredAccess )) {
  1159. //
  1160. // If this object was audited when it was opened, it may
  1161. // be necessary to generate an audit now. Check the audit
  1162. // mask that was saved when the handle was created.
  1163. //
  1164. // It is safe to do this check in a non-atomic fashion,
  1165. // because bits will never be added to this mask once it is
  1166. // created.
  1167. //
  1168. if ( (ObjectTableEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE) &&
  1169. (ObjectInfo != NULL) &&
  1170. (ObjectInfo->AuditMask != 0) &&
  1171. (DesiredAccess != 0) &&
  1172. (AccessMode != KernelMode)) {
  1173. ObpAuditObjectAccess( Handle, ObjectInfo, &ObjectHeader->Type->Name, DesiredAccess );
  1174. }
  1175. ObpIncrPointerCount(ObjectHeader);
  1176. ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry );
  1177. KeLeaveCriticalRegionThread(&Thread->Tcb);
  1178. *FileObject = &ObjectHeader->Body;
  1179. ASSERT( *FileObject != NULL );
  1180. return STATUS_SUCCESS;
  1181. } else {
  1182. Status = STATUS_ACCESS_DENIED;
  1183. }
  1184. } else {
  1185. Status = STATUS_OBJECT_TYPE_MISMATCH;
  1186. }
  1187. ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry );
  1188. } else {
  1189. Status = STATUS_INVALID_HANDLE;
  1190. }
  1191. KeLeaveCriticalRegionThread(&Thread->Tcb);
  1192. //
  1193. // No handle translation is possible. Set the object address to NULL
  1194. // and return an error status.
  1195. //
  1196. *FileObject = NULL;
  1197. return Status;
  1198. }
  1199. VOID
  1200. ObAuditObjectAccess(
  1201. IN HANDLE Handle,
  1202. IN POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL,
  1203. IN KPROCESSOR_MODE AccessMode,
  1204. IN ACCESS_MASK DesiredAccess
  1205. )
  1206. /*++
  1207. Routine Description:
  1208. This routine will determine if it is necessary to audit the operation being
  1209. performed on the passed handle. If so, it will clear the bits in the handle
  1210. and generate the appropriate audit before returning.
  1211. The bits in the handle's audit mask are cleared in an atomic way so that
  1212. multiple threads coming through this code do not generate more than one
  1213. audit for the same operation.
  1214. Arguments:
  1215. Handle - Supplies the handle being accessed.
  1216. AccessMode - The mode (kernel or user) that originated the handle.
  1217. DesiredAccess - Supplies the access mask describing how the handle is being used
  1218. in this operation.
  1219. Return Value:
  1220. None.
  1221. --*/
  1222. {
  1223. PHANDLE_TABLE HandleTable;
  1224. PHANDLE_TABLE_ENTRY ObjectTableEntry;
  1225. POBJECT_HEADER ObjectHeader;
  1226. PKTHREAD CurrentThread;
  1227. //
  1228. // Exit fast if we have nothing to do.
  1229. //
  1230. if (ARGUMENT_PRESENT(HandleInformation)) {
  1231. if (!(HandleInformation->HandleAttributes & OBJ_AUDIT_OBJECT_CLOSE)) {
  1232. return;
  1233. }
  1234. }
  1235. //
  1236. // Do not currently support this on kernel mode
  1237. // handles.
  1238. //
  1239. if (AccessMode == KernelMode) {
  1240. return;
  1241. }
  1242. HandleTable = ObpGetObjectTable();
  1243. ASSERT(HandleTable != NULL);
  1244. //
  1245. // Translate the specified handle to an object table index.
  1246. //
  1247. CurrentThread = KeGetCurrentThread ();
  1248. KeEnterCriticalRegionThread (CurrentThread);
  1249. ObjectTableEntry = ExMapHandleToPointer( HandleTable, Handle );
  1250. //
  1251. // Make sure the object table entry really does exist
  1252. //
  1253. if (ObjectTableEntry != NULL) {
  1254. PHANDLE_TABLE_ENTRY_INFO ObjectInfo;
  1255. ObjectInfo = ExGetHandleInfo(HandleTable, Handle, TRUE);
  1256. ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
  1257. //
  1258. // If this object was audited when it was opened, it may
  1259. // be necessary to generate an audit now. Check the audit
  1260. // mask that was saved when the handle was created.
  1261. //
  1262. // It is safe to do this check in a non-atomic fashion,
  1263. // because bits will never be added to this mask once it is
  1264. // created.
  1265. //
  1266. // Note: is OBJ_AUDIT_OBJECT_CLOSE in ObAttributes kept in synch with
  1267. // HandleAttributes?
  1268. //
  1269. if ( (ObjectTableEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE) &&
  1270. (ObjectInfo != NULL) &&
  1271. (ObjectInfo->AuditMask != 0) &&
  1272. (DesiredAccess != 0)) {
  1273. ObpAuditObjectAccess( Handle, ObjectInfo, &ObjectHeader->Type->Name, DesiredAccess );
  1274. }
  1275. ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry );
  1276. }
  1277. KeLeaveCriticalRegionThread (CurrentThread);
  1278. }
  1279. VOID
  1280. ObpAuditObjectAccess(
  1281. IN HANDLE Handle,
  1282. IN PHANDLE_TABLE_ENTRY_INFO ObjectTableEntryInfo,
  1283. IN PUNICODE_STRING ObjectTypeName,
  1284. IN ACCESS_MASK DesiredAccess
  1285. )
  1286. /*++
  1287. Routine Description:
  1288. This routine will determine if it is necessary to audit the operation being
  1289. performed on the passed handle. If so, it will clear the bits in the handle
  1290. and generate the appropriate audit before returning.
  1291. The bits in the handle's audit mask are cleared in an atomic way so that
  1292. multiple threads coming through this code do not generate more than one
  1293. audit for the same operation.
  1294. Arguments:
  1295. Handle - Supplies the handle being accessed.
  1296. ObjectTableEntry - Supplies the object table entry for the handle passed in the
  1297. first parameter.
  1298. DesiredAccess - Supplies the access mask describing how the handle is being used
  1299. in this operation.
  1300. Return Value:
  1301. None.
  1302. --*/
  1303. {
  1304. ACCESS_MASK t1, t2, r;
  1305. ACCESS_MASK BitsToAudit;
  1306. //
  1307. // Determine if this access is to
  1308. // be audited, and if so, clear the bits
  1309. // in the ObjectTableEntry.
  1310. //
  1311. while (ObjectTableEntryInfo->AuditMask != 0) {
  1312. t1 = ObjectTableEntryInfo->AuditMask;
  1313. t2 = t1 & ~DesiredAccess;
  1314. if (t2 != t1) {
  1315. r = (ACCESS_MASK) InterlockedCompareExchange((PLONG)&ObjectTableEntryInfo->AuditMask, t2, t1);
  1316. if (r == t1) {
  1317. //
  1318. // AuditMask was == t1, so AuditMask is now == t2
  1319. // it worked, r contains what was in AuditMask, which
  1320. // we can examine safely.
  1321. //
  1322. BitsToAudit = r & DesiredAccess;
  1323. //
  1324. // Generate audit here
  1325. //
  1326. if (BitsToAudit != 0) {
  1327. SeOperationAuditAlarm( NULL,
  1328. Handle,
  1329. ObjectTypeName,
  1330. BitsToAudit,
  1331. NULL
  1332. );
  1333. }
  1334. return;
  1335. }
  1336. //
  1337. // else, somebody changed it, go around for another try
  1338. //
  1339. } else {
  1340. //
  1341. // There are no bits in the AuditMask that we
  1342. // want to audit here, just leave.
  1343. //
  1344. return;
  1345. }
  1346. }
  1347. }
  1348. NTSTATUS
  1349. ObReferenceObjectByName (
  1350. IN PUNICODE_STRING ObjectName,
  1351. IN ULONG Attributes,
  1352. IN PACCESS_STATE AccessState OPTIONAL,
  1353. IN ACCESS_MASK DesiredAccess OPTIONAL,
  1354. IN POBJECT_TYPE ObjectType,
  1355. IN KPROCESSOR_MODE AccessMode,
  1356. IN OUT PVOID ParseContext OPTIONAL,
  1357. OUT PVOID *Object
  1358. )
  1359. /*++
  1360. Routine Description:
  1361. Given a name of an object this routine returns a pointer
  1362. to the body of the object with proper ref counts
  1363. Arguments:
  1364. ObjectName - Supplies the name of the object being referenced
  1365. Attributes - Supplies the desired handle attributes
  1366. AccessState - Supplies an optional pointer to the current access
  1367. status describing already granted access types, the privileges used
  1368. to get them, and any access types yet to be granted.
  1369. DesiredAccess - Optionally supplies the desired access to the
  1370. for the object
  1371. ObjectType - Specifies the object type according to the caller
  1372. AccessMode - Supplies the processor mode of the access
  1373. ParseContext - Optionally supplies a context to pass down to the
  1374. parse routine
  1375. Object - Receives a pointer to the referenced object body
  1376. Return Value:
  1377. An appropriate NTSTATUS value
  1378. --*/
  1379. {
  1380. UNICODE_STRING CapturedObjectName;
  1381. PVOID ExistingObject;
  1382. ACCESS_STATE LocalAccessState;
  1383. AUX_ACCESS_DATA AuxData;
  1384. NTSTATUS Status;
  1385. OBP_LOOKUP_CONTEXT LookupContext;
  1386. PAGED_CODE();
  1387. ObpValidateIrql("ObReferenceObjectByName");
  1388. //
  1389. // If the object name descriptor is not specified, or the object name
  1390. // length is zero (tested after capture), then the object name is
  1391. // invalid.
  1392. //
  1393. if (ObjectName == NULL) {
  1394. return STATUS_OBJECT_NAME_INVALID;
  1395. }
  1396. //
  1397. // Capture the object name.
  1398. //
  1399. Status = ObpCaptureObjectName( AccessMode,
  1400. ObjectName,
  1401. &CapturedObjectName,
  1402. TRUE );
  1403. if (NT_SUCCESS(Status)) {
  1404. //
  1405. // No buffer has been allocated for a zero length name so no free
  1406. // needed
  1407. //
  1408. if (CapturedObjectName.Length == 0) {
  1409. return STATUS_OBJECT_NAME_INVALID;
  1410. }
  1411. //
  1412. // If the access state is not specified, then create the access
  1413. // state.
  1414. //
  1415. if (!ARGUMENT_PRESENT(AccessState)) {
  1416. AccessState = &LocalAccessState;
  1417. Status = SeCreateAccessState( &LocalAccessState,
  1418. &AuxData,
  1419. DesiredAccess,
  1420. &ObjectType->TypeInfo.GenericMapping );
  1421. if (!NT_SUCCESS(Status)) {
  1422. goto FreeBuffer;
  1423. }
  1424. }
  1425. //
  1426. // Lookup object by name.
  1427. //
  1428. Status = ObpLookupObjectName( NULL,
  1429. &CapturedObjectName,
  1430. Attributes,
  1431. ObjectType,
  1432. AccessMode,
  1433. ParseContext,
  1434. NULL,
  1435. NULL,
  1436. AccessState,
  1437. &LookupContext,
  1438. &ExistingObject );
  1439. //
  1440. // If the directory is returned locked, then unlock it.
  1441. //
  1442. ObpReleaseLookupContext( &LookupContext );
  1443. //
  1444. // If the lookup was successful, then return the existing
  1445. // object if access is allowed. Otherwise, return NULL.
  1446. //
  1447. *Object = NULL;
  1448. if (NT_SUCCESS(Status)) {
  1449. if (ObpCheckObjectReference( ExistingObject,
  1450. AccessState,
  1451. FALSE,
  1452. AccessMode,
  1453. &Status )) {
  1454. *Object = ExistingObject;
  1455. }
  1456. }
  1457. //
  1458. // If the access state was generated, then delete the access
  1459. // state.
  1460. //
  1461. if (AccessState == &LocalAccessState) {
  1462. SeDeleteAccessState(AccessState);
  1463. }
  1464. //
  1465. // Free the object name buffer.
  1466. //
  1467. FreeBuffer:
  1468. ObpFreeObjectNameBuffer(&CapturedObjectName);
  1469. }
  1470. return Status;
  1471. }
  1472. NTSTATUS
  1473. ObReferenceObjectByPointer (
  1474. IN PVOID Object,
  1475. IN ACCESS_MASK DesiredAccess,
  1476. IN POBJECT_TYPE ObjectType,
  1477. IN KPROCESSOR_MODE AccessMode
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. This routine adds another reference count to an object denoted by
  1482. a pointer to the object body
  1483. Arguments:
  1484. Object - Supplies a pointer to the object being referenced
  1485. DesiredAccess - Specifies the desired access for the reference
  1486. ObjectType - Specifies the object type according to the caller
  1487. AccessMode - Supplies the processor mode of the access
  1488. Return Value:
  1489. STATUS_SUCCESS if successful and STATUS_OBJECT_TYPE_MISMATCH otherwise
  1490. --*/
  1491. {
  1492. POBJECT_HEADER ObjectHeader;
  1493. UNREFERENCED_PARAMETER (DesiredAccess);
  1494. //
  1495. // Translate the pointer to the object body to a pointer to the
  1496. // object header
  1497. //
  1498. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1499. //
  1500. // If the specified object type does not match and either the caller is
  1501. // not kernel mode or it is not a symbolic link object then it is an
  1502. // error
  1503. //
  1504. if ((ObjectHeader->Type != ObjectType) && (AccessMode != KernelMode ||
  1505. ObjectType == ObpSymbolicLinkObjectType)) {
  1506. return( STATUS_OBJECT_TYPE_MISMATCH );
  1507. }
  1508. //
  1509. // Otherwise increment the pointer count and return success to
  1510. // our caller
  1511. //
  1512. ObpIncrPointerCount( ObjectHeader );
  1513. return( STATUS_SUCCESS );
  1514. }
  1515. VOID
  1516. ObpDeferObjectDeletion (
  1517. IN POBJECT_HEADER ObjectHeader
  1518. )
  1519. {
  1520. PVOID OldValue;
  1521. //
  1522. // Push this object on the list. If we make an empty to non-empty
  1523. // transition then we may have to start a worker thread.
  1524. //
  1525. while (1) {
  1526. OldValue = ObpRemoveObjectList;
  1527. ObjectHeader->NextToFree = OldValue;
  1528. if (InterlockedCompareExchangePointer (&ObpRemoveObjectList,
  1529. ObjectHeader,
  1530. OldValue) == OldValue) {
  1531. break;
  1532. }
  1533. }
  1534. if (OldValue == NULL) {
  1535. //
  1536. // If we have to start the worker thread then go ahead
  1537. // and enqueue the work item
  1538. //
  1539. ExQueueWorkItem( &ObpRemoveObjectWorkItem, CriticalWorkQueue );
  1540. }
  1541. }
  1542. LONG_PTR
  1543. FASTCALL
  1544. ObfReferenceObject (
  1545. IN PVOID Object
  1546. )
  1547. /*++
  1548. Routine Description:
  1549. This function increments the reference count for an object.
  1550. N.B. This function should be used to increment the reference count
  1551. when the accessing mode is kernel or the objct type is known.
  1552. Arguments:
  1553. Object - Supplies a pointer to the object whose reference count is
  1554. incremented.
  1555. Return Value:
  1556. None.
  1557. --*/
  1558. {
  1559. POBJECT_HEADER ObjectHeader;
  1560. LONG_PTR RetVal;
  1561. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1562. RetVal = ObpIncrPointerCount( ObjectHeader );
  1563. ASSERT (RetVal != 1);
  1564. return RetVal;
  1565. }
  1566. LONG_PTR
  1567. FASTCALL
  1568. ObReferenceObjectEx (
  1569. IN PVOID Object,
  1570. IN ULONG Count
  1571. )
  1572. /*++
  1573. Routine Description:
  1574. This function increments the reference count for an object by the specified amount.
  1575. Arguments:
  1576. Object - Supplies a pointer to the object whose reference count is
  1577. incremented.
  1578. Count - Amount to increment by
  1579. Return Value:
  1580. LONG - New value of count
  1581. --*/
  1582. {
  1583. POBJECT_HEADER ObjectHeader;
  1584. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1585. return ObpIncrPointerCountEx (ObjectHeader, Count);
  1586. }
  1587. LONG_PTR
  1588. FASTCALL
  1589. ObDereferenceObjectEx (
  1590. IN PVOID Object,
  1591. IN ULONG Count
  1592. )
  1593. /*++
  1594. Routine Description:
  1595. This function decrements the reference count for an object by the specified amount.
  1596. Arguments:
  1597. Object - Supplies a pointer to the object whose reference count is
  1598. incremented.
  1599. Count - Amount to decrement by
  1600. Return Value:
  1601. LONG - New value of count
  1602. --*/
  1603. {
  1604. POBJECT_HEADER ObjectHeader;
  1605. LONG_PTR Result;
  1606. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1607. Result = ObpDecrPointerCountEx (ObjectHeader, Count);
  1608. if (Result == 0) {
  1609. ObpDeferObjectDeletion (ObjectHeader);
  1610. }
  1611. return Result;
  1612. }
  1613. BOOLEAN
  1614. FASTCALL
  1615. ObReferenceObjectSafe (
  1616. IN PVOID Object
  1617. )
  1618. /*++
  1619. Routine Description:
  1620. This function increments the reference count for an object. It returns
  1621. FALSE if the object is being deleted or TRUE if it's safe to use the object further
  1622. Arguments:
  1623. Object - Supplies a pointer to the object whose reference count is
  1624. incremented.
  1625. Return Value:
  1626. TRUE - The object was successfuly referenced and safe to use
  1627. FALSE - The object is being deleted
  1628. --*/
  1629. {
  1630. POBJECT_HEADER ObjectHeader;
  1631. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1632. if (ObpSafeInterlockedIncrement(&ObjectHeader->PointerCount)) {
  1633. #ifdef POOL_TAGGING
  1634. if(ObpTraceEnabled) {
  1635. ObpPushStackInfo(ObjectHeader, TRUE);
  1636. }
  1637. #endif // POOL_TAGGING
  1638. return TRUE;
  1639. }
  1640. return FALSE;
  1641. }
  1642. LONG_PTR
  1643. FASTCALL
  1644. ObfDereferenceObject (
  1645. IN PVOID Object
  1646. )
  1647. /*++
  1648. Routine Description:
  1649. This routine decrments the refernce count of the specified object and
  1650. does whatever cleanup there is if the count goes to zero.
  1651. Arguments:
  1652. Object - Supplies a pointer to the body of the object being dereferenced
  1653. Return Value:
  1654. None.
  1655. --*/
  1656. {
  1657. POBJECT_HEADER ObjectHeader;
  1658. POBJECT_TYPE ObjectType;
  1659. KIRQL OldIrql;
  1660. LONG_PTR Result;
  1661. //
  1662. // Translate a pointer to the object body to a pointer to the object
  1663. // header.
  1664. //
  1665. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1666. #if DBG
  1667. {
  1668. POBJECT_HEADER_NAME_INFO NameInfo;
  1669. NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
  1670. if (NameInfo) {
  1671. InterlockedDecrement(&NameInfo->DbgDereferenceCount) ;
  1672. }
  1673. }
  1674. #endif
  1675. //
  1676. // Decrement the point count and if the result is now then
  1677. // there is extra work to do
  1678. //
  1679. ObjectType = ObjectHeader->Type;
  1680. Result = ObpDecrPointerCount( ObjectHeader );
  1681. if (Result == 0) {
  1682. //
  1683. // Find out the level we're at and the object type
  1684. //
  1685. OldIrql = KeGetCurrentIrql();
  1686. ASSERT(ObjectHeader->HandleCount == 0);
  1687. //
  1688. // If we're at the passive level then go ahead and delete the
  1689. // object now.
  1690. //
  1691. if (OldIrql == PASSIVE_LEVEL) {
  1692. #ifdef POOL_TAGGING
  1693. //
  1694. // The object is going away, so we deregister it.
  1695. //
  1696. if (ObpTraceEnabled && !ObpTraceNoDeregister) {
  1697. ObpDeregisterObject( ObjectHeader );
  1698. }
  1699. #endif //POOL_TAGGING
  1700. ObpRemoveObjectRoutine( Object, FALSE );
  1701. return Result;
  1702. } else {
  1703. //
  1704. // Objects can't be deleted from an IRQL above PASSIVE_LEVEL.
  1705. // So queue the delete operation.
  1706. //
  1707. ObpDeferObjectDeletion (ObjectHeader);
  1708. }
  1709. }
  1710. return Result;
  1711. }
  1712. VOID
  1713. ObDereferenceObjectDeferDelete (
  1714. IN PVOID Object
  1715. )
  1716. {
  1717. POBJECT_HEADER ObjectHeader;
  1718. LONG_PTR Result;
  1719. #if DBG
  1720. POBJECT_HEADER_NAME_INFO NameInfo;
  1721. #endif
  1722. //
  1723. // Translate a pointer to the object body to a pointer to the object
  1724. // header.
  1725. //
  1726. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1727. #if DBG
  1728. NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
  1729. if (NameInfo) {
  1730. InterlockedDecrement(&NameInfo->DbgDereferenceCount) ;
  1731. }
  1732. #endif
  1733. //
  1734. // Decrement the point count and if the result is now then
  1735. // there is extra work to do
  1736. //
  1737. Result = ObpDecrPointerCount( ObjectHeader );
  1738. if (Result == 0) {
  1739. ObpDeferObjectDeletion (ObjectHeader);
  1740. }
  1741. }
  1742. VOID
  1743. ObpProcessRemoveObjectQueue (
  1744. PVOID Parameter
  1745. )
  1746. /*++
  1747. Routine Description:
  1748. This is the work routine for the remove object work queue. Its
  1749. job is to remove and process items from the remove object queue.
  1750. Arguments:
  1751. Parameter - Ignored
  1752. Return Value:
  1753. None.
  1754. --*/
  1755. {
  1756. POBJECT_HEADER ObjectHeader, NextObject;
  1757. UNREFERENCED_PARAMETER (Parameter);
  1758. //
  1759. // Process the list of defered delete objects.
  1760. // The list head serves two purposes. First it maintains
  1761. // the list of objects we need to delete and second
  1762. // it signals that this thread is active.
  1763. // While we are processing the latest list we leave the
  1764. // header as the value 1. This will never be an object address
  1765. // as the bottom bits should be clear for an object.
  1766. //
  1767. while (1) {
  1768. ObjectHeader = InterlockedExchangePointer (&ObpRemoveObjectList,
  1769. (PVOID) 1);
  1770. while (1) {
  1771. #ifdef POOL_TAGGING
  1772. if (ObpTraceEnabled && !ObpTraceNoDeregister) {
  1773. ObpDeregisterObject( ObjectHeader );
  1774. }
  1775. #endif
  1776. NextObject = ObjectHeader->NextToFree;
  1777. ObpRemoveObjectRoutine( &ObjectHeader->Body, TRUE );
  1778. ObjectHeader = NextObject;
  1779. if (ObjectHeader == NULL || ObjectHeader == (PVOID) 1) {
  1780. break;
  1781. }
  1782. }
  1783. if (ObpRemoveObjectList == (PVOID) 1 &&
  1784. InterlockedCompareExchangePointer (&ObpRemoveObjectList,
  1785. NULL,
  1786. (PVOID) 1) == (PVOID) 1) {
  1787. break;
  1788. }
  1789. }
  1790. }
  1791. VOID
  1792. ObpRemoveObjectRoutine (
  1793. IN PVOID Object,
  1794. IN BOOLEAN CalledOnWorkerThread
  1795. )
  1796. /*++
  1797. Routine Description:
  1798. This routine is used to delete an object whose reference count has
  1799. gone to zero.
  1800. Arguments:
  1801. Object - Supplies a pointer to the body of the object being deleted
  1802. CalledOnWorkerThread - TRUE if called on worker thread, FALSE if called in
  1803. the context of the ObDereferenceObject.
  1804. Return Value:
  1805. None.
  1806. --*/
  1807. {
  1808. NTSTATUS Status;
  1809. POBJECT_HEADER ObjectHeader;
  1810. POBJECT_TYPE ObjectType;
  1811. POBJECT_HEADER_CREATOR_INFO CreatorInfo;
  1812. POBJECT_HEADER_NAME_INFO NameInfo;
  1813. PAGED_CODE();
  1814. ObpValidateIrql( "ObpRemoveObjectRoutine" );
  1815. //
  1816. // Retrieve an object header from the object body, and also get
  1817. // the object type, creator and name info if available
  1818. //
  1819. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1820. ObjectType = ObjectHeader->Type;
  1821. CreatorInfo = OBJECT_HEADER_TO_CREATOR_INFO( ObjectHeader );
  1822. NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
  1823. //
  1824. // If there is a creator info record and we are on the list
  1825. // for the object type then remove this object from the list
  1826. //
  1827. if (CreatorInfo != NULL && !IsListEmpty( &CreatorInfo->TypeList )) {
  1828. //
  1829. // Get exclusive access to the object type object
  1830. //
  1831. ObpEnterObjectTypeMutex( ObjectType );
  1832. RemoveEntryList( &CreatorInfo->TypeList );
  1833. //
  1834. // We are done with the object type object so we can now release it
  1835. //
  1836. ObpLeaveObjectTypeMutex( ObjectType );
  1837. }
  1838. //
  1839. // If there is a name info record and the name buffer is not null
  1840. // then free the buffer and zero out the name record
  1841. //
  1842. if (NameInfo != NULL && NameInfo->Name.Buffer != NULL) {
  1843. ExFreePool( NameInfo->Name.Buffer );
  1844. NameInfo->Name.Buffer = NULL;
  1845. NameInfo->Name.Length = 0;
  1846. NameInfo->Name.MaximumLength = 0;
  1847. }
  1848. //
  1849. // Security descriptor deletion must precede the
  1850. // call to the object's DeleteProcedure. Check if we have
  1851. // a security descriptor and if so then call the routine
  1852. // to delete the security descritpor.
  1853. //
  1854. if (ObjectHeader->SecurityDescriptor != NULL) {
  1855. #if DBG
  1856. KIRQL SaveIrql;
  1857. #endif
  1858. ObpBeginTypeSpecificCallOut( SaveIrql );
  1859. Status = (ObjectType->TypeInfo.SecurityProcedure)( Object,
  1860. DeleteSecurityDescriptor,
  1861. NULL, NULL, NULL,
  1862. &ObjectHeader->SecurityDescriptor,
  1863. 0,
  1864. NULL );
  1865. ObpEndTypeSpecificCallOut( SaveIrql, "Security", ObjectType, Object );
  1866. }
  1867. //
  1868. // Now if there is a delete callback for the object type invoke
  1869. // the routine
  1870. //
  1871. if (ObjectType->TypeInfo.DeleteProcedure) {
  1872. #if DBG
  1873. KIRQL SaveIrql;
  1874. #endif
  1875. ObpBeginTypeSpecificCallOut( SaveIrql );
  1876. if (!CalledOnWorkerThread) {
  1877. ObjectHeader->Flags |= OB_FLAG_DELETED_INLINE;
  1878. }
  1879. (*(ObjectType->TypeInfo.DeleteProcedure))(Object);
  1880. ObpEndTypeSpecificCallOut( SaveIrql, "Delete", ObjectType, Object );
  1881. }
  1882. //
  1883. // Finally return the object back to pool including releasing any quota
  1884. // charges
  1885. //
  1886. ObpFreeObject( Object );
  1887. }
  1888. VOID
  1889. ObpDeleteNameCheck (
  1890. IN PVOID Object
  1891. )
  1892. /*++
  1893. Routine Description:
  1894. This routine removes the name of an object from its parent directory
  1895. Arguments:
  1896. Object - Supplies a pointer to the object body whose name is being checked
  1897. TypeMutexHeld - Indicates if the lock on object type is being held by the
  1898. caller
  1899. Return Value:
  1900. None.
  1901. --*/
  1902. {
  1903. POBJECT_HEADER ObjectHeader;
  1904. POBJECT_TYPE ObjectType;
  1905. POBJECT_HEADER_NAME_INFO NameInfo;
  1906. PVOID DirObject;
  1907. OBP_LOOKUP_CONTEXT LookupContext;
  1908. PAGED_CODE();
  1909. ObpValidateIrql( "ObpDeleteNameCheck" );
  1910. //
  1911. // Translate the object body to an object header also get
  1912. // the object type and name info if present
  1913. //
  1914. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1915. NameInfo = ObpReferenceNameInfo( ObjectHeader );
  1916. ObjectType = ObjectHeader->Type;
  1917. //
  1918. // Make sure that the object has a zero handle count, has a non
  1919. // empty name buffer, and is not a permanent object
  1920. //
  1921. if ((ObjectHeader->HandleCount == 0) &&
  1922. (NameInfo != NULL) &&
  1923. (NameInfo->Name.Length != 0) &&
  1924. (!(ObjectHeader->Flags & OB_FLAG_PERMANENT_OBJECT)) &&
  1925. (NameInfo->Directory != NULL)) {
  1926. ObpInitializeLookupContext(&LookupContext);
  1927. ObpLockLookupContext ( &LookupContext, NameInfo->Directory );
  1928. DirObject = NULL;
  1929. //
  1930. // Check that the object we is still in the directory otherwise
  1931. // then is nothing for us to remove
  1932. //
  1933. if (Object == ObpLookupDirectoryEntry( NameInfo->Directory,
  1934. &NameInfo->Name,
  1935. 0,
  1936. FALSE,
  1937. &LookupContext )) {
  1938. //
  1939. // Now reacquire the lock on the object type and
  1940. // check check the handle count again. If it is still
  1941. // zero then we can do the actual delete name operation
  1942. //
  1943. //
  1944. // Delete the directory entry, if the entry is still there
  1945. //
  1946. ObpLockObject( ObjectHeader );
  1947. if (ObjectHeader->HandleCount == 0 &&
  1948. (ObjectHeader->Flags & OB_FLAG_PERMANENT_OBJECT) == 0) {
  1949. //
  1950. // Delete the directory entry
  1951. //
  1952. ObpDeleteDirectoryEntry( &LookupContext );
  1953. //
  1954. // If this is a symbolic link object then we also need to
  1955. // delete the symbolic link
  1956. //
  1957. if (ObjectType == ObpSymbolicLinkObjectType) {
  1958. ObpDeleteSymbolicLinkName( (POBJECT_SYMBOLIC_LINK)Object );
  1959. }
  1960. DirObject = NameInfo->Directory;
  1961. }
  1962. ObpUnlockObject( ObjectHeader );
  1963. }
  1964. ObpReleaseLookupContext( &LookupContext );
  1965. //
  1966. // If there is a directory object for the name then decrement
  1967. // its reference count for it and for the object
  1968. //
  1969. if (DirObject != NULL) {
  1970. //
  1971. // Dereference the name twice: one because we referenced it to
  1972. // saftely access the name info, and the second deref is because
  1973. // we want a deletion for the NameInfo
  1974. //
  1975. ObpDereferenceNameInfo(NameInfo);
  1976. ObpDereferenceNameInfo(NameInfo);
  1977. ObDereferenceObject( Object );
  1978. }
  1979. } else {
  1980. ObpDereferenceNameInfo(NameInfo);
  1981. }
  1982. return;
  1983. }
  1984. //
  1985. // Thunks to support standard call callers
  1986. //
  1987. #ifdef ObDereferenceObject
  1988. #undef ObDereferenceObject
  1989. #endif
  1990. LONG_PTR
  1991. ObDereferenceObject (
  1992. IN PVOID Object
  1993. )
  1994. /*++
  1995. Routine Description:
  1996. This is really just a thunk for the Obf version of the dereference
  1997. routine
  1998. Arguments:
  1999. Object - Supplies a pointer to the body of the object being dereferenced
  2000. Return Value:
  2001. None.
  2002. --*/
  2003. {
  2004. return ObfDereferenceObject (Object) ;
  2005. }
  2006. BOOLEAN
  2007. ObIsObjectDeletionInline(
  2008. IN PVOID Object
  2009. )
  2010. /*++
  2011. Routine Description:
  2012. This is available only of object DeleteProcedure callbacks. It allows the
  2013. callback to determine whether the stack on which it is invoked is
  2014. Arguments:
  2015. Object - Supplies a pointer to the body of the object being deleted
  2016. Return Value:
  2017. TRUE if the deletion procedure is being invoked on the same stack as the
  2018. ObDereferenceObject, and FALSE if the procedure is being invoked from a
  2019. queued work item.
  2020. --*/
  2021. {
  2022. POBJECT_HEADER ObjectHeader;
  2023. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  2024. return ((ObjectHeader->Flags & OB_FLAG_DELETED_INLINE) != 0);
  2025. }