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 **************************************************************/
26 /**********************************************************************
28 * NtOpenDirectoryObject
31 * Opens a namespace directory object.
34 * DirectoryHandle (OUT)
35 * Variable which receives the directory handle.
38 * Desired access to the directory.
41 * Structure describing the directory.
49 NTSTATUS STDCALL NtOpenDirectoryObject(PHANDLE DirectoryHandle,
50 ACCESS_MASK DesiredAccess,
51 POBJECT_ATTRIBUTES ObjectAttributes)
58 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
59 ObjectAttributes->Attributes,
66 if (!NT_SUCCESS(Status))
71 Status = ObCreateHandle(PsGetCurrentProcess(),
76 return STATUS_SUCCESS;
80 /**********************************************************************
82 * NtQueryDirectoryObject
85 * Reads information from a directory in the system namespace.
89 * Handle, obtained with NtOpenDirectoryObject(), which
90 * must grant DIRECTORY_QUERY access to the directory
93 * DirObjInformation (OUT)
94 * Buffer to hold the data read.
97 * Size of the buffer in bytes.
100 * When TRUE, only 1 entry is written in DirObjInformation;
101 * otherwise as many as will fit in the buffer.
104 * If TRUE start reading at index 0.
105 * If FALSE start reading at the index specified
106 * by object index *ObjectIndex.
109 * Zero based index into the directory, interpretation
110 * depends on RestartScan.
113 * Caller supplied storage for the number of bytes
121 * Changed 4th, and 5th parameter names after
122 * G.Nebbett "WNT/W2k Native API Reference".
125 NTSTATUS STDCALL NtQueryDirectoryObject (IN HANDLE DirObjHandle,
126 OUT POBJDIR_INFORMATION
128 IN ULONG BufferLength,
129 IN BOOLEAN ReturnSingleEntry,
130 IN BOOLEAN RestartScan,
131 IN OUT PULONG ObjectIndex,
132 OUT PULONG DataWritten OPTIONAL)
134 PDIRECTORY_OBJECT dir = NULL;
135 PLIST_ENTRY current_entry = NULL;
136 POBJECT_HEADER current = NULL;
138 NTSTATUS Status = STATUS_SUCCESS;
139 DWORD DirectoryCount = 0;
140 DWORD DirectorySize = 0;
141 ULONG SpaceLeft = BufferLength;
142 ULONG SpaceRequired = 0;
143 ULONG NameLength = 0;
144 ULONG TypeNameLength = 0;
145 POBJDIR_INFORMATION current_odi = DirObjInformation;
146 PBYTE FirstFree = (PBYTE) DirObjInformation;
149 DPRINT("NtQueryDirectoryObject(DirObjHandle %x)\n", DirObjHandle);
151 /* FIXME: if previous mode == user, use ProbeForWrite
154 /* Reference the DIRECTORY_OBJECT */
155 Status = ObReferenceObjectByHandle(DirObjHandle,
161 if (!NT_SUCCESS(Status))
165 /* Check ObjectIndex is not NULL */
166 if (NULL == ObjectIndex)
168 return (STATUS_INVALID_PARAMETER);
171 * Compute the number of directory entries
172 * and the size of the array (in bytes).
173 * One more entry marks the end of the array.
175 if (FALSE == ReturnSingleEntry)
177 for ( current_entry = dir->head.Flink;
178 (current_entry != & dir->head);
179 current_entry = current_entry->Flink
189 // count is DirectoryCount + one null entry
190 DirectorySize = (DirectoryCount + 1) * sizeof (OBJDIR_INFORMATION);
191 if (DirectorySize > SpaceLeft)
193 return (STATUS_BUFFER_TOO_SMALL);
196 * Optionally, skip over some entries at the start of the directory
197 * (use *ObjectIndex value)
199 current_entry = dir->head.Flink;
200 if (FALSE == RestartScan)
202 /* RestartScan == FALSE */
203 register ULONG EntriesToSkip = *ObjectIndex;
208 ((EntriesToSkip --) && (current_entry != & dir->head));
209 current_entry = current_entry->Flink
211 if ((EntriesToSkip) && (current_entry == & dir->head))
213 return (STATUS_NO_MORE_ENTRIES);
217 * Initialize the array of OBJDIR_INFORMATION.
219 RtlZeroMemory (FirstFree, DirectorySize);
221 * Move FirstFree to point to the Unicode strings area
223 FirstFree += DirectorySize;
225 * Compute how much space is left after allocating the
226 * array in the user buffer.
228 SpaceLeft -= DirectorySize;
229 /* Scan the directory */
233 * Check if we reached the end of the directory.
235 if (current_entry == & dir->head)
238 if (i) break; /* DONE */
239 /* FIXME: better error handling here! */
240 return (STATUS_NO_MORE_ENTRIES);
243 * Compute the current OBJECT_HEADER memory
246 current = CONTAINING_RECORD(current_entry, OBJECT_HEADER, Entry);
248 * Compute the space required in the user buffer to copy
249 * the data from the current object:
251 * Name (WCHAR) 0 TypeName (WCHAR) 0
253 NameLength = (wcslen (current->Name.Buffer) * sizeof (WCHAR));
254 TypeNameLength = (wcslen (current->ObjectType->TypeName.Buffer) * sizeof (WCHAR));
255 SpaceRequired = (NameLength + 1) * sizeof (WCHAR)
256 + (TypeNameLength + 1) * sizeof (WCHAR);
258 * Check for free space in the user buffer.
260 if (SpaceRequired > SpaceLeft)
262 return (STATUS_BUFFER_TOO_SMALL);
265 * Copy the current directory entry's data into the buffer
266 * and update the OBJDIR_INFORMATION entry in the array.
268 /* --- Object's name --- */
269 current_odi->ObjectName.Length = NameLength;
270 current_odi->ObjectName.MaximumLength = (NameLength + sizeof (WCHAR));
271 current_odi->ObjectName.Buffer = (PWCHAR) FirstFree;
272 wcscpy ((PWCHAR) FirstFree, current->Name.Buffer);
273 FirstFree += (current_odi->ObjectName.MaximumLength);
274 /* --- Object type's name --- */
275 current_odi->ObjectTypeName.Length = TypeNameLength;
276 current_odi->ObjectTypeName.MaximumLength = (TypeNameLength + sizeof (WCHAR));
277 current_odi->ObjectTypeName.Buffer = (PWCHAR) FirstFree;
278 wcscpy ((PWCHAR) FirstFree, current->ObjectType->TypeName.Buffer);
279 FirstFree += (current_odi->ObjectTypeName.MaximumLength);
280 /* Next entry in the array */
282 /* Decrease the space left count */
283 SpaceLeft -= SpaceRequired;
284 /* Increase the object index number */
286 /* Next object in the directory */
287 current_entry = current_entry->Flink;
289 } while (FALSE == ReturnSingleEntry);
291 * Store current index in ObjectIndex
293 *ObjectIndex += DirectoryCount;
295 * Report to the caller how much bytes
296 * we wrote in the user buffer.
298 if (NULL != DataWritten)
300 *DataWritten = (BufferLength - SpaceLeft);
302 return (STATUS_SUCCESS);
305 #endif /* LIBCAPTIVE */
307 /**********************************************************************
308 * NAME (EXPORTED as Zw)
309 * NtCreateDirectoryObject
312 * Creates or opens a directory object (a container for other
316 * DirectoryHandle (OUT)
317 * Caller supplied storage for the handle of the
321 * Access desired to the directory.
324 * Object attributes initialized with
325 * InitializeObjectAttributes.
331 NtCreateDirectoryObject(PHANDLE DirectoryHandle,
332 ACCESS_MASK DesiredAccess,
333 POBJECT_ATTRIBUTES ObjectAttributes)
335 PDIRECTORY_OBJECT dir;
337 DPRINT("NtCreateDirectoryObject(DirectoryHandle %x, "
338 "DesiredAccess %x, ObjectAttributes %x, "
339 "ObjectAttributes->ObjectName %S)\n",
340 DirectoryHandle, DesiredAccess, ObjectAttributes,
341 ObjectAttributes->ObjectName);
343 return(ObCreateObject(DirectoryHandle,