bff9f584bfc70ade809ba6ac27fa4307f5fda58b
[reactos.git] / reactos / ntoskrnl / ob / dirobj.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ob/dirobj.c
5 * PURPOSE: Interface functions to directory object
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * 22/05/98: Created
9 */
10
11 /* INCLUDES ***************************************************************/
12
13 #include <wchar.h>
14 #include <ddk/ntddk.h>
15 #include <internal/ob.h>
16 #include <internal/io.h>
17 #include <internal/string.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22
23 /* FUNCTIONS **************************************************************/
24
25 NTSTATUS NtOpenDirectoryObject(PHANDLE DirectoryHandle,
26 ACCESS_MASK DesiredAccess,
27 POBJECT_ATTRIBUTES ObjectAttributes)
28 {
29 return(ZwOpenDirectoryObject(DirectoryHandle,
30 DesiredAccess,
31 ObjectAttributes));
32 }
33
34 NTSTATUS ZwOpenDirectoryObject(PHANDLE DirectoryHandle,
35 ACCESS_MASK DesiredAccess,
36 POBJECT_ATTRIBUTES ObjectAttributes)
37 /*
38 * FUNCTION: Opens a namespace directory object
39 * ARGUMENTS:
40 * DirectoryHandle (OUT) = Variable which receives the directory handle
41 * DesiredAccess = Desired access to the directory
42 * ObjectAttributes = Structure describing the directory
43 * RETURNS: Status
44 * NOTES: Undocumented
45 */
46 {
47 PVOID Object;
48 NTSTATUS Status;
49
50 *DirectoryHandle = 0;
51
52 Status = ObReferenceObjectByName(ObjectAttributes->ObjectName,
53 ObjectAttributes->Attributes,
54 NULL,
55 DesiredAccess,
56 ObDirectoryType,
57 UserMode,
58 NULL,
59 &Object);
60 if (!NT_SUCCESS(Status))
61 {
62 return(Status);
63 }
64
65 Status = ObCreateHandle(PsGetCurrentProcess(),
66 Object,
67 DesiredAccess,
68 FALSE,
69 DirectoryHandle);
70 return(STATUS_SUCCESS);
71 }
72
73 NTSTATUS NtQueryDirectoryObject(IN HANDLE DirObjHandle,
74 OUT POBJDIR_INFORMATION DirObjInformation,
75 IN ULONG BufferLength,
76 IN BOOLEAN GetNextIndex,
77 IN BOOLEAN IgnoreInputIndex,
78 IN OUT PULONG ObjectIndex,
79 OUT PULONG DataWritten OPTIONAL)
80 {
81 return(ZwQueryDirectoryObject(DirObjHandle,
82 DirObjInformation,
83 BufferLength,
84 GetNextIndex,
85 IgnoreInputIndex,
86 ObjectIndex,
87 DataWritten));
88 }
89
90 NTSTATUS ZwQueryDirectoryObject(IN HANDLE DirObjHandle,
91 OUT POBJDIR_INFORMATION DirObjInformation,
92 IN ULONG BufferLength,
93 IN BOOLEAN GetNextIndex,
94 IN BOOLEAN IgnoreInputIndex,
95 IN OUT PULONG ObjectIndex,
96 OUT PULONG DataWritten OPTIONAL)
97 /*
98 * FUNCTION: Reads information from a namespace directory
99 * ARGUMENTS:
100 * DirObjInformation (OUT) = Buffer to hold the data read
101 * BufferLength = Size of the buffer in bytes
102 * GetNextIndex = If TRUE then set ObjectIndex to the index of the
103 * next object
104 * If FALSE then set ObjectIndex to the number of
105 * objects in the directory
106 * IgnoreInputIndex = If TRUE start reading at index 0
107 * If FALSE start reading at the index specified
108 * by object index
109 * ObjectIndex = Zero based index into the directory, interpretation
110 * depends on IgnoreInputIndex and GetNextIndex
111 * DataWritten (OUT) = Caller supplied storage for the number of bytes
112 * written (or NULL)
113 * RETURNS: Status
114 */
115 {
116 PDIRECTORY_OBJECT dir = NULL;
117 ULONG EntriesToRead;
118 PLIST_ENTRY current_entry;
119 POBJECT_HEADER current;
120 ULONG i=0;
121 ULONG EntriesToSkip;
122 NTSTATUS Status;
123
124 DPRINT("ZwQueryDirectoryObject(DirObjHandle %x)\n",DirObjHandle);
125 DPRINT("dir %x namespc_root %x\n",dir,HEADER_TO_BODY(&(namespc_root.hdr)));
126
127 // assert_irql(PASSIVE_LEVEL);
128
129 Status = ObReferenceObjectByHandle(DirObjHandle,
130 DIRECTORY_QUERY,
131 ObDirectoryType,
132 UserMode,
133 (PVOID*)&dir,
134 NULL);
135 if (Status != STATUS_SUCCESS)
136 {
137 return(Status);
138 }
139
140 EntriesToRead = BufferLength / sizeof(OBJDIR_INFORMATION);
141 *DataWritten = 0;
142
143 DPRINT("EntriesToRead %d\n",EntriesToRead);
144
145 current_entry = dir->head.Flink;
146
147 /*
148 * Optionally, skip over some entries at the start of the directory
149 */
150 if (!IgnoreInputIndex)
151 {
152 CHECKPOINT;
153
154 EntriesToSkip = *ObjectIndex;
155 while ( i<EntriesToSkip && current_entry!=NULL)
156 {
157 current_entry = current_entry->Flink;
158 }
159 }
160
161 DPRINT("DirObjInformation %x\n",DirObjInformation);
162
163 /*
164 * Read the maximum entries possible into the buffer
165 */
166 while ( i<EntriesToRead && current_entry!=(&(dir->head)))
167 {
168 current = CONTAINING_RECORD(current_entry,OBJECT_HEADER,Entry);
169 DPRINT("Scanning %w\n",current->Name.Buffer);
170 DirObjInformation[i].ObjectName.Buffer =
171 ExAllocatePool(NonPagedPool,(current->Name.Length+1)*2);
172 DirObjInformation[i].ObjectName.Length = current->Name.Length;
173 DirObjInformation[i].ObjectName.MaximumLength = current->Name.Length;
174 DPRINT("DirObjInformation[i].ObjectName.Buffer %x\n",
175 DirObjInformation[i].ObjectName.Buffer);
176 RtlCopyUnicodeString(&DirObjInformation[i].ObjectName,
177 &(current->Name));
178 i++;
179 current_entry = current_entry->Flink;
180 (*DataWritten) = (*DataWritten) + sizeof(OBJDIR_INFORMATION);
181 CHECKPOINT;
182 }
183 CHECKPOINT;
184
185 /*
186 * Optionally, count the number of entries in the directory
187 */
188 if (GetNextIndex)
189 {
190 *ObjectIndex=i;
191 }
192 else
193 {
194 while ( current_entry!=(&(dir->head)) )
195 {
196 current_entry=current_entry->Flink;
197 i++;
198 }
199 *ObjectIndex=i;
200 }
201 return(STATUS_SUCCESS);
202 }
203
204
205 NTSTATUS STDCALL NtCreateDirectoryObject(PHANDLE DirectoryHandle,
206 ACCESS_MASK DesiredAccess,
207 POBJECT_ATTRIBUTES ObjectAttributes)
208 {
209 return(ZwCreateDirectoryObject(DirectoryHandle,
210 DesiredAccess,
211 ObjectAttributes));
212 }
213
214 NTSTATUS STDCALL ZwCreateDirectoryObject(PHANDLE DirectoryHandle,
215 ACCESS_MASK DesiredAccess,
216 POBJECT_ATTRIBUTES ObjectAttributes)
217 /*
218 * FUNCTION: Creates or opens a directory object (a container for other
219 * objects)
220 * ARGUMENTS:
221 * DirectoryHandle (OUT) = Caller supplied storage for the handle
222 * of the directory
223 * DesiredAccess = Access desired to the directory
224 * ObjectAttributes = Object attributes initialized with
225 * InitializeObjectAttributes
226 * RETURNS: Status
227 */
228 {
229 PDIRECTORY_OBJECT dir;
230
231 dir = ObCreateObject(DirectoryHandle,
232 DesiredAccess,
233 ObjectAttributes,
234 ObDirectoryType);
235 return(STATUS_SUCCESS);
236 }
237
238 VOID InitializeObjectAttributes(POBJECT_ATTRIBUTES InitializedAttributes,
239 PUNICODE_STRING ObjectName,
240 ULONG Attributes,
241 HANDLE RootDirectory,
242 PSECURITY_DESCRIPTOR SecurityDescriptor)
243 /*
244 * FUNCTION: Sets up a parameter of type OBJECT_ATTRIBUTES for a
245 * subsequent call to ZwCreateXXX or ZwOpenXXX
246 * ARGUMENTS:
247 * InitializedAttributes (OUT) = Caller supplied storage for the
248 * object attributes
249 * ObjectName = Full path name for object
250 * Attributes = Attributes for the object
251 * RootDirectory = Where the object should be placed or NULL
252 * SecurityDescriptor = Ignored
253 *
254 * NOTE:
255 * Either ObjectName is a fully qualified pathname or a path relative
256 * to RootDirectory
257 */
258 {
259 DPRINT("InitializeObjectAttributes(InitializedAttributes %x "
260 "ObjectName %x Attributes %x RootDirectory %x)\n",
261 InitializedAttributes,ObjectName,Attributes,RootDirectory);
262 InitializedAttributes->Length=sizeof(OBJECT_ATTRIBUTES);
263 InitializedAttributes->RootDirectory=RootDirectory;
264 InitializedAttributes->ObjectName=ObjectName;
265 InitializedAttributes->Attributes=Attributes;
266 InitializedAttributes->SecurityDescriptor=SecurityDescriptor;
267 InitializedAttributes->SecurityQualityOfService=NULL;
268 }
269