2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ob/namespce.c
5 * PURPOSE: Manages all functions related to the Object Manager name-
6 * space, such as finding objects or querying their names.
7 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 * Thomas Weidenmueller (w3seek@reactos.org)
12 /* INCLUDES ******************************************************************/
14 #define NTDDI_VERSION NTDDI_WINXP
19 BOOLEAN ObpCaseInsensitive
= TRUE
;
20 POBJECT_DIRECTORY NameSpaceRoot
= NULL
;
21 POBJECT_DIRECTORY ObpTypeDirectoryObject
= NULL
;
23 /* PRIVATE FUNCTIONS *********************************************************/
27 ObpCreateDosDevicesDirectory(VOID
)
29 OBJECT_ATTRIBUTES ObjectAttributes
;
30 UNICODE_STRING Name
, LinkName
;
31 HANDLE Handle
, SymHandle
;
34 /* Create the '\??' directory */
35 RtlInitUnicodeString(&Name
, L
"\\??");
36 InitializeObjectAttributes(&ObjectAttributes
,
41 Status
= NtCreateDirectoryObject(&Handle
,
44 if (!NT_SUCCESS(Status
)) return FALSE
;
46 /* Initialize the GLOBALROOT path */
47 RtlInitUnicodeString(&LinkName
, L
"GLOBALROOT");
48 RtlInitUnicodeString(&Name
, L
"");
49 InitializeObjectAttributes(&ObjectAttributes
,
54 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
55 SYMBOLIC_LINK_ALL_ACCESS
,
58 if (NT_SUCCESS(Status
)) NtClose(SymHandle
);
60 /* Link \??\Global to \?? */
61 RtlInitUnicodeString(&LinkName
, L
"Global");
62 RtlInitUnicodeString(&Name
, L
"\\??");
63 InitializeObjectAttributes(&ObjectAttributes
,
68 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
69 SYMBOLIC_LINK_ALL_ACCESS
,
72 if (NT_SUCCESS(Status
)) NtClose(SymHandle
);
74 /* Close the directory handle */
76 if (!NT_SUCCESS(Status
)) return Status
;
78 /* Create link from '\DosDevices' to '\??' directory */
79 RtlCreateUnicodeString(&LinkName
, L
"\\DosDevices");
80 InitializeObjectAttributes(&ObjectAttributes
,
85 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
86 SYMBOLIC_LINK_ALL_ACCESS
,
89 if (NT_SUCCESS(Status
)) NtClose(SymHandle
);
91 /* FIXME: Hack Hack! */
92 ObSystemDeviceMap
= ExAllocatePoolWithTag(NonPagedPool
,
93 sizeof(*ObSystemDeviceMap
),
94 TAG('O', 'b', 'D', 'm'));
95 RtlZeroMemory(ObSystemDeviceMap
, sizeof(*ObSystemDeviceMap
));
103 ObDereferenceDeviceMap(IN PEPROCESS Process
)
106 PDEVICE_MAP DeviceMap
= Process
->DeviceMap
;
108 /* FIXME: We don't use Process Devicemaps yet */
111 /* FIXME: Acquire the DeviceMap Spinlock */
112 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
114 /* Delete the device map link and dereference it */
115 Process
->DeviceMap
= NULL
;
116 if (--DeviceMap
->ReferenceCount
)
118 /* Nobody is referencing it anymore, unlink the DOS directory */
119 DeviceMap
->DosDevicesDirectory
->DeviceMap
= NULL
;
121 /* FIXME: Release the DeviceMap Spinlock */
122 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
124 /* Dereference the DOS Devices Directory and free the Device Map */
125 ObDereferenceObject(DeviceMap
->DosDevicesDirectory
);
126 ExFreePool(DeviceMap
);
130 /* FIXME: Release the DeviceMap Spinlock */
131 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
138 ObInheritDeviceMap(IN PEPROCESS Parent
,
139 IN PEPROCESS Process
)
141 /* FIXME: Devicemap Support */
145 * @name ObpDeleteNameCheck
147 * The ObpDeleteNameCheck routine checks if a named object should be
148 * removed from the object directory namespace.
151 * Pointer to the object to check for possible removal.
155 * @remarks An object is removed if the following 4 criteria are met:
156 * 1) The object has 0 handles open
157 * 2) The object is in the directory namespace and has a name
158 * 3) The object is not permanent
163 ObpDeleteNameCheck(IN PVOID Object
)
165 POBJECT_HEADER ObjectHeader
;
166 OBP_LOOKUP_CONTEXT Context
;
167 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
168 POBJECT_TYPE ObjectType
;
169 PVOID Directory
= NULL
;
171 /* Get object structures */
172 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
173 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
174 ObjectType
= ObjectHeader
->Type
;
176 /* Check if we have a name information structure */
179 /* Add a query reference */
180 if (!ObpIncrementQueryReference(ObjectHeader
, ObjectNameInfo
))
182 /* No references, so the name info is invalid */
183 ObjectNameInfo
= NULL
;
188 * Check if the handle count is 0, if the object is named,
189 * and if the object isn't a permanent object.
191 if (!(ObjectHeader
->HandleCount
) &&
193 (ObjectNameInfo
->Name
.Length
) &&
194 (ObjectNameInfo
->Directory
) &&
195 !(ObjectHeader
->Flags
& OB_FLAG_PERMANENT
))
197 /* Setup a lookup context */
198 ObpInitializeDirectoryLookup(&Context
);
200 /* Lock the directory */
201 ObpAcquireDirectoryLockExclusive(ObjectNameInfo
->Directory
, &Context
);
204 Object
= ObpLookupEntryDirectory(ObjectNameInfo
->Directory
,
205 &ObjectNameInfo
->Name
,
211 /* Lock the object type */
212 ObpEnterObjectTypeMutex(ObjectType
);
214 /* Make sure we can still delete the object */
215 if (!(ObjectHeader
->HandleCount
) &&
216 !(ObjectHeader
->Flags
& OB_FLAG_PERMANENT
))
218 /* First delete it from the directory */
219 ObpDeleteEntryDirectory(&Context
);
221 /* Check if this is a symbolic link */
222 if (ObjectType
== ObSymbolicLinkType
)
224 /* Remove internal name */
225 ObpDeleteSymbolicLinkName(Object
);
228 /* Add a query reference */
229 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
230 if (!ObpIncrementQueryReference(ObjectHeader
, ObjectNameInfo
))
232 /* No references, so the name info is invalid */
233 ObjectNameInfo
= NULL
;
236 /* Check if the magic protection flag is set */
237 if ((ObjectNameInfo
) &&
238 (ObjectNameInfo
->QueryReferences
& 0x40000000))
240 /* Add deletion flag */
241 InterlockedExchangeAdd(&ObjectNameInfo
->QueryReferences
,
245 /* Get the directory */
246 Directory
= ObjectNameInfo
->Directory
;
249 /* Release the lock */
250 ObpLeaveObjectTypeMutex(ObjectType
);
253 /* Cleanup after lookup */
254 ObpCleanupDirectoryLookup(&Context
);
256 /* Remove another query reference since we added one on top */
257 ObpDecrementQueryReference(ObjectNameInfo
);
259 /* Check if we were inserted in a directory */
262 /* We were, so first remove the extra reference we had added */
263 ObpDecrementQueryReference(ObjectNameInfo
);
265 /* Now dereference the object as well */
266 ObDereferenceObject(Object
);
271 /* Remove the reference we added */
272 if (ObjectNameInfo
) ObpDecrementQueryReference(ObjectNameInfo
);
278 ObpLookupObjectName(IN HANDLE RootHandle
,
279 IN PUNICODE_STRING ObjectName
,
281 IN POBJECT_TYPE ObjectType
,
282 IN KPROCESSOR_MODE AccessMode
,
283 IN OUT PVOID ParseContext
,
284 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos
,
285 IN PVOID InsertObject
,
286 IN PACCESS_STATE AccessState
,
287 IN POBP_LOOKUP_CONTEXT LookupContext
,
288 OUT PVOID
*FoundObject
)
291 POBJECT_HEADER ObjectHeader
;
292 UNICODE_STRING ComponentName
, RemainingName
;
293 BOOLEAN InsideRoot
= FALSE
;
294 PDEVICE_MAP DeviceMap
= NULL
;
295 POBJECT_DIRECTORY Directory
= NULL
, ParentDirectory
= NULL
, RootDirectory
;
296 POBJECT_DIRECTORY ReferencedDirectory
= NULL
, ReferencedParentDirectory
= NULL
;
298 OB_PARSE_METHOD ParseRoutine
;
300 KPROCESSOR_MODE AccessCheckMode
;
302 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
304 OBTRACE(OB_NAMESPACE_DEBUG
,
305 "%s - Finding Object: %wZ. Expecting: %p\n",
310 /* Initialize starting state */
311 ObpInitializeDirectoryLookup(LookupContext
);
313 Status
= STATUS_SUCCESS
;
316 /* Check if case-insensitivity is forced */
317 if ((ObpCaseInsensitive
) || (ObjectType
->TypeInfo
.CaseInsensitive
))
319 /* Add the flag to disable case sensitivity */
320 Attributes
|= OBJ_CASE_INSENSITIVE
;
323 /* Check if this is a access checks are being forced */
324 AccessCheckMode
= (Attributes
& OBJ_FORCE_ACCESS_CHECK
) ?
325 UserMode
: AccessMode
;
327 /* Check if we got a Root Directory */
330 /* We did. Reference it */
331 Status
= ObReferenceObjectByHandle(RootHandle
,
335 (PVOID
*)&RootDirectory
,
337 if (!NT_SUCCESS(Status
)) return Status
;
340 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(RootDirectory
);
342 /* The name cannot start with a separator, unless this is a file */
343 if ((ObjectName
->Buffer
) &&
344 (ObjectName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
) &&
345 (ObjectHeader
->Type
!= IoFileObjectType
))
347 /* The syntax is bad, so fail this request */
348 ObDereferenceObject(RootDirectory
);
349 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
352 /* Don't parse a Directory */
353 if (ObjectHeader
->Type
!= ObDirectoryType
)
355 /* Make sure the Object Type has a parse routine */
356 ParseRoutine
= ObjectHeader
->Type
->TypeInfo
.ParseProcedure
;
359 /* We can't parse a name if we don't have a parse routine */
360 ObDereferenceObject(RootDirectory
);
361 return STATUS_INVALID_HANDLE
;
367 /* Start with the full name */
368 RemainingName
= *ObjectName
;
370 /* Call the Parse Procedure */
371 ObpCalloutStart(&CalloutIrql
);
372 Status
= ParseRoutine(RootDirectory
,
382 ObpCalloutEnd(CalloutIrql
, "Parse", ObjectHeader
->Type
, Object
);
384 /* Check for success or failure, so not reparse */
385 if ((Status
!= STATUS_REPARSE
) &&
386 (Status
!= STATUS_REPARSE_OBJECT
))
388 /* Check for failure */
389 if (!NT_SUCCESS(Status
))
391 /* Parse routine might not have cleared this, do it */
396 /* Modify status to reflect failure inside Ob */
397 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
400 /* We're done, return the status and object */
401 *FoundObject
= Object
;
402 ObDereferenceObject(RootDirectory
);
405 else if ((!ObjectName
->Length
) ||
406 (!ObjectName
->Buffer
) ||
407 (ObjectName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
))
409 /* Reparsed to the root directory, so start over */
410 ObDereferenceObject(RootDirectory
);
411 RootDirectory
= NameSpaceRoot
;
413 /* Don't use this anymore, since we're starting at root */
419 else if (!(ObjectName
->Length
) || !(ObjectName
->Buffer
))
421 /* Just return the Root Directory if we didn't get a name*/
422 Status
= ObReferenceObjectByPointer(RootDirectory
,
426 if (NT_SUCCESS(Status
)) Object
= RootDirectory
;
428 /* Remove the first reference we added and return the object */
429 ObDereferenceObject(RootDirectory
);
430 *FoundObject
= Object
;
436 /* We did not get a Root Directory, so use the root */
437 RootDirectory
= NameSpaceRoot
;
439 /* It must start with a path separator */
440 if (!(ObjectName
->Length
) ||
441 !(ObjectName
->Buffer
) ||
442 (ObjectName
->Buffer
[0] != OBJ_NAME_PATH_SEPARATOR
))
444 /* This name is invalid, so fail */
445 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
448 /* Check if the name is only the path separator */
449 if (ObjectName
->Length
== sizeof(OBJ_NAME_PATH_SEPARATOR
))
451 /* So the caller only wants the root directory; do we have one? */
454 /* This must be the first time we're creating it... right? */
457 /* Yes, so return it to ObInsert so that it can create it */
458 Status
= ObReferenceObjectByPointer(InsertObject
,
462 if (NT_SUCCESS(Status
)) *FoundObject
= InsertObject
;
467 /* This should never really happen */
469 return STATUS_INVALID_PARAMETER
;
474 /* We do have the root directory, so just return it */
475 Status
= ObReferenceObjectByPointer(RootDirectory
,
479 if (NT_SUCCESS(Status
)) *FoundObject
= RootDirectory
;
487 RemainingName
= *ObjectName
;
492 /* Check if we should use the Root Directory */
495 /* Yes, use the root directory and remember that */
496 Directory
= RootDirectory
;
500 /* Check if the name starts with a path separator */
501 if ((RemainingName
.Length
) &&
502 (RemainingName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
))
504 /* Skip the path separator */
505 RemainingName
.Buffer
++;
506 RemainingName
.Length
-= sizeof(OBJ_NAME_PATH_SEPARATOR
);
509 /* Find the next Part Name */
510 ComponentName
= RemainingName
;
511 while (RemainingName
.Length
)
513 /* Break if we found the \ ending */
514 if (RemainingName
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
) break;
517 RemainingName
.Buffer
++;
518 RemainingName
.Length
-= sizeof(OBJ_NAME_PATH_SEPARATOR
);
521 /* Get its size and make sure it's valid */
522 ComponentName
.Length
-= RemainingName
.Length
;
523 if (!ComponentName
.Length
)
525 /* Invalid size, fail */
526 Status
= STATUS_OBJECT_NAME_INVALID
;
530 /* Check if this is a user-mode call that needs to traverse */
531 if ((AccessCheckMode
!= KernelMode
) &&
532 !(AccessState
->Flags
& TOKEN_HAS_TRAVERSE_PRIVILEGE
))
534 /* We shouldn't have referenced a directory yet */
535 ASSERT(ReferencedDirectory
== NULL
);
537 /* Reference the directory */
538 ObReferenceObject(Directory
);
539 ReferencedDirectory
= Directory
;
541 /* Check if we have a parent directory */
544 /* Check for traverse access */
545 if (!ObpCheckTraverseAccess(ParentDirectory
,
552 /* We don't have it, fail */
558 /* Check if we don't have a remaining name yet */
559 if (!RemainingName
.Length
)
561 /* Check if we don't have a referenced directory yet */
562 if (!ReferencedDirectory
)
565 ObReferenceObject(Directory
);
566 ReferencedDirectory
= Directory
;
569 /* Check if we are inserting an object */
572 /* Lock the directory */
573 ObpAcquireDirectoryLockExclusive(Directory
, LookupContext
);
578 Object
= ObpLookupEntryDirectory(Directory
,
581 InsertObject
? FALSE
: TRUE
,
585 /* We didn't find it... do we still have a path? */
586 if (RemainingName
.Length
)
588 /* Then tell the caller the path wasn't found */
589 Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
592 else if (!InsertObject
)
594 /* Otherwise, we have a path, but the name isn't valid */
595 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
599 /* Check create access for the object */
600 if (!ObCheckCreateObjectAccess(Directory
,
601 ObjectType
== ObDirectoryType
?
602 DIRECTORY_CREATE_SUBDIRECTORY
:
603 DIRECTORY_CREATE_OBJECT
,
610 /* We don't have create access, fail */
614 /* Get the object header */
615 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(InsertObject
);
617 /* FIXME: Check if this is a Section Object or Sym Link */
618 /* FIXME: If it is, then check if this isn't session 0 */
619 /* FIXME: If it isn't, check for SeCreateGlobalPrivilege */
620 /* FIXME: If privilege isn't there, check for unsecure name */
621 /* FIXME: If it isn't a known unsecure name, then fail */
623 /* Create Object Name */
624 NewName
= ExAllocatePoolWithTag(PagedPool
,
625 ComponentName
.Length
,
628 !(ObpInsertEntryDirectory(Directory
,
632 /* Either couldn't allocate the name, or insert failed */
633 if (NewName
) ExFreePool(NewName
);
635 /* Fail due to memory reasons */
636 Status
= STATUS_INSUFFICIENT_RESOURCES
;
640 /* Reference newly to be inserted object */
641 ObReferenceObject(InsertObject
);
643 /* Get the name information */
644 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
646 /* Reference the directory */
647 ObReferenceObject(Directory
);
650 RtlCopyMemory(NewName
,
651 ComponentName
.Buffer
,
652 ComponentName
.Length
);
654 /* Check if we had an old name */
655 if (ObjectNameInfo
->Name
.Buffer
)
658 ExFreePool(ObjectNameInfo
->Name
.Buffer
);
662 ObjectNameInfo
->Name
.Buffer
= NewName
;
663 ObjectNameInfo
->Name
.Length
= ComponentName
.Length
;
664 ObjectNameInfo
->Name
.MaximumLength
= ComponentName
.Length
;
666 /* Return Status and the Expected Object */
667 Status
= STATUS_SUCCESS
;
668 Object
= InsertObject
;
670 /* Get out of here */
675 /* We found it, so now get its header */
676 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
679 * Check for a parse Procedure, but don't bother to parse for an insert
680 * unless it's a Symbolic Link, in which case we MUST parse
682 ParseRoutine
= ObjectHeader
->Type
->TypeInfo
.ParseProcedure
;
683 if ((ParseRoutine
) &&
684 (!(InsertObject
) || (ParseRoutine
== ObpParseSymbolicLink
)))
686 /* Use the Root Directory next time */
689 /* Increment the pointer count */
690 InterlockedExchangeAdd(&ObjectHeader
->PointerCount
, 1);
692 /* Cleanup from the first lookup */
693 ObpCleanupDirectoryLookup(LookupContext
);
695 /* Check if we have a referenced directory */
696 if (ReferencedDirectory
)
698 /* We do, dereference it */
699 ObDereferenceObject(ReferencedDirectory
);
700 ReferencedDirectory
= NULL
;
703 /* Check if we have a referenced parent directory */
704 if (ReferencedParentDirectory
)
706 /* We do, dereference it */
707 ObDereferenceObject(ReferencedParentDirectory
);
708 ReferencedParentDirectory
= NULL
;
711 /* Call the Parse Procedure */
712 ObpCalloutStart(&CalloutIrql
);
713 Status
= ParseRoutine(Object
,
723 ObpCalloutEnd(CalloutIrql
, "Parse", ObjectHeader
->Type
, Object
);
725 /* Remove our extra reference */
726 ObDereferenceObject(&ObjectHeader
->Body
);
728 /* Check if we have to reparse */
729 if ((Status
== STATUS_REPARSE
) ||
730 (Status
== STATUS_REPARSE_OBJECT
))
732 /* Start over from root if we got sent back there */
733 if ((Status
== STATUS_REPARSE_OBJECT
) ||
734 (ObjectName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
))
736 /* Check if we got a root directory */
739 /* Stop using it, because we have a new directory now */
740 ObDereferenceObject(RootDirectory
);
745 ParentDirectory
= NULL
;
746 RootDirectory
= NameSpaceRoot
;
748 /* Check for reparse status */
749 if (Status
== STATUS_REPARSE_OBJECT
)
751 /* Did we actually get an object to which to reparse? */
754 /* We didn't, so set a failure status */
755 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
759 /* We did, so we're free to parse the new object */
765 /* Restart the search */
768 else if (RootDirectory
== NameSpaceRoot
)
770 /* We got STATUS_REPARSE but are at the Root Directory */
772 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
775 else if (!NT_SUCCESS(Status
))
782 /* We didn't reparse but we didn't find the Object Either */
783 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
786 /* Break out of the loop */
791 /* No parse routine...do we still have a remaining name? */
792 if (!RemainingName
.Length
)
794 /* Are we creating an object? */
797 /* Check if this is a user-mode call that needs to traverse */
798 if ((AccessCheckMode
!= KernelMode
) &&
799 !(AccessState
->Flags
& TOKEN_HAS_TRAVERSE_PRIVILEGE
))
801 /* Check if we can get it */
802 if (!ObpCheckTraverseAccess(Directory
,
809 /* We don't have access, fail */
815 /* Reference the Object */
816 Status
= ObReferenceObjectByPointer(Object
,
820 if (!NT_SUCCESS(Status
)) Object
= NULL
;
823 /* And get out of the reparse loop */
828 /* We still have a name; check if this is a directory object */
829 if (ObjectHeader
->Type
== ObDirectoryType
)
831 /* Check if we have a referenced parent directory */
832 if (ReferencedParentDirectory
)
835 ObDereferenceObject(ReferencedParentDirectory
);
838 /* Restart the lookup from this directory */
839 ReferencedParentDirectory
= ReferencedDirectory
;
840 ParentDirectory
= Directory
;
842 ReferencedDirectory
= NULL
;
846 /* We still have a name, but no parse routine for it */
847 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
855 /* Check if we failed */
856 if (!NT_SUCCESS(Status
))
858 /* Cleanup after lookup */
859 ObpCleanupDirectoryLookup(LookupContext
);
862 /* Check if we have a device map and dereference it if so */
863 if (DeviceMap
) ObfDereferenceDeviceMap(DeviceMap
);
865 /* Check if we have a referenced directory and dereference it if so */
866 if (ReferencedDirectory
) ObDereferenceObject(ReferencedDirectory
);
868 /* Check if we have a referenced parent directory */
869 if (ReferencedParentDirectory
)
871 /* We do, dereference it */
872 ObDereferenceObject(ReferencedParentDirectory
);
875 /* Set the found object and check if we got one */
876 *FoundObject
= Object
;
879 /* Nothing was found. Did we reparse or get success? */
880 if ((Status
== STATUS_REPARSE
) || (NT_SUCCESS(Status
)))
882 /* Set correct failure */
883 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
887 /* Check if we had a root directory */
888 if (RootHandle
) ObDereferenceObject(RootDirectory
);
890 /* Return status to caller */
891 OBTRACE(OB_NAMESPACE_DEBUG
,
892 "%s - Found Object: %p. Expected: %p\n",
899 /* PUBLIC FUNCTIONS *********************************************************/
903 ObQueryNameString(IN PVOID Object
,
904 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
906 OUT PULONG ReturnLength
)
908 POBJECT_HEADER_NAME_INFO LocalInfo
;
909 POBJECT_HEADER ObjectHeader
;
910 POBJECT_DIRECTORY ParentDirectory
;
914 /* Get the Kernel Meta-Structures */
915 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
916 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
918 /* Check if a Query Name Procedure is available */
919 if (ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure
)
921 /* Call the procedure */
922 return ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure(Object
,
930 /* Check if the object doesn't even have a name */
931 if (!(LocalInfo
) || !(LocalInfo
->Name
.Buffer
))
933 /* We're returning the name structure */
934 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
936 /* Check if we were given enough space */
937 if (*ReturnLength
> Length
) return STATUS_INFO_LENGTH_MISMATCH
;
939 /* Return an empty buffer */
940 RtlInitEmptyUnicodeString(&ObjectNameInfo
->Name
, NULL
, 0);
941 return STATUS_SUCCESS
;
945 * Find the size needed for the name. We won't do
946 * this during the Name Creation loop because we want
947 * to let the caller know that the buffer isn't big
948 * enough right at the beginning, not work our way through
949 * and find out at the end
951 if (Object
== NameSpaceRoot
)
953 /* Size of the '\' string */
954 NameSize
= sizeof(OBJ_NAME_PATH_SEPARATOR
);
958 /* Get the Object Directory and add name of Object */
959 ParentDirectory
= LocalInfo
->Directory
;
960 NameSize
= sizeof(OBJ_NAME_PATH_SEPARATOR
) + LocalInfo
->Name
.Length
;
962 /* Loop inside the directory to get the top-most one (meaning root) */
963 while ((ParentDirectory
!= NameSpaceRoot
) && (ParentDirectory
))
965 /* Get the Name Information */
966 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(
967 OBJECT_TO_OBJECT_HEADER(ParentDirectory
));
969 /* Add the size of the Directory Name */
970 if (LocalInfo
&& LocalInfo
->Directory
)
972 /* Size of the '\' string + Directory Name */
973 NameSize
+= sizeof(OBJ_NAME_PATH_SEPARATOR
) +
974 LocalInfo
->Name
.Length
;
976 /* Move to next parent Directory */
977 ParentDirectory
= LocalInfo
->Directory
;
981 /* Directory with no name. We append "...\" */
982 NameSize
+= sizeof(L
"...") + sizeof(OBJ_NAME_PATH_SEPARATOR
);
988 /* Finally, add the name of the structure and the null char */
989 *ReturnLength
= NameSize
+
990 sizeof(OBJECT_NAME_INFORMATION
) +
991 sizeof(UNICODE_NULL
);
993 /* Check if we were given enough space */
994 if (*ReturnLength
> Length
) return STATUS_INFO_LENGTH_MISMATCH
;
997 * Now we will actually create the name. We work backwards because
998 * it's easier to start off from the Name we have and walk up the
999 * parent directories. We use the same logic as Name Length calculation.
1001 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
1002 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectNameInfo
+ *ReturnLength
);
1003 *--ObjectName
= UNICODE_NULL
;
1005 /* Check if the object is actually the Root directory */
1006 if (Object
== NameSpaceRoot
)
1008 /* This is already the Root Directory, return "\\" */
1009 *--ObjectName
= OBJ_NAME_PATH_SEPARATOR
;
1010 ObjectNameInfo
->Name
.Length
= (USHORT
)NameSize
;
1011 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(NameSize
+
1012 sizeof(UNICODE_NULL
));
1013 ObjectNameInfo
->Name
.Buffer
= ObjectName
;
1014 return STATUS_SUCCESS
;
1018 /* Start by adding the Object's Name */
1019 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectName
-
1020 LocalInfo
->Name
.Length
);
1021 RtlCopyMemory(ObjectName
,
1022 LocalInfo
->Name
.Buffer
,
1023 LocalInfo
->Name
.Length
);
1025 /* Now parse the Parent directories until we reach the top */
1026 ParentDirectory
= LocalInfo
->Directory
;
1027 while ((ParentDirectory
!= NameSpaceRoot
) && (ParentDirectory
))
1029 /* Get the name information */
1030 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(
1031 OBJECT_TO_OBJECT_HEADER(ParentDirectory
));
1034 *(--ObjectName
) = OBJ_NAME_PATH_SEPARATOR
;
1036 /* Add the Parent Directory's Name */
1037 if (LocalInfo
&& LocalInfo
->Name
.Buffer
)
1040 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectName
-
1041 LocalInfo
->Name
.Length
);
1042 RtlCopyMemory(ObjectName
,
1043 LocalInfo
->Name
.Buffer
,
1044 LocalInfo
->Name
.Length
);
1046 /* Move to next parent */
1047 ParentDirectory
= LocalInfo
->Directory
;
1051 /* Directory without a name, we add "..." */
1052 ObjectName
-= sizeof(L
"...");
1053 ObjectName
= L
"...";
1058 /* Add Root Directory Name */
1059 *(--ObjectName
) = OBJ_NAME_PATH_SEPARATOR
;
1060 ObjectNameInfo
->Name
.Length
= (USHORT
)NameSize
;
1061 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(NameSize
+
1062 sizeof(UNICODE_NULL
));
1063 ObjectNameInfo
->Name
.Buffer
= ObjectName
;
1066 /* Return success */
1067 return STATUS_SUCCESS
;
1072 ObQueryDeviceMapInformation(IN PEPROCESS Process
,
1073 IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo
)
1078 * FIXME: This is an ugly hack for now, to always return the System Device Map
1079 * instead of returning the Process Device Map. Not important yet since we don't use it
1082 /* FIXME: Acquire the DeviceMap Spinlock */
1083 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
1086 DeviceMapInfo
->Query
.DriveMap
= ObSystemDeviceMap
->DriveMap
;
1087 RtlCopyMemory(DeviceMapInfo
->Query
.DriveType
,
1088 ObSystemDeviceMap
->DriveType
,
1089 sizeof(ObSystemDeviceMap
->DriveType
));
1091 /* FIXME: Release the DeviceMap Spinlock */
1092 // KeReleasepinLock(DeviceMap->Lock, OldIrql);