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/objmgr.h>
17 #include <internal/string.h>
20 #include <internal/debug.h>
22 /* GLOBALS ****************************************************************/
24 OBJECT_TYPE DirectoryObjectType
= {{0,0,NULL
},
29 sizeof(DIRECTORY_OBJECT
),
45 // DIRECTORY_OBJECT directory;
48 } namespc_root
= {{0,},};
50 /* FUNCTIONS **************************************************************/
52 NTSTATUS
ZwOpenDirectoryObject(PHANDLE DirectoryHandle
,
53 ACCESS_MASK DesiredAccess
,
54 POBJECT_ATTRIBUTES ObjectAttributes
)
56 * FUNCTION: Opens a namespace directory object
58 * DirectoryHandle (OUT) = Variable which receives the directory handle
59 * DesiredAccess = Desired access to the directory
60 * ObjectAttributes = Structure describing the directory
68 Status
= ObOpenObjectByName(ObjectAttributes
,&Object
);
69 if (!NT_SUCCESS(Status
))
74 if (BODY_TO_HEADER(Object
)->Type
!=OBJTYP_DIRECTORY
)
76 return(STATUS_UNSUCCESSFUL
);
79 *DirectoryHandle
= ObAddHandle(Object
);
80 return(STATUS_SUCCESS
);
83 NTSTATUS
ZwQueryDirectoryObject(IN HANDLE DirObjHandle
,
84 OUT POBJDIR_INFORMATION DirObjInformation
,
85 IN ULONG BufferLength
,
86 IN BOOLEAN GetNextIndex
,
87 IN BOOLEAN IgnoreInputIndex
,
88 IN OUT PULONG ObjectIndex
,
89 OUT PULONG DataWritten OPTIONAL
)
91 * FUNCTION: Reads information from a namespace directory
93 * DirObjInformation (OUT) = Buffer to hold the data read
94 * BufferLength = Size of the buffer in bytes
95 * GetNextIndex = If TRUE then set ObjectIndex to the index of the
97 * If FALSE then set ObjectIndex to the number of
98 * objects in the directory
99 * IgnoreInputIndex = If TRUE start reading at index 0
100 * If FALSE start reading at the index specified
102 * ObjectIndex = Zero based index into the directory, interpretation
103 * depends on IgnoreInputIndex and GetNextIndex
104 * DataWritten (OUT) = Caller supplied storage for the number of bytes
109 POBJECT_HEADER hdr
= ObGetObjectByHandle(DirObjHandle
);
110 PDIRECTORY_OBJECT dir
= (PDIRECTORY_OBJECT
)(HEADER_TO_BODY(hdr
));
112 PLIST_ENTRY current_entry
;
113 POBJECT_HEADER current
;
117 assert_irql(PASSIVE_LEVEL
);
119 EntriesToRead
= BufferLength
/ sizeof(OBJDIR_INFORMATION
);
122 current_entry
= dir
->head
.Flink
;
125 * Optionally, skip over some entries at the start of the directory
127 if (!IgnoreInputIndex
)
129 EntriesToSkip
= *ObjectIndex
;
130 while ( i
<EntriesToSkip
&& current_entry
!=NULL
)
132 current_entry
= current_entry
->Flink
;
137 * Read the maximum entries possible into the buffer
139 while ( i
<EntriesToRead
&& current_entry
!=NULL
)
141 current
= CONTAINING_RECORD(current_entry
,OBJECT_HEADER
,entry
);
142 RtlCopyUnicodeString(&DirObjInformation
[i
].ObjectName
,
145 current_entry
= current_entry
->Flink
;
146 (*DataWritten
) = (*DataWritten
) + sizeof(OBJDIR_INFORMATION
);
150 * Optionally, count the number of entries in the directory
158 while ( current_entry
!=NULL
)
160 current_entry
=current_entry
->Flink
;
165 return(STATUS_SUCCESS
);
169 NTSTATUS
ObReferenceObjectByName(PUNICODE_STRING ObjectPath
,
171 PACCESS_STATE PassedAccessState
,
172 ACCESS_MASK DesiredAccess
,
173 POBJECT_TYPE ObjectType
,
174 KPROCESSOR_MODE Accessmode
,
181 NTSTATUS
ObOpenObjectByName(POBJECT_ATTRIBUTES ObjectAttributes
,
185 DPRINT("ObOpenObjectByName(ObjectAttributes %x, Object %x)\n",
186 ObjectAttributes
,Object
);
187 DPRINT("ObjectAttributes = {ObjectName %x ObjectName->Buffer %w}\n",
188 ObjectAttributes
->ObjectName
,ObjectAttributes
->ObjectName
->Buffer
);
190 *Object
= ObLookupObject(ObjectAttributes
->RootDirectory
,
191 ObjectAttributes
->ObjectName
->Buffer
);
192 DPRINT("*Object %x\n",*Object
);
195 return(STATUS_NO_SUCH_FILE
);
197 return(STATUS_SUCCESS
);
202 * FUNCTION: Initialize the object manager namespace
205 ANSI_STRING ansi_str
;
207 ObInitializeObjectHeader(OBJTYP_DIRECTORY
,NULL
,&namespc_root
.hdr
);
208 InitializeListHead(&namespc_root
.head
);
210 RtlInitAnsiString(&ansi_str
,"Directory");
211 RtlAnsiStringToUnicodeString(&DirectoryObjectType
.TypeName
,&ansi_str
,
213 ObRegisterType(OBJTYP_DIRECTORY
,&DirectoryObjectType
);
216 NTSTATUS
ZwCreateDirectoryObject(PHANDLE DirectoryHandle
,
217 ACCESS_MASK DesiredAccess
,
218 POBJECT_ATTRIBUTES ObjectAttributes
)
220 * FUNCTION: Creates or opens a directory object (a container for other
223 * DirectoryHandle (OUT) = Caller supplied storage for the handle
225 * DesiredAccess = Access desired to the directory
226 * ObjectAttributes = Object attributes initialized with
227 * InitializeObjectAttributes
231 PDIRECTORY_OBJECT dir
;
233 dir
= ObGenericCreateObject(DirectoryHandle
,DesiredAccess
,ObjectAttributes
,
237 * Initialize the object body
239 InitializeListHead(&dir
->head
);
240 KeInitializeSpinLock(&(dir
->Lock
));
242 return(STATUS_SUCCESS
);
245 VOID
InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes
,
246 PUNICODE_STRING ObjectName
,
248 HANDLE RootDirectory
,
249 PSECURITY_DESCRIPTOR SecurityDescriptor
)
251 * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a
252 * subsequent call to ZwCreateXXX or ZwOpenXXX
254 * InitializedAttributes (OUT) = Caller supplied storage for the
256 * ObjectName = Full path name for object
257 * Attributes = Attributes for the object
258 * RootDirectory = Where the object should be placed or NULL
259 * SecurityDescriptor = Ignored
262 * Either ObjectName is a fully qualified pathname or a path relative
266 DPRINT("InitializeObjectAttributes(InitializedAttributes %x "
267 "ObjectName %x Attributes %x RootDirectory %x)\n",
268 InitializedAttributes
,ObjectName
,Attributes
,RootDirectory
);
269 InitializedAttributes
->Length
=sizeof(OBJECT_ATTRIBUTES
);
270 InitializedAttributes
->RootDirectory
=RootDirectory
;
271 InitializedAttributes
->ObjectName
=ObjectName
;
272 InitializedAttributes
->Attributes
=Attributes
;
273 InitializedAttributes
->SecurityDescriptor
=SecurityDescriptor
;
274 InitializedAttributes
->SecurityQualityOfService
=NULL
;
277 static PVOID
ObDirLookup(PDIRECTORY_OBJECT dir
, PWSTR name
)
279 * FUNCTION: Looks up an entry within a namespace directory
281 * dir = Directory to lookup in
282 * name = Entry name to find
283 * RETURNS: A pointer to the object body if found
287 LIST_ENTRY
* current
= ((PDIRECTORY_OBJECT
)dir
)->head
.Flink
;
288 POBJECT_HEADER current_obj
;
289 DPRINT("ObDirLookup(dir %x, name %w)\n",dir
,name
);
292 return(BODY_TO_HEADER(dir
));
294 if (name
[0]=='.'&&name
[1]==0)
296 return(BODY_TO_HEADER(dir
));
298 if (name
[0]=='.'&&name
[1]=='.'&&name
[2]==0)
300 return(BODY_TO_HEADER(BODY_TO_HEADER(dir
)->Parent
));
302 while (current
!=(&((PDIRECTORY_OBJECT
)dir
)->head
))
304 current_obj
= CONTAINING_RECORD(current
,OBJECT_HEADER
,entry
);
305 if ( wcscmp(current_obj
->name
.Buffer
, name
)==0)
309 current
= current
->Flink
;
315 VOID
ObCreateEntry(PDIRECTORY_OBJECT parent
,POBJECT_HEADER Object
)
317 * FUNCTION: Add an entry to a namespace directory
319 * parent = directory to add in
320 * name = Name to give the entry
321 * Object = Header of the object to add the entry for
324 DPRINT("ObjCreateEntry(%x,%x,%x,%w)\n",parent
,Object
,Object
->name
.Buffer
,
325 Object
->name
.Buffer
);
326 DPRINT("root type %d\n",namespc_root
.hdr
.Type
);
327 DPRINT("%x\n",&(namespc_root
.hdr
.Type
));
328 DPRINT("type %x\n",&(parent
->Type
));
329 DPRINT("type %x\n",&(BODY_TO_HEADER(parent
)->Type
));
330 DPRINT("type %d\n",parent
->Type
);
331 assert(parent
->Type
== OBJTYP_DIRECTORY
);
334 * Insert ourselves in our parents list
336 InsertTailList(&parent
->head
,&Object
->entry
);
339 PVOID
ObLookupObject(HANDLE rooth
, PWSTR string
)
341 * FUNCTION: Lookup an object within the system namespc
343 * root = Directory to start lookup from
344 * _string = Pathname to lookup
345 * RETURNS: On success a pointer to the object body
351 PDIRECTORY_OBJECT current_dir
= NULL
;
352 POBJECT_HEADER current_hdr
;
354 DPRINT("root %x string %w\n",rooth
,string
);
358 current_dir
= HEADER_TO_BODY(&(namespc_root
.hdr
));
362 ObReferenceObjectByHandle(rooth
,DIRECTORY_TRAVERSE
,NULL
,
363 UserMode
,(PVOID
*)¤t_dir
,NULL
);
371 DPRINT("current_dir %x\n",current_dir
);
372 DPRINT("type %d\n",current_dir
->Type
);
376 DPRINT("string = %w\n",string
);
380 DbgPrint("(%s:%d) Non absolute pathname passed to %s\n",__FILE__
,
381 __LINE__
,__FUNCTION__
);
386 DPRINT("current %w\n",current
);
387 next
= wcschr(string
+1,'\\');
392 DPRINT("next %x\n",next
);
396 DPRINT("Scanning %w next %w current %x\n",current
,next
+1,
400 * Check the current object is a directory
402 if (current_dir
->Type
!=OBJTYP_DIRECTORY
)
404 DbgPrint("(%s:%d) Bad path component\n",__FILE__
,
411 * Lookup the next component of the path in the directory
413 current_hdr
=(PDIRECTORY_OBJECT
)ObDirLookup(current_dir
,current
);
414 if (current_hdr
==NULL
)
416 DbgPrint("(%s:%d) Path component not found\n",__FILE__
,
421 current_dir
= HEADER_TO_BODY(current_hdr
);
424 next
= wcschr(next
+1,'\\');
431 DPRINT("current_dir %x current %x\n",current_dir
,current
);
432 DPRINT("current %w\n",current
);
433 current_hdr
= ObDirLookup(current_dir
,current
);
434 if (current_hdr
==NULL
)
438 DPRINT("Returning %x %x\n",current_hdr
,HEADER_TO_BODY(current_hdr
));
439 return(HEADER_TO_BODY(current_hdr
));