- Fix multiple bugs in VfatGetNameInformation:
[reactos.git] / reactos / ntoskrnl / ob / obname.c
1 /*
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)
8 * Eric Kohl
9 * Thomas Weidenmueller (w3seek@reactos.org)
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #define NTDDI_VERSION NTDDI_WINXP
15 #include <ntoskrnl.h>
16 #define NDEBUG
17 #include <internal/debug.h>
18
19 POBJECT_DIRECTORY NameSpaceRoot = NULL;
20 POBJECT_DIRECTORY ObpTypeDirectoryObject = NULL;
21
22 /* PRIVATE FUNCTIONS *********************************************************/
23
24 VOID
25 NTAPI
26 ObDereferenceDeviceMap(IN PEPROCESS Process)
27 {
28 //KIRQL OldIrql;
29 PDEVICE_MAP DeviceMap = Process->DeviceMap;
30
31 /* FIXME: We don't use Process Devicemaps yet */
32 if (DeviceMap)
33 {
34 /* FIXME: Acquire the DeviceMap Spinlock */
35 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
36
37 /* Delete the device map link and dereference it */
38 Process->DeviceMap = NULL;
39 if (--DeviceMap->ReferenceCount)
40 {
41 /* Nobody is referencing it anymore, unlink the DOS directory */
42 DeviceMap->DosDevicesDirectory->DeviceMap = NULL;
43
44 /* FIXME: Release the DeviceMap Spinlock */
45 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
46
47 /* Dereference the DOS Devices Directory and free the Device Map */
48 ObDereferenceObject(DeviceMap->DosDevicesDirectory);
49 ExFreePool(DeviceMap);
50 }
51 else
52 {
53 /* FIXME: Release the DeviceMap Spinlock */
54 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
55 }
56 }
57 }
58
59 VOID
60 NTAPI
61 ObInheritDeviceMap(IN PEPROCESS Parent,
62 IN PEPROCESS Process)
63 {
64 /* FIXME: Devicemap Support */
65 }
66
67 /*++
68 * @name ObpDeleteNameCheck
69 *
70 * The ObpDeleteNameCheck routine checks if a named object should be
71 * removed from the object directory namespace.
72 *
73 * @param Object
74 * Pointer to the object to check for possible removal.
75 *
76 * @return None.
77 *
78 * @remarks An object is removed if the following 4 criteria are met:
79 * 1) The object has 0 handles open
80 * 2) The object is in the directory namespace and has a name
81 * 3) The object is not permanent
82 *
83 *--*/
84 VOID
85 NTAPI
86 ObpDeleteNameCheck(IN PVOID Object)
87 {
88 POBJECT_HEADER ObjectHeader;
89 OBP_LOOKUP_CONTEXT Context;
90 POBJECT_HEADER_NAME_INFO ObjectNameInfo;
91 POBJECT_TYPE ObjectType;
92 PVOID Directory = NULL;
93
94 /* Get object structures */
95 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
96 ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
97 ObjectType = ObjectHeader->Type;
98
99 /*
100 * Check if the handle count is 0, if the object is named,
101 * and if the object isn't a permanent object.
102 */
103 if (!(ObjectHeader->HandleCount) &&
104 (ObjectNameInfo) &&
105 (ObjectNameInfo->Name.Length) &&
106 !(ObjectHeader->Flags & OB_FLAG_PERMANENT))
107 {
108 /* Make sure it's still inserted */
109 Context.Directory = ObjectNameInfo->Directory;
110 Context.DirectoryLocked = TRUE;
111 Object = ObpLookupEntryDirectory(ObjectNameInfo->Directory,
112 &ObjectNameInfo->Name,
113 0,
114 FALSE,
115 &Context);
116 if ((Object) && !(ObjectHeader->HandleCount))
117 {
118 /* First delete it from the directory */
119 ObpDeleteEntryDirectory(&Context);
120
121 /* Now check if we have a security callback */
122 if (ObjectType->TypeInfo.SecurityRequired)
123 {
124 /* Call it */
125 ObjectType->TypeInfo.SecurityProcedure(Object,
126 DeleteSecurityDescriptor,
127 0,
128 NULL,
129 NULL,
130 &ObjectHeader->
131 SecurityDescriptor,
132 ObjectType->
133 TypeInfo.PoolType,
134 NULL);
135 }
136
137 /* Free the name */
138 ExFreePool(ObjectNameInfo->Name.Buffer);
139 RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
140
141 /* Clear the current directory and de-reference it */
142 Directory = ObjectNameInfo->Directory;
143 ObjectNameInfo->Directory = NULL;
144 }
145
146 /* Check if we were inserted in a directory */
147 if (Directory)
148 {
149 /* We were, so dereference the directory and the object as well */
150 ObDereferenceObject(Directory);
151 ObDereferenceObject(Object);
152 }
153 }
154 }
155
156 NTSTATUS
157 NTAPI
158 ObFindObject(IN HANDLE RootHandle,
159 IN PUNICODE_STRING ObjectName,
160 IN ULONG Attributes,
161 IN KPROCESSOR_MODE AccessMode,
162 IN PVOID *ReturnedObject,
163 IN POBJECT_TYPE ObjectType,
164 IN POBP_LOOKUP_CONTEXT Context,
165 IN PACCESS_STATE AccessState,
166 IN PSECURITY_QUALITY_OF_SERVICE SecurityQos,
167 IN PVOID ParseContext,
168 OUT PVOID ExpectedObject)
169 {
170 PVOID RootDirectory;
171 PVOID CurrentDirectory = NULL;
172 PVOID CurrentObject = NULL;
173 POBJECT_HEADER CurrentHeader;
174 NTSTATUS Status = STATUS_SUCCESS;
175 PVOID NewName;
176 POBJECT_HEADER_NAME_INFO ObjectNameInfo;
177 UNICODE_STRING RemainingPath, PartName;
178 BOOLEAN InsideRoot = FALSE;
179 OB_PARSE_METHOD ParseRoutine;
180 PAGED_CODE();
181
182 /* Assume failure */
183 OBTRACE(OB_NAMESPACE_DEBUG,
184 "%s - Finding Object: %wZ. Expecting: %p\n",
185 __FUNCTION__,
186 ObjectName,
187 ExpectedObject);
188 *ReturnedObject = NULL;
189
190 /* Check if we got a Root Directory */
191 if (RootHandle)
192 {
193 /* We did. Reference it */
194 Status = ObReferenceObjectByHandle(RootHandle,
195 0,
196 NULL,
197 AccessMode,
198 &RootDirectory,
199 NULL);
200 if (!NT_SUCCESS(Status)) return Status;
201
202 /* Get the header */
203 CurrentHeader = OBJECT_TO_OBJECT_HEADER(RootDirectory);
204
205 /* The name cannot start with a separator, unless this is a file */
206 if ((ObjectName->Buffer) &&
207 (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) &&
208 (CurrentHeader->Type != IoFileObjectType))
209 {
210 /* The syntax is bad, so fail this request */
211 ObDereferenceObject(RootDirectory);
212 return STATUS_OBJECT_PATH_SYNTAX_BAD;
213 }
214
215 /* Don't parse a Directory */
216 if (CurrentHeader->Type != ObDirectoryType)
217 {
218 /* Make sure the Object Type has a parse routine */
219 ParseRoutine = CurrentHeader->Type->TypeInfo.ParseProcedure;
220 if (!ParseRoutine)
221 {
222 /* We can't parse a name if we don't have a parse routine */
223 ObDereferenceObject(RootDirectory);
224 return STATUS_INVALID_HANDLE;
225 }
226
227 /* Now parse */
228 while (TRUE)
229 {
230 /* Start with the full name */
231 RemainingPath = *ObjectName;
232
233 /* Call the Parse Procedure */
234 Status = ParseRoutine(RootDirectory,
235 ObjectType,
236 AccessState,
237 AccessMode,
238 Attributes,
239 ObjectName,
240 &RemainingPath,
241 ParseContext,
242 SecurityQos,
243 &CurrentObject);
244
245 /* Check for success or failure, so not reparse */
246 if ((Status != STATUS_REPARSE) &&
247 (Status != STATUS_REPARSE_OBJECT))
248 {
249 /* Check for failure */
250 if (!NT_SUCCESS(Status))
251 {
252 /* Parse routine might not have cleared this, do it */
253 CurrentObject = NULL;
254 }
255 else if (!CurrentObject)
256 {
257 /* Modify status to reflect failure inside Ob */
258 Status = STATUS_OBJECT_NAME_NOT_FOUND;
259 }
260
261 /* We're done, return the status and object */
262 *ReturnedObject = CurrentObject;
263 ObDereferenceObject(RootDirectory);
264 return Status;
265 }
266 else if ((!ObjectName->Length) ||
267 (!ObjectName->Buffer) ||
268 (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
269 {
270 /* Reparsed to the root directory, so start over */
271 ObDereferenceObject(RootDirectory);
272 RootDirectory = NameSpaceRoot;
273
274 /* Don't use this anymore, since we're starting at root */
275 RootHandle = NULL;
276 break;
277 }
278 }
279 }
280 else if (!(ObjectName->Length) || !(ObjectName->Buffer))
281 {
282 /* Just return the Root Directory if we didn't get a name*/
283 Status = ObReferenceObjectByPointer(RootDirectory,
284 0,
285 ObjectType,
286 AccessMode);
287 if (NT_SUCCESS(Status)) *ReturnedObject = RootDirectory;
288 ObDereferenceObject(RootDirectory);
289 return Status;
290 }
291 }
292 else
293 {
294 /* We did not get a Root Directory, so use the root */
295 RootDirectory = NameSpaceRoot;
296
297 /* It must start with a path separator */
298 if (!(ObjectName->Length) ||
299 !(ObjectName->Buffer) ||
300 (ObjectName->Buffer[0] != OBJ_NAME_PATH_SEPARATOR))
301 {
302 /* This name is invalid, so fail */
303 return STATUS_OBJECT_PATH_SYNTAX_BAD;
304 }
305
306 /* Check if the name is only the path separator */
307 if (ObjectName->Length == sizeof(OBJ_NAME_PATH_SEPARATOR))
308 {
309 /* So the caller only wants the root directory; do we have one? */
310 if (!RootDirectory)
311 {
312 /* This must be the first time we're creating it... right? */
313 if (ExpectedObject)
314 {
315 /* Yes, so return it to ObInsert so that it can create it */
316 Status = ObReferenceObjectByPointer(ExpectedObject,
317 0,
318 ObjectType,
319 AccessMode);
320 if (NT_SUCCESS(Status)) *ReturnedObject = ExpectedObject;
321 return Status;
322 }
323 else
324 {
325 /* This should never really happen */
326 ASSERT(FALSE);
327 return STATUS_INVALID_PARAMETER;
328 }
329 }
330 else
331 {
332 /* We do have the root directory, so just return it */
333 Status = ObReferenceObjectByPointer(RootDirectory,
334 0,
335 ObjectType,
336 AccessMode);
337 if (NT_SUCCESS(Status)) *ReturnedObject = RootDirectory;
338 return Status;
339 }
340 }
341 }
342
343 /* Save the name */
344 ReparseNewDir:
345 RemainingPath = *ObjectName;
346
347 /* Reparse */
348 while (TRUE)
349 {
350 /* Check if we should use the Root Directory */
351 if (!InsideRoot)
352 {
353 /* Yes, use the root directory and remember that */
354 CurrentDirectory = RootDirectory;
355 InsideRoot = TRUE;
356 }
357
358 /* Check if the name starts with a path separator */
359 if ((RemainingPath.Length) &&
360 (RemainingPath.Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
361 {
362 /* Skip the path separator */
363 RemainingPath.Buffer++;
364 RemainingPath.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
365 }
366
367 /* Find the next Part Name */
368 PartName = RemainingPath;
369 while (RemainingPath.Length)
370 {
371 /* Break if we found the \ ending */
372 if (RemainingPath.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) break;
373
374 /* Move on */
375 RemainingPath.Buffer++;
376 RemainingPath.Length -= sizeof(OBJ_NAME_PATH_SEPARATOR);
377 }
378
379 /* Get its size and make sure it's valid */
380 if (!(PartName.Length -= RemainingPath.Length))
381 {
382 Status = STATUS_OBJECT_NAME_INVALID;
383 break;
384 }
385
386 /* Do the look up */
387 Context->DirectoryLocked = TRUE;
388 Context->Directory = CurrentDirectory;
389 CurrentObject = ObpLookupEntryDirectory(CurrentDirectory,
390 &PartName,
391 Attributes,
392 FALSE,
393 Context);
394 if (!CurrentObject)
395 {
396 /* We didn't find it... do we still have a path? */
397 if (RemainingPath.Length)
398 {
399 /* Then tell the caller the path wasn't found */
400 Status = STATUS_OBJECT_PATH_NOT_FOUND;
401 break;
402 }
403 else if (!ExpectedObject)
404 {
405 /* Otherwise, we have a path, but the name isn't valid */
406 Status = STATUS_OBJECT_NAME_NOT_FOUND;
407 break;
408 }
409
410 /* Reference newly to be inserted object */
411 ObReferenceObject(ExpectedObject);
412 CurrentHeader = OBJECT_TO_OBJECT_HEADER(ExpectedObject);
413
414 /* Create Object Name */
415 NewName = ExAllocatePoolWithTag(NonPagedPool,
416 PartName.MaximumLength,
417 OB_NAME_TAG);
418 ObjectNameInfo = OBJECT_HEADER_TO_NAME_INFO(CurrentHeader);
419
420 /* Copy the Name */
421 RtlMoveMemory(NewName, PartName.Buffer, PartName.MaximumLength);
422
423 /* Free old name */
424 if (ObjectNameInfo->Name.Buffer) ExFreePool(ObjectNameInfo->Name.Buffer);
425
426 /* Write new one */
427 ObjectNameInfo->Name.Buffer = NewName;
428 ObjectNameInfo->Name.Length = PartName.Length;
429 ObjectNameInfo->Name.MaximumLength = PartName.MaximumLength;
430
431 /* Rereference the Directory and insert */
432 ObReferenceObject(CurrentDirectory);
433 ObpInsertEntryDirectory(CurrentDirectory, Context, CurrentHeader);
434
435 /* Return Status and the Expected Object */
436 Status = STATUS_SUCCESS;
437 CurrentObject = ExpectedObject;
438
439 /* Get out of here */
440 break;
441 }
442
443 Reparse:
444 /* We found it, so now get its header */
445 CurrentHeader = OBJECT_TO_OBJECT_HEADER(CurrentObject);
446
447 /*
448 * Check for a parse Procedure, but don't bother to parse for an insert
449 * unless it's a Symbolic Link, in which case we MUST parse
450 */
451 ParseRoutine = CurrentHeader->Type->TypeInfo.ParseProcedure;
452 if (ParseRoutine &&
453 (!ExpectedObject || ParseRoutine == ObpParseSymbolicLink))
454 {
455 /* Use the Root Directory next time */
456 InsideRoot = FALSE;
457
458 /* Call the Parse Procedure */
459 Status = ParseRoutine(CurrentObject,
460 ObjectType,
461 AccessState,
462 AccessMode,
463 Attributes,
464 ObjectName,
465 &RemainingPath,
466 ParseContext,
467 SecurityQos,
468 &CurrentObject);
469
470 /* Check if we have to reparse */
471 if ((Status == STATUS_REPARSE) ||
472 (Status == STATUS_REPARSE_OBJECT))
473 {
474 /* Start over from root if we got sent back there */
475 if ((Status == STATUS_REPARSE_OBJECT) ||
476 (ObjectName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR))
477 {
478 /* Check if we got a root directory */
479 if (RootHandle)
480 {
481 /* Stop using it, because we have a new directory now */
482 ObDereferenceObject(RootDirectory);
483 RootHandle = NULL;
484 }
485
486 /* Start at Root */
487 RootDirectory = NameSpaceRoot;
488
489 /* Check for reparse status */
490 if (Status == STATUS_REPARSE_OBJECT)
491 {
492 /* Did we actually get an object to which to reparse? */
493 if (!CurrentObject)
494 {
495 /* We didn't, so set a failure status */
496 Status = STATUS_OBJECT_NAME_NOT_FOUND;
497 }
498 else
499 {
500 /* We did, so we're free to parse the new object */
501 InsideRoot = TRUE;
502 goto Reparse;
503 }
504 }
505
506 /* Restart the search */
507 goto ReparseNewDir;
508 }
509 else if (RootDirectory == NameSpaceRoot)
510 {
511 /* We got STATUS_REPARSE but are at the Root Directory */
512 CurrentObject = NULL;
513 Status = STATUS_OBJECT_NAME_NOT_FOUND;
514 }
515 }
516 else if (!NT_SUCCESS(Status))
517 {
518 /* Total failure */
519 CurrentObject = NULL;
520 }
521 else if (!CurrentObject)
522 {
523 /* We didn't reparse but we didn't find the Object Either */
524 Status = STATUS_OBJECT_NAME_NOT_FOUND;
525 }
526
527 /* Break out of the loop */
528 break;
529 }
530 else
531 {
532 /* No parse routine...do we still have a remaining name? */
533 if (!RemainingPath.Length)
534 {
535 /* Are we creating an object? */
536 if (!ExpectedObject)
537 {
538 /* We don't... reference the Object */
539 Status = ObReferenceObjectByPointer(CurrentObject,
540 0,
541 ObjectType,
542 AccessMode);
543 if (!NT_SUCCESS(Status)) CurrentObject = NULL;
544 }
545
546 /* And get out of the reparse loop */
547 break;
548 }
549 else
550 {
551 /* We still have a name; check if this is a directory object */
552 if (CurrentHeader->Type == ObDirectoryType)
553 {
554 /* Restart from this directory */
555 CurrentDirectory = CurrentObject;
556 }
557 else
558 {
559 /* We still have a name, but no parse routine for it */
560 Status = STATUS_OBJECT_TYPE_MISMATCH;
561 CurrentObject = NULL;
562 break;
563 }
564 }
565 }
566 }
567
568 /* Write what we found, and if it's null, check if we got success */
569 if (!(*ReturnedObject = CurrentObject) && (NT_SUCCESS(Status)))
570 {
571 /* Nothing found... but we have success. Correct the status code */
572 Status = STATUS_OBJECT_NAME_NOT_FOUND;
573 }
574
575 /* Check if we had a root directory */
576 if (RootHandle)
577 {
578 /* Dereference it */
579 ObDereferenceObject(RootDirectory);
580 }
581
582 /* Return status to caller */
583 OBTRACE(OB_NAMESPACE_DEBUG,
584 "%s - Found Object: %p. Expected: %p\n",
585 __FUNCTION__,
586 *ReturnedObject,
587 ExpectedObject);
588 return Status;
589 }
590
591 /* PUBLIC FUNCTIONS *********************************************************/
592
593 NTSTATUS
594 NTAPI
595 ObQueryNameString(IN PVOID Object,
596 OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
597 IN ULONG Length,
598 OUT PULONG ReturnLength)
599 {
600 POBJECT_HEADER_NAME_INFO LocalInfo;
601 POBJECT_HEADER ObjectHeader;
602 POBJECT_DIRECTORY ParentDirectory;
603 ULONG NameSize;
604 PWCH ObjectName;
605
606 /* Get the Kernel Meta-Structures */
607 ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
608 LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
609
610 /* Check if a Query Name Procedure is available */
611 if (ObjectHeader->Type->TypeInfo.QueryNameProcedure)
612 {
613 /* Call the procedure */
614 return ObjectHeader->Type->TypeInfo.QueryNameProcedure(Object,
615 TRUE, //fixme
616 ObjectNameInfo,
617 Length,
618 ReturnLength,
619 KernelMode);
620 }
621
622 /* Check if the object doesn't even have a name */
623 if (!(LocalInfo) || !(LocalInfo->Name.Buffer))
624 {
625 /* We're returning the name structure */
626 *ReturnLength = sizeof(OBJECT_NAME_INFORMATION);
627
628 /* Check if we were given enough space */
629 if (*ReturnLength > Length) return STATUS_INFO_LENGTH_MISMATCH;
630
631 /* Return an empty buffer */
632 RtlInitEmptyUnicodeString(&ObjectNameInfo->Name, NULL, 0);
633 return STATUS_SUCCESS;
634 }
635
636 /*
637 * Find the size needed for the name. We won't do
638 * this during the Name Creation loop because we want
639 * to let the caller know that the buffer isn't big
640 * enough right at the beginning, not work our way through
641 * and find out at the end
642 */
643 if (Object == NameSpaceRoot)
644 {
645 /* Size of the '\' string */
646 NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR);
647 }
648 else
649 {
650 /* Get the Object Directory and add name of Object */
651 ParentDirectory = LocalInfo->Directory;
652 NameSize = sizeof(OBJ_NAME_PATH_SEPARATOR) + LocalInfo->Name.Length;
653
654 /* Loop inside the directory to get the top-most one (meaning root) */
655 while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
656 {
657 /* Get the Name Information */
658 LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
659 OBJECT_TO_OBJECT_HEADER(ParentDirectory));
660
661 /* Add the size of the Directory Name */
662 if (LocalInfo && LocalInfo->Directory)
663 {
664 /* Size of the '\' string + Directory Name */
665 NameSize += sizeof(OBJ_NAME_PATH_SEPARATOR) +
666 LocalInfo->Name.Length;
667
668 /* Move to next parent Directory */
669 ParentDirectory = LocalInfo->Directory;
670 }
671 else
672 {
673 /* Directory with no name. We append "...\" */
674 NameSize += sizeof(L"...") + sizeof(OBJ_NAME_PATH_SEPARATOR);
675 break;
676 }
677 }
678 }
679
680 /* Finally, add the name of the structure and the null char */
681 *ReturnLength = NameSize +
682 sizeof(OBJECT_NAME_INFORMATION) +
683 sizeof(UNICODE_NULL);
684
685 /* Check if we were given enough space */
686 if (*ReturnLength > Length) return STATUS_INFO_LENGTH_MISMATCH;
687
688 /*
689 * Now we will actually create the name. We work backwards because
690 * it's easier to start off from the Name we have and walk up the
691 * parent directories. We use the same logic as Name Length calculation.
692 */
693 LocalInfo = OBJECT_HEADER_TO_NAME_INFO(ObjectHeader);
694 ObjectName = (PWCH)((ULONG_PTR)ObjectNameInfo + *ReturnLength);
695 *--ObjectName = UNICODE_NULL;
696
697 /* Check if the object is actually the Root directory */
698 if (Object == NameSpaceRoot)
699 {
700 /* This is already the Root Directory, return "\\" */
701 *--ObjectName = OBJ_NAME_PATH_SEPARATOR;
702 ObjectNameInfo->Name.Length = (USHORT)NameSize;
703 ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
704 sizeof(UNICODE_NULL));
705 ObjectNameInfo->Name.Buffer = ObjectName;
706 return STATUS_SUCCESS;
707 }
708 else
709 {
710 /* Start by adding the Object's Name */
711 ObjectName = (PWCH)((ULONG_PTR)ObjectName -
712 LocalInfo->Name.Length);
713 RtlMoveMemory(ObjectName,
714 LocalInfo->Name.Buffer,
715 LocalInfo->Name.Length);
716
717 /* Now parse the Parent directories until we reach the top */
718 ParentDirectory = LocalInfo->Directory;
719 while ((ParentDirectory != NameSpaceRoot) && (ParentDirectory))
720 {
721 /* Get the name information */
722 LocalInfo = OBJECT_HEADER_TO_NAME_INFO(
723 OBJECT_TO_OBJECT_HEADER(ParentDirectory));
724
725 /* Add the "\" */
726 *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
727
728 /* Add the Parent Directory's Name */
729 if (LocalInfo && LocalInfo->Name.Buffer)
730 {
731 /* Add the name */
732 ObjectName = (PWCH)((ULONG_PTR)ObjectName -
733 LocalInfo->Name.Length);
734 RtlMoveMemory(ObjectName,
735 LocalInfo->Name.Buffer,
736 LocalInfo->Name.Length);
737
738 /* Move to next parent */
739 ParentDirectory = LocalInfo->Directory;
740 }
741 else
742 {
743 /* Directory without a name, we add "..." */
744 DPRINT("Nameless Directory\n");
745 ObjectName -= sizeof(L"...");
746 ObjectName = L"...";
747 break;
748 }
749 }
750
751 /* Add Root Directory Name */
752 *(--ObjectName) = OBJ_NAME_PATH_SEPARATOR;
753 ObjectNameInfo->Name.Length = (USHORT)NameSize;
754 ObjectNameInfo->Name.MaximumLength = (USHORT)(NameSize +
755 sizeof(UNICODE_NULL));
756 ObjectNameInfo->Name.Buffer = ObjectName;
757 }
758
759 /* Return success */
760 return STATUS_SUCCESS;
761 }
762
763 VOID
764 NTAPI
765 ObQueryDeviceMapInformation(IN PEPROCESS Process,
766 IN PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo)
767 {
768 //KIRQL OldIrql ;
769
770 /*
771 * FIXME: This is an ugly hack for now, to always return the System Device Map
772 * instead of returning the Process Device Map. Not important yet since we don't use it
773 */
774
775 /* FIXME: Acquire the DeviceMap Spinlock */
776 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
777
778 /* Make a copy */
779 DeviceMapInfo->Query.DriveMap = ObSystemDeviceMap->DriveMap;
780 RtlMoveMemory(DeviceMapInfo->Query.DriveType,
781 ObSystemDeviceMap->DriveType,
782 sizeof(ObSystemDeviceMap->DriveType));
783
784 /* FIXME: Release the DeviceMap Spinlock */
785 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
786 }
787
788 /* EOF */