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
;
177 * Check if the handle count is 0, if the object is named,
178 * and if the object isn't a permanent object.
180 if (!(ObjectHeader
->HandleCount
) &&
182 (ObjectNameInfo
->Name
.Length
) &&
183 !(ObjectHeader
->Flags
& OB_FLAG_PERMANENT
))
185 Context
.Object
= NULL
;
187 /* Make sure it's still inserted */
188 Context
.Directory
= ObjectNameInfo
->Directory
;
189 Context
.DirectoryLocked
= TRUE
;
190 Object
= ObpLookupEntryDirectory(ObjectNameInfo
->Directory
,
191 &ObjectNameInfo
->Name
,
195 if ((Object
) && !(ObjectHeader
->HandleCount
))
197 /* Lock the object type */
198 ObpEnterObjectTypeMutex(ObjectType
);
200 /* First delete it from the directory */
201 ObpDeleteEntryDirectory(&Context
);
203 /* Now check if we have a security callback */
204 if (ObjectType
->TypeInfo
.SecurityRequired
)
207 ObjectType
->TypeInfo
.SecurityProcedure(Object
,
208 DeleteSecurityDescriptor
,
219 /* Release the lock */
220 ObpLeaveObjectTypeMutex(ObjectType
);
223 ExFreePool(ObjectNameInfo
->Name
.Buffer
);
224 RtlInitEmptyUnicodeString(&ObjectNameInfo
->Name
, NULL
, 0);
226 Context
.Object
= NULL
;
228 /* Clear the current directory and de-reference it */
229 Directory
= ObjectNameInfo
->Directory
;
230 ObjectNameInfo
->Directory
= NULL
;
233 /* Check if we were inserted in a directory */
236 /* We were, so dereference the directory and the object as well */
237 ObDereferenceObject(Directory
);
238 ObDereferenceObject(Object
);
245 ObpLookupObjectName(IN HANDLE RootHandle
,
246 IN PUNICODE_STRING ObjectName
,
248 IN POBJECT_TYPE ObjectType
,
249 IN KPROCESSOR_MODE AccessMode
,
250 IN OUT PVOID ParseContext
,
251 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos
,
252 IN PVOID ExpectedObject
,
253 IN PACCESS_STATE AccessState
,
254 IN POBP_LOOKUP_CONTEXT Context
,
255 OUT PVOID
*ReturnedObject
)
258 PVOID CurrentDirectory
= NULL
;
259 PVOID CurrentObject
= NULL
;
260 POBJECT_HEADER CurrentHeader
;
261 NTSTATUS Status
= STATUS_SUCCESS
;
263 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
264 UNICODE_STRING RemainingPath
, PartName
;
265 BOOLEAN InsideRoot
= FALSE
;
266 OB_PARSE_METHOD ParseRoutine
;
270 OBTRACE(OB_NAMESPACE_DEBUG
,
271 "%s - Finding Object: %wZ. Expecting: %p\n",
275 *ReturnedObject
= NULL
;
277 /* Check if we got a Root Directory */
280 /* We did. Reference it */
281 Status
= ObReferenceObjectByHandle(RootHandle
,
287 if (!NT_SUCCESS(Status
)) return Status
;
290 CurrentHeader
= OBJECT_TO_OBJECT_HEADER(RootDirectory
);
292 /* The name cannot start with a separator, unless this is a file */
293 if ((ObjectName
->Buffer
) &&
294 (ObjectName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
) &&
295 (CurrentHeader
->Type
!= IoFileObjectType
))
297 /* The syntax is bad, so fail this request */
298 ObDereferenceObject(RootDirectory
);
299 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
302 /* Don't parse a Directory */
303 if (CurrentHeader
->Type
!= ObDirectoryType
)
305 /* Make sure the Object Type has a parse routine */
306 ParseRoutine
= CurrentHeader
->Type
->TypeInfo
.ParseProcedure
;
309 /* We can't parse a name if we don't have a parse routine */
310 ObDereferenceObject(RootDirectory
);
311 return STATUS_INVALID_HANDLE
;
317 /* Start with the full name */
318 RemainingPath
= *ObjectName
;
320 /* Call the Parse Procedure */
321 Status
= ParseRoutine(RootDirectory
,
332 /* Check for success or failure, so not reparse */
333 if ((Status
!= STATUS_REPARSE
) &&
334 (Status
!= STATUS_REPARSE_OBJECT
))
336 /* Check for failure */
337 if (!NT_SUCCESS(Status
))
339 /* Parse routine might not have cleared this, do it */
340 CurrentObject
= NULL
;
342 else if (!CurrentObject
)
344 /* Modify status to reflect failure inside Ob */
345 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
348 /* We're done, return the status and object */
349 *ReturnedObject
= CurrentObject
;
350 ObDereferenceObject(RootDirectory
);
353 else if ((!ObjectName
->Length
) ||
354 (!ObjectName
->Buffer
) ||
355 (ObjectName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
))
357 /* Reparsed to the root directory, so start over */
358 ObDereferenceObject(RootDirectory
);
359 RootDirectory
= NameSpaceRoot
;
361 /* Don't use this anymore, since we're starting at root */
367 else if (!(ObjectName
->Length
) || !(ObjectName
->Buffer
))
369 /* Just return the Root Directory if we didn't get a name*/
370 Status
= ObReferenceObjectByPointer(RootDirectory
,
374 if (NT_SUCCESS(Status
)) *ReturnedObject
= RootDirectory
;
375 ObDereferenceObject(RootDirectory
);
381 /* We did not get a Root Directory, so use the root */
382 RootDirectory
= NameSpaceRoot
;
384 /* It must start with a path separator */
385 if (!(ObjectName
->Length
) ||
386 !(ObjectName
->Buffer
) ||
387 (ObjectName
->Buffer
[0] != OBJ_NAME_PATH_SEPARATOR
))
389 /* This name is invalid, so fail */
390 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
393 /* Check if the name is only the path separator */
394 if (ObjectName
->Length
== sizeof(OBJ_NAME_PATH_SEPARATOR
))
396 /* So the caller only wants the root directory; do we have one? */
399 /* This must be the first time we're creating it... right? */
402 /* Yes, so return it to ObInsert so that it can create it */
403 Status
= ObReferenceObjectByPointer(ExpectedObject
,
407 if (NT_SUCCESS(Status
)) *ReturnedObject
= ExpectedObject
;
412 /* This should never really happen */
414 return STATUS_INVALID_PARAMETER
;
419 /* We do have the root directory, so just return it */
420 Status
= ObReferenceObjectByPointer(RootDirectory
,
424 if (NT_SUCCESS(Status
)) *ReturnedObject
= RootDirectory
;
432 RemainingPath
= *ObjectName
;
437 /* Check if we should use the Root Directory */
440 /* Yes, use the root directory and remember that */
441 CurrentDirectory
= RootDirectory
;
445 /* Check if the name starts with a path separator */
446 if ((RemainingPath
.Length
) &&
447 (RemainingPath
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
))
449 /* Skip the path separator */
450 RemainingPath
.Buffer
++;
451 RemainingPath
.Length
-= sizeof(OBJ_NAME_PATH_SEPARATOR
);
454 /* Find the next Part Name */
455 PartName
= RemainingPath
;
456 while (RemainingPath
.Length
)
458 /* Break if we found the \ ending */
459 if (RemainingPath
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
) break;
462 RemainingPath
.Buffer
++;
463 RemainingPath
.Length
-= sizeof(OBJ_NAME_PATH_SEPARATOR
);
466 /* Get its size and make sure it's valid */
467 if (!(PartName
.Length
-= RemainingPath
.Length
))
469 Status
= STATUS_OBJECT_NAME_INVALID
;
474 Context
->DirectoryLocked
= TRUE
;
475 Context
->Directory
= CurrentDirectory
;
476 CurrentObject
= ObpLookupEntryDirectory(CurrentDirectory
,
483 /* We didn't find it... do we still have a path? */
484 if (RemainingPath
.Length
)
486 /* Then tell the caller the path wasn't found */
487 Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
490 else if (!ExpectedObject
)
492 /* Otherwise, we have a path, but the name isn't valid */
493 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
497 /* Reference newly to be inserted object */
498 ObReferenceObject(ExpectedObject
);
499 CurrentHeader
= OBJECT_TO_OBJECT_HEADER(ExpectedObject
);
501 /* Create Object Name */
502 NewName
= ExAllocatePoolWithTag(NonPagedPool
,
503 PartName
.MaximumLength
,
505 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(CurrentHeader
);
508 RtlMoveMemory(NewName
, PartName
.Buffer
, PartName
.MaximumLength
);
511 if (ObjectNameInfo
->Name
.Buffer
) ExFreePool(ObjectNameInfo
->Name
.Buffer
);
514 ObjectNameInfo
->Name
.Buffer
= NewName
;
515 ObjectNameInfo
->Name
.Length
= PartName
.Length
;
516 ObjectNameInfo
->Name
.MaximumLength
= PartName
.MaximumLength
;
518 /* Rereference the Directory and insert */
519 ObReferenceObject(CurrentDirectory
);
520 ObpInsertEntryDirectory(CurrentDirectory
, Context
, CurrentHeader
);
522 /* Return Status and the Expected Object */
523 Status
= STATUS_SUCCESS
;
524 CurrentObject
= ExpectedObject
;
526 /* Get out of here */
531 /* We found it, so now get its header */
532 CurrentHeader
= OBJECT_TO_OBJECT_HEADER(CurrentObject
);
535 * Check for a parse Procedure, but don't bother to parse for an insert
536 * unless it's a Symbolic Link, in which case we MUST parse
538 ParseRoutine
= CurrentHeader
->Type
->TypeInfo
.ParseProcedure
;
540 (!ExpectedObject
|| ParseRoutine
== ObpParseSymbolicLink
))
542 /* Use the Root Directory next time */
545 /* Call the Parse Procedure */
546 Status
= ParseRoutine(CurrentObject
,
557 /* Check if we have to reparse */
558 if ((Status
== STATUS_REPARSE
) ||
559 (Status
== STATUS_REPARSE_OBJECT
))
561 /* Start over from root if we got sent back there */
562 if ((Status
== STATUS_REPARSE_OBJECT
) ||
563 (ObjectName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
))
565 /* Check if we got a root directory */
568 /* Stop using it, because we have a new directory now */
569 ObDereferenceObject(RootDirectory
);
574 RootDirectory
= NameSpaceRoot
;
576 /* Check for reparse status */
577 if (Status
== STATUS_REPARSE_OBJECT
)
579 /* Did we actually get an object to which to reparse? */
582 /* We didn't, so set a failure status */
583 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
587 /* We did, so we're free to parse the new object */
593 /* Restart the search */
596 else if (RootDirectory
== NameSpaceRoot
)
598 /* We got STATUS_REPARSE but are at the Root Directory */
599 CurrentObject
= NULL
;
600 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
603 else if (!NT_SUCCESS(Status
))
606 CurrentObject
= NULL
;
608 else if (!CurrentObject
)
610 /* We didn't reparse but we didn't find the Object Either */
611 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
614 /* Break out of the loop */
619 /* No parse routine...do we still have a remaining name? */
620 if (!RemainingPath
.Length
)
622 /* Are we creating an object? */
625 /* We don't... reference the Object */
626 Status
= ObReferenceObjectByPointer(CurrentObject
,
630 if (!NT_SUCCESS(Status
)) CurrentObject
= NULL
;
633 /* And get out of the reparse loop */
638 /* We still have a name; check if this is a directory object */
639 if (CurrentHeader
->Type
== ObDirectoryType
)
641 /* Restart from this directory */
642 CurrentDirectory
= CurrentObject
;
646 /* We still have a name, but no parse routine for it */
647 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
648 CurrentObject
= NULL
;
655 /* Write what we found, and if it's null, check if we got success */
656 if (!(*ReturnedObject
= CurrentObject
) && (NT_SUCCESS(Status
)))
658 /* Nothing found... but we have success. Correct the status code */
659 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
662 /* Check if we had a root directory */
666 ObDereferenceObject(RootDirectory
);
669 /* Return status to caller */
670 OBTRACE(OB_NAMESPACE_DEBUG
,
671 "%s - Found Object: %p. Expected: %p\n",
678 /* PUBLIC FUNCTIONS *********************************************************/
682 ObQueryNameString(IN PVOID Object
,
683 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
685 OUT PULONG ReturnLength
)
687 POBJECT_HEADER_NAME_INFO LocalInfo
;
688 POBJECT_HEADER ObjectHeader
;
689 POBJECT_DIRECTORY ParentDirectory
;
693 /* Get the Kernel Meta-Structures */
694 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
695 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
697 /* Check if a Query Name Procedure is available */
698 if (ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure
)
700 /* Call the procedure */
701 return ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure(Object
,
709 /* Check if the object doesn't even have a name */
710 if (!(LocalInfo
) || !(LocalInfo
->Name
.Buffer
))
712 /* We're returning the name structure */
713 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
715 /* Check if we were given enough space */
716 if (*ReturnLength
> Length
) return STATUS_INFO_LENGTH_MISMATCH
;
718 /* Return an empty buffer */
719 RtlInitEmptyUnicodeString(&ObjectNameInfo
->Name
, NULL
, 0);
720 return STATUS_SUCCESS
;
724 * Find the size needed for the name. We won't do
725 * this during the Name Creation loop because we want
726 * to let the caller know that the buffer isn't big
727 * enough right at the beginning, not work our way through
728 * and find out at the end
730 if (Object
== NameSpaceRoot
)
732 /* Size of the '\' string */
733 NameSize
= sizeof(OBJ_NAME_PATH_SEPARATOR
);
737 /* Get the Object Directory and add name of Object */
738 ParentDirectory
= LocalInfo
->Directory
;
739 NameSize
= sizeof(OBJ_NAME_PATH_SEPARATOR
) + LocalInfo
->Name
.Length
;
741 /* Loop inside the directory to get the top-most one (meaning root) */
742 while ((ParentDirectory
!= NameSpaceRoot
) && (ParentDirectory
))
744 /* Get the Name Information */
745 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(
746 OBJECT_TO_OBJECT_HEADER(ParentDirectory
));
748 /* Add the size of the Directory Name */
749 if (LocalInfo
&& LocalInfo
->Directory
)
751 /* Size of the '\' string + Directory Name */
752 NameSize
+= sizeof(OBJ_NAME_PATH_SEPARATOR
) +
753 LocalInfo
->Name
.Length
;
755 /* Move to next parent Directory */
756 ParentDirectory
= LocalInfo
->Directory
;
760 /* Directory with no name. We append "...\" */
761 NameSize
+= sizeof(L
"...") + sizeof(OBJ_NAME_PATH_SEPARATOR
);
767 /* Finally, add the name of the structure and the null char */
768 *ReturnLength
= NameSize
+
769 sizeof(OBJECT_NAME_INFORMATION
) +
770 sizeof(UNICODE_NULL
);
772 /* Check if we were given enough space */
773 if (*ReturnLength
> Length
) return STATUS_INFO_LENGTH_MISMATCH
;
776 * Now we will actually create the name. We work backwards because
777 * it's easier to start off from the Name we have and walk up the
778 * parent directories. We use the same logic as Name Length calculation.
780 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
781 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectNameInfo
+ *ReturnLength
);
782 *--ObjectName
= UNICODE_NULL
;
784 /* Check if the object is actually the Root directory */
785 if (Object
== NameSpaceRoot
)
787 /* This is already the Root Directory, return "\\" */
788 *--ObjectName
= OBJ_NAME_PATH_SEPARATOR
;
789 ObjectNameInfo
->Name
.Length
= (USHORT
)NameSize
;
790 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(NameSize
+
791 sizeof(UNICODE_NULL
));
792 ObjectNameInfo
->Name
.Buffer
= ObjectName
;
793 return STATUS_SUCCESS
;
797 /* Start by adding the Object's Name */
798 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectName
-
799 LocalInfo
->Name
.Length
);
800 RtlCopyMemory(ObjectName
,
801 LocalInfo
->Name
.Buffer
,
802 LocalInfo
->Name
.Length
);
804 /* Now parse the Parent directories until we reach the top */
805 ParentDirectory
= LocalInfo
->Directory
;
806 while ((ParentDirectory
!= NameSpaceRoot
) && (ParentDirectory
))
808 /* Get the name information */
809 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(
810 OBJECT_TO_OBJECT_HEADER(ParentDirectory
));
813 *(--ObjectName
) = OBJ_NAME_PATH_SEPARATOR
;
815 /* Add the Parent Directory's Name */
816 if (LocalInfo
&& LocalInfo
->Name
.Buffer
)
819 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectName
-
820 LocalInfo
->Name
.Length
);
821 RtlCopyMemory(ObjectName
,
822 LocalInfo
->Name
.Buffer
,
823 LocalInfo
->Name
.Length
);
825 /* Move to next parent */
826 ParentDirectory
= LocalInfo
->Directory
;
830 /* Directory without a name, we add "..." */
831 ObjectName
-= sizeof(L
"...");
837 /* Add Root Directory Name */
838 *(--ObjectName
) = OBJ_NAME_PATH_SEPARATOR
;
839 ObjectNameInfo
->Name
.Length
= (USHORT
)NameSize
;
840 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(NameSize
+
841 sizeof(UNICODE_NULL
));
842 ObjectNameInfo
->Name
.Buffer
= ObjectName
;
846 return STATUS_SUCCESS
;
851 ObQueryDeviceMapInformation(IN PEPROCESS Process
,
852 IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo
)
857 * FIXME: This is an ugly hack for now, to always return the System Device Map
858 * instead of returning the Process Device Map. Not important yet since we don't use it
861 /* FIXME: Acquire the DeviceMap Spinlock */
862 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
865 DeviceMapInfo
->Query
.DriveMap
= ObSystemDeviceMap
->DriveMap
;
866 RtlCopyMemory(DeviceMapInfo
->Query
.DriveType
,
867 ObSystemDeviceMap
->DriveType
,
868 sizeof(ObSystemDeviceMap
->DriveType
));
870 /* FIXME: Release the DeviceMap Spinlock */
871 // KeReleasepinLock(DeviceMap->Lock, OldIrql);