3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ob/namespc.c
6 * PURPOSE: Manages the system namespace
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
11 /* INCLUDES ***************************************************************/
15 #include <internal/debug.h>
18 /* GLOBALS ****************************************************************/
20 POBJECT_TYPE ObDirectoryType
= NULL
;
21 POBJECT_TYPE ObTypeObjectType
= NULL
;
23 PDIRECTORY_OBJECT NameSpaceRoot
= NULL
;
24 PDIRECTORY_OBJECT ObpTypeDirectoryObject
= NULL
;
25 /* FIXME: Move this somewhere else once devicemap support is in */
26 PDEVICE_MAP ObSystemDeviceMap
= NULL
;
29 static GENERIC_MAPPING ObpDirectoryMapping
= {
30 STANDARD_RIGHTS_READ
|DIRECTORY_QUERY
|DIRECTORY_TRAVERSE
,
31 STANDARD_RIGHTS_WRITE
|DIRECTORY_CREATE_OBJECT
|DIRECTORY_CREATE_SUBDIRECTORY
,
32 STANDARD_RIGHTS_EXECUTE
|DIRECTORY_QUERY
|DIRECTORY_TRAVERSE
,
33 DIRECTORY_ALL_ACCESS
};
35 static GENERIC_MAPPING ObpTypeMapping
= {
37 STANDARD_RIGHTS_WRITE
,
38 STANDARD_RIGHTS_EXECUTE
,
43 ObpAllocateObject(POBJECT_CREATE_INFORMATION ObjectCreateInfo
,
44 PUNICODE_STRING ObjectName
,
45 POBJECT_TYPE ObjectType
,
47 POBJECT_HEADER
*ObjectHeader
);
49 /* FUNCTIONS **************************************************************/
55 ObReferenceObjectByName(PUNICODE_STRING ObjectPath
,
57 PACCESS_STATE PassedAccessState
,
58 ACCESS_MASK DesiredAccess
,
59 POBJECT_TYPE ObjectType
,
60 KPROCESSOR_MODE AccessMode
,
65 UNICODE_STRING RemainingPath
;
66 UNICODE_STRING ObjectName
;
67 OBJECT_ATTRIBUTES ObjectAttributes
;
68 OBJECT_CREATE_INFORMATION ObjectCreateInfo
;
73 InitializeObjectAttributes(&ObjectAttributes
,
75 Attributes
| OBJ_OPENIF
,
79 /* Capture all the info */
80 DPRINT("Capturing Create Info\n");
81 Status
= ObpCaptureObjectAttributes(&ObjectAttributes
,
86 if (!NT_SUCCESS(Status
))
88 DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status
);
92 Status
= ObFindObject(&ObjectCreateInfo
,
98 ObpReleaseCapturedAttributes(&ObjectCreateInfo
);
99 if (ObjectName
.Buffer
) ExFreePool(ObjectName
.Buffer
);
101 if (!NT_SUCCESS(Status
))
105 DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath
.Buffer
, Object
);
107 if (RemainingPath
.Buffer
!= NULL
|| Object
== NULL
)
109 DPRINT("Object %p\n", Object
);
111 RtlFreeUnicodeString (&RemainingPath
);
112 return(STATUS_OBJECT_NAME_NOT_FOUND
);
115 RtlFreeUnicodeString (&RemainingPath
);
116 return(STATUS_SUCCESS
);
120 /**********************************************************************
125 * Obtain a handle to an existing object.
149 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes
,
150 IN POBJECT_TYPE ObjectType
,
151 IN OUT PVOID ParseContext
,
152 IN KPROCESSOR_MODE AccessMode
,
153 IN ACCESS_MASK DesiredAccess
,
154 IN PACCESS_STATE PassedAccessState
,
157 UNICODE_STRING RemainingPath
;
159 UNICODE_STRING ObjectName
;
160 OBJECT_CREATE_INFORMATION ObjectCreateInfo
;
165 DPRINT("ObOpenObjectByName(...)\n");
167 /* Capture all the info */
168 DPRINT("Capturing Create Info\n");
169 Status
= ObpCaptureObjectAttributes(ObjectAttributes
,
174 if (!NT_SUCCESS(Status
))
176 DPRINT("ObpCaptureObjectAttributes() failed (Status %lx)\n", Status
);
180 Status
= ObFindObject(&ObjectCreateInfo
,
185 ObpReleaseCapturedAttributes(&ObjectCreateInfo
);
186 if (ObjectName
.Buffer
) ExFreePool(ObjectName
.Buffer
);
187 if (!NT_SUCCESS(Status
))
189 DPRINT("ObFindObject() failed (Status %lx)\n", Status
);
193 DPRINT("OBject: %x, Remaining Path: %wZ\n", Object
, &RemainingPath
);
196 RtlFreeUnicodeString(&RemainingPath
);
197 return STATUS_UNSUCCESSFUL
;
199 if (RemainingPath
.Buffer
!= NULL
)
201 if (wcschr(RemainingPath
.Buffer
+ 1, L
'\\') == NULL
)
202 Status
= STATUS_OBJECT_NAME_NOT_FOUND
;
204 Status
=STATUS_OBJECT_PATH_NOT_FOUND
;
205 RtlFreeUnicodeString(&RemainingPath
);
206 ObDereferenceObject(Object
);
210 Status
= ObpCreateHandle(PsGetCurrentProcess(),
216 ObDereferenceObject(Object
);
217 RtlFreeUnicodeString(&RemainingPath
);
224 ObQueryDeviceMapInformation(PEPROCESS Process
,
225 PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo
)
230 * FIXME: This is an ugly hack for now, to always return the System Device Map
231 * instead of returning the Process Device Map. Not important yet since we don't use it
234 /* FIXME: Acquire the DeviceMap Spinlock */
235 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
238 DeviceMapInfo
->Query
.DriveMap
= ObSystemDeviceMap
->DriveMap
;
239 RtlMoveMemory(DeviceMapInfo
->Query
.DriveType
, ObSystemDeviceMap
->DriveType
, sizeof(ObSystemDeviceMap
->DriveType
));
241 /* FIXME: Release the DeviceMap Spinlock */
242 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
246 ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent
,
247 POBJECT_HEADER Header
,
250 * FUNCTION: Add an entry to a namespace directory
252 * Parent = directory to add in
253 * Header = Header of the object to add the entry for
254 * Name = Name to give the entry
259 ASSERT(HEADER_TO_OBJECT_NAME(Header
));
260 HEADER_TO_OBJECT_NAME(Header
)->Directory
= Parent
;
262 KeAcquireSpinLock(&Parent
->Lock
, &oldlvl
);
263 InsertTailList(&Parent
->head
, &Header
->Entry
);
264 KeReleaseSpinLock(&Parent
->Lock
, oldlvl
);
269 ObpRemoveEntryDirectory(POBJECT_HEADER Header
)
271 * FUNCTION: Remove an entry from a namespace directory
273 * Header = Header of the object to remove
278 DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header
);
280 KeAcquireSpinLock(&(HEADER_TO_OBJECT_NAME(Header
)->Directory
->Lock
),&oldlvl
);
281 if (Header
->Entry
.Flink
&& Header
->Entry
.Blink
)
283 RemoveEntryList(&(Header
->Entry
));
284 Header
->Entry
.Flink
= Header
->Entry
.Blink
= NULL
;
286 KeReleaseSpinLock(&(HEADER_TO_OBJECT_NAME(Header
)->Directory
->Lock
),oldlvl
);
291 ObpCreateDirectory(OB_OPEN_REASON Reason
,
295 ACCESS_MASK GrantedAccess
)
297 PDIRECTORY_OBJECT Directory
= ObjectBody
;
299 if (Reason
== ObCreateHandle
)
301 InitializeListHead(&Directory
->head
);
302 KeInitializeSpinLock(&Directory
->Lock
);
305 return STATUS_SUCCESS
;
309 ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject
,
313 PLIST_ENTRY current
= DirectoryObject
->head
.Flink
;
314 POBJECT_HEADER current_obj
;
316 DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject
, Name
);
320 return(DirectoryObject
);
322 if (Name
[0]=='.' && Name
[1]==0)
324 return(DirectoryObject
);
326 if (Name
[0]=='.' && Name
[1]=='.' && Name
[2]==0)
328 return(HEADER_TO_OBJECT_NAME(BODY_TO_HEADER(DirectoryObject
))->Directory
);
330 while (current
!=(&(DirectoryObject
->head
)))
332 current_obj
= CONTAINING_RECORD(current
,OBJECT_HEADER
,Entry
);
333 DPRINT(" Scanning: %S for: %S\n",HEADER_TO_OBJECT_NAME(current_obj
)->Name
.Buffer
, Name
);
334 if (Attributes
& OBJ_CASE_INSENSITIVE
)
336 if (_wcsicmp(HEADER_TO_OBJECT_NAME(current_obj
)->Name
.Buffer
, Name
)==0)
338 DPRINT("Found it %x\n",¤t_obj
->Body
);
339 return(¤t_obj
->Body
);
344 if ( wcscmp(HEADER_TO_OBJECT_NAME(current_obj
)->Name
.Buffer
, Name
)==0)
346 DPRINT("Found it %x\n",¤t_obj
->Body
);
347 return(¤t_obj
->Body
);
350 current
= current
->Flink
;
352 DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__
);
358 ObpParseDirectory(PVOID Object
,
360 PUNICODE_STRING FullPath
,
369 DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
376 return STATUS_UNSUCCESSFUL
;
383 End
= wcschr(Start
, L
'\\');
389 KeAcquireSpinLock(&(((PDIRECTORY_OBJECT
)Object
)->Lock
), &oldlvl
);
390 FoundObject
= ObpFindEntryDirectory(Object
, Start
, Attributes
);
391 if (FoundObject
== NULL
)
393 KeReleaseSpinLock(&(((PDIRECTORY_OBJECT
)Object
)->Lock
), oldlvl
);
398 return STATUS_UNSUCCESSFUL
;
401 ObReferenceObjectByPointer(FoundObject
,
402 STANDARD_RIGHTS_REQUIRED
,
405 KeReleaseSpinLock(&(((PDIRECTORY_OBJECT
)Object
)->Lock
), oldlvl
);
416 *NextObject
= FoundObject
;
418 return STATUS_SUCCESS
;
425 OBJECT_ATTRIBUTES ObjectAttributes
;
427 SECURITY_DESCRIPTOR SecurityDescriptor
;
428 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer
;
430 /* Initialize the security descriptor cache */
433 /* Create the Type Type */
434 DPRINT("Creating Type Type\n");
435 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
436 RtlInitUnicodeString(&Name
, L
"Type");
437 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
438 ObjectTypeInitializer
.ValidAccessMask
= OBJECT_TYPE_ALL_ACCESS
;
439 ObjectTypeInitializer
.UseDefaultObject
= TRUE
;
440 ObjectTypeInitializer
.MaintainTypeList
= TRUE
;
441 ObjectTypeInitializer
.PoolType
= NonPagedPool
;
442 ObjectTypeInitializer
.GenericMapping
= ObpTypeMapping
;
443 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(OBJECT_TYPE
);
444 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &ObTypeObjectType
);
446 /* Create the Directory Type */
447 DPRINT("Creating Directory Type\n");
448 RtlZeroMemory(&ObjectTypeInitializer
, sizeof(ObjectTypeInitializer
));
449 RtlInitUnicodeString(&Name
, L
"Directory");
450 ObjectTypeInitializer
.Length
= sizeof(ObjectTypeInitializer
);
451 ObjectTypeInitializer
.ValidAccessMask
= DIRECTORY_ALL_ACCESS
;
452 ObjectTypeInitializer
.UseDefaultObject
= FALSE
;
453 ObjectTypeInitializer
.OpenProcedure
= ObpCreateDirectory
;
454 ObjectTypeInitializer
.ParseProcedure
= ObpParseDirectory
;
455 ObjectTypeInitializer
.MaintainTypeList
= FALSE
;
456 ObjectTypeInitializer
.GenericMapping
= ObpDirectoryMapping
;
457 ObjectTypeInitializer
.DefaultNonPagedPoolCharge
= sizeof(DIRECTORY_OBJECT
);
458 ObpCreateTypeObject(&ObjectTypeInitializer
, &Name
, &ObDirectoryType
);
460 /* Create security descriptor */
461 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
462 SECURITY_DESCRIPTOR_REVISION1
);
463 RtlSetOwnerSecurityDescriptor(&SecurityDescriptor
,
466 RtlSetGroupSecurityDescriptor(&SecurityDescriptor
,
469 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
,
474 /* Create root directory */
475 DPRINT("Creating Root Directory\n");
476 InitializeObjectAttributes(&ObjectAttributes
,
480 &SecurityDescriptor
);
481 ObCreateObject(KernelMode
,
486 sizeof(DIRECTORY_OBJECT
),
489 (PVOID
*)&NameSpaceRoot
);
490 ObInsertObject((PVOID
)NameSpaceRoot
,
492 DIRECTORY_ALL_ACCESS
,
497 /* Create '\ObjectTypes' directory */
498 RtlInitUnicodeString(&Name
, L
"\\ObjectTypes");
499 InitializeObjectAttributes(&ObjectAttributes
,
503 &SecurityDescriptor
);
504 ObCreateObject(KernelMode
,
509 sizeof(DIRECTORY_OBJECT
),
512 (PVOID
*)&ObpTypeDirectoryObject
);
513 ObInsertObject((PVOID
)ObpTypeDirectoryObject
,
515 DIRECTORY_ALL_ACCESS
,
520 /* Insert the two objects we already created but couldn't add */
521 /* NOTE: Uses TypeList & Creator Info in OB 2.0 */
522 ObpAddEntryDirectory(ObpTypeDirectoryObject
, BODY_TO_HEADER(ObTypeObjectType
), NULL
);
523 ObpAddEntryDirectory(ObpTypeDirectoryObject
, BODY_TO_HEADER(ObDirectoryType
), NULL
);
525 /* Create 'symbolic link' object type */
526 ObInitSymbolicLinkImplementation();
528 /* FIXME: Hack Hack! */
529 ObSystemDeviceMap
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*ObSystemDeviceMap
), TAG('O', 'b', 'D', 'm'));
530 RtlZeroMemory(ObSystemDeviceMap
, sizeof(*ObSystemDeviceMap
));
535 ObpCreateTypeObject(POBJECT_TYPE_INITIALIZER ObjectTypeInitializer
,
536 PUNICODE_STRING TypeName
,
537 POBJECT_TYPE
*ObjectType
)
539 POBJECT_HEADER Header
;
540 POBJECT_TYPE LocalObjectType
;
543 DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", TypeName
);
545 /* Allocate the Object */
546 Status
= ObpAllocateObject(NULL
,
549 OBJECT_ALLOC_SIZE(sizeof(OBJECT_TYPE
)),
551 if (!NT_SUCCESS(Status
))
553 DPRINT1("ObpAllocateObject failed!\n");
557 LocalObjectType
= (POBJECT_TYPE
)&Header
->Body
;
558 DPRINT("Local ObjectType: %p Header: %p \n", LocalObjectType
, Header
);
560 /* Check if this is the first Object Type */
561 if (!ObTypeObjectType
)
563 ObTypeObjectType
= LocalObjectType
;
564 Header
->Type
= ObTypeObjectType
;
565 LocalObjectType
->Key
= TAG('O', 'b', 'j', 'T');
570 Tag
[0] = TypeName
->Buffer
[0];
571 Tag
[1] = TypeName
->Buffer
[1];
572 Tag
[2] = TypeName
->Buffer
[2];
573 Tag
[3] = TypeName
->Buffer
[3];
576 DPRINT("Convert: %s \n", Tag
);
577 LocalObjectType
->Key
= *(PULONG
)Tag
;
581 LocalObjectType
->TypeInfo
= *ObjectTypeInitializer
;
582 LocalObjectType
->Name
= *TypeName
;
584 /* Insert it into the Object Directory */
585 if (ObpTypeDirectoryObject
)
587 ObpAddEntryDirectory(ObpTypeDirectoryObject
, Header
, TypeName
->Buffer
);
588 ObReferenceObject(ObpTypeDirectoryObject
);
591 *ObjectType
= LocalObjectType
;