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

1270 lines
29 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. obp.h
  5. Abstract:
  6. Private include file for the OB subcomponent of the NTOS project
  7. Author:
  8. Steve Wood (stevewo) 31-Mar-1989
  9. Revision History:
  10. --*/
  11. #include "ntos.h"
  12. #include "seopaque.h"
  13. #include <zwapi.h>
  14. #define OBP_PAGEDPOOL_NAMESPACE
  15. //
  16. // The Object Header structures are private, but are defined in ob.h
  17. // so that various macros can directly access header fields.
  18. //
  19. struct _OBJECT_HEADER;
  20. struct _OBJECT_BODY_HEADER;
  21. //
  22. // Setup default pool tags
  23. //
  24. #ifdef POOL_TAGGING
  25. #define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,' bO')
  26. #define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,' bO')
  27. #endif
  28. //
  29. // Define some macros that will verify that our callbacks don't give us a bad irql
  30. //
  31. #if DBG
  32. #define ObpBeginTypeSpecificCallOut( IRQL ) (IRQL)=KeGetCurrentIrql()
  33. #define ObpEndTypeSpecificCallOut( IRQL, str, ot, o ) { \
  34. if ((IRQL)!=KeGetCurrentIrql()) { \
  35. DbgPrint( "OB: ObjectType: %wZ Procedure: %s Object: %08x\n", &ot->Name, str, o ); \
  36. DbgPrint( " Returned at %x IRQL, but was called at %x IRQL\n", KeGetCurrentIrql(), IRQL ); \
  37. DbgBreakPoint(); \
  38. } \
  39. }
  40. #else
  41. #define ObpBeginTypeSpecificCallOut( IRQL )
  42. #define ObpEndTypeSpecificCallOut( IRQL, str, ot, o )
  43. #endif // DBG
  44. //
  45. // Define some more macros to validate the current irql
  46. //
  47. #if DBG
  48. #define ObpValidateIrql( str ) \
  49. if (KeGetCurrentIrql() > APC_LEVEL) { \
  50. DbgPrint( "OB: %s called at IRQL %d\n", (str), KeGetCurrentIrql() ); \
  51. DbgBreakPoint(); \
  52. }
  53. #else
  54. #define ObpValidateIrql( str )
  55. #endif // DBG
  56. //
  57. // This global lock protects the granted access lists when we are collecting stack traces
  58. //
  59. EX_PUSH_LOCK ObpLock;
  60. KEVENT ObpDefaultObject;
  61. WORK_QUEUE_ITEM ObpRemoveObjectWorkItem;
  62. PVOID ObpRemoveObjectList;
  63. //
  64. // This global lock is used to protect the device map tear down and build up
  65. // We can no longer use an individual lock in the device map itself because
  66. // that wasn't sufficient to protect the device map itself.
  67. //
  68. #ifdef OBP_PAGEDPOOL_NAMESPACE
  69. #define OB_NAMESPACE_POOL_TYPE PagedPool
  70. FAST_MUTEX ObpDeviceMapLock;
  71. #define OBP_DECLARE_OLDIRQL
  72. #define ObpLockDeviceMap() \
  73. ExAcquireFastMutex( &ObpDeviceMapLock )
  74. #define ObpUnlockDeviceMap() \
  75. ExReleaseFastMutex( &ObpDeviceMapLock )
  76. #else // !OBP_PAGEDPOOL_NAMESPACE
  77. #define OB_NAMESPACE_POOL_TYPE NonPagedPool
  78. KSPIN_LOCK ObpDeviceMapLock;
  79. #define ObpLockDeviceMap() \
  80. ExAcquireSpinLock( &ObpDeviceMapLock, &OldIrql )
  81. #define ObpUnlockDeviceMap() \
  82. ExReleaseSpinLock( &ObpDeviceMapLock, OldIrql )
  83. #endif // OBP_PAGEDPOOL_NAMESPACE
  84. #define ObpIncrPointerCountEx(np,Count) (InterlockedExchangeAdd (&np->PointerCount, Count) + Count)
  85. #define ObpDecrPointerCountEx(np,Count) (InterlockedExchangeAdd (&np->PointerCount, -(LONG)(Count)) - Count)
  86. #ifndef POOL_TAGGING
  87. #define ObpIncrPointerCount(np) InterlockedIncrement( &np->PointerCount )
  88. #define ObpDecrPointerCount(np) InterlockedDecrement( &np->PointerCount )
  89. #define ObpDecrPointerCountWithResult(np) (InterlockedDecrement( &np->PointerCount ) == 0)
  90. #define ObpPushStackInfo(np, inc)
  91. #else //POOL_TAGGING
  92. VOID
  93. ObpInitStackTrace();
  94. VOID
  95. ObpRegisterObject (
  96. POBJECT_HEADER ObjectHeader
  97. );
  98. VOID
  99. ObpDeregisterObject (
  100. POBJECT_HEADER ObjectHeader
  101. );
  102. VOID
  103. ObpPushStackInfo (
  104. POBJECT_HEADER ObjectHeader,
  105. BOOLEAN IsRef
  106. );
  107. extern BOOLEAN ObpTraceEnabled;
  108. #define ObpIncrPointerCount(np) ((ObpTraceEnabled ? ObpPushStackInfo(np,TRUE) : 0),InterlockedIncrement( &np->PointerCount ))
  109. #define ObpDecrPointerCount(np) ((ObpTraceEnabled ? ObpPushStackInfo(np,FALSE) : 0),InterlockedDecrement( &np->PointerCount ))
  110. #define ObpDecrPointerCountWithResult(np) ((ObpTraceEnabled ? ObpPushStackInfo(np,FALSE) : 0),(InterlockedDecrement( &np->PointerCount ) == 0))
  111. #endif //POOL_TAGGING
  112. #define ObpIncrHandleCount(np) InterlockedIncrement( &np->HandleCount )
  113. #define ObpDecrHandleCount(np) (InterlockedDecrement( &np->HandleCount ) == 0)
  114. //
  115. // Define macros to acquire and release an object type fast mutex.
  116. //
  117. //
  118. // VOID
  119. // ObpEnterObjectTypeMutex (
  120. // IN POBJECT_TYPE ObjectType
  121. // )
  122. //
  123. #define ObpEnterObjectTypeMutex(_ObjectType) { \
  124. ObpValidateIrql("ObpEnterObjectTypeMutex"); \
  125. KeEnterCriticalRegion(); \
  126. ExAcquireResourceExclusiveLite(&(_ObjectType)->Mutex, TRUE); \
  127. }
  128. //
  129. // VOID
  130. // ObpLeaveObjectTypeMutex (
  131. // IN POBJECT_TYPE ObjectType
  132. // )
  133. //
  134. #define ObpLeaveObjectTypeMutex(_ObjectType) { \
  135. ExReleaseResourceLite(&(_ObjectType)->Mutex); \
  136. KeLeaveCriticalRegion(); \
  137. ObpValidateIrql("ObpLeaveObjectTypeMutex"); \
  138. }
  139. #define LOCK_HASH_MASK (OBJECT_LOCK_COUNT - 1)
  140. #define ObpHashObjectHeader(_ObjectHeader) \
  141. ((((ULONG_PTR)(_ObjectHeader)) >> 8) & LOCK_HASH_MASK)
  142. #define ObpLockObject(_ObjectHeader) { \
  143. ULONG_PTR LockIndex = ObpHashObjectHeader(_ObjectHeader); \
  144. ObpValidateIrql("ObpEnterObjectTypeMutex"); \
  145. KeEnterCriticalRegion(); \
  146. ExAcquireResourceExclusiveLite(&((_ObjectHeader)->Type->ObjectLocks[LockIndex]), TRUE); \
  147. }
  148. #define ObpLockObjectShared(_ObjectHeader) { \
  149. ULONG_PTR LockIndex = ObpHashObjectHeader(_ObjectHeader); \
  150. ObpValidateIrql("ObpEnterObjectTypeMutex"); \
  151. KeEnterCriticalRegion(); \
  152. ExAcquireResourceSharedLite(&((_ObjectHeader)->Type->ObjectLocks[LockIndex]), TRUE); \
  153. }
  154. #define ObpUnlockObject(_ObjectHeader) { \
  155. ULONG_PTR LockIndex = ObpHashObjectHeader(_ObjectHeader); \
  156. ExReleaseResourceLite(&((_ObjectHeader)->Type->ObjectLocks[LockIndex])); \
  157. KeLeaveCriticalRegion(); \
  158. ObpValidateIrql("ObpLeaveObjectTypeMutex"); \
  159. }
  160. //
  161. // A Macro to return the object table for the current process
  162. //
  163. #define ObpGetObjectTable() (PsGetCurrentProcess()->ObjectTable)
  164. //
  165. // Macro to test whether or not the object manager is responsible for
  166. // an object's security descriptor, or if the object has its own
  167. // security management routines.
  168. //
  169. #define ObpCentralizedSecurity(_ObjectType) \
  170. ((_ObjectType)->TypeInfo.SecurityProcedure == SeDefaultObjectMethod)
  171. //
  172. // Declare a global table of object types.
  173. //
  174. #define OBP_MAX_DEFINED_OBJECT_TYPES 48
  175. POBJECT_TYPE ObpObjectTypes[ OBP_MAX_DEFINED_OBJECT_TYPES ];
  176. //
  177. // This is some special purpose code to keep a table of access masks correlated with
  178. // back traces. If used these routines replace the GrantedAccess mask in the
  179. // preceding object table entry with a granted access index and a call back index.
  180. //
  181. #if i386
  182. ACCESS_MASK
  183. ObpTranslateGrantedAccessIndex (
  184. USHORT GrantedAccessIndex
  185. );
  186. USHORT
  187. ObpComputeGrantedAccessIndex (
  188. ACCESS_MASK GrantedAccess
  189. );
  190. USHORT ObpCurCachedGrantedAccessIndex;
  191. USHORT ObpMaxCachedGrantedAccessIndex;
  192. PACCESS_MASK ObpCachedGrantedAccesses;
  193. #endif // i386
  194. //
  195. // The three low order bits of the object table entry are used for handle
  196. // attributes.
  197. //
  198. // Define the bit mask for the protect from close handle attribute.
  199. //
  200. #define OBJ_PROTECT_CLOSE 0x1
  201. //
  202. // We moved the PROTECT_CLOSE in the granted access mask
  203. //
  204. extern ULONG ObpAccessProtectCloseBit;
  205. //
  206. // The bit mask for inherit MUST be 0x2.
  207. //
  208. #if (OBJ_INHERIT != 0x2)
  209. #error Object inheritance bit definition conflicts
  210. #endif
  211. //
  212. // Define the bit mask for the generate audit on close attribute.
  213. //
  214. // When a handle to an object with security is created, audit routines will
  215. // be called to perform any auditing that may be required. The audit routines
  216. // will return a boolean indicating whether or not audits should be generated
  217. // on close.
  218. //
  219. #define OBJ_AUDIT_OBJECT_CLOSE 0x00000004L
  220. //
  221. // The following three bits are available for handle attributes in the
  222. // Object field of an ObjectTableEntry.
  223. //
  224. #define OBJ_HANDLE_ATTRIBUTES (OBJ_PROTECT_CLOSE | OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)
  225. #define ObpDecodeGrantedAccess(Access) \
  226. ((Access) & ~ObpAccessProtectCloseBit)
  227. #define ObpGetHandleAttributes(HandleTableEntry) \
  228. ((((HandleTableEntry)->GrantedAccess) & ObpAccessProtectCloseBit) ? \
  229. ((((HandleTableEntry)->ObAttributes) & OBJ_HANDLE_ATTRIBUTES) | OBJ_PROTECT_CLOSE) : \
  230. (((HandleTableEntry)->ObAttributes) & (OBJ_INHERIT | OBJ_AUDIT_OBJECT_CLOSE)) )
  231. #define ObpEncodeProtectClose(ObjectTableEntry) \
  232. if ( (ObjectTableEntry).ObAttributes & OBJ_PROTECT_CLOSE ) { \
  233. \
  234. (ObjectTableEntry).ObAttributes &= ~OBJ_PROTECT_CLOSE; \
  235. (ObjectTableEntry).GrantedAccess |= ObpAccessProtectCloseBit; \
  236. }
  237. //
  238. // Security Descriptor Cache
  239. //
  240. // Cache entry header.
  241. //
  242. typedef struct _SECURITY_DESCRIPTOR_HEADER {
  243. LIST_ENTRY Link;
  244. ULONG RefCount;
  245. ULONG FullHash;
  246. #if defined (_WIN64)
  247. PVOID Spare; // Align to 16 byte boundary.
  248. #endif
  249. QUAD SecurityDescriptor;
  250. } SECURITY_DESCRIPTOR_HEADER, *PSECURITY_DESCRIPTOR_HEADER;
  251. //
  252. // Macro to convert a security descriptor into its security descriptor header
  253. //
  254. #define SD_TO_SD_HEADER(_sd) \
  255. CONTAINING_RECORD( (_sd), SECURITY_DESCRIPTOR_HEADER, SecurityDescriptor )
  256. //
  257. // Macro to convert a header link into its security descriptor header
  258. //
  259. #define LINK_TO_SD_HEADER(_link) \
  260. CONTAINING_RECORD( (_link), SECURITY_DESCRIPTOR_HEADER, Link )
  261. //
  262. // Number of minor hash entries
  263. //
  264. #define SECURITY_DESCRIPTOR_CACHE_ENTRIES 257
  265. //
  266. // Lock state signatures
  267. //
  268. #define OBP_LOCK_WAITEXCLUSIVE_SIGNATURE 0xAAAA1234
  269. #define OBP_LOCK_WAITSHARED_SIGNATURE 0xBBBB1234
  270. #define OBP_LOCK_OWNEDEXCLUSIVE_SIGNATURE 0xCCCC1234
  271. #define OBP_LOCK_OWNEDSHARED_SIGNATURE 0xDDDD1234
  272. #define OBP_LOCK_RELEASED_SIGNATURE 0xEEEE1234
  273. #define OBP_LOCK_UNUSED_SIGNATURE 0xFFFF1234
  274. //
  275. // Lookup directories
  276. //
  277. typedef struct _OBP_LOOKUP_CONTEXT {
  278. POBJECT_DIRECTORY Directory;
  279. PVOID Object;
  280. USHORT HashIndex;
  281. BOOLEAN DirectoryLocked;
  282. volatile ULONG LockStateSignature;
  283. } OBP_LOOKUP_CONTEXT, *POBP_LOOKUP_CONTEXT;
  284. //
  285. // Context for the sweep routine. Passed through handle enumeration.
  286. //
  287. typedef struct _OBP_SWEEP_CONTEXT {
  288. PHANDLE_TABLE HandleTable;
  289. KPROCESSOR_MODE PreviousMode;
  290. } OBP_SWEEP_CONTEXT, *POBP_SWEEP_CONTEXT;
  291. //
  292. // Global data
  293. //
  294. POBJECT_TYPE ObpTypeObjectType;
  295. POBJECT_TYPE ObpDirectoryObjectType;
  296. POBJECT_TYPE ObpSymbolicLinkObjectType;
  297. POBJECT_TYPE ObpDeviceMapObjectType;
  298. POBJECT_DIRECTORY ObpRootDirectoryObject;
  299. POBJECT_DIRECTORY ObpTypeDirectoryObject;
  300. typedef union {
  301. WCHAR Name[sizeof(ULARGE_INTEGER)/sizeof(WCHAR)];
  302. ULARGE_INTEGER Alignment;
  303. } ALIGNEDNAME;
  304. extern const ALIGNEDNAME ObpDosDevicesShortNamePrefix;
  305. extern const ALIGNEDNAME ObpDosDevicesShortNameRoot;
  306. extern const UNICODE_STRING ObpDosDevicesShortName;
  307. ERESOURCE SecurityDescriptorCacheLock;
  308. //
  309. // Define date structures for the object creation information region.
  310. //
  311. extern GENERAL_LOOKASIDE ObpCreateInfoLookasideList;
  312. //
  313. // Define data structures for the object name buffer lookaside list.
  314. //
  315. #define OBJECT_NAME_BUFFER_SIZE 248
  316. extern GENERAL_LOOKASIDE ObpNameBufferLookasideList;
  317. //
  318. // There is one global kernel handle table accessed via negative handle
  319. // and only in kernel mode
  320. //
  321. PHANDLE_TABLE ObpKernelHandleTable;
  322. //
  323. // The following macros are used to test and manipulate special kernel
  324. // handles. A kernel handle is just a regular handle with its sign
  325. // bit set. But must exclude -1 and -2 values which are the current
  326. // process and current thread constants.
  327. //
  328. #define KERNEL_HANDLE_MASK ((ULONG_PTR)((LONG)0x80000000))
  329. #define IsKernelHandle(H,M) \
  330. (((KERNEL_HANDLE_MASK & (ULONG_PTR)(H)) == KERNEL_HANDLE_MASK) && \
  331. ((M) == KernelMode) && \
  332. ((H) != NtCurrentThread()) && \
  333. ((H) != NtCurrentProcess()))
  334. #define EncodeKernelHandle(H) (HANDLE)(KERNEL_HANDLE_MASK | (ULONG_PTR)(H))
  335. #define DecodeKernelHandle(H) (HANDLE)(KERNEL_HANDLE_MASK ^ (ULONG_PTR)(H))
  336. //
  337. // Test macro for overflow
  338. //
  339. #define ObpIsOverflow(A,B) ((A) > ((A) + (B)))
  340. //
  341. // Internal Entry Points defined in obcreate.c and some associated macros
  342. //
  343. #define ObpFreeObjectCreateInformation(_ObjectCreateInfo) { \
  344. ObpReleaseObjectCreateInformation((_ObjectCreateInfo)); \
  345. ObpFreeObjectCreateInfoBuffer((_ObjectCreateInfo)); \
  346. }
  347. #define ObpReleaseObjectCreateInformation(_ObjectCreateInfo) { \
  348. if ((_ObjectCreateInfo)->SecurityDescriptor != NULL) { \
  349. SeReleaseSecurityDescriptor((_ObjectCreateInfo)->SecurityDescriptor, \
  350. (_ObjectCreateInfo)->ProbeMode, \
  351. TRUE); \
  352. (_ObjectCreateInfo)->SecurityDescriptor = NULL; \
  353. } \
  354. }
  355. NTSTATUS
  356. ObpCaptureObjectCreateInformation (
  357. IN POBJECT_TYPE ObjectType OPTIONAL,
  358. IN KPROCESSOR_MODE ProbeMode,
  359. IN KPROCESSOR_MODE CreatorMode,
  360. IN POBJECT_ATTRIBUTES ObjectAttributes,
  361. OUT PUNICODE_STRING CapturedObjectName,
  362. IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
  363. IN LOGICAL UseLookaside
  364. );
  365. NTSTATUS
  366. ObpCaptureObjectName (
  367. IN KPROCESSOR_MODE ProbeMode,
  368. IN PUNICODE_STRING ObjectName,
  369. IN OUT PUNICODE_STRING CapturedObjectName,
  370. IN LOGICAL UseLookaside
  371. );
  372. PWCHAR
  373. ObpAllocateObjectNameBuffer (
  374. IN ULONG Length,
  375. IN LOGICAL UseLookaside,
  376. IN OUT PUNICODE_STRING ObjectName
  377. );
  378. VOID
  379. FASTCALL
  380. ObpFreeObjectNameBuffer (
  381. IN PUNICODE_STRING ObjectName
  382. );
  383. NTSTATUS
  384. ObpAllocateObject (
  385. IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
  386. IN KPROCESSOR_MODE OwnershipMode,
  387. IN POBJECT_TYPE ObjectType,
  388. IN PUNICODE_STRING ObjectName,
  389. IN ULONG ObjectBodySize,
  390. OUT POBJECT_HEADER *ReturnedObjectHeader
  391. );
  392. VOID
  393. FASTCALL
  394. ObpFreeObject (
  395. IN PVOID Object
  396. );
  397. /*++
  398. POBJECT_CREATE_INFORMATION
  399. ObpAllocateObjectCreateInfoBuffer (
  400. VOID
  401. )
  402. Routine Description:
  403. This function allocates a created information buffer.
  404. N.B. This function is nonpageable.
  405. Arguments:
  406. None.
  407. Return Value:
  408. If the allocation is successful, then the address of the allocated
  409. create information buffer is is returned as the function value.
  410. Otherwise, a value of NULL is returned.
  411. --*/
  412. #define ObpAllocateObjectCreateInfoBuffer() \
  413. (POBJECT_CREATE_INFORMATION)ExAllocateFromPPLookasideList(LookasideCreateInfoList)
  414. /*++
  415. VOID
  416. FASTCALL
  417. ObpFreeObjectCreateInfoBuffer (
  418. IN POBJECT_CREATE_INFORMATION ObjectCreateInfo
  419. )
  420. Routine Description:
  421. This function frees a create information buffer.
  422. N.B. This function is nonpageable.
  423. Arguments:
  424. ObjectCreateInfo - Supplies a pointer to a create information buffer.
  425. Return Value:
  426. None.
  427. --*/
  428. #define ObpFreeObjectCreateInfoBuffer(ObjectCreateInfo) \
  429. ExFreeToPPLookasideList(LookasideCreateInfoList, ObjectCreateInfo)
  430. //
  431. // Internal Entry Points defined in oblink.c
  432. //
  433. NTSTATUS
  434. ObpParseSymbolicLink (
  435. IN PVOID ParseObject,
  436. IN PVOID ObjectType,
  437. IN PACCESS_STATE AccessState,
  438. IN KPROCESSOR_MODE AccessMode,
  439. IN ULONG Attributes,
  440. IN OUT PUNICODE_STRING CompleteName,
  441. IN OUT PUNICODE_STRING RemainingName,
  442. IN OUT PVOID Context OPTIONAL,
  443. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
  444. OUT PVOID *Object
  445. );
  446. VOID
  447. ObpDeleteSymbolicLink (
  448. IN PVOID Object
  449. );
  450. VOID
  451. ObpCreateSymbolicLinkName (
  452. POBJECT_SYMBOLIC_LINK SymbolicLink
  453. );
  454. VOID
  455. ObpDeleteSymbolicLinkName (
  456. POBJECT_SYMBOLIC_LINK SymbolicLink
  457. );
  458. //
  459. // Internal Entry Points defined in obdir.c
  460. //
  461. PVOID
  462. ObpLookupDirectoryEntry (
  463. IN POBJECT_DIRECTORY Directory,
  464. IN PUNICODE_STRING Name,
  465. IN ULONG Attributes,
  466. IN BOOLEAN SearchShadow,
  467. OUT POBP_LOOKUP_CONTEXT LookupContext
  468. );
  469. BOOLEAN
  470. ObpInsertDirectoryEntry (
  471. IN POBJECT_DIRECTORY Directory,
  472. IN POBP_LOOKUP_CONTEXT LookupContext,
  473. IN POBJECT_HEADER ObjectHeader
  474. );
  475. BOOLEAN
  476. ObpDeleteDirectoryEntry (
  477. IN POBP_LOOKUP_CONTEXT LookupContext
  478. );
  479. NTSTATUS
  480. ObpLookupObjectName (
  481. IN HANDLE RootDirectoryHandle,
  482. IN PUNICODE_STRING ObjectName,
  483. IN ULONG Attributes,
  484. IN POBJECT_TYPE ObjectType,
  485. IN KPROCESSOR_MODE AccessMode,
  486. IN PVOID ParseContext OPTIONAL,
  487. IN PSECURITY_QUALITY_OF_SERVICE SecurityQos OPTIONAL,
  488. IN PVOID InsertObject OPTIONAL,
  489. IN OUT PACCESS_STATE AccessState,
  490. OUT POBP_LOOKUP_CONTEXT LookupContext,
  491. OUT PVOID *FoundObject
  492. );
  493. VOID
  494. ObpUnlockObjectDirectoryPath (
  495. IN POBJECT_DIRECTORY LockedDirectory
  496. );
  497. PDEVICE_MAP
  498. ObpReferenceDeviceMap(
  499. );
  500. VOID
  501. FASTCALL
  502. ObfDereferenceDeviceMap(
  503. IN PDEVICE_MAP DeviceMap
  504. );
  505. //
  506. // Internal entry points defined in obref.c
  507. //
  508. VOID
  509. ObpDeleteNameCheck (
  510. IN PVOID Object
  511. );
  512. VOID
  513. ObpProcessRemoveObjectQueue (
  514. PVOID Parameter
  515. );
  516. VOID
  517. ObpRemoveObjectRoutine (
  518. IN PVOID Object,
  519. IN BOOLEAN CalledOnWorkerThread
  520. );
  521. //
  522. // Internal entry points defined in obhandle.c
  523. //
  524. POBJECT_HANDLE_COUNT_ENTRY
  525. ObpInsertHandleCount (
  526. POBJECT_HEADER ObjectHeader
  527. );
  528. NTSTATUS
  529. ObpIncrementHandleCount (
  530. OB_OPEN_REASON OpenReason,
  531. PEPROCESS Process,
  532. PVOID Object,
  533. POBJECT_TYPE ObjectType,
  534. PACCESS_STATE AccessState OPTIONAL,
  535. KPROCESSOR_MODE AccessMode,
  536. ULONG Attributes
  537. );
  538. VOID
  539. ObpDecrementHandleCount (
  540. PEPROCESS Process,
  541. POBJECT_HEADER ObjectHeader,
  542. POBJECT_TYPE ObjectType,
  543. ACCESS_MASK GrantedAccess
  544. );
  545. NTSTATUS
  546. ObpCreateHandle (
  547. IN OB_OPEN_REASON OpenReason,
  548. IN PVOID Object,
  549. IN POBJECT_TYPE ExpectedObjectType OPTIONAL,
  550. IN PACCESS_STATE AccessState,
  551. IN ULONG ObjectPointerBias OPTIONAL,
  552. IN ULONG Attributes,
  553. IN POBP_LOOKUP_CONTEXT LookupContext,
  554. IN KPROCESSOR_MODE AccessMode,
  555. OUT PVOID *ReferencedNewObject OPTIONAL,
  556. OUT PHANDLE Handle
  557. );
  558. NTSTATUS
  559. ObpIncrementUnnamedHandleCount (
  560. PACCESS_MASK DesiredAccess,
  561. PEPROCESS Process,
  562. PVOID Object,
  563. POBJECT_TYPE ObjectType,
  564. KPROCESSOR_MODE AccessMode,
  565. ULONG Attributes
  566. );
  567. NTSTATUS
  568. ObpCreateUnnamedHandle (
  569. IN PVOID Object,
  570. IN ACCESS_MASK DesiredAccess,
  571. IN ULONG ObjectPointerBias OPTIONAL,
  572. IN ULONG Attributes,
  573. IN KPROCESSOR_MODE AccessMode,
  574. OUT PVOID *ReferencedNewObject OPTIONAL,
  575. OUT PHANDLE Handle
  576. );
  577. NTSTATUS
  578. ObpChargeQuotaForObject (
  579. IN POBJECT_HEADER ObjectHeader,
  580. IN POBJECT_TYPE ObjectType,
  581. OUT PBOOLEAN NewObject
  582. );
  583. NTSTATUS
  584. ObpValidateDesiredAccess (
  585. IN ACCESS_MASK DesiredAccess
  586. );
  587. //
  588. // Internal entry points defined in obse.c
  589. //
  590. BOOLEAN
  591. ObpCheckPseudoHandleAccess (
  592. IN PVOID Object,
  593. IN ACCESS_MASK DesiredAccess,
  594. OUT PNTSTATUS AccessStatus,
  595. IN BOOLEAN TypeMutexLocked
  596. );
  597. BOOLEAN
  598. ObpCheckTraverseAccess (
  599. IN PVOID DirectoryObject,
  600. IN ACCESS_MASK TraverseAccess,
  601. IN PACCESS_STATE AccessState OPTIONAL,
  602. IN BOOLEAN TypeMutexLocked,
  603. IN KPROCESSOR_MODE PreviousMode,
  604. OUT PNTSTATUS AccessStatus
  605. );
  606. BOOLEAN
  607. ObpCheckObjectReference (
  608. IN PVOID Object,
  609. IN OUT PACCESS_STATE AccessState,
  610. IN BOOLEAN TypeMutexLocked,
  611. IN KPROCESSOR_MODE AccessMode,
  612. OUT PNTSTATUS AccessStatus
  613. );
  614. //
  615. // Internal entry points defined in obsdata.c
  616. //
  617. NTSTATUS
  618. ObpInitSecurityDescriptorCache (
  619. VOID
  620. );
  621. ULONG
  622. ObpHashSecurityDescriptor (
  623. PSECURITY_DESCRIPTOR SecurityDescriptor
  624. );
  625. ULONG
  626. ObpHashBuffer (
  627. PVOID Data,
  628. ULONG Length
  629. );
  630. PSECURITY_DESCRIPTOR_HEADER
  631. ObpCreateCacheEntry (
  632. PSECURITY_DESCRIPTOR InputSecurityDescriptor,
  633. ULONG FullHash,
  634. ULONG RefBias
  635. );
  636. PSECURITY_DESCRIPTOR
  637. ObpReferenceSecurityDescriptor (
  638. POBJECT_HEADER ObjectHeader
  639. );
  640. PVOID
  641. ObpDestroySecurityDescriptorHeader (
  642. IN PSECURITY_DESCRIPTOR_HEADER Header
  643. );
  644. BOOLEAN
  645. ObpCompareSecurityDescriptors (
  646. IN PSECURITY_DESCRIPTOR SD1,
  647. IN PSECURITY_DESCRIPTOR SD2
  648. );
  649. NTSTATUS
  650. ObpValidateAccessMask (
  651. PACCESS_STATE AccessState
  652. );
  653. ObpCloseHandleTableEntry (
  654. IN PHANDLE_TABLE ObjectTable,
  655. IN PHANDLE_TABLE_ENTRY ObjectTableEntry,
  656. IN HANDLE Handle,
  657. IN KPROCESSOR_MODE PreviousMode,
  658. IN BOOLEAN Rundown,
  659. IN BOOLEAN CanNotRaise
  660. );
  661. NTSTATUS
  662. ObpCloseHandle (
  663. IN HANDLE Handle,
  664. IN KPROCESSOR_MODE PreviousMode,
  665. IN BOOLEAN CanNotRaise
  666. );
  667. VOID
  668. ObpDeleteObjectType (
  669. IN PVOID Object
  670. );
  671. VOID
  672. ObpAuditObjectAccess(
  673. IN HANDLE Handle,
  674. IN PHANDLE_TABLE_ENTRY_INFO ObjectTableEntryInfo,
  675. IN PUNICODE_STRING ObjectTypeName,
  676. IN ACCESS_MASK DesiredAccess
  677. );
  678. //
  679. // Inline functions
  680. //
  681. FORCEINLINE
  682. BOOLEAN
  683. ObpSafeInterlockedIncrement(
  684. IN OUT PLONG lpValue
  685. )
  686. /*
  687. Routine Description:
  688. This function increments the LONG value passed in.
  689. Unlike the InterlockedIncrement function, this will not increment from 0 to 1.
  690. It will return FALSE if it's trying to reference from 0.
  691. Arguments:
  692. lpValue - The pointer to the LONG value that should be safe incremented
  693. Return Value:
  694. Returns FALSE if the current value is 0 (so it cannot increment to 1). TRUE means the LONG
  695. value was increnemted
  696. */
  697. {
  698. LONG PointerCount, NewPointerCount;
  699. //
  700. // If the object is being deleted then the reference count is zero. So the idea here is to reference
  701. // the long value but avoid the 0 -> 1 transition that would cause a double delete.
  702. //
  703. PointerCount = *(volatile *) lpValue;
  704. do {
  705. if (PointerCount == 0) {
  706. return FALSE;
  707. }
  708. NewPointerCount = InterlockedCompareExchange (lpValue,
  709. PointerCount+1,
  710. PointerCount);
  711. //
  712. // If the exchange compare completed ok then we did a reference so return true.
  713. //
  714. if (NewPointerCount == PointerCount) {
  715. return TRUE;
  716. }
  717. //
  718. // We failed because somebody else got in and changed the refence count on us. Use the new value to
  719. // prime the exchange again.
  720. //
  721. PointerCount = NewPointerCount;
  722. } while (TRUE);
  723. return TRUE;
  724. }
  725. POBJECT_HEADER_NAME_INFO
  726. FORCEINLINE
  727. ObpReferenceNameInfo(
  728. IN POBJECT_HEADER ObjectHeader
  729. )
  730. /*
  731. Routine Description:
  732. This function references the name information structure. This is a substitute
  733. for the previous global locking mechanism that used the RootDirectoryMutex to protect
  734. the fields inside the NAME_INFO as well.
  735. If the function returnes a non-NULL name info, the name buffer and Directory will not go away
  736. until the ObpDereferenceNameInfo call.
  737. Arguments:
  738. ObjectHeader - The object header whose name should be safe-referenced
  739. Return Value:
  740. Returns NULL if the object doesn't have a name information structure, or if the name info is being deleted
  741. Returns a pointer to the POBJECT_HEADER_NAME_INFO if it's safe to use the fields inside it.
  742. */
  743. {
  744. POBJECT_HEADER_NAME_INFO NameInfo;
  745. NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
  746. if ((NameInfo != NULL)
  747. &&
  748. ObpSafeInterlockedIncrement( &NameInfo->QueryReferences )) {
  749. return NameInfo;
  750. }
  751. return NULL;
  752. }
  753. VOID
  754. FORCEINLINE
  755. ObpDereferenceNameInfo(
  756. IN POBJECT_HEADER_NAME_INFO NameInfo
  757. )
  758. /*
  759. Routine Description:
  760. This function dereferences the name information structure. If the number of references
  761. drops to 0, the name is freed and the directory dereferenced
  762. Arguments:
  763. NameInfo - The pointer to the name info structure, as returned by ObpReferenceNameInfo.
  764. (NULL value is allowed)
  765. Return Value:
  766. None
  767. */
  768. {
  769. if ( (NameInfo != NULL)
  770. &&
  771. (InterlockedDecrement(&NameInfo->QueryReferences) == 0)) {
  772. PVOID DirObject;
  773. //
  774. // Free the name buffer and zero out the name data fields
  775. //
  776. if (NameInfo->Name.Buffer != NULL) {
  777. ExFreePool( NameInfo->Name.Buffer );
  778. NameInfo->Name.Buffer = NULL;
  779. NameInfo->Name.Length = 0;
  780. NameInfo->Name.MaximumLength = 0;
  781. }
  782. DirObject = NameInfo->Directory;
  783. if (DirObject != NULL) {
  784. NameInfo->Directory = NULL;
  785. ObDereferenceObjectDeferDelete( DirObject );
  786. }
  787. }
  788. }
  789. VOID
  790. FORCEINLINE
  791. ObpLockDirectoryExclusive(
  792. IN POBJECT_DIRECTORY Directory,
  793. IN POBP_LOOKUP_CONTEXT LockContext
  794. )
  795. /*
  796. Routine Description:
  797. This Function locks exclusively the Directory. It is used for write access to
  798. the directory structure.
  799. Arguments:
  800. Directory - The directory being locked
  801. Return Value:
  802. None
  803. */
  804. {
  805. LockContext->LockStateSignature = OBP_LOCK_WAITEXCLUSIVE_SIGNATURE;
  806. KeEnterCriticalRegion();
  807. ExAcquirePushLockExclusive( &Directory->Lock );
  808. LockContext->LockStateSignature = OBP_LOCK_OWNEDEXCLUSIVE_SIGNATURE;
  809. }
  810. VOID
  811. FORCEINLINE
  812. ObpLockDirectoryShared (
  813. IN POBJECT_DIRECTORY Directory,
  814. IN POBP_LOOKUP_CONTEXT LockContext
  815. )
  816. /*
  817. Routine Description:
  818. This Function locks shared the Directory. It is used to read fields inside
  819. the directory structure.
  820. Arguments:
  821. Directory - The directory being locked
  822. Return Value:
  823. None
  824. */
  825. {
  826. LockContext->LockStateSignature = OBP_LOCK_WAITSHARED_SIGNATURE;
  827. KeEnterCriticalRegion();
  828. ExAcquirePushLockShared( &Directory->Lock );
  829. LockContext->LockStateSignature = OBP_LOCK_OWNEDSHARED_SIGNATURE;
  830. }
  831. VOID
  832. FORCEINLINE
  833. ObpUnlockDirectory(
  834. IN POBJECT_DIRECTORY Directory,
  835. IN POBP_LOOKUP_CONTEXT LockContext
  836. )
  837. /*
  838. Routine Description:
  839. This Function unlocks a Directory (previously locked exclusive or shared).
  840. Arguments:
  841. Directory - The directory that needs to be unlocked
  842. Return Value:
  843. None
  844. */
  845. {
  846. ExReleasePushLock( &Directory->Lock );
  847. LockContext->LockStateSignature = OBP_LOCK_RELEASED_SIGNATURE;
  848. KeLeaveCriticalRegion();
  849. }
  850. VOID
  851. FORCEINLINE
  852. ObpInitializeLookupContext(
  853. IN POBP_LOOKUP_CONTEXT LookupContext
  854. )
  855. /*
  856. Routine Description:
  857. This Function initialize a lookup context structure.
  858. Arguments:
  859. LookupContext - The LookupContext to be initialized
  860. Return Value:
  861. None
  862. */
  863. {
  864. LookupContext->DirectoryLocked = FALSE;
  865. LookupContext->Object = NULL;
  866. LookupContext->Directory = NULL;
  867. LookupContext->LockStateSignature = OBP_LOCK_UNUSED_SIGNATURE;
  868. }
  869. VOID
  870. FORCEINLINE
  871. ObpLockLookupContext (
  872. IN POBP_LOOKUP_CONTEXT LookupContext,
  873. IN POBJECT_DIRECTORY Directory
  874. )
  875. /*
  876. Routine Description:
  877. This function locks a lookup context. The directory
  878. is exclusively owned after this call and it's safe to access
  879. the directory in write mode. This function is intended to be used in
  880. insertion / deletion into/from the specified directory.
  881. The directory is unlocked at the next ObpReleaseLookupContext.
  882. Arguments:
  883. LookupContext - The LookupContext to be initialized
  884. Directory - The directory beling locked for exclusive access.
  885. Return Value:
  886. None
  887. */
  888. {
  889. ObpLockDirectoryExclusive(Directory, LookupContext);
  890. LookupContext->DirectoryLocked = TRUE;
  891. LookupContext->Directory = Directory;
  892. }
  893. VOID
  894. FORCEINLINE
  895. ObpReleaseLookupContext (
  896. IN POBP_LOOKUP_CONTEXT LookupContext
  897. )
  898. /*
  899. Routine Description:
  900. This function undoes the references and locking changes during these calls:
  901. ObpLockLookupContext and ObpLookupDirectoryEntry.
  902. N.B. If ObpLookupDirectoryEntry is called several times in a loop, each call
  903. will undo the references done at the previous call. ObpReleaseLookupContext
  904. should be called only ones at the end.
  905. Arguments:
  906. LookupContext - The LookupContext to be released
  907. Return Value:
  908. None
  909. */
  910. {
  911. //
  912. // If the context was locked we need to unlock the directory
  913. //
  914. if (LookupContext->DirectoryLocked) {
  915. ObpUnlockDirectory( LookupContext->Directory, LookupContext );
  916. LookupContext->Directory = NULL;
  917. LookupContext->DirectoryLocked = FALSE;
  918. }
  919. //
  920. // Remove the references added to the name info and object
  921. //
  922. if (LookupContext->Object) {
  923. POBJECT_HEADER_NAME_INFO NameInfo;
  924. NameInfo = OBJECT_HEADER_TO_NAME_INFO(OBJECT_TO_OBJECT_HEADER(LookupContext->Object));
  925. ObpDereferenceNameInfo( NameInfo );
  926. ObDereferenceObject(LookupContext->Object);
  927. LookupContext->Object = NULL;
  928. }
  929. }