2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ob/namespc.c
5 * PURPOSE: Manages the system namespace
6 * PROGRAMMER: David Welch (welch@mcmail.com)
11 /* INCLUDES ***************************************************************/
15 #include <ddk/ntddk.h>
16 #include <internal/ob.h>
17 #include <internal/io.h>
18 #include <internal/string.h>
21 #include <internal/debug.h>
23 /* GLOBALS ****************************************************************/
25 POBJECT_TYPE ObDirectoryType
= NULL
;
30 // DIRECTORY_OBJECT directory;
33 } namespc_root
= {{0,},};
35 /* FUNCTIONS **************************************************************/
37 NTSTATUS
NtOpenDirectoryObject(PHANDLE DirectoryHandle
,
38 ACCESS_MASK DesiredAccess
,
39 POBJECT_ATTRIBUTES ObjectAttributes
)
41 return(ZwOpenDirectoryObject(DirectoryHandle
,
46 NTSTATUS
ZwOpenDirectoryObject(PHANDLE DirectoryHandle
,
47 ACCESS_MASK DesiredAccess
,
48 POBJECT_ATTRIBUTES ObjectAttributes
)
50 * FUNCTION: Opens a namespace directory object
52 * DirectoryHandle (OUT) = Variable which receives the directory handle
53 * DesiredAccess = Desired access to the directory
54 * ObjectAttributes = Structure describing the directory
65 Status
= ObOpenObjectByName(ObjectAttributes
,&Object
,&Ignored
);
66 if (!NT_SUCCESS(Status
))
71 if (BODY_TO_HEADER(Object
)->Type
!=OBJTYP_DIRECTORY
)
73 return(STATUS_UNSUCCESSFUL
);
76 *DirectoryHandle
= ObInsertHandle(KeGetCurrentProcess(),Object
,
79 return(STATUS_SUCCESS
);
82 NTSTATUS
NtQueryDirectoryObject(IN HANDLE DirObjHandle
,
83 OUT POBJDIR_INFORMATION DirObjInformation
,
84 IN ULONG BufferLength
,
85 IN BOOLEAN GetNextIndex
,
86 IN BOOLEAN IgnoreInputIndex
,
87 IN OUT PULONG ObjectIndex
,
88 OUT PULONG DataWritten OPTIONAL
)
90 return(ZwQueryDirectoryObject(DirObjHandle
,
99 NTSTATUS
ZwQueryDirectoryObject(IN HANDLE DirObjHandle
,
100 OUT POBJDIR_INFORMATION DirObjInformation
,
101 IN ULONG BufferLength
,
102 IN BOOLEAN GetNextIndex
,
103 IN BOOLEAN IgnoreInputIndex
,
104 IN OUT PULONG ObjectIndex
,
105 OUT PULONG DataWritten OPTIONAL
)
107 * FUNCTION: Reads information from a namespace directory
109 * DirObjInformation (OUT) = Buffer to hold the data read
110 * BufferLength = Size of the buffer in bytes
111 * GetNextIndex = If TRUE then set ObjectIndex to the index of the
113 * If FALSE then set ObjectIndex to the number of
114 * objects in the directory
115 * IgnoreInputIndex = If TRUE start reading at index 0
116 * If FALSE start reading at the index specified
118 * ObjectIndex = Zero based index into the directory, interpretation
119 * depends on IgnoreInputIndex and GetNextIndex
120 * DataWritten (OUT) = Caller supplied storage for the number of bytes
125 PDIRECTORY_OBJECT dir
= NULL
;
127 PLIST_ENTRY current_entry
;
128 POBJECT_HEADER current
;
133 DPRINT("ZwQueryDirectoryObject(DirObjHandle %x)\n",DirObjHandle
);
134 DPRINT("dir %x namespc_root %x\n",dir
,HEADER_TO_BODY(&(namespc_root
.hdr
)));
136 // assert_irql(PASSIVE_LEVEL);
138 Status
= ObReferenceObjectByHandle(DirObjHandle
,
144 if (Status
!= STATUS_SUCCESS
)
149 EntriesToRead
= BufferLength
/ sizeof(OBJDIR_INFORMATION
);
152 DPRINT("EntriesToRead %d\n",EntriesToRead
);
154 current_entry
= dir
->head
.Flink
;
157 * Optionally, skip over some entries at the start of the directory
159 if (!IgnoreInputIndex
)
163 EntriesToSkip
= *ObjectIndex
;
164 while ( i
<EntriesToSkip
&& current_entry
!=NULL
)
166 current_entry
= current_entry
->Flink
;
170 DPRINT("DirObjInformation %x\n",DirObjInformation
);
173 * Read the maximum entries possible into the buffer
175 while ( i
<EntriesToRead
&& current_entry
!=(&(dir
->head
)))
177 current
= CONTAINING_RECORD(current_entry
,OBJECT_HEADER
,Entry
);
178 DPRINT("Scanning %w\n",current
->Name
.Buffer
);
179 DirObjInformation
[i
].ObjectName
.Buffer
=
180 ExAllocatePool(NonPagedPool
,(current
->Name
.Length
+1)*2);
181 DirObjInformation
[i
].ObjectName
.Length
= current
->Name
.Length
;
182 DirObjInformation
[i
].ObjectName
.MaximumLength
= current
->Name
.Length
;
183 DPRINT("DirObjInformation[i].ObjectName.Buffer %x\n",
184 DirObjInformation
[i
].ObjectName
.Buffer
);
185 RtlCopyUnicodeString(&DirObjInformation
[i
].ObjectName
,
188 current_entry
= current_entry
->Flink
;
189 (*DataWritten
) = (*DataWritten
) + sizeof(OBJDIR_INFORMATION
);
195 * Optionally, count the number of entries in the directory
203 while ( current_entry
!=(&(dir
->head
)) )
205 current_entry
=current_entry
->Flink
;
210 return(STATUS_SUCCESS
);
214 NTSTATUS
ObReferenceObjectByName(PUNICODE_STRING ObjectPath
,
216 PACCESS_STATE PassedAccessState
,
217 ACCESS_MASK DesiredAccess
,
218 POBJECT_TYPE ObjectType
,
219 KPROCESSOR_MODE AccessMode
,
226 NTSTATUS
ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes
,
227 PVOID
* Object
, PWSTR
* UnparsedSection
)
231 DPRINT("ObOpenObjectByName(ObjectAttributes %x, Object %x)\n",
232 ObjectAttributes
,Object
);
233 DPRINT("ObjectAttributes = {ObjectName %x ObjectName->Buffer %w}\n",
234 ObjectAttributes
->ObjectName
,ObjectAttributes
->ObjectName
->Buffer
);
235 DPRINT("ObjectAttributes->ObjectName->Length %d\n",
236 ObjectAttributes
->ObjectName
->Length
);
239 Status
= ObLookupObject(ObjectAttributes
->RootDirectory
,
240 ObjectAttributes
->ObjectName
->Buffer
,
243 DPRINT("*Object %x\n",*Object
);
244 DPRINT("ObjectAttributes->ObjectName->Length %d\n",
245 ObjectAttributes
->ObjectName
->Length
);
251 * FUNCTION: Initialize the object manager namespace
254 ANSI_STRING AnsiString
;
256 ObDirectoryType
= ExAllocatePool(NonPagedPool
,sizeof(OBJECT_TYPE
));
258 ObDirectoryType
->TotalObjects
= 0;
259 ObDirectoryType
->TotalHandles
= 0;
260 ObDirectoryType
->MaxObjects
= ULONG_MAX
;
261 ObDirectoryType
->MaxHandles
= ULONG_MAX
;
262 ObDirectoryType
->PagedPoolCharge
= 0;
263 ObDirectoryType
->NonpagedPoolCharge
= sizeof(DIRECTORY_OBJECT
);
264 ObDirectoryType
->Dump
= NULL
;
265 ObDirectoryType
->Open
= NULL
;
266 ObDirectoryType
->Close
= NULL
;
267 ObDirectoryType
->Delete
= NULL
;
268 ObDirectoryType
->Parse
= NULL
;
269 ObDirectoryType
->Security
= NULL
;
270 ObDirectoryType
->QueryName
= NULL
;
271 ObDirectoryType
->OkayToClose
= NULL
;
273 RtlInitAnsiString(&AnsiString
,"Directory");
274 RtlAnsiStringToUnicodeString(&ObDirectoryType
->TypeName
,
277 ObInitializeObjectHeader(ObDirectoryType
,NULL
,&namespc_root
.hdr
);
278 InitializeListHead(&namespc_root
.head
);
281 NTSTATUS
NtCreateDirectoryObject(PHANDLE DirectoryHandle
,
282 ACCESS_MASK DesiredAccess
,
283 POBJECT_ATTRIBUTES ObjectAttributes
)
285 return(ZwCreateDirectoryObject(DirectoryHandle
,
290 NTSTATUS
ZwCreateDirectoryObject(PHANDLE DirectoryHandle
,
291 ACCESS_MASK DesiredAccess
,
292 POBJECT_ATTRIBUTES ObjectAttributes
)
294 * FUNCTION: Creates or opens a directory object (a container for other
297 * DirectoryHandle (OUT) = Caller supplied storage for the handle
299 * DesiredAccess = Access desired to the directory
300 * ObjectAttributes = Object attributes initialized with
301 * InitializeObjectAttributes
305 PDIRECTORY_OBJECT dir
;
307 dir
= ObGenericCreateObject(DirectoryHandle
,DesiredAccess
,ObjectAttributes
,
311 * Initialize the object body
313 InitializeListHead(&dir
->head
);
314 KeInitializeSpinLock(&(dir
->Lock
));
316 return(STATUS_SUCCESS
);
319 VOID
InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes
,
320 PUNICODE_STRING ObjectName
,
322 HANDLE RootDirectory
,
323 PSECURITY_DESCRIPTOR SecurityDescriptor
)
325 * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a
326 * subsequent call to ZwCreateXXX or ZwOpenXXX
328 * InitializedAttributes (OUT) = Caller supplied storage for the
330 * ObjectName = Full path name for object
331 * Attributes = Attributes for the object
332 * RootDirectory = Where the object should be placed or NULL
333 * SecurityDescriptor = Ignored
336 * Either ObjectName is a fully qualified pathname or a path relative
340 DPRINT("InitializeObjectAttributes(InitializedAttributes %x "
341 "ObjectName %x Attributes %x RootDirectory %x)\n",
342 InitializedAttributes
,ObjectName
,Attributes
,RootDirectory
);
343 InitializedAttributes
->Length
=sizeof(OBJECT_ATTRIBUTES
);
344 InitializedAttributes
->RootDirectory
=RootDirectory
;
345 InitializedAttributes
->ObjectName
=ObjectName
;
346 InitializedAttributes
->Attributes
=Attributes
;
347 InitializedAttributes
->SecurityDescriptor
=SecurityDescriptor
;
348 InitializedAttributes
->SecurityQualityOfService
=NULL
;
351 static PVOID
ObDirLookup(PDIRECTORY_OBJECT dir
, PWSTR name
)
353 * FUNCTION: Looks up an entry within a namespace directory
355 * dir = Directory to lookup in
356 * name = Entry name to find
357 * RETURNS: A pointer to the object body if found
361 LIST_ENTRY
* current
= dir
->head
.Flink
;
362 POBJECT_HEADER current_obj
;
364 DPRINT("ObDirLookup(dir %x, name %w)\n",dir
,name
);
370 if (name
[0]=='.'&&name
[1]==0)
374 if (name
[0]=='.'&&name
[1]=='.'&&name
[2]==0)
376 return(BODY_TO_HEADER(dir
)->Parent
);
378 while (current
!=(&(dir
->head
)))
380 current_obj
= CONTAINING_RECORD(current
,OBJECT_HEADER
,Entry
);
381 DPRINT("Scanning %w\n",current_obj
->Name
.Buffer
);
382 if ( wcscmp(current_obj
->Name
.Buffer
, name
)==0)
384 return(HEADER_TO_BODY(current_obj
));
386 current
= current
->Flink
;
388 DPRINT("%s() = NULL\n",__FUNCTION__
);
392 VOID
ObRemoveEntry(POBJECT_HEADER Header
)
396 DPRINT("ObRemoveEntry(Header %x)\n",Header
);
398 KeAcquireSpinLock(&(Header
->Parent
->Lock
),&oldlvl
);
399 RemoveEntryList(&(Header
->Entry
));
400 KeReleaseSpinLock(&(Header
->Parent
->Lock
),oldlvl
);
403 VOID
ObCreateEntry(PDIRECTORY_OBJECT parent
,POBJECT_HEADER Object
)
405 * FUNCTION: Add an entry to a namespace directory
407 * parent = directory to add in
408 * name = Name to give the entry
409 * Object = Header of the object to add the entry for
412 DPRINT("ObjCreateEntry(%x,%x,%x,%w)\n",parent
,Object
,Object
->Name
.Buffer
,
413 Object
->Name
.Buffer
);
416 * Insert ourselves in our parents list
418 InsertTailList(&parent
->head
,&Object
->Entry
);
421 NTSTATUS
ObLookupObject(HANDLE rootdir
, PWSTR string
, PVOID
* Object
,
422 PWSTR
* UnparsedSection
)
424 * FUNCTION: Lookup an object within the system namespc
426 * root = Directory to start lookup from
427 * _string = Pathname to lookup
428 * RETURNS: On success a pointer to the object body
434 PDIRECTORY_OBJECT current_dir
= NULL
;
437 DPRINT("ObLookupObject(rootdir %x, string %x, string %w, Object %x, "
438 "UnparsedSection %x)\n",rootdir
,string
,string
,Object
,
442 *UnparsedSection
= NULL
;
447 current_dir
= HEADER_TO_BODY(&(namespc_root
.hdr
));
451 ObReferenceObjectByHandle(rootdir
,DIRECTORY_TRAVERSE
,NULL
,
452 UserMode
,(PVOID
*)¤t_dir
,NULL
);
461 return(STATUS_SUCCESS
);
466 DbgPrint("(%s:%d) Non absolute pathname passed to %s\n",__FILE__
,
467 __LINE__
,__FUNCTION__
);
468 return(STATUS_UNSUCCESSFUL
);
475 BODY_TO_HEADER(current_dir
)->ObjectType
==ObDirectoryType
)
479 next
= wcschr(next
+1,'\\');
485 DPRINT("current %w current[5] %x next %x ",current
,current
[5],next
);
488 DPRINT("(next+1) %w",next
+1);
492 current_dir
=(PDIRECTORY_OBJECT
)ObDirLookup(current_dir
,current
);
493 if (current_dir
==NULL
)
495 DbgPrint("(%s:%d) Path component not found\n",__FILE__
,
497 return(STATUS_UNSUCCESSFUL
);
500 if (BODY_TO_HEADER(current_dir
)->ObjectType
==IoSymbolicLinkType
)
502 current_dir
= IoOpenSymlink(current_dir
);
506 DPRINT("next %x\n",next
);
507 DPRINT("current %x current %w\n",current
,current
);
510 if (current_dir
==NULL
)
512 Status
= STATUS_UNSUCCESSFUL
;
516 Status
= STATUS_SUCCESS
;
523 *UnparsedSection
= next
;
524 if (BODY_TO_HEADER(current_dir
)->ObjectType
== IoDeviceType
)
526 Status
= STATUS_FS_QUERY_REQUIRED
;
530 Status
= STATUS_UNSUCCESSFUL
;
534 *Object
= current_dir
;