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 OBJECT_TYPE DirectoryObjectType
= {{0,0,NULL
},
30 sizeof(DIRECTORY_OBJECT
),
46 // DIRECTORY_OBJECT directory;
49 } namespc_root
= {{0,},};
51 /* FUNCTIONS **************************************************************/
53 NTSTATUS
ZwOpenDirectoryObject(PHANDLE DirectoryHandle
,
54 ACCESS_MASK DesiredAccess
,
55 POBJECT_ATTRIBUTES ObjectAttributes
)
57 * FUNCTION: Opens a namespace directory object
59 * DirectoryHandle (OUT) = Variable which receives the directory handle
60 * DesiredAccess = Desired access to the directory
61 * ObjectAttributes = Structure describing the directory
72 Status
= ObOpenObjectByName(ObjectAttributes
,&Object
,&Ignored
);
73 if (!NT_SUCCESS(Status
))
78 if (BODY_TO_HEADER(Object
)->Type
!=OBJTYP_DIRECTORY
)
80 return(STATUS_UNSUCCESSFUL
);
83 *DirectoryHandle
= ObAddHandle(Object
);
85 return(STATUS_SUCCESS
);
88 NTSTATUS
ZwQueryDirectoryObject(IN HANDLE DirObjHandle
,
89 OUT POBJDIR_INFORMATION DirObjInformation
,
90 IN ULONG BufferLength
,
91 IN BOOLEAN GetNextIndex
,
92 IN BOOLEAN IgnoreInputIndex
,
93 IN OUT PULONG ObjectIndex
,
94 OUT PULONG DataWritten OPTIONAL
)
96 * FUNCTION: Reads information from a namespace directory
98 * DirObjInformation (OUT) = Buffer to hold the data read
99 * BufferLength = Size of the buffer in bytes
100 * GetNextIndex = If TRUE then set ObjectIndex to the index of the
102 * If FALSE then set ObjectIndex to the number of
103 * objects in the directory
104 * IgnoreInputIndex = If TRUE start reading at index 0
105 * If FALSE start reading at the index specified
107 * ObjectIndex = Zero based index into the directory, interpretation
108 * depends on IgnoreInputIndex and GetNextIndex
109 * DataWritten (OUT) = Caller supplied storage for the number of bytes
114 COMMON_BODY_HEADER
* hdr
= ObGetObjectByHandle(DirObjHandle
);
115 PDIRECTORY_OBJECT dir
= (PDIRECTORY_OBJECT
)hdr
;
117 PLIST_ENTRY current_entry
;
118 POBJECT_HEADER current
;
122 DPRINT("ZwQueryDirectoryObject(DirObjHandle %x)\n",DirObjHandle
);
123 DPRINT("dir %x namespc_root %x\n",dir
,HEADER_TO_BODY(&(namespc_root
.hdr
)));
125 assert_irql(PASSIVE_LEVEL
);
127 EntriesToRead
= BufferLength
/ sizeof(OBJDIR_INFORMATION
);
130 DPRINT("EntriesToRead %d\n",EntriesToRead
);
132 current_entry
= dir
->head
.Flink
;
135 * Optionally, skip over some entries at the start of the directory
137 if (!IgnoreInputIndex
)
141 EntriesToSkip
= *ObjectIndex
;
142 while ( i
<EntriesToSkip
&& current_entry
!=NULL
)
144 current_entry
= current_entry
->Flink
;
148 DPRINT("DirObjInformation %x\n",DirObjInformation
);
151 * Read the maximum entries possible into the buffer
153 while ( i
<EntriesToRead
&& current_entry
!=(&(dir
->head
)))
155 current
= CONTAINING_RECORD(current_entry
,OBJECT_HEADER
,entry
);
156 DPRINT("Scanning %w\n",current
->name
.Buffer
);
157 DirObjInformation
[i
].ObjectName
.Buffer
=
158 ExAllocatePool(NonPagedPool
,current
->name
.Length
);
159 DirObjInformation
[i
].ObjectName
.Length
= current
->name
.Length
;
160 DirObjInformation
[i
].ObjectName
.MaximumLength
= current
->name
.Length
;
161 DPRINT("DirObjInformation[i].ObjectName.Buffer %x\n",
162 DirObjInformation
[i
].ObjectName
.Buffer
);
163 RtlCopyUnicodeString(&DirObjInformation
[i
].ObjectName
,
166 current_entry
= current_entry
->Flink
;
167 (*DataWritten
) = (*DataWritten
) + sizeof(OBJDIR_INFORMATION
);
173 * Optionally, count the number of entries in the directory
181 while ( current_entry
!=(&(dir
->head
)) )
183 current_entry
=current_entry
->Flink
;
188 return(STATUS_SUCCESS
);
192 NTSTATUS
ObReferenceObjectByName(PUNICODE_STRING ObjectPath
,
194 PACCESS_STATE PassedAccessState
,
195 ACCESS_MASK DesiredAccess
,
196 POBJECT_TYPE ObjectType
,
197 KPROCESSOR_MODE Accessmode
,
204 NTSTATUS
ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes
,
205 PVOID
* Object
, PWSTR
* UnparsedSection
)
209 DPRINT("ObOpenObjectByName(ObjectAttributes %x, Object %x)\n",
210 ObjectAttributes
,Object
);
211 DPRINT("ObjectAttributes = {ObjectName %x ObjectName->Buffer %w}\n",
212 ObjectAttributes
->ObjectName
,ObjectAttributes
->ObjectName
->Buffer
);
215 Status
= ObLookupObject(ObjectAttributes
->RootDirectory
,
216 ObjectAttributes
->ObjectName
->Buffer
,
219 DPRINT("*Object %x\n",*Object
);
225 * FUNCTION: Initialize the object manager namespace
228 ANSI_STRING ansi_str
;
230 ObInitializeObjectHeader(OBJTYP_DIRECTORY
,NULL
,&namespc_root
.hdr
);
231 InitializeListHead(&namespc_root
.head
);
233 RtlInitAnsiString(&ansi_str
,"Directory");
234 RtlAnsiStringToUnicodeString(&DirectoryObjectType
.TypeName
,&ansi_str
,
236 ObRegisterType(OBJTYP_DIRECTORY
,&DirectoryObjectType
);
239 NTSTATUS
ZwCreateDirectoryObject(PHANDLE DirectoryHandle
,
240 ACCESS_MASK DesiredAccess
,
241 POBJECT_ATTRIBUTES ObjectAttributes
)
243 * FUNCTION: Creates or opens a directory object (a container for other
246 * DirectoryHandle (OUT) = Caller supplied storage for the handle
248 * DesiredAccess = Access desired to the directory
249 * ObjectAttributes = Object attributes initialized with
250 * InitializeObjectAttributes
254 PDIRECTORY_OBJECT dir
;
256 dir
= ObGenericCreateObject(DirectoryHandle
,DesiredAccess
,ObjectAttributes
,
260 * Initialize the object body
262 InitializeListHead(&dir
->head
);
263 KeInitializeSpinLock(&(dir
->Lock
));
265 return(STATUS_SUCCESS
);
268 VOID
InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes
,
269 PUNICODE_STRING ObjectName
,
271 HANDLE RootDirectory
,
272 PSECURITY_DESCRIPTOR SecurityDescriptor
)
274 * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a
275 * subsequent call to ZwCreateXXX or ZwOpenXXX
277 * InitializedAttributes (OUT) = Caller supplied storage for the
279 * ObjectName = Full path name for object
280 * Attributes = Attributes for the object
281 * RootDirectory = Where the object should be placed or NULL
282 * SecurityDescriptor = Ignored
285 * Either ObjectName is a fully qualified pathname or a path relative
289 DPRINT("InitializeObjectAttributes(InitializedAttributes %x "
290 "ObjectName %x Attributes %x RootDirectory %x)\n",
291 InitializedAttributes
,ObjectName
,Attributes
,RootDirectory
);
292 InitializedAttributes
->Length
=sizeof(OBJECT_ATTRIBUTES
);
293 InitializedAttributes
->RootDirectory
=RootDirectory
;
294 InitializedAttributes
->ObjectName
=ObjectName
;
295 InitializedAttributes
->Attributes
=Attributes
;
296 InitializedAttributes
->SecurityDescriptor
=SecurityDescriptor
;
297 InitializedAttributes
->SecurityQualityOfService
=NULL
;
300 static PVOID
ObDirLookup(PDIRECTORY_OBJECT dir
, PWSTR name
)
302 * FUNCTION: Looks up an entry within a namespace directory
304 * dir = Directory to lookup in
305 * name = Entry name to find
306 * RETURNS: A pointer to the object body if found
310 LIST_ENTRY
* current
= dir
->head
.Flink
;
311 POBJECT_HEADER current_obj
;
313 DPRINT("ObDirLookup(dir %x, name %w)\n",dir
,name
);
319 if (name
[0]=='.'&&name
[1]==0)
323 if (name
[0]=='.'&&name
[1]=='.'&&name
[2]==0)
325 return(BODY_TO_HEADER(dir
)->Parent
);
327 while (current
!=(&(dir
->head
)))
329 current_obj
= CONTAINING_RECORD(current
,OBJECT_HEADER
,entry
);
330 DPRINT("Scanning %w\n",current_obj
->name
.Buffer
);
331 if ( wcscmp(current_obj
->name
.Buffer
, name
)==0)
333 return(HEADER_TO_BODY(current_obj
));
335 current
= current
->Flink
;
337 DPRINT("%s() = NULL\n",__FUNCTION__
);
342 VOID
ObCreateEntry(PDIRECTORY_OBJECT parent
,POBJECT_HEADER Object
)
344 * FUNCTION: Add an entry to a namespace directory
346 * parent = directory to add in
347 * name = Name to give the entry
348 * Object = Header of the object to add the entry for
351 DPRINT("ObjCreateEntry(%x,%x,%x,%w)\n",parent
,Object
,Object
->name
.Buffer
,
352 Object
->name
.Buffer
);
353 assert(parent
->Type
== OBJTYP_DIRECTORY
);
356 * Insert ourselves in our parents list
358 InsertTailList(&parent
->head
,&Object
->entry
);
361 NTSTATUS
ObLookupObject(HANDLE rootdir
, PWSTR string
, PVOID
* Object
,
362 PWSTR
* UnparsedSection
)
364 * FUNCTION: Lookup an object within the system namespc
366 * root = Directory to start lookup from
367 * _string = Pathname to lookup
368 * RETURNS: On success a pointer to the object body
374 PDIRECTORY_OBJECT current_dir
= NULL
;
377 DPRINT("ObLookupObject(rootdir %x, string %x, string %w, Object %x, "
378 "UnparsedSection %x)\n",rootdir
,string
,string
,Object
,
382 *UnparsedSection
= NULL
;
387 current_dir
= HEADER_TO_BODY(&(namespc_root
.hdr
));
391 ObReferenceObjectByHandle(rootdir
,DIRECTORY_TRAVERSE
,NULL
,
392 UserMode
,(PVOID
*)¤t_dir
,NULL
);
401 return(STATUS_SUCCESS
);
406 DbgPrint("(%s:%d) Non absolute pathname passed to %s\n",__FILE__
,
407 __LINE__
,__FUNCTION__
);
408 return(STATUS_UNSUCCESSFUL
);
414 while (next
!=NULL
&& current_dir
->Type
==OBJTYP_DIRECTORY
)
418 next
= wcschr(next
+1,'\\');
424 DPRINT("current %w current[5] %x next %x ",current
,current
[5],next
);
427 DPRINT("(next+1) %w",next
+1);
431 current_dir
=(PDIRECTORY_OBJECT
)ObDirLookup(current_dir
,current
);
432 if (current_dir
==NULL
)
434 DbgPrint("(%s:%d) Path component not found\n",__FILE__
,
437 return(STATUS_UNSUCCESSFUL
);
440 DPRINT("current_dir %x\n",current_dir
);
441 DPRINT("current_dir->Type %d OBJTYP_SYMLNK %d OBJTYP_DIRECTORY %d\n",
442 current_dir
->Type
,OBJTYP_SYMLNK
,OBJTYP_DIRECTORY
);
443 DPRINT("&(current_dir->Type) %x\n",&(current_dir
->Type
));
444 if (current_dir
->Type
==OBJTYP_SYMLNK
)
446 current_dir
= IoOpenSymlink(current_dir
);
450 DPRINT("next %x\n",next
);
451 DPRINT("current %x current %w\n",current
,current
);
454 if (current_dir
==NULL
)
456 Status
= STATUS_UNSUCCESSFUL
;
460 Status
= STATUS_SUCCESS
;
467 *UnparsedSection
= next
;
468 switch(current_dir
->Type
)
472 Status
= STATUS_FS_QUERY_REQUIRED
;
477 Status
= STATUS_UNSUCCESSFUL
;
482 *Object
= current_dir
;