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.

1859 lines
51 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. obquery.c
  5. Abstract:
  6. Query Object system service
  7. Author:
  8. Steve Wood (stevewo) 12-May-1989
  9. Revision History:
  10. --*/
  11. #include "obp.h"
  12. //
  13. // Local procedure prototypes
  14. //
  15. //
  16. // The following structure is used to pass the call back routine
  17. // "ObpSetHandleAttributes" the captured object information and
  18. // the processor mode of the caller.
  19. //
  20. typedef struct __OBP_SET_HANDLE_ATTRIBUTES {
  21. OBJECT_HANDLE_FLAG_INFORMATION ObjectInformation;
  22. KPROCESSOR_MODE PreviousMode;
  23. } OBP_SET_HANDLE_ATTRIBUTES, *POBP_SET_HANDLE_ATTRIBUTES;
  24. BOOLEAN
  25. ObpSetHandleAttributes (
  26. IN OUT PVOID TableEntry,
  27. IN ULONG_PTR Parameter
  28. );
  29. #if defined(ALLOC_PRAGMA)
  30. #pragma alloc_text(PAGE,NtQueryObject)
  31. #pragma alloc_text(PAGE,ObpQueryNameString)
  32. #pragma alloc_text(PAGE,ObQueryNameString)
  33. #pragma alloc_text(PAGE,ObQueryTypeName)
  34. #pragma alloc_text(PAGE,ObQueryTypeInfo)
  35. #pragma alloc_text(PAGE,ObQueryObjectAuditingByHandle)
  36. #pragma alloc_text(PAGE,NtSetInformationObject)
  37. #pragma alloc_text(PAGE,ObpSetHandleAttributes)
  38. #pragma alloc_text(PAGE,ObSetHandleAttributes)
  39. #endif
  40. NTSTATUS
  41. NtQueryObject (
  42. IN HANDLE Handle,
  43. IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
  44. OUT PVOID ObjectInformation,
  45. IN ULONG ObjectInformationLength,
  46. OUT PULONG ReturnLength OPTIONAL
  47. )
  48. /*++
  49. Routine description:
  50. This routine is used to query information about a given object
  51. Arguments:
  52. Handle - Supplies a handle to the object being queried. This value
  53. is ignored if the requested information class is for type
  54. information.
  55. ObjectInformationClass - Specifies the type of information to return
  56. ObjectInformation - Supplies an output buffer for the information being
  57. returned
  58. ObjectInformationLength - Specifies, in bytes, the length of the
  59. preceding object information buffer
  60. ReturnLength - Optionally receives the length, in bytes, used to store
  61. the object information
  62. Return Value:
  63. An appropriate status value
  64. --*/
  65. {
  66. KPROCESSOR_MODE PreviousMode;
  67. NTSTATUS Status;
  68. PVOID Object;
  69. POBJECT_HEADER ObjectHeader;
  70. POBJECT_HEADER_QUOTA_INFO QuotaInfo;
  71. POBJECT_HEADER_NAME_INFO NameInfo;
  72. POBJECT_TYPE ObjectType;
  73. POBJECT_HEADER ObjectDirectoryHeader;
  74. POBJECT_DIRECTORY ObjectDirectory;
  75. ACCESS_MASK GrantedAccess;
  76. POBJECT_HANDLE_FLAG_INFORMATION HandleFlags;
  77. OBJECT_HANDLE_INFORMATION HandleInformation = {0};
  78. ULONG NameInfoSize;
  79. ULONG SecurityDescriptorSize;
  80. ULONG TempReturnLength;
  81. OBJECT_BASIC_INFORMATION ObjectBasicInfo;
  82. POBJECT_TYPES_INFORMATION TypesInformation;
  83. POBJECT_TYPE_INFORMATION TypeInfo;
  84. ULONG i;
  85. PAGED_CODE();
  86. //
  87. // Initialize our local variables
  88. //
  89. TempReturnLength = 0;
  90. //
  91. // Get previous processor mode and probe output argument if necessary.
  92. //
  93. PreviousMode = KeGetPreviousMode();
  94. if (PreviousMode != KernelMode) {
  95. try {
  96. if (ObjectInformationClass != ObjectHandleFlagInformation) {
  97. ProbeForWrite( ObjectInformation,
  98. ObjectInformationLength,
  99. sizeof( ULONG ));
  100. } else {
  101. ProbeForWrite( ObjectInformation,
  102. ObjectInformationLength,
  103. 1 );
  104. }
  105. //
  106. // We'll use a local temp return length variable to pass
  107. // through to the later ob query calls which will increment
  108. // its value. We can't pass the users return length directly
  109. // because the user might also be altering its value behind
  110. // our back.
  111. //
  112. if (ARGUMENT_PRESENT( ReturnLength )) {
  113. ProbeForWriteUlong( ReturnLength );
  114. }
  115. } except( EXCEPTION_EXECUTE_HANDLER ) {
  116. return( GetExceptionCode() );
  117. }
  118. }
  119. //
  120. // If the query is not for types information then we
  121. // will have to get the object in question. Otherwise
  122. // for types information there really isn't an object
  123. // to grab.
  124. //
  125. if (ObjectInformationClass != ObjectTypesInformation) {
  126. Status = ObReferenceObjectByHandle( Handle,
  127. 0,
  128. NULL,
  129. PreviousMode,
  130. &Object,
  131. &HandleInformation );
  132. if (!NT_SUCCESS( Status )) {
  133. return( Status );
  134. }
  135. GrantedAccess = HandleInformation.GrantedAccess;
  136. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  137. ObjectType = ObjectHeader->Type;
  138. } else {
  139. GrantedAccess = 0;
  140. Object = NULL;
  141. ObjectHeader = NULL;
  142. ObjectType = NULL;
  143. Status = STATUS_SUCCESS;
  144. }
  145. //
  146. // Now process the particular information class being
  147. // requested
  148. //
  149. switch( ObjectInformationClass ) {
  150. case ObjectBasicInformation:
  151. //
  152. // Make sure the output buffer is long enough and then
  153. // fill in the appropriate fields into our local copy
  154. // of basic information.
  155. //
  156. if (ObjectInformationLength != sizeof( OBJECT_BASIC_INFORMATION )) {
  157. ObDereferenceObject( Object );
  158. return( STATUS_INFO_LENGTH_MISMATCH );
  159. }
  160. ObjectBasicInfo.Attributes = HandleInformation.HandleAttributes;
  161. if (ObjectHeader->Flags & OB_FLAG_PERMANENT_OBJECT) {
  162. ObjectBasicInfo.Attributes |= OBJ_PERMANENT;
  163. }
  164. if (ObjectHeader->Flags & OB_FLAG_EXCLUSIVE_OBJECT) {
  165. ObjectBasicInfo.Attributes |= OBJ_EXCLUSIVE;
  166. }
  167. ObjectBasicInfo.GrantedAccess = GrantedAccess;
  168. ObjectBasicInfo.HandleCount = (ULONG)ObjectHeader->HandleCount;
  169. ObjectBasicInfo.PointerCount = (ULONG)ObjectHeader->PointerCount;
  170. QuotaInfo = OBJECT_HEADER_TO_QUOTA_INFO( ObjectHeader );
  171. if (QuotaInfo != NULL) {
  172. ObjectBasicInfo.PagedPoolCharge = QuotaInfo->PagedPoolCharge;
  173. ObjectBasicInfo.NonPagedPoolCharge = QuotaInfo->NonPagedPoolCharge;
  174. } else {
  175. ObjectBasicInfo.PagedPoolCharge = 0;
  176. ObjectBasicInfo.NonPagedPoolCharge = 0;
  177. }
  178. if (ObjectType == ObpSymbolicLinkObjectType) {
  179. ObjectBasicInfo.CreationTime = ((POBJECT_SYMBOLIC_LINK)Object)->CreationTime;
  180. } else {
  181. RtlZeroMemory( &ObjectBasicInfo.CreationTime,
  182. sizeof( ObjectBasicInfo.CreationTime ));
  183. }
  184. //
  185. // Compute the size of the object name string by taking its name plus
  186. // seperators and traversing up to the root adding each directories
  187. // name length plus seperators
  188. //
  189. NameInfo = ObpReferenceNameInfo( ObjectHeader );
  190. if ((NameInfo != NULL) && (NameInfo->Directory != NULL)) {
  191. PVOID ReferencedDirectory = NULL;
  192. //
  193. // We grab the root directory lock and test again the directory
  194. //
  195. ObjectDirectory = NameInfo->Directory;
  196. ASSERT (ObjectDirectory);
  197. ObfReferenceObject( ObjectDirectory );
  198. ReferencedDirectory = ObjectDirectory;
  199. NameInfoSize = sizeof( OBJ_NAME_PATH_SEPARATOR ) + NameInfo->Name.Length;
  200. ObpDereferenceNameInfo( NameInfo );
  201. NameInfo = NULL;
  202. while (ObjectDirectory) {
  203. ObjectDirectoryHeader = OBJECT_TO_OBJECT_HEADER( ObjectDirectory );
  204. NameInfo = ObpReferenceNameInfo( ObjectDirectoryHeader );
  205. if ((NameInfo != NULL) && (NameInfo->Directory != NULL)) {
  206. NameInfoSize += sizeof( OBJ_NAME_PATH_SEPARATOR ) + NameInfo->Name.Length;
  207. ObjectDirectory = NameInfo->Directory;
  208. ObfReferenceObject( ObjectDirectory );
  209. ObpDereferenceNameInfo( NameInfo );
  210. NameInfo = NULL;
  211. ObDereferenceObject( ReferencedDirectory );
  212. ReferencedDirectory = ObjectDirectory;
  213. } else {
  214. break;
  215. }
  216. }
  217. if (ReferencedDirectory) {
  218. ObDereferenceObject( ReferencedDirectory );
  219. }
  220. NameInfoSize += sizeof( OBJECT_NAME_INFORMATION ) + sizeof( UNICODE_NULL );
  221. } else {
  222. NameInfoSize = 0;
  223. }
  224. ObpDereferenceNameInfo( NameInfo );
  225. NameInfo = NULL;
  226. ObjectBasicInfo.NameInfoSize = NameInfoSize;
  227. ObjectBasicInfo.TypeInfoSize = ObjectType->Name.Length + sizeof( UNICODE_NULL ) +
  228. sizeof( OBJECT_TYPE_INFORMATION );
  229. if ((GrantedAccess & READ_CONTROL) &&
  230. ARGUMENT_PRESENT( ObjectHeader->SecurityDescriptor )) {
  231. SECURITY_INFORMATION SecurityInformation;
  232. //
  233. // Request a complete security descriptor
  234. //
  235. SecurityInformation = OWNER_SECURITY_INFORMATION |
  236. GROUP_SECURITY_INFORMATION |
  237. DACL_SECURITY_INFORMATION |
  238. SACL_SECURITY_INFORMATION;
  239. SecurityDescriptorSize = 0;
  240. (ObjectType->TypeInfo.SecurityProcedure)( Object,
  241. QuerySecurityDescriptor,
  242. &SecurityInformation,
  243. NULL,
  244. &SecurityDescriptorSize,
  245. &ObjectHeader->SecurityDescriptor,
  246. ObjectType->TypeInfo.PoolType,
  247. &ObjectType->TypeInfo.GenericMapping );
  248. } else {
  249. SecurityDescriptorSize = 0;
  250. }
  251. ObjectBasicInfo.SecurityDescriptorSize = SecurityDescriptorSize;
  252. //
  253. // Now that we've packaged up our local copy of basic info we need
  254. // to copy it into the output buffer and set the return
  255. // length
  256. //
  257. try {
  258. *(POBJECT_BASIC_INFORMATION) ObjectInformation = ObjectBasicInfo;
  259. TempReturnLength = ObjectInformationLength;
  260. } except( EXCEPTION_EXECUTE_HANDLER ) {
  261. //
  262. // Fall through, since we cannot undo what we have done.
  263. //
  264. }
  265. break;
  266. case ObjectNameInformation:
  267. //
  268. // Call a local worker routine
  269. //
  270. Status = ObpQueryNameString( Object,
  271. (POBJECT_NAME_INFORMATION)ObjectInformation,
  272. ObjectInformationLength,
  273. &TempReturnLength,
  274. PreviousMode );
  275. break;
  276. case ObjectTypeInformation:
  277. //
  278. // Call a local worker routine
  279. //
  280. Status = ObQueryTypeInfo( ObjectType,
  281. (POBJECT_TYPE_INFORMATION)ObjectInformation,
  282. ObjectInformationLength,
  283. &TempReturnLength );
  284. break;
  285. case ObjectTypesInformation:
  286. try {
  287. //
  288. // The first thing we do is set the return length to cover the
  289. // types info record. Later in each call to query type info
  290. // this value will be updated as necessary
  291. //
  292. TempReturnLength = sizeof( OBJECT_TYPES_INFORMATION );
  293. //
  294. // Make sure there is enough room to hold the types info record
  295. // and if so then compute the number of defined types there are
  296. //
  297. TypesInformation = (POBJECT_TYPES_INFORMATION)ObjectInformation;
  298. if (ObjectInformationLength < sizeof( OBJECT_TYPES_INFORMATION ) ) {
  299. Status = STATUS_INFO_LENGTH_MISMATCH;
  300. } else {
  301. TypesInformation->NumberOfTypes = 0;
  302. for (i=0; i<OBP_MAX_DEFINED_OBJECT_TYPES; i++) {
  303. ObjectType = ObpObjectTypes[ i ];
  304. if (ObjectType == NULL) {
  305. break;
  306. }
  307. TypesInformation->NumberOfTypes += 1;
  308. }
  309. }
  310. //
  311. // For each defined type we will query the type info for the
  312. // object type and adjust the TypeInfo pointer to the next
  313. // free spot
  314. //
  315. TypeInfo = (POBJECT_TYPE_INFORMATION)(((PUCHAR)TypesInformation) + ALIGN_UP( sizeof(*TypesInformation), ULONG_PTR ));
  316. for (i=0; i<OBP_MAX_DEFINED_OBJECT_TYPES; i++) {
  317. ObjectType = ObpObjectTypes[ i ];
  318. if (ObjectType == NULL) {
  319. break;
  320. }
  321. Status = ObQueryTypeInfo( ObjectType,
  322. TypeInfo,
  323. ObjectInformationLength,
  324. &TempReturnLength );
  325. if (NT_SUCCESS( Status )) {
  326. TypeInfo = (POBJECT_TYPE_INFORMATION)
  327. ((PCHAR)(TypeInfo+1) + ALIGN_UP( TypeInfo->TypeName.MaximumLength, ULONG_PTR ));
  328. }
  329. }
  330. } except( EXCEPTION_EXECUTE_HANDLER ) {
  331. Status = GetExceptionCode();
  332. }
  333. break;
  334. case ObjectHandleFlagInformation:
  335. try {
  336. //
  337. // Set the amount of data we are going to return
  338. //
  339. TempReturnLength = sizeof(OBJECT_HANDLE_FLAG_INFORMATION);
  340. HandleFlags = (POBJECT_HANDLE_FLAG_INFORMATION)ObjectInformation;
  341. //
  342. // Make sure we have enough room for the query, and if so we'll
  343. // set the output based on the flags stored in the handle
  344. //
  345. if (ObjectInformationLength < sizeof( OBJECT_HANDLE_FLAG_INFORMATION)) {
  346. Status = STATUS_INFO_LENGTH_MISMATCH;
  347. } else {
  348. HandleFlags->Inherit = FALSE;
  349. if (HandleInformation.HandleAttributes & OBJ_INHERIT) {
  350. HandleFlags->Inherit = TRUE;
  351. }
  352. HandleFlags->ProtectFromClose = FALSE;
  353. if (HandleInformation.HandleAttributes & OBJ_PROTECT_CLOSE) {
  354. HandleFlags->ProtectFromClose = TRUE;
  355. }
  356. }
  357. } except( EXCEPTION_EXECUTE_HANDLER ) {
  358. Status = GetExceptionCode();
  359. }
  360. break;
  361. default:
  362. //
  363. // To get to this point we must have had an object and the
  364. // information class is not defined, so we should dereference the
  365. // object and return to our user the bad status
  366. //
  367. ObDereferenceObject( Object );
  368. return( STATUS_INVALID_INFO_CLASS );
  369. }
  370. //
  371. // Now if the caller asked for a return length we'll set it from
  372. // our local copy
  373. //
  374. try {
  375. if (ARGUMENT_PRESENT( ReturnLength ) ) {
  376. *ReturnLength = TempReturnLength;
  377. }
  378. } except( EXCEPTION_EXECUTE_HANDLER ) {
  379. //
  380. // Fall through, since we cannot undo what we have done.
  381. //
  382. }
  383. //
  384. // In the end we can free the object if there was one and return
  385. // to our caller
  386. //
  387. if (Object != NULL) {
  388. ObDereferenceObject( Object );
  389. }
  390. return( Status );
  391. }
  392. NTSTATUS
  393. ObSetHandleAttributes (
  394. IN HANDLE Handle,
  395. IN POBJECT_HANDLE_FLAG_INFORMATION HandleFlags,
  396. IN KPROCESSOR_MODE PreviousMode
  397. )
  398. {
  399. BOOLEAN AttachedToProcess = FALSE;
  400. KAPC_STATE ApcState;
  401. OBP_SET_HANDLE_ATTRIBUTES CapturedInformation;
  402. PVOID ObjectTable;
  403. HANDLE ObjectHandle;
  404. NTSTATUS Status;
  405. PAGED_CODE();
  406. CapturedInformation.PreviousMode = PreviousMode;
  407. CapturedInformation.ObjectInformation = *HandleFlags;
  408. //
  409. // Get the address of the object table for the current process. Or
  410. // get the system handle table if this is a kernel handle and we are
  411. // in kernel mode
  412. //
  413. if (IsKernelHandle( Handle, PreviousMode )) {
  414. //
  415. // Make the handle look like a regular handle
  416. //
  417. ObjectHandle = DecodeKernelHandle( Handle );
  418. //
  419. // The global kernel handle table
  420. //
  421. ObjectTable = ObpKernelHandleTable;
  422. //
  423. // Go to the system process
  424. //
  425. if (PsGetCurrentProcess() != PsInitialSystemProcess) {
  426. KeStackAttachProcess (&PsInitialSystemProcess->Pcb, &ApcState);
  427. AttachedToProcess = TRUE;
  428. }
  429. } else {
  430. ObjectTable = ObpGetObjectTable();
  431. ObjectHandle = Handle;
  432. }
  433. //
  434. // Make the change to the handle table entry. The callback
  435. // routine will do the actual change
  436. //
  437. if (ExChangeHandle( ObjectTable,
  438. ObjectHandle,
  439. ObpSetHandleAttributes,
  440. (ULONG_PTR)&CapturedInformation) ) {
  441. Status = STATUS_SUCCESS;
  442. } else {
  443. Status = STATUS_ACCESS_DENIED;
  444. }
  445. //
  446. // If we are attached to the system process then return
  447. // back to our caller
  448. //
  449. if (AttachedToProcess) {
  450. KeUnstackDetachProcess(&ApcState);
  451. AttachedToProcess = FALSE;
  452. }
  453. return Status;
  454. }
  455. NTSTATUS
  456. NTAPI
  457. NtSetInformationObject (
  458. IN HANDLE Handle,
  459. IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
  460. IN PVOID ObjectInformation,
  461. IN ULONG ObjectInformationLength
  462. )
  463. /*++
  464. Routine description:
  465. This routine is used to set handle information about a specified
  466. handle
  467. Arguments:
  468. Handle - Supplies the handle being modified
  469. ObjectInformationClass - Specifies the class of information being
  470. modified. The only accepted value is ObjectHandleFlagInformation
  471. ObjectInformation - Supplies the buffer containing the handle
  472. flag information structure
  473. ObjectInformationLength - Specifies the length, in bytes, of the
  474. object information buffer
  475. Return Value:
  476. An appropriate status value
  477. --*/
  478. {
  479. NTSTATUS Status;
  480. OBJECT_HANDLE_FLAG_INFORMATION CapturedFlags;
  481. KPROCESSOR_MODE PreviousMode;
  482. PAGED_CODE();
  483. Status = STATUS_INVALID_INFO_CLASS;
  484. switch (ObjectInformationClass) {
  485. case ObjectHandleFlagInformation:
  486. {
  487. if (ObjectInformationLength != sizeof(OBJECT_HANDLE_FLAG_INFORMATION)) {
  488. return STATUS_INFO_LENGTH_MISMATCH;
  489. }
  490. //
  491. // Get previous processor mode and probe and capture the input
  492. // buffer
  493. //
  494. PreviousMode = KeGetPreviousMode();
  495. try {
  496. if (PreviousMode != KernelMode) {
  497. ProbeForRead(ObjectInformation, ObjectInformationLength, 1);
  498. }
  499. CapturedFlags = *(POBJECT_HANDLE_FLAG_INFORMATION)ObjectInformation;
  500. } except(ExSystemExceptionFilter()) {
  501. return GetExceptionCode();
  502. }
  503. Status = ObSetHandleAttributes (Handle,
  504. &CapturedFlags,
  505. PreviousMode);
  506. }
  507. break;
  508. case ObjectSessionInformation:
  509. {
  510. PreviousMode = KeGetPreviousMode();
  511. if (!SeSinglePrivilegeCheck( SeTcbPrivilege,
  512. PreviousMode)) {
  513. Status = STATUS_PRIVILEGE_NOT_HELD;
  514. } else {
  515. PVOID Object;
  516. OBJECT_HANDLE_INFORMATION HandleInformation;
  517. Status = ObReferenceObjectByHandle(Handle,
  518. 0,
  519. ObpDirectoryObjectType,
  520. PreviousMode,
  521. &Object,
  522. &HandleInformation
  523. );
  524. if (NT_SUCCESS(Status)) {
  525. POBJECT_DIRECTORY Directory;
  526. OBP_LOOKUP_CONTEXT LockContext;
  527. Directory = (POBJECT_DIRECTORY)Object;
  528. ObpInitializeLookupContext( &LockContext );
  529. ObpLockDirectoryExclusive(Directory, &LockContext);
  530. Directory->SessionId = PsGetCurrentProcessSessionId();
  531. ObpUnlockDirectory(Directory, &LockContext);
  532. ObDereferenceObject(Object);
  533. }
  534. }
  535. }
  536. break;
  537. }
  538. //
  539. // And return to our caller
  540. //
  541. return Status;
  542. }
  543. #define OBP_MISSING_NAME_LITERAL L"..."
  544. #define OBP_MISSING_NAME_LITERAL_SIZE (sizeof( OBP_MISSING_NAME_LITERAL ) - sizeof( UNICODE_NULL ))
  545. NTSTATUS
  546. ObQueryNameString (
  547. IN PVOID Object,
  548. OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
  549. IN ULONG Length,
  550. OUT PULONG ReturnLength
  551. )
  552. /*++
  553. Routine description:
  554. This routine processes a query of an object's name information
  555. Arguments:
  556. Object - Supplies the object being queried
  557. ObjectNameInfo - Supplies the buffer to store the name string
  558. information
  559. Length - Specifies the length, in bytes, of the original object
  560. name info buffer.
  561. ReturnLength - Contains the number of bytes already used up
  562. in the object name info. On return this receives an updated
  563. byte count.
  564. (Length minus ReturnLength) is really now many bytes are left
  565. in the output buffer. The buffer supplied to this call may
  566. actually be offset within the original users buffer
  567. Return Value:
  568. An appropriate status value
  569. --*/
  570. {
  571. return ObpQueryNameString( Object,
  572. ObjectNameInfo,
  573. Length,
  574. ReturnLength,
  575. KernelMode );
  576. }
  577. NTSTATUS
  578. ObpQueryNameString (
  579. IN PVOID Object,
  580. OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
  581. IN ULONG Length,
  582. OUT PULONG ReturnLength,
  583. IN KPROCESSOR_MODE Mode
  584. )
  585. /*++
  586. Routine description:
  587. This routine processes a query of an object's name information
  588. Arguments:
  589. Object - Supplies the object being queried
  590. ObjectNameInfo - Supplies the buffer to store the name string
  591. information
  592. Length - Specifies the length, in bytes, of the original object
  593. name info buffer.
  594. ReturnLength - Contains the number of bytes already used up
  595. in the object name info. On return this receives an updated
  596. byte count.
  597. (Length minus ReturnLength) is really now many bytes are left
  598. in the output buffer. The buffer supplied to this call may
  599. actually be offset within the original users buffer
  600. Mode - Mode of caller
  601. Return Value:
  602. An appropriate status value
  603. --*/
  604. {
  605. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  606. POBJECT_HEADER ObjectHeader;
  607. POBJECT_HEADER_NAME_INFO NameInfo;
  608. POBJECT_HEADER ObjectDirectoryHeader;
  609. POBJECT_DIRECTORY ObjectDirectory;
  610. ULONG NameInfoSize = 0;
  611. PUNICODE_STRING String;
  612. PWCH StringBuffer;
  613. ULONG NameSize;
  614. PVOID ReferencedObject = NULL;
  615. BOOLEAN DoFullQuery = TRUE;
  616. ULONG BufferLength;
  617. PWCH OriginalBuffer;
  618. BOOLEAN ForceRetry = FALSE;
  619. PAGED_CODE();
  620. //
  621. // Get the object header and name info record if it exists
  622. //
  623. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  624. NameInfo = ObpReferenceNameInfo( ObjectHeader );
  625. //
  626. // If the object type has a query name callback routine then
  627. // that is how we get the name
  628. //
  629. if (ObjectHeader->Type->TypeInfo.QueryNameProcedure != NULL) {
  630. try {
  631. #if DBG
  632. KIRQL SaveIrql;
  633. #endif
  634. ObpBeginTypeSpecificCallOut( SaveIrql );
  635. ObpEndTypeSpecificCallOut( SaveIrql, "Query", ObjectHeader->Type, Object );
  636. Status = (*ObjectHeader->Type->TypeInfo.QueryNameProcedure)( Object,
  637. (BOOLEAN)((NameInfo != NULL) && (NameInfo->Name.Length != 0)),
  638. ObjectNameInfo,
  639. Length,
  640. ReturnLength,
  641. Mode );
  642. } except( EXCEPTION_EXECUTE_HANDLER ) {
  643. Status = GetExceptionCode();
  644. }
  645. ObpDereferenceNameInfo( NameInfo );
  646. return( Status );
  647. }
  648. //
  649. // Otherwise, the object type does not specify a query name
  650. // procedure so we get to do the work. The first thing
  651. // to check is if the object doesn't even have a name. If
  652. // object doesn't have a name then we'll return an empty name
  653. // info structure.
  654. //
  655. RETRY:
  656. if ((NameInfo == NULL) || (NameInfo->Name.Buffer == NULL)) {
  657. //
  658. // Compute the length of our return buffer, set the output
  659. // if necessary and make sure the supplied buffer is large
  660. // enough
  661. //
  662. NameInfoSize = sizeof( OBJECT_NAME_INFORMATION );
  663. try {
  664. *ReturnLength = NameInfoSize;
  665. } except( EXCEPTION_EXECUTE_HANDLER ) {
  666. ObpDereferenceNameInfo( NameInfo );
  667. return( GetExceptionCode() );
  668. }
  669. if (Length < NameInfoSize) {
  670. ObpDereferenceNameInfo( NameInfo );
  671. return( STATUS_INFO_LENGTH_MISMATCH );
  672. }
  673. //
  674. // Initialize the output buffer to be an empty string
  675. // and then return to our caller
  676. //
  677. try {
  678. ObjectNameInfo->Name.Length = 0;
  679. ObjectNameInfo->Name.MaximumLength = 0;
  680. ObjectNameInfo->Name.Buffer = NULL;
  681. } except( EXCEPTION_EXECUTE_HANDLER ) {
  682. //
  683. // Fall through, since we cannot undo what we have done.
  684. //
  685. ObpDereferenceNameInfo(NameInfo);
  686. return( GetExceptionCode() );
  687. }
  688. ObpDereferenceNameInfo(NameInfo);
  689. return( STATUS_SUCCESS );
  690. }
  691. try {
  692. //
  693. // The object does have a name but now see if this is
  694. // just the root directory object in which case the name size
  695. // is only the "\" character
  696. //
  697. if (Object == ObpRootDirectoryObject) {
  698. NameSize = sizeof( OBJ_NAME_PATH_SEPARATOR );
  699. } else {
  700. //
  701. // The named object is not the root so for every directory
  702. // working out way up we'll add its size to the name keeping
  703. // track of "\" characters inbetween each component. We first
  704. // start with the object name itself and then move on to
  705. // the directories
  706. //
  707. ObjectDirectory = NameInfo->Directory;
  708. if (ObjectDirectory) {
  709. ObfReferenceObject( ObjectDirectory );
  710. ReferencedObject = ObjectDirectory;
  711. }
  712. NameSize = sizeof( OBJ_NAME_PATH_SEPARATOR ) + NameInfo->Name.Length;
  713. ObpDereferenceNameInfo( NameInfo );
  714. NameInfo = NULL;
  715. //
  716. // While we are not at the root we'll keep moving up
  717. //
  718. while ((ObjectDirectory != ObpRootDirectoryObject) && (ObjectDirectory)) {
  719. //
  720. // Get the name information for this directory
  721. //
  722. ObjectDirectoryHeader = OBJECT_TO_OBJECT_HEADER( ObjectDirectory );
  723. NameInfo = ObpReferenceNameInfo( ObjectDirectoryHeader );
  724. if ((NameInfo != NULL) && (NameInfo->Directory != NULL)) {
  725. //
  726. // This directory has a name so add it to the accumulated
  727. // size and move up the tree
  728. //
  729. NameSize += sizeof( OBJ_NAME_PATH_SEPARATOR ) + NameInfo->Name.Length;
  730. ObjectDirectory = NameInfo->Directory;
  731. if (ObjectDirectory) {
  732. ObfReferenceObject( ObjectDirectory );
  733. }
  734. ObpDereferenceNameInfo( NameInfo );
  735. NameInfo = NULL;
  736. ObDereferenceObject( ReferencedObject );
  737. ReferencedObject = ObjectDirectory;
  738. //
  739. // UNICODE_STRINGs can only hold MAXUSHORT bytes.
  740. //
  741. if (NameSize > MAXUSHORT) {
  742. break;
  743. }
  744. } else {
  745. //
  746. // This directory does not have a name so we'll give it
  747. // the "..." name and stop the loop
  748. //
  749. NameSize += sizeof( OBJ_NAME_PATH_SEPARATOR ) + OBP_MISSING_NAME_LITERAL_SIZE;
  750. break;
  751. }
  752. }
  753. }
  754. //
  755. // UNICODE_STRINGs can only hold MAXUSHORT bytes
  756. //
  757. if (NameSize > MAXUSHORT) {
  758. Status = STATUS_NAME_TOO_LONG;
  759. DoFullQuery = FALSE;
  760. leave;
  761. }
  762. //
  763. // At this point NameSize is the number of bytes we need to store the
  764. // name of the object from the root down. The total buffer size we are
  765. // going to need will include this size, plus object name information
  766. // structure, plus an ending null character
  767. //
  768. NameInfoSize = NameSize + sizeof( OBJECT_NAME_INFORMATION ) + sizeof( UNICODE_NULL );
  769. //
  770. // Set the output size and make sure the supplied buffer is large enough
  771. // to hold the information
  772. //
  773. try {
  774. *ReturnLength = NameInfoSize;
  775. } except( EXCEPTION_EXECUTE_HANDLER ) {
  776. Status = GetExceptionCode();
  777. DoFullQuery = FALSE;
  778. leave;
  779. }
  780. if (Length < NameInfoSize) {
  781. Status = STATUS_INFO_LENGTH_MISMATCH;
  782. DoFullQuery = FALSE;
  783. leave;
  784. }
  785. } finally {
  786. ObpDereferenceNameInfo( NameInfo );
  787. NameInfo = NULL;
  788. if (ReferencedObject) {
  789. ObDereferenceObject( ReferencedObject );
  790. ReferencedObject = NULL;
  791. }
  792. }
  793. if (!DoFullQuery) {
  794. return Status;
  795. }
  796. NameInfo = ObpReferenceNameInfo( ObjectHeader );
  797. //
  798. // Check whether someone else removed the name meanwhile
  799. //
  800. if (!NameInfo) {
  801. //
  802. // The name is gone, we need to jump to the code path that handles
  803. // empty object name
  804. //
  805. goto RETRY;
  806. }
  807. //
  808. // Set the String buffer to point to the byte right after the
  809. // last byte in the output string. This following logic actually
  810. // fills in the buffer backwards working from the name back to the
  811. // root
  812. //
  813. StringBuffer = (PWCH)ObjectNameInfo;
  814. StringBuffer = (PWCH)((PCH)StringBuffer + NameInfoSize);
  815. OriginalBuffer = (PWCH)((PCH)ObjectNameInfo + sizeof( OBJECT_NAME_INFORMATION ));
  816. try {
  817. //
  818. // Terminate the string with a null and backup one unicode
  819. // character
  820. //
  821. *--StringBuffer = UNICODE_NULL;
  822. //
  823. // If the object in question is not the root directory
  824. // then we are going to put its name in the string buffer
  825. // When we finally reach the root directory we'll append on
  826. // the final "\"
  827. //
  828. if (Object != ObpRootDirectoryObject) {
  829. //
  830. // Add in the objects name
  831. //
  832. String = &NameInfo->Name;
  833. StringBuffer = (PWCH)((PCH)StringBuffer - String->Length);
  834. if (StringBuffer <= OriginalBuffer) {
  835. ForceRetry = TRUE;
  836. leave;
  837. }
  838. RtlCopyMemory( StringBuffer, String->Buffer, String->Length );
  839. //
  840. // While we are not at the root directory we'll keep
  841. // moving up
  842. //
  843. ObjectDirectory = NameInfo->Directory;
  844. if (ObjectDirectory) {
  845. //
  846. // Reference the directory for this object to make sure it's
  847. // valid while looking up
  848. //
  849. ObfReferenceObject( ObjectDirectory );
  850. ReferencedObject = ObjectDirectory;
  851. }
  852. ObpDereferenceNameInfo( NameInfo );
  853. NameInfo = NULL;
  854. while ((ObjectDirectory != ObpRootDirectoryObject) && (ObjectDirectory)) {
  855. //
  856. // Get the name information for this directory
  857. //
  858. ObjectDirectoryHeader = OBJECT_TO_OBJECT_HEADER( ObjectDirectory );
  859. NameInfo = ObpReferenceNameInfo( ObjectDirectoryHeader );
  860. //
  861. // Tack on the "\" between the last name we added and
  862. // this new name
  863. //
  864. *--StringBuffer = OBJ_NAME_PATH_SEPARATOR;
  865. //
  866. // Preappend the directory name, if it has one, and
  867. // move up to the next directory.
  868. //
  869. if ((NameInfo != NULL) && (NameInfo->Directory != NULL)) {
  870. String = &NameInfo->Name;
  871. StringBuffer = (PWCH)((PCH)StringBuffer - String->Length);
  872. if (StringBuffer <= OriginalBuffer) {
  873. ForceRetry = TRUE;
  874. leave;
  875. }
  876. RtlCopyMemory( StringBuffer, String->Buffer, String->Length );
  877. ObjectDirectory = NameInfo->Directory;
  878. if (ObjectDirectory) {
  879. ObfReferenceObject( ObjectDirectory );
  880. }
  881. //
  882. // Dereference the name info (it must be done before dereferencing the object)
  883. //
  884. ObpDereferenceNameInfo( NameInfo );
  885. NameInfo = NULL;
  886. ObDereferenceObject( ReferencedObject );
  887. ReferencedObject = ObjectDirectory;
  888. } else {
  889. //
  890. // The directory is nameless so use the "..." for
  891. // its name and break out of the loop
  892. //
  893. StringBuffer = (PWCH)((PCH)StringBuffer - OBP_MISSING_NAME_LITERAL_SIZE);
  894. //
  895. // Because we don't hold the global lock any more, we can have a special case
  896. // where a directory of 1 or 2 letters name AND inserted into the root
  897. // can go away meanwhile and "..." will be too long to fit the remaining space
  898. // We already copied the buffer so we cannot rollback everything we done.
  899. // We'll return \.. if the original directory was 1 char length,
  900. // \..\ for 2 char length
  901. //
  902. if (StringBuffer < OriginalBuffer) {
  903. StringBuffer = OriginalBuffer;
  904. }
  905. RtlCopyMemory( StringBuffer,
  906. OBP_MISSING_NAME_LITERAL,
  907. OBP_MISSING_NAME_LITERAL_SIZE );
  908. //
  909. // Test if we are in the case commented above. If yes, we need to move the
  910. // current pointer to the next char, so the final assignment for \ a few lines
  911. // below will take effect on the start of the block.
  912. //
  913. if (StringBuffer == OriginalBuffer) {
  914. StringBuffer++;
  915. }
  916. break;
  917. }
  918. }
  919. }
  920. //
  921. // Tack on the "\" for the root directory and then set the
  922. // output unicode string variable to have the right size
  923. // and point to the right spot.
  924. //
  925. *--StringBuffer = OBJ_NAME_PATH_SEPARATOR;
  926. BufferLength = (USHORT)((ULONG_PTR)ObjectNameInfo + NameInfoSize - (ULONG_PTR)StringBuffer);
  927. ObjectNameInfo->Name.MaximumLength = (USHORT)BufferLength;
  928. ObjectNameInfo->Name.Length = (USHORT)(BufferLength - sizeof( UNICODE_NULL ));
  929. ObjectNameInfo->Name.Buffer = OriginalBuffer;
  930. //
  931. // If one of the parent directories disappeared, the final length
  932. // will be smaller than we estimated before. We need to move the string to
  933. // the beginning and adjust the returned size.
  934. //
  935. if (OriginalBuffer != StringBuffer) {
  936. RtlMoveMemory(OriginalBuffer, StringBuffer, BufferLength);
  937. *ReturnLength = BufferLength + sizeof( OBJECT_NAME_INFORMATION );
  938. }
  939. } except( EXCEPTION_EXECUTE_HANDLER ) {
  940. //
  941. // Fall through, since we cannot undo what we have done.
  942. //
  943. // This should probably get the exception code and return
  944. // that value. However, the caller we'll get an exception
  945. // at the first access of the ObjectNameInfo
  946. //
  947. }
  948. ObpDereferenceNameInfo( NameInfo );
  949. if (ReferencedObject) {
  950. ObDereferenceObject( ReferencedObject );
  951. }
  952. if (ForceRetry) {
  953. //
  954. // The query failed maybe because the object name changed during the query
  955. //
  956. NameInfo = ObpReferenceNameInfo( ObjectHeader );
  957. ForceRetry = FALSE;
  958. goto RETRY;
  959. }
  960. return STATUS_SUCCESS;
  961. }
  962. NTSTATUS
  963. ObQueryTypeName (
  964. IN PVOID Object,
  965. PUNICODE_STRING ObjectTypeName,
  966. IN ULONG Length,
  967. OUT PULONG ReturnLength
  968. )
  969. /*++
  970. Routine description:
  971. This routine processes a query of an object's type name
  972. Arguments:
  973. Object - Supplies the object being queried
  974. ObjectTypeName - Supplies the buffer to store the type name
  975. string information
  976. Length - Specifies the length, in bytes, of the object type
  977. name buffer
  978. ReturnLength - Contains the number of bytes already used up
  979. in the object type name buffer. On return this receives
  980. an updated byte count
  981. (Length minus ReturnLength) is really now many bytes are left
  982. in the output buffer. The buffer supplied to this call may
  983. actually be offset within the original users buffer
  984. Return Value:
  985. An appropriate status value
  986. --*/
  987. {
  988. POBJECT_TYPE ObjectType;
  989. POBJECT_HEADER ObjectHeader;
  990. ULONG TypeNameSize;
  991. PUNICODE_STRING String;
  992. PWCH StringBuffer;
  993. ULONG NameSize;
  994. PAGED_CODE();
  995. //
  996. // From the object get its object type and from that get the size of
  997. // the object type name. The total size for we need for the output
  998. // buffer must fit the name, a terminating null, and a preceding
  999. // unicode string structure
  1000. //
  1001. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1002. ObjectType = ObjectHeader->Type;
  1003. NameSize = ObjectType->Name.Length;
  1004. TypeNameSize = NameSize + sizeof( UNICODE_NULL ) + sizeof( UNICODE_STRING );
  1005. //
  1006. // Update the number of bytes we need and make sure the output buffer is
  1007. // large enough
  1008. //
  1009. try {
  1010. *ReturnLength = TypeNameSize;
  1011. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1012. return( GetExceptionCode() );
  1013. }
  1014. if (Length < TypeNameSize) {
  1015. return( STATUS_INFO_LENGTH_MISMATCH );
  1016. }
  1017. //
  1018. // Set string buffer to point to the one byte beyond the
  1019. // buffer that we're going to fill in
  1020. //
  1021. StringBuffer = (PWCH)ObjectTypeName;
  1022. StringBuffer = (PWCH)((PCH)StringBuffer + TypeNameSize);
  1023. String = &ObjectType->Name;
  1024. try {
  1025. //
  1026. // Tack on the terminating null character and copy over
  1027. // the type name
  1028. //
  1029. *--StringBuffer = UNICODE_NULL;
  1030. StringBuffer = (PWCH)((PCH)StringBuffer - String->Length);
  1031. RtlCopyMemory( StringBuffer, String->Buffer, String->Length );
  1032. //
  1033. // Now set the preceding unicode string to have the right
  1034. // lengths and to point to this buffer
  1035. //
  1036. ObjectTypeName->Length = (USHORT)NameSize;
  1037. ObjectTypeName->MaximumLength = (USHORT)(NameSize+sizeof( UNICODE_NULL ));
  1038. ObjectTypeName->Buffer = StringBuffer;
  1039. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1040. //
  1041. // Fall through, since we cannot undo what we have done.
  1042. //
  1043. }
  1044. return( STATUS_SUCCESS );
  1045. }
  1046. NTSTATUS
  1047. ObQueryTypeInfo (
  1048. IN POBJECT_TYPE ObjectType,
  1049. OUT POBJECT_TYPE_INFORMATION ObjectTypeInfo,
  1050. IN ULONG Length,
  1051. OUT PULONG ReturnLength
  1052. )
  1053. /*++
  1054. Routine description:
  1055. This routine processes the query for object type information
  1056. Arguments:
  1057. Object - Supplies a pointer to the object type being queried
  1058. ObjectTypeInfo - Supplies the buffer to store the type information
  1059. Length - Specifies the length, in bytes, of the object type
  1060. information buffer
  1061. ReturnLength - Contains the number of bytes already used up
  1062. in the object type information buffer. On return this receives
  1063. an updated byte count
  1064. (Length minus ReturnLength) is really now many bytes are left
  1065. in the output buffer. The buffer supplied to this call may
  1066. actually be offset within the original users buffer
  1067. Return Value:
  1068. An appropriate status value
  1069. --*/
  1070. {
  1071. NTSTATUS Status;
  1072. try {
  1073. //
  1074. // The total number of bytes needed for this query includes the
  1075. // object type information structure plus the name of the type
  1076. // rounded up to a ulong boundary
  1077. //
  1078. *ReturnLength += sizeof( *ObjectTypeInfo ) + ALIGN_UP( ObjectType->Name.MaximumLength, ULONG );
  1079. //
  1080. // Make sure the buffer is large enough for this information and
  1081. // then fill in the record
  1082. //
  1083. if (Length < *ReturnLength) {
  1084. Status = STATUS_INFO_LENGTH_MISMATCH;
  1085. } else {
  1086. ObjectTypeInfo->TotalNumberOfObjects = ObjectType->TotalNumberOfObjects;
  1087. ObjectTypeInfo->TotalNumberOfHandles = ObjectType->TotalNumberOfHandles;
  1088. ObjectTypeInfo->HighWaterNumberOfObjects = ObjectType->HighWaterNumberOfObjects;
  1089. ObjectTypeInfo->HighWaterNumberOfHandles = ObjectType->HighWaterNumberOfHandles;
  1090. ObjectTypeInfo->InvalidAttributes = ObjectType->TypeInfo.InvalidAttributes;
  1091. ObjectTypeInfo->GenericMapping = ObjectType->TypeInfo.GenericMapping;
  1092. ObjectTypeInfo->ValidAccessMask = ObjectType->TypeInfo.ValidAccessMask;
  1093. ObjectTypeInfo->SecurityRequired = ObjectType->TypeInfo.SecurityRequired;
  1094. ObjectTypeInfo->MaintainHandleCount = ObjectType->TypeInfo.MaintainHandleCount;
  1095. ObjectTypeInfo->PoolType = ObjectType->TypeInfo.PoolType;
  1096. ObjectTypeInfo->DefaultPagedPoolCharge = ObjectType->TypeInfo.DefaultPagedPoolCharge;
  1097. ObjectTypeInfo->DefaultNonPagedPoolCharge = ObjectType->TypeInfo.DefaultNonPagedPoolCharge;
  1098. //
  1099. // The type name goes right after this structure. We cannot use
  1100. // rtl routine like RtlCopyUnicodeString that might use the local
  1101. // memory to keep state, because this is the user buffer and it
  1102. // could be changing by user
  1103. //
  1104. ObjectTypeInfo->TypeName.Buffer = (PWSTR)(ObjectTypeInfo+1);
  1105. ObjectTypeInfo->TypeName.Length = ObjectType->Name.Length;
  1106. ObjectTypeInfo->TypeName.MaximumLength = ObjectType->Name.MaximumLength;
  1107. RtlCopyMemory( (PWSTR)(ObjectTypeInfo+1),
  1108. ObjectType->Name.Buffer,
  1109. ObjectType->Name.Length );
  1110. ((PWSTR)(ObjectTypeInfo+1))[ ObjectType->Name.Length/sizeof(WCHAR) ] = UNICODE_NULL;
  1111. Status = STATUS_SUCCESS;
  1112. }
  1113. } except( EXCEPTION_EXECUTE_HANDLER ) {
  1114. Status = GetExceptionCode();
  1115. }
  1116. return Status;
  1117. }
  1118. NTSTATUS
  1119. ObQueryObjectAuditingByHandle (
  1120. IN HANDLE Handle,
  1121. OUT PBOOLEAN GenerateOnClose
  1122. )
  1123. /*++
  1124. Routine description:
  1125. This routine tells the caller if the indicated handle will
  1126. generate an audit if it is closed
  1127. Arguments:
  1128. Handle - Supplies the handle being queried
  1129. GenerateOnClose - Receives TRUE if the handle will generate
  1130. an audit if closed and FALSE otherwise
  1131. Return Value:
  1132. An appropriate status value
  1133. --*/
  1134. {
  1135. PHANDLE_TABLE ObjectTable;
  1136. PHANDLE_TABLE_ENTRY ObjectTableEntry;
  1137. ULONG CapturedAttributes;
  1138. NTSTATUS Status;
  1139. PETHREAD CurrentThread;
  1140. PAGED_CODE();
  1141. ObpValidateIrql( "ObQueryObjectAuditingByHandle" );
  1142. CurrentThread = PsGetCurrentThread ();
  1143. //
  1144. // For the current process we'll grab its object table and
  1145. // then get the object table entry
  1146. //
  1147. if (IsKernelHandle( Handle, KeGetPreviousMode() )) {
  1148. Handle = DecodeKernelHandle( Handle );
  1149. ObjectTable = ObpKernelHandleTable;
  1150. } else {
  1151. ObjectTable = PsGetCurrentProcessByThread (CurrentThread)->ObjectTable;
  1152. }
  1153. //
  1154. // Protect ourselves from being interrupted while we hold a handle table
  1155. // entry lock
  1156. //
  1157. KeEnterCriticalRegionThread(&CurrentThread->Tcb);
  1158. ObjectTableEntry = ExMapHandleToPointer( ObjectTable,
  1159. Handle );
  1160. //
  1161. // If we were given a valid handle we'll look at the attributes
  1162. // stored in the object table entry to decide if we generate
  1163. // an audit on close
  1164. //
  1165. if (ObjectTableEntry != NULL) {
  1166. CapturedAttributes = ObjectTableEntry->ObAttributes;
  1167. ExUnlockHandleTableEntry( ObjectTable, ObjectTableEntry );
  1168. if (CapturedAttributes & OBJ_AUDIT_OBJECT_CLOSE) {
  1169. *GenerateOnClose = TRUE;
  1170. } else {
  1171. *GenerateOnClose = FALSE;
  1172. }
  1173. Status = STATUS_SUCCESS;
  1174. } else {
  1175. Status = STATUS_INVALID_HANDLE;
  1176. }
  1177. KeLeaveCriticalRegionThread(&CurrentThread->Tcb);
  1178. return Status;
  1179. }
  1180. #if DBG
  1181. PUNICODE_STRING
  1182. ObGetObjectName (
  1183. IN PVOID Object
  1184. )
  1185. /*++
  1186. Routine description:
  1187. This routine returns a pointer to the name of object
  1188. Arguments:
  1189. Object - Supplies the object being queried
  1190. Return Value:
  1191. The address of the unicode string that stores the object
  1192. name if available and NULL otherwise
  1193. --*/
  1194. {
  1195. POBJECT_HEADER ObjectHeader;
  1196. POBJECT_HEADER_NAME_INFO NameInfo;
  1197. //
  1198. // Translate the input object to a name info structure
  1199. //
  1200. ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
  1201. NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectHeader );
  1202. //
  1203. // If the object has a name then return the address of
  1204. // the name otherwise return null
  1205. //
  1206. if ((NameInfo != NULL) && (NameInfo->Name.Length != 0)) {
  1207. return &NameInfo->Name;
  1208. } else {
  1209. return NULL;
  1210. }
  1211. }
  1212. #endif // DBG
  1213. //
  1214. // Local support routine
  1215. //
  1216. BOOLEAN
  1217. ObpSetHandleAttributes (
  1218. IN OUT PHANDLE_TABLE_ENTRY ObjectTableEntry,
  1219. IN ULONG_PTR Parameter
  1220. )
  1221. /*++
  1222. Routine description:
  1223. This is the call back routine for the ExChangeHandle from
  1224. NtSetInformationObject
  1225. Arguments:
  1226. ObjectTableEntry - Supplies a pointer to the object table entry being
  1227. modified
  1228. Parameter - Supplies a pointer to the OBJECT_HANDLE_FLAG_INFORMATION
  1229. structure to set into the table entry
  1230. Return Value:
  1231. Returns TRUE if the operation is successful otherwise FALSE
  1232. --*/
  1233. {
  1234. POBP_SET_HANDLE_ATTRIBUTES ObjectInformation;
  1235. POBJECT_HEADER ObjectHeader;
  1236. ObjectInformation = (POBP_SET_HANDLE_ATTRIBUTES)Parameter;
  1237. //
  1238. // Get a pointer to the object type via the object header and if the
  1239. // caller has asked for inherit but the object type says that inherit
  1240. // is an invalid flag then return false
  1241. //
  1242. ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
  1243. if ((ObjectInformation->ObjectInformation.Inherit) &&
  1244. ((ObjectHeader->Type->TypeInfo.InvalidAttributes & OBJ_INHERIT) != 0)) {
  1245. return FALSE;
  1246. }
  1247. //
  1248. // For each piece of information (inheriit and protect from close) that
  1249. // is in the object information buffer we'll set or clear the bits in
  1250. // the object table entry. The bits modified are the low order bits of
  1251. // used to store the pointer to the object header.
  1252. //
  1253. if (ObjectInformation->ObjectInformation.Inherit) {
  1254. ObjectTableEntry->ObAttributes |= OBJ_INHERIT;
  1255. } else {
  1256. ObjectTableEntry->ObAttributes &= ~OBJ_INHERIT;
  1257. }
  1258. if (ObjectInformation->ObjectInformation.ProtectFromClose) {
  1259. ObjectTableEntry->GrantedAccess |= ObpAccessProtectCloseBit;
  1260. } else {
  1261. ObjectTableEntry->GrantedAccess &= ~ObpAccessProtectCloseBit;
  1262. }
  1263. //
  1264. // And return to our caller
  1265. //
  1266. return TRUE;
  1267. }