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
17 #include <internal/debug.h>
19 POBJECT_DIRECTORY NameSpaceRoot
= NULL
;
20 POBJECT_DIRECTORY ObpTypeDirectoryObject
= NULL
;
22 /* PRIVATE FUNCTIONS *********************************************************/
26 ObpCreateDosDevicesDirectory(VOID
)
28 OBJECT_ATTRIBUTES ObjectAttributes
;
29 UNICODE_STRING Name
, LinkName
;
30 HANDLE Handle
, SymHandle
;
33 /* Create the '\??' directory */
34 RtlInitUnicodeString(&Name
, L
"\\??");
35 InitializeObjectAttributes(&ObjectAttributes
,
40 Status
= NtCreateDirectoryObject(&Handle
,
43 if (!NT_SUCCESS(Status
)) return FALSE
;
45 /* Initialize the GLOBALROOT path */
46 RtlInitUnicodeString(&LinkName
, L
"GLOBALROOT");
47 RtlInitUnicodeString(&Name
, L
"");
48 InitializeObjectAttributes(&ObjectAttributes
,
53 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
54 SYMBOLIC_LINK_ALL_ACCESS
,
57 if (NT_SUCCESS(Status
)) NtClose(SymHandle
);
59 /* Link \??\Global to \?? */
60 RtlInitUnicodeString(&LinkName
, L
"Global");
61 RtlInitUnicodeString(&Name
, L
"\\??");
62 InitializeObjectAttributes(&ObjectAttributes
,
67 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
68 SYMBOLIC_LINK_ALL_ACCESS
,
71 if (NT_SUCCESS(Status
)) NtClose(SymHandle
);
73 /* Close the directory handle */
75 if (!NT_SUCCESS(Status
)) return Status
;
77 /* Create link from '\DosDevices' to '\??' directory */
78 RtlCreateUnicodeString(&LinkName
, L
"\\DosDevices");
79 InitializeObjectAttributes(&ObjectAttributes
,
84 Status
= NtCreateSymbolicLinkObject(&SymHandle
,
85 SYMBOLIC_LINK_ALL_ACCESS
,
88 if (NT_SUCCESS(Status
)) NtClose(SymHandle
);
90 /* FIXME: Hack Hack! */
91 ObSystemDeviceMap
= ExAllocatePoolWithTag(NonPagedPool
,
92 sizeof(*ObSystemDeviceMap
),
93 TAG('O', 'b', 'D', 'm'));
94 RtlZeroMemory(ObSystemDeviceMap
, sizeof(*ObSystemDeviceMap
));
102 ObDereferenceDeviceMap(IN PEPROCESS Process
)
105 PDEVICE_MAP DeviceMap
= Process
->DeviceMap
;
107 /* FIXME: We don't use Process Devicemaps yet */
110 /* FIXME: Acquire the DeviceMap Spinlock */
111 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
113 /* Delete the device map link and dereference it */
114 Process
->DeviceMap
= NULL
;
115 if (--DeviceMap
->ReferenceCount
)
117 /* Nobody is referencing it anymore, unlink the DOS directory */
118 DeviceMap
->DosDevicesDirectory
->DeviceMap
= NULL
;
120 /* FIXME: Release the DeviceMap Spinlock */
121 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
123 /* Dereference the DOS Devices Directory and free the Device Map */
124 ObDereferenceObject(DeviceMap
->DosDevicesDirectory
);
125 ExFreePool(DeviceMap
);
129 /* FIXME: Release the DeviceMap Spinlock */
130 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
137 ObInheritDeviceMap(IN PEPROCESS Parent
,
138 IN PEPROCESS Process
)
140 /* FIXME: Devicemap Support */
144 * @name ObpDeleteNameCheck
146 * The ObpDeleteNameCheck routine checks if a named object should be
147 * removed from the object directory namespace.
150 * Pointer to the object to check for possible removal.
154 * @remarks An object is removed if the following 4 criteria are met:
155 * 1) The object has 0 handles open
156 * 2) The object is in the directory namespace and has a name
157 * 3) The object is not permanent
162 ObpDeleteNameCheck(IN PVOID Object
)
164 POBJECT_HEADER ObjectHeader
;
165 OBP_LOOKUP_CONTEXT Context
;
166 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
167 POBJECT_TYPE ObjectType
;
168 PVOID Directory
= NULL
;
170 /* Get object structures */
171 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
172 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
173 ObjectType
= ObjectHeader
->Type
;
176 * Check if the handle count is 0, if the object is named,
177 * and if the object isn't a permanent object.
179 if (!(ObjectHeader
->HandleCount
) &&
181 (ObjectNameInfo
->Name
.Length
) &&
182 !(ObjectHeader
->Flags
& OB_FLAG_PERMANENT
))
184 /* Make sure it's still inserted */
185 Context
.Directory
= ObjectNameInfo
->Directory
;
186 Context
.DirectoryLocked
= TRUE
;
187 Object
= ObpLookupEntryDirectory(ObjectNameInfo
->Directory
,
188 &ObjectNameInfo
->Name
,
192 if ((Object
) && !(ObjectHeader
->HandleCount
))
194 /* Lock the object type */
195 ObpEnterObjectTypeMutex(ObjectType
);
197 /* First delete it from the directory */
198 ObpDeleteEntryDirectory(&Context
);
200 /* Now check if we have a security callback */
201 if (ObjectType
->TypeInfo
.SecurityRequired
)
204 ObjectType
->TypeInfo
.SecurityProcedure(Object
,
205 DeleteSecurityDescriptor
,
216 /* Release the lock */
217 ObpLeaveObjectTypeMutex(ObjectType
);
220 ExFreePool(ObjectNameInfo
->Name
.Buffer
);
221 RtlInitEmptyUnicodeString(&ObjectNameInfo
->Name
, NULL
, 0);
223 /* Clear the current directory and de-reference it */
224 Directory
= ObjectNameInfo
->Directory
;
225 ObjectNameInfo
->Directory
= NULL
;
228 /* Check if we were inserted in a directory */
231 /* We were, so dereference the directory and the object as well */
232 ObDereferenceObject(Directory
);
233 ObDereferenceObject(Object
);
240 ObFindObject(IN HANDLE RootHandle
,
241 IN PUNICODE_STRING ObjectName
,
243 IN KPROCESSOR_MODE AccessMode
,
244 IN PVOID
*ReturnedObject
,
245 IN POBJECT_TYPE ObjectType
,
246 IN POBP_LOOKUP_CONTEXT Context
,
247 IN PACCESS_STATE AccessState
,
248 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos
,
249 IN OUT PVOID ParseContext
,
250 OUT PVOID ExpectedObject
)
253 PVOID CurrentDirectory
= NULL
;
254 PVOID CurrentObject
= NULL
;
255 POBJECT_HEADER CurrentHeader
;
256 NTSTATUS Status
= STATUS_SUCCESS
;
258 POBJECT_HEADER_NAME_INFO ObjectNameInfo
;
259 UNICODE_STRING RemainingPath
, PartName
;
260 BOOLEAN InsideRoot
= FALSE
;
261 OB_PARSE_METHOD ParseRoutine
;
265 OBTRACE(OB_NAMESPACE_DEBUG
,
266 "%s - Finding Object: %wZ. Expecting: %p\n",
270 *ReturnedObject
= NULL
;
272 /* Check if we got a Root Directory */
275 /* We did. Reference it */
276 Status
= ObReferenceObjectByHandle(RootHandle
,
282 if (!NT_SUCCESS(Status
)) return Status
;
285 CurrentHeader
= OBJECT_TO_OBJECT_HEADER(RootDirectory
);
287 /* The name cannot start with a separator, unless this is a file */
288 if ((ObjectName
->Buffer
) &&
289 (ObjectName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
) &&
290 (CurrentHeader
->Type
!= IoFileObjectType
))
292 /* The syntax is bad, so fail this request */
293 ObDereferenceObject(RootDirectory
);
294 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
297 /* Don't parse a Directory */
298 if (CurrentHeader
->Type
!= ObDirectoryType
)
300 /* Make sure the Object Type has a parse routine */
301 ParseRoutine
= CurrentHeader
->Type
->TypeInfo
.ParseProcedure
;
304 /* We can't parse a name if we don't have a parse routine */
305 ObDereferenceObject(RootDirectory
);
306 return STATUS_INVALID_HANDLE
;
312 /* Start with the full name */
313 RemainingPath
= *ObjectName
;
315 /* Call the Parse Procedure */
316 Status
= ParseRoutine(RootDirectory
,
327 /* Check for success or failure, so not reparse */
328 if ((Status
!= STATUS_REPARSE
) &&
329 (Status
!= STATUS_REPARSE_OBJECT
))
331 /* Check for failure */
332 if (!NT_SUCCESS(Status
))
334 /* Parse routine might not have cleared this, do it */
335 CurrentObject
= NULL
;
337 else if (!CurrentObject
)
339 /* Modify status to reflect failure inside Ob */
340 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
343 /* We're done, return the status and object */
344 *ReturnedObject
= CurrentObject
;
345 ObDereferenceObject(RootDirectory
);
348 else if ((!ObjectName
->Length
) ||
349 (!ObjectName
->Buffer
) ||
350 (ObjectName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
))
352 /* Reparsed to the root directory, so start over */
353 ObDereferenceObject(RootDirectory
);
354 RootDirectory
= NameSpaceRoot
;
356 /* Don't use this anymore, since we're starting at root */
362 else if (!(ObjectName
->Length
) || !(ObjectName
->Buffer
))
364 /* Just return the Root Directory if we didn't get a name*/
365 Status
= ObReferenceObjectByPointer(RootDirectory
,
369 if (NT_SUCCESS(Status
)) *ReturnedObject
= RootDirectory
;
370 ObDereferenceObject(RootDirectory
);
376 /* We did not get a Root Directory, so use the root */
377 RootDirectory
= NameSpaceRoot
;
379 /* It must start with a path separator */
380 if (!(ObjectName
->Length
) ||
381 !(ObjectName
->Buffer
) ||
382 (ObjectName
->Buffer
[0] != OBJ_NAME_PATH_SEPARATOR
))
384 /* This name is invalid, so fail */
385 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
388 /* Check if the name is only the path separator */
389 if (ObjectName
->Length
== sizeof(OBJ_NAME_PATH_SEPARATOR
))
391 /* So the caller only wants the root directory; do we have one? */
394 /* This must be the first time we're creating it... right? */
397 /* Yes, so return it to ObInsert so that it can create it */
398 Status
= ObReferenceObjectByPointer(ExpectedObject
,
402 if (NT_SUCCESS(Status
)) *ReturnedObject
= ExpectedObject
;
407 /* This should never really happen */
409 return STATUS_INVALID_PARAMETER
;
414 /* We do have the root directory, so just return it */
415 Status
= ObReferenceObjectByPointer(RootDirectory
,
419 if (NT_SUCCESS(Status
)) *ReturnedObject
= RootDirectory
;
427 RemainingPath
= *ObjectName
;
432 /* Check if we should use the Root Directory */
435 /* Yes, use the root directory and remember that */
436 CurrentDirectory
= RootDirectory
;
440 /* Check if the name starts with a path separator */
441 if ((RemainingPath
.Length
) &&
442 (RemainingPath
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
))
444 /* Skip the path separator */
445 RemainingPath
.Buffer
++;
446 RemainingPath
.Length
-= sizeof(OBJ_NAME_PATH_SEPARATOR
);
449 /* Find the next Part Name */
450 PartName
= RemainingPath
;
451 while (RemainingPath
.Length
)
453 /* Break if we found the \ ending */
454 if (RemainingPath
.Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
) break;
457 RemainingPath
.Buffer
++;
458 RemainingPath
.Length
-= sizeof(OBJ_NAME_PATH_SEPARATOR
);
461 /* Get its size and make sure it's valid */
462 if (!(PartName
.Length
-= RemainingPath
.Length
))
464 Status
= STATUS_OBJECT_NAME_INVALID
;
469 Context
->DirectoryLocked
= TRUE
;
470 Context
->Directory
= CurrentDirectory
;
471 CurrentObject
= ObpLookupEntryDirectory(CurrentDirectory
,
478 /* We didn't find it... do we still have a path? */
479 if (RemainingPath
.Length
)
481 /* Then tell the caller the path wasn't found */
482 Status
= STATUS_OBJECT_PATH_NOT_FOUND
;
485 else if (!ExpectedObject
)
487 /* Otherwise, we have a path, but the name isn't valid */
488 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
492 /* Reference newly to be inserted object */
493 ObReferenceObject(ExpectedObject
);
494 CurrentHeader
= OBJECT_TO_OBJECT_HEADER(ExpectedObject
);
496 /* Create Object Name */
497 NewName
= ExAllocatePoolWithTag(NonPagedPool
,
498 PartName
.MaximumLength
,
500 ObjectNameInfo
= OBJECT_HEADER_TO_NAME_INFO(CurrentHeader
);
503 RtlCopyMemory(NewName
, PartName
.Buffer
, PartName
.MaximumLength
);
506 if (ObjectNameInfo
->Name
.Buffer
) ExFreePool(ObjectNameInfo
->Name
.Buffer
);
509 ObjectNameInfo
->Name
.Buffer
= NewName
;
510 ObjectNameInfo
->Name
.Length
= PartName
.Length
;
511 ObjectNameInfo
->Name
.MaximumLength
= PartName
.MaximumLength
;
513 /* Rereference the Directory and insert */
514 ObReferenceObject(CurrentDirectory
);
515 ObpInsertEntryDirectory(CurrentDirectory
, Context
, CurrentHeader
);
517 /* Return Status and the Expected Object */
518 Status
= STATUS_SUCCESS
;
519 CurrentObject
= ExpectedObject
;
521 /* Get out of here */
526 /* We found it, so now get its header */
527 CurrentHeader
= OBJECT_TO_OBJECT_HEADER(CurrentObject
);
530 * Check for a parse Procedure, but don't bother to parse for an insert
531 * unless it's a Symbolic Link, in which case we MUST parse
533 ParseRoutine
= CurrentHeader
->Type
->TypeInfo
.ParseProcedure
;
535 (!ExpectedObject
|| ParseRoutine
== ObpParseSymbolicLink
))
537 /* Use the Root Directory next time */
540 /* Call the Parse Procedure */
541 Status
= ParseRoutine(CurrentObject
,
552 /* Check if we have to reparse */
553 if ((Status
== STATUS_REPARSE
) ||
554 (Status
== STATUS_REPARSE_OBJECT
))
556 /* Start over from root if we got sent back there */
557 if ((Status
== STATUS_REPARSE_OBJECT
) ||
558 (ObjectName
->Buffer
[0] == OBJ_NAME_PATH_SEPARATOR
))
560 /* Check if we got a root directory */
563 /* Stop using it, because we have a new directory now */
564 ObDereferenceObject(RootDirectory
);
569 RootDirectory
= NameSpaceRoot
;
571 /* Check for reparse status */
572 if (Status
== STATUS_REPARSE_OBJECT
)
574 /* Did we actually get an object to which to reparse? */
577 /* We didn't, so set a failure status */
578 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
582 /* We did, so we're free to parse the new object */
588 /* Restart the search */
591 else if (RootDirectory
== NameSpaceRoot
)
593 /* We got STATUS_REPARSE but are at the Root Directory */
594 CurrentObject
= NULL
;
595 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
598 else if (!NT_SUCCESS(Status
))
601 CurrentObject
= NULL
;
603 else if (!CurrentObject
)
605 /* We didn't reparse but we didn't find the Object Either */
606 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
609 /* Break out of the loop */
614 /* No parse routine...do we still have a remaining name? */
615 if (!RemainingPath
.Length
)
617 /* Are we creating an object? */
620 /* We don't... reference the Object */
621 Status
= ObReferenceObjectByPointer(CurrentObject
,
625 if (!NT_SUCCESS(Status
)) CurrentObject
= NULL
;
628 /* And get out of the reparse loop */
633 /* We still have a name; check if this is a directory object */
634 if (CurrentHeader
->Type
== ObDirectoryType
)
636 /* Restart from this directory */
637 CurrentDirectory
= CurrentObject
;
641 /* We still have a name, but no parse routine for it */
642 Status
= STATUS_OBJECT_TYPE_MISMATCH
;
643 CurrentObject
= NULL
;
650 /* Write what we found, and if it's null, check if we got success */
651 if (!(*ReturnedObject
= CurrentObject
) && (NT_SUCCESS(Status
)))
653 /* Nothing found... but we have success. Correct the status code */
654 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
657 /* Check if we had a root directory */
661 ObDereferenceObject(RootDirectory
);
664 /* Return status to caller */
665 OBTRACE(OB_NAMESPACE_DEBUG
,
666 "%s - Found Object: %p. Expected: %p\n",
673 /* PUBLIC FUNCTIONS *********************************************************/
677 ObQueryNameString(IN PVOID Object
,
678 OUT POBJECT_NAME_INFORMATION ObjectNameInfo
,
680 OUT PULONG ReturnLength
)
682 POBJECT_HEADER_NAME_INFO LocalInfo
;
683 POBJECT_HEADER ObjectHeader
;
684 POBJECT_DIRECTORY ParentDirectory
;
688 /* Get the Kernel Meta-Structures */
689 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
690 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
692 /* Check if a Query Name Procedure is available */
693 if (ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure
)
695 /* Call the procedure */
696 return ObjectHeader
->Type
->TypeInfo
.QueryNameProcedure(Object
,
704 /* Check if the object doesn't even have a name */
705 if (!(LocalInfo
) || !(LocalInfo
->Name
.Buffer
))
707 /* We're returning the name structure */
708 *ReturnLength
= sizeof(OBJECT_NAME_INFORMATION
);
710 /* Check if we were given enough space */
711 if (*ReturnLength
> Length
) return STATUS_INFO_LENGTH_MISMATCH
;
713 /* Return an empty buffer */
714 RtlInitEmptyUnicodeString(&ObjectNameInfo
->Name
, NULL
, 0);
715 return STATUS_SUCCESS
;
719 * Find the size needed for the name. We won't do
720 * this during the Name Creation loop because we want
721 * to let the caller know that the buffer isn't big
722 * enough right at the beginning, not work our way through
723 * and find out at the end
725 if (Object
== NameSpaceRoot
)
727 /* Size of the '\' string */
728 NameSize
= sizeof(OBJ_NAME_PATH_SEPARATOR
);
732 /* Get the Object Directory and add name of Object */
733 ParentDirectory
= LocalInfo
->Directory
;
734 NameSize
= sizeof(OBJ_NAME_PATH_SEPARATOR
) + LocalInfo
->Name
.Length
;
736 /* Loop inside the directory to get the top-most one (meaning root) */
737 while ((ParentDirectory
!= NameSpaceRoot
) && (ParentDirectory
))
739 /* Get the Name Information */
740 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(
741 OBJECT_TO_OBJECT_HEADER(ParentDirectory
));
743 /* Add the size of the Directory Name */
744 if (LocalInfo
&& LocalInfo
->Directory
)
746 /* Size of the '\' string + Directory Name */
747 NameSize
+= sizeof(OBJ_NAME_PATH_SEPARATOR
) +
748 LocalInfo
->Name
.Length
;
750 /* Move to next parent Directory */
751 ParentDirectory
= LocalInfo
->Directory
;
755 /* Directory with no name. We append "...\" */
756 NameSize
+= sizeof(L
"...") + sizeof(OBJ_NAME_PATH_SEPARATOR
);
762 /* Finally, add the name of the structure and the null char */
763 *ReturnLength
= NameSize
+
764 sizeof(OBJECT_NAME_INFORMATION
) +
765 sizeof(UNICODE_NULL
);
767 /* Check if we were given enough space */
768 if (*ReturnLength
> Length
) return STATUS_INFO_LENGTH_MISMATCH
;
771 * Now we will actually create the name. We work backwards because
772 * it's easier to start off from the Name we have and walk up the
773 * parent directories. We use the same logic as Name Length calculation.
775 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(ObjectHeader
);
776 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectNameInfo
+ *ReturnLength
);
777 *--ObjectName
= UNICODE_NULL
;
779 /* Check if the object is actually the Root directory */
780 if (Object
== NameSpaceRoot
)
782 /* This is already the Root Directory, return "\\" */
783 *--ObjectName
= OBJ_NAME_PATH_SEPARATOR
;
784 ObjectNameInfo
->Name
.Length
= (USHORT
)NameSize
;
785 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(NameSize
+
786 sizeof(UNICODE_NULL
));
787 ObjectNameInfo
->Name
.Buffer
= ObjectName
;
788 return STATUS_SUCCESS
;
792 /* Start by adding the Object's Name */
793 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectName
-
794 LocalInfo
->Name
.Length
);
795 RtlCopyMemory(ObjectName
,
796 LocalInfo
->Name
.Buffer
,
797 LocalInfo
->Name
.Length
);
799 /* Now parse the Parent directories until we reach the top */
800 ParentDirectory
= LocalInfo
->Directory
;
801 while ((ParentDirectory
!= NameSpaceRoot
) && (ParentDirectory
))
803 /* Get the name information */
804 LocalInfo
= OBJECT_HEADER_TO_NAME_INFO(
805 OBJECT_TO_OBJECT_HEADER(ParentDirectory
));
808 *(--ObjectName
) = OBJ_NAME_PATH_SEPARATOR
;
810 /* Add the Parent Directory's Name */
811 if (LocalInfo
&& LocalInfo
->Name
.Buffer
)
814 ObjectName
= (PWCH
)((ULONG_PTR
)ObjectName
-
815 LocalInfo
->Name
.Length
);
816 RtlCopyMemory(ObjectName
,
817 LocalInfo
->Name
.Buffer
,
818 LocalInfo
->Name
.Length
);
820 /* Move to next parent */
821 ParentDirectory
= LocalInfo
->Directory
;
825 /* Directory without a name, we add "..." */
826 DPRINT("Nameless Directory\n");
827 ObjectName
-= sizeof(L
"...");
833 /* Add Root Directory Name */
834 *(--ObjectName
) = OBJ_NAME_PATH_SEPARATOR
;
835 ObjectNameInfo
->Name
.Length
= (USHORT
)NameSize
;
836 ObjectNameInfo
->Name
.MaximumLength
= (USHORT
)(NameSize
+
837 sizeof(UNICODE_NULL
));
838 ObjectNameInfo
->Name
.Buffer
= ObjectName
;
842 return STATUS_SUCCESS
;
847 ObQueryDeviceMapInformation(IN PEPROCESS Process
,
848 IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo
)
853 * FIXME: This is an ugly hack for now, to always return the System Device Map
854 * instead of returning the Process Device Map. Not important yet since we don't use it
857 /* FIXME: Acquire the DeviceMap Spinlock */
858 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
861 DeviceMapInfo
->Query
.DriveMap
= ObSystemDeviceMap
->DriveMap
;
862 RtlCopyMemory(DeviceMapInfo
->Query
.DriveType
,
863 ObSystemDeviceMap
->DriveType
,
864 sizeof(ObSystemDeviceMap
->DriveType
));
866 /* FIXME: Release the DeviceMap Spinlock */
867 // KeReleasepinLock(DeviceMap->Lock, OldIrql);