1 /* $Id: dirobj.c,v 1.13 2002/01/23 23:39:26 chorns Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ob/dirobj.c
6 * PURPOSE: Interface functions to directory object
7 * PROGRAMMER: David Welch (welch@mcmail.com)
12 /* INCLUDES ***************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/io.h>
19 #include <internal/debug.h>
22 /* FUNCTIONS **************************************************************/
25 /**********************************************************************
27 * NtOpenDirectoryObject
30 * Opens a namespace directory object.
33 * DirectoryHandle (OUT)
34 * Variable which receives the directory handle.
37 * Desired access to the directory.
40 * Structure describing the directory.
48 NTSTATUS STDCALL
NtOpenDirectoryObject(PHANDLE DirectoryHandle
,
49 ACCESS_MASK DesiredAccess
,
50 POBJECT_ATTRIBUTES ObjectAttributes
)
57 Status
= ObReferenceObjectByName(ObjectAttributes
->ObjectName
,
58 ObjectAttributes
->Attributes
,
65 if (!NT_SUCCESS(Status
))
70 Status
= ObCreateHandle(PsGetCurrentProcess(),
75 return STATUS_SUCCESS
;
79 /**********************************************************************
81 * NtQueryDirectoryObject
84 * Reads information from a directory in the system namespace.
88 * Handle, obtained with NtOpenDirectoryObject(), which
89 * must grant DIRECTORY_QUERY access to the directory
92 * DirObjInformation (OUT)
93 * Buffer to hold the data read.
96 * Size of the buffer in bytes.
99 * When TRUE, only 1 entry is written in DirObjInformation;
100 * otherwise as many as will fit in the buffer.
103 * If TRUE start reading at index 0.
104 * If FALSE start reading at the index specified
105 * by object index *ObjectIndex.
108 * Zero based index into the directory, interpretation
109 * depends on RestartScan.
112 * Caller supplied storage for the number of bytes
120 * Changed 4th, and 5th parameter names after
121 * G.Nebbett "WNT/W2k Native API Reference".
124 NTSTATUS STDCALL
NtQueryDirectoryObject (IN HANDLE DirObjHandle
,
125 OUT POBJDIR_INFORMATION
127 IN ULONG BufferLength
,
128 IN BOOLEAN ReturnSingleEntry
,
129 IN BOOLEAN RestartScan
,
130 IN OUT PULONG ObjectIndex
,
131 OUT PULONG DataWritten OPTIONAL
)
133 PDIRECTORY_OBJECT dir
= NULL
;
134 PLIST_ENTRY current_entry
= NULL
;
135 POBJECT_HEADER current
= NULL
;
137 NTSTATUS Status
= STATUS_SUCCESS
;
138 DWORD DirectoryCount
= 0;
139 DWORD DirectorySize
= 0;
140 ULONG SpaceLeft
= BufferLength
;
141 ULONG SpaceRequired
= 0;
142 ULONG NameLength
= 0;
143 ULONG TypeNameLength
= 0;
144 POBJDIR_INFORMATION current_odi
= DirObjInformation
;
145 PBYTE FirstFree
= (PBYTE
) DirObjInformation
;
148 DPRINT("NtQueryDirectoryObject(DirObjHandle %x)\n", DirObjHandle
);
150 /* FIXME: if previous mode == user, use ProbeForWrite
153 /* Reference the DIRECTORY_OBJECT */
154 Status
= ObReferenceObjectByHandle(DirObjHandle
,
160 if (!NT_SUCCESS(Status
))
164 /* Check ObjectIndex is not NULL */
165 if (NULL
== ObjectIndex
)
167 return (STATUS_INVALID_PARAMETER
);
170 * Compute the number of directory entries
171 * and the size of the array (in bytes).
172 * One more entry marks the end of the array.
174 if (FALSE
== ReturnSingleEntry
)
176 for ( current_entry
= dir
->head
.Flink
;
177 (current_entry
!= & dir
->head
);
178 current_entry
= current_entry
->Flink
188 DirectorySize
= DirectoryCount
* sizeof (OBJDIR_INFORMATION
);
189 if (DirectorySize
> SpaceLeft
)
191 return (STATUS_BUFFER_TOO_SMALL
);
194 * Optionally, skip over some entries at the start of the directory
195 * (use *ObjectIndex value)
197 current_entry
= dir
->head
.Flink
;
198 if (FALSE
== RestartScan
)
200 /* RestartScan == FALSE */
201 register ULONG EntriesToSkip
= *ObjectIndex
;
206 ((EntriesToSkip
--) && (current_entry
!= & dir
->head
));
207 current_entry
= current_entry
->Flink
209 if ((EntriesToSkip
) && (current_entry
== & dir
->head
))
211 return (STATUS_NO_MORE_ENTRIES
);
215 * Initialize the array of OBJDIR_INFORMATION.
217 RtlZeroMemory (FirstFree
, DirectorySize
);
219 * Move FirstFree to point to the Unicode strings area
221 FirstFree
+= DirectorySize
;
223 * Compute how much space is left after allocating the
224 * array in the user buffer.
226 SpaceLeft
-= DirectorySize
;
227 /* Scan the directory */
231 * Check if we reached the end of the directory.
233 if (current_entry
== & dir
->head
)
236 if (i
) break; /* DONE */
237 /* FIXME: better error handling here! */
238 return (STATUS_NO_MORE_ENTRIES
);
241 * Compute the current OBJECT_HEADER memory
244 current
= CONTAINING_RECORD(current_entry
, OBJECT_HEADER
, Entry
);
246 * Compute the space required in the user buffer to copy
247 * the data from the current object:
249 * Name (WCHAR) 0 TypeName (WCHAR) 0
251 NameLength
= (wcslen (current
->Name
.Buffer
) * sizeof (WCHAR
));
252 TypeNameLength
= (wcslen (current
->ObjectType
->TypeName
.Buffer
) * sizeof (WCHAR
));
253 SpaceRequired
= (NameLength
+ 1) * sizeof (WCHAR
)
254 + (TypeNameLength
+ 1) * sizeof (WCHAR
);
256 * Check for free space in the user buffer.
258 if (SpaceRequired
> SpaceLeft
)
260 return (STATUS_BUFFER_TOO_SMALL
);
263 * Copy the current directory entry's data into the buffer
264 * and update the OBJDIR_INFORMATION entry in the array.
266 /* --- Object's name --- */
267 current_odi
->ObjectName
.Length
= NameLength
;
268 current_odi
->ObjectName
.MaximumLength
= (NameLength
+ sizeof (WCHAR
));
269 current_odi
->ObjectName
.Buffer
= (PWCHAR
) FirstFree
;
270 wcscpy ((PWCHAR
) FirstFree
, current
->Name
.Buffer
);
271 FirstFree
+= (current_odi
->ObjectName
.MaximumLength
);
272 /* --- Object type's name --- */
273 current_odi
->ObjectTypeName
.Length
= TypeNameLength
;
274 current_odi
->ObjectTypeName
.MaximumLength
= (TypeNameLength
+ sizeof (WCHAR
));
275 current_odi
->ObjectTypeName
.Buffer
= (PWCHAR
) FirstFree
;
276 wcscpy ((PWCHAR
) FirstFree
, current
->ObjectType
->TypeName
.Buffer
);
277 FirstFree
+= (current_odi
->ObjectTypeName
.MaximumLength
);
278 /* Next entry in the array */
280 /* Decrease the space left count */
281 SpaceLeft
-= SpaceRequired
;
282 /* Increase the object index number */
284 /* Next object in the directory */
285 current_entry
= current_entry
->Flink
;
287 } while (FALSE
== ReturnSingleEntry
);
289 * Store current index in ObjectIndex
291 *ObjectIndex
+= DirectoryCount
;
293 * Report to the caller how much bytes
294 * we wrote in the user buffer.
296 if (NULL
!= DataWritten
)
298 *DataWritten
= (BufferLength
- SpaceLeft
);
300 return (STATUS_SUCCESS
);
304 /**********************************************************************
305 * NAME (EXPORTED as Zw)
306 * NtCreateDirectoryObject
309 * Creates or opens a directory object (a container for other
313 * DirectoryHandle (OUT)
314 * Caller supplied storage for the handle of the
318 * Access desired to the directory.
321 * Object attributes initialized with
322 * InitializeObjectAttributes.
328 NtCreateDirectoryObject(PHANDLE DirectoryHandle
,
329 ACCESS_MASK DesiredAccess
,
330 POBJECT_ATTRIBUTES ObjectAttributes
)
332 PDIRECTORY_OBJECT dir
;
334 DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, "
335 "DesiredAccess %x, ObjectAttributes %x, "
336 "ObjectAttributes->ObjectName %S)\n",
337 DirectoryHandle
, DesiredAccess
, ObjectAttributes
,
338 ObjectAttributes
->ObjectName
);
340 return(ObCreateObject(DirectoryHandle
,