1 /* $Id: namespc.c,v 1.50 2004/11/21 10:59:10 weiden Exp $
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
7 * PROGRAMMER: David Welch (welch@mcmail.com)
12 /* INCLUDES ***************************************************************/
16 #include <internal/debug.h>
19 /* GLOBALS ****************************************************************/
21 POBJECT_TYPE ObDirectoryType
= NULL
;
22 POBJECT_TYPE ObTypeObjectType
= NULL
;
24 PDIRECTORY_OBJECT NameSpaceRoot
= NULL
;
25 /* FIXME: Move this somewhere else once devicemap support is in */
26 PDEVICE_MAP ObSystemDeviceMap
= NULL
;
28 static GENERIC_MAPPING ObpDirectoryMapping
= {
29 STANDARD_RIGHTS_READ
|DIRECTORY_QUERY
|DIRECTORY_TRAVERSE
,
30 STANDARD_RIGHTS_WRITE
|DIRECTORY_CREATE_OBJECT
|DIRECTORY_CREATE_SUBDIRECTORY
,
31 STANDARD_RIGHTS_EXECUTE
|DIRECTORY_QUERY
|DIRECTORY_TRAVERSE
,
32 DIRECTORY_ALL_ACCESS
};
34 static GENERIC_MAPPING ObpTypeMapping
= {
36 STANDARD_RIGHTS_WRITE
,
37 STANDARD_RIGHTS_EXECUTE
,
40 /* FUNCTIONS **************************************************************/
46 ObReferenceObjectByName(PUNICODE_STRING ObjectPath
,
48 PACCESS_STATE PassedAccessState
,
49 ACCESS_MASK DesiredAccess
,
50 POBJECT_TYPE ObjectType
,
51 KPROCESSOR_MODE AccessMode
,
56 UNICODE_STRING RemainingPath
;
57 OBJECT_ATTRIBUTES ObjectAttributes
;
60 InitializeObjectAttributes(&ObjectAttributes
,
65 Status
= ObFindObject(&ObjectAttributes
,
69 if (!NT_SUCCESS(Status
))
74 DPRINT("RemainingPath.Buffer '%S' Object %p\n", RemainingPath
.Buffer
, Object
);
76 if (RemainingPath
.Buffer
!= NULL
|| Object
== NULL
)
79 DPRINT("Object %p\n", Object
);
81 RtlFreeUnicodeString (&RemainingPath
);
82 return(STATUS_OBJECT_NAME_NOT_FOUND
);
85 RtlFreeUnicodeString (&RemainingPath
);
86 return(STATUS_SUCCESS
);
90 /**********************************************************************
95 * Obtain a handle to an existing object.
119 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes
,
120 IN POBJECT_TYPE ObjectType
,
121 IN OUT PVOID ParseContext
,
122 IN KPROCESSOR_MODE AccessMode
,
123 IN ACCESS_MASK DesiredAccess
,
124 IN PACCESS_STATE PassedAccessState
,
127 UNICODE_STRING RemainingPath
;
131 DPRINT("ObOpenObjectByName(...)\n");
133 Status
= ObFindObject(ObjectAttributes
,
137 if (!NT_SUCCESS(Status
))
139 DPRINT("ObFindObject() failed (Status %lx)\n", Status
);
143 if (RemainingPath
.Buffer
!= NULL
||
146 RtlFreeUnicodeString(&RemainingPath
);
147 return STATUS_UNSUCCESSFUL
;
150 Status
= ObCreateHandle(PsGetCurrentProcess(),
156 ObDereferenceObject(Object
);
157 RtlFreeUnicodeString(&RemainingPath
);
164 ObQueryDeviceMapInformation(PEPROCESS Process
,
165 PPROCESS_DEVICEMAP_INFORMATION DeviceMapInfo
)
170 * FIXME: This is an ugly hack for now, to always return the System Device Map
171 * instead of returning the Process Device Map. Not important yet since we don't use it
174 /* FIXME: Acquire the DeviceMap Spinlock */
175 // KeAcquireSpinLock(DeviceMap->Lock, &OldIrql);
178 DeviceMapInfo
->Query
.DriveMap
= ObSystemDeviceMap
->DriveMap
;
179 RtlMoveMemory(DeviceMapInfo
->Query
.DriveType
, ObSystemDeviceMap
->DriveType
, sizeof(ObSystemDeviceMap
->DriveType
));
181 /* FIXME: Release the DeviceMap Spinlock */
182 // KeReleasepinLock(DeviceMap->Lock, OldIrql);
186 ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent
,
187 POBJECT_HEADER Header
,
190 * FUNCTION: Add an entry to a namespace directory
192 * Parent = directory to add in
193 * Header = Header of the object to add the entry for
194 * Name = Name to give the entry
199 RtlCreateUnicodeString(&Header
->Name
, Name
);
200 Header
->Parent
= Parent
;
202 KeAcquireSpinLock(&Parent
->Lock
, &oldlvl
);
203 InsertTailList(&Parent
->head
, &Header
->Entry
);
204 KeReleaseSpinLock(&Parent
->Lock
, oldlvl
);
209 ObpRemoveEntryDirectory(POBJECT_HEADER Header
)
211 * FUNCTION: Remove an entry from a namespace directory
213 * Header = Header of the object to remove
218 DPRINT("ObpRemoveEntryDirectory(Header %x)\n",Header
);
220 KeAcquireSpinLock(&(Header
->Parent
->Lock
),&oldlvl
);
221 RemoveEntryList(&(Header
->Entry
));
222 KeReleaseSpinLock(&(Header
->Parent
->Lock
),oldlvl
);
227 ObpFindEntryDirectory(PDIRECTORY_OBJECT DirectoryObject
,
231 PLIST_ENTRY current
= DirectoryObject
->head
.Flink
;
232 POBJECT_HEADER current_obj
;
234 DPRINT("ObFindEntryDirectory(dir %x, name %S)\n",DirectoryObject
, Name
);
238 return(DirectoryObject
);
240 if (Name
[0]=='.' && Name
[1]==0)
242 return(DirectoryObject
);
244 if (Name
[0]=='.' && Name
[1]=='.' && Name
[2]==0)
246 return(BODY_TO_HEADER(DirectoryObject
)->Parent
);
248 while (current
!=(&(DirectoryObject
->head
)))
250 current_obj
= CONTAINING_RECORD(current
,OBJECT_HEADER
,Entry
);
251 DPRINT(" Scanning: %S for: %S\n",current_obj
->Name
.Buffer
, Name
);
252 if (Attributes
& OBJ_CASE_INSENSITIVE
)
254 if (_wcsicmp(current_obj
->Name
.Buffer
, Name
)==0)
256 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj
));
257 return(HEADER_TO_BODY(current_obj
));
262 if ( wcscmp(current_obj
->Name
.Buffer
, Name
)==0)
264 DPRINT("Found it %x\n",HEADER_TO_BODY(current_obj
));
265 return(HEADER_TO_BODY(current_obj
));
268 current
= current
->Flink
;
270 DPRINT(" Not Found: %s() = NULL\n",__FUNCTION__
);
276 ObpParseDirectory(PVOID Object
,
278 PUNICODE_STRING FullPath
,
286 DPRINT("ObpParseDirectory(Object %x, Path %x, *Path %S)\n",
293 return STATUS_UNSUCCESSFUL
;
300 End
= wcschr(Start
, L
'\\');
306 FoundObject
= ObpFindEntryDirectory(Object
, Start
, Attributes
);
307 if (FoundObject
== NULL
)
313 return STATUS_UNSUCCESSFUL
;
316 ObReferenceObjectByPointer(FoundObject
,
317 STANDARD_RIGHTS_REQUIRED
,
331 *NextObject
= FoundObject
;
333 return STATUS_SUCCESS
;
338 ObpCreateDirectory(PVOID ObjectBody
,
341 POBJECT_ATTRIBUTES ObjectAttributes
)
343 PDIRECTORY_OBJECT DirectoryObject
= (PDIRECTORY_OBJECT
)ObjectBody
;
345 DPRINT("ObpCreateDirectory(ObjectBody %x, Parent %x, RemainingPath %S)\n",
346 ObjectBody
, Parent
, RemainingPath
);
348 if (RemainingPath
!= NULL
&& wcschr(RemainingPath
+1, '\\') != NULL
)
350 return(STATUS_UNSUCCESSFUL
);
353 InitializeListHead(&DirectoryObject
->head
);
354 KeInitializeSpinLock(&DirectoryObject
->Lock
);
356 return(STATUS_SUCCESS
);
363 * FUNCTION: Initialize the object manager namespace
366 OBJECT_ATTRIBUTES ObjectAttributes
;
368 SECURITY_DESCRIPTOR SecurityDescriptor
;
370 /* Initialize the security descriptor cache */
373 /* create 'directory' object type */
374 ObDirectoryType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
376 ObDirectoryType
->Tag
= TAG('D', 'I', 'R', 'T');
377 ObDirectoryType
->TotalObjects
= 0;
378 ObDirectoryType
->TotalHandles
= 0;
379 ObDirectoryType
->MaxObjects
= ULONG_MAX
;
380 ObDirectoryType
->MaxHandles
= ULONG_MAX
;
381 ObDirectoryType
->PagedPoolCharge
= 0;
382 ObDirectoryType
->NonpagedPoolCharge
= sizeof(DIRECTORY_OBJECT
);
383 ObDirectoryType
->Mapping
= &ObpDirectoryMapping
;
384 ObDirectoryType
->Dump
= NULL
;
385 ObDirectoryType
->Open
= NULL
;
386 ObDirectoryType
->Close
= NULL
;
387 ObDirectoryType
->Delete
= NULL
;
388 ObDirectoryType
->Parse
= ObpParseDirectory
;
389 ObDirectoryType
->Security
= NULL
;
390 ObDirectoryType
->QueryName
= NULL
;
391 ObDirectoryType
->OkayToClose
= NULL
;
392 ObDirectoryType
->Create
= ObpCreateDirectory
;
393 ObDirectoryType
->DuplicationNotify
= NULL
;
395 RtlRosInitUnicodeStringFromLiteral(&ObDirectoryType
->TypeName
,
398 /* create 'type' object type*/
399 ObTypeObjectType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
401 ObTypeObjectType
->Tag
= TAG('T', 'y', 'p', 'T');
402 ObTypeObjectType
->TotalObjects
= 0;
403 ObTypeObjectType
->TotalHandles
= 0;
404 ObTypeObjectType
->MaxObjects
= ULONG_MAX
;
405 ObTypeObjectType
->MaxHandles
= ULONG_MAX
;
406 ObTypeObjectType
->PagedPoolCharge
= 0;
407 ObTypeObjectType
->NonpagedPoolCharge
= sizeof(TYPE_OBJECT
);
408 ObTypeObjectType
->Mapping
= &ObpTypeMapping
;
409 ObTypeObjectType
->Dump
= NULL
;
410 ObTypeObjectType
->Open
= NULL
;
411 ObTypeObjectType
->Close
= NULL
;
412 ObTypeObjectType
->Delete
= NULL
;
413 ObTypeObjectType
->Parse
= NULL
;
414 ObTypeObjectType
->Security
= NULL
;
415 ObTypeObjectType
->QueryName
= NULL
;
416 ObTypeObjectType
->OkayToClose
= NULL
;
417 ObTypeObjectType
->Create
= NULL
;
418 ObTypeObjectType
->DuplicationNotify
= NULL
;
420 RtlRosInitUnicodeStringFromLiteral(&ObTypeObjectType
->TypeName
,
423 /* Create security descriptor */
424 RtlCreateSecurityDescriptor(&SecurityDescriptor
,
425 SECURITY_DESCRIPTOR_REVISION1
);
427 RtlSetOwnerSecurityDescriptor(&SecurityDescriptor
,
431 RtlSetGroupSecurityDescriptor(&SecurityDescriptor
,
435 RtlSetDaclSecurityDescriptor(&SecurityDescriptor
,
440 /* Create root directory */
441 InitializeObjectAttributes(&ObjectAttributes
,
445 &SecurityDescriptor
);
446 ObCreateObject(KernelMode
,
451 sizeof(DIRECTORY_OBJECT
),
454 (PVOID
*)&NameSpaceRoot
);
456 /* Create '\ObjectTypes' directory */
457 RtlRosInitUnicodeStringFromLiteral(&Name
,
459 InitializeObjectAttributes(&ObjectAttributes
,
463 &SecurityDescriptor
);
464 ObCreateObject(KernelMode
,
469 sizeof(DIRECTORY_OBJECT
),
474 ObpCreateTypeObject(ObDirectoryType
);
475 ObpCreateTypeObject(ObTypeObjectType
);
477 /* Create 'symbolic link' object type */
478 ObInitSymbolicLinkImplementation();
480 /* FIXME: Hack Hack! */
481 ObSystemDeviceMap
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(*ObSystemDeviceMap
), TAG('O', 'b', 'D', 'm'));
482 RtlZeroMemory(ObSystemDeviceMap
, sizeof(*ObSystemDeviceMap
));
487 ObpCreateTypeObject(POBJECT_TYPE ObjectType
)
489 OBJECT_ATTRIBUTES ObjectAttributes
;
490 WCHAR NameString
[120];
491 PTYPE_OBJECT TypeObject
= NULL
;
495 DPRINT("ObpCreateTypeObject(ObjectType: %wZ)\n", &ObjectType
->TypeName
);
496 wcscpy(NameString
, L
"\\ObjectTypes\\");
497 wcscat(NameString
, ObjectType
->TypeName
.Buffer
);
498 RtlInitUnicodeString(&Name
,
501 InitializeObjectAttributes(&ObjectAttributes
,
506 Status
= ObCreateObject(KernelMode
,
514 (PVOID
*)&TypeObject
);
515 if (NT_SUCCESS(Status
))
517 TypeObject
->ObjectType
= ObjectType
;
520 return(STATUS_SUCCESS
);