Thomas Weidenmueller <w3seek@reactos.com>
[reactos.git] / reactos / ntoskrnl / io / dir.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/io/dir.c
6 * PURPOSE: Directory functions
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* FUNCTIONS *****************************************************************/
18
19
20
21 /*
22 * @implemented
23 */
24 NTSTATUS
25 STDCALL
26 NtNotifyChangeDirectoryFile (
27 IN HANDLE FileHandle,
28 IN HANDLE Event OPTIONAL,
29 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
30 IN PVOID ApcContext OPTIONAL,
31 OUT PIO_STATUS_BLOCK IoStatusBlock,
32 OUT PVOID Buffer,
33 IN ULONG BufferSize,
34 IN ULONG CompletionFilter,
35 IN BOOLEAN WatchTree
36 )
37 {
38 PIRP Irp;
39 PDEVICE_OBJECT DeviceObject;
40 PFILE_OBJECT FileObject;
41 PIO_STACK_LOCATION IoStack;
42 KPROCESSOR_MODE PreviousMode;
43 NTSTATUS Status = STATUS_SUCCESS;
44
45 DPRINT("NtNotifyChangeDirectoryFile()\n");
46
47 PAGED_CODE();
48
49 PreviousMode = ExGetPreviousMode();
50
51 if(PreviousMode != KernelMode)
52 {
53 _SEH_TRY
54 {
55 ProbeForWrite(IoStatusBlock,
56 sizeof(IO_STATUS_BLOCK),
57 sizeof(ULONG));
58 if(BufferSize != 0)
59 {
60 ProbeForWrite(Buffer,
61 BufferSize,
62 sizeof(ULONG));
63 }
64 }
65 _SEH_HANDLE
66 {
67 Status = _SEH_GetExceptionCode();
68 }
69 _SEH_END;
70
71 if(!NT_SUCCESS(Status))
72 {
73 return Status;
74 }
75 }
76
77 Status = ObReferenceObjectByHandle(FileHandle,
78 FILE_LIST_DIRECTORY,
79 IoFileObjectType,
80 PreviousMode,
81 (PVOID *)&FileObject,
82 NULL);
83
84 if (Status != STATUS_SUCCESS)
85 {
86 return(Status);
87 }
88 DeviceObject = FileObject->DeviceObject;
89
90 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
91 if (Irp==NULL)
92 {
93 ObDereferenceObject(FileObject);
94 return STATUS_UNSUCCESSFUL;
95 }
96
97 if (Event == NULL)
98 {
99 Event = &FileObject->Event;
100 }
101
102 /* Trigger FileObject/Event dereferencing */
103 Irp->Tail.Overlay.OriginalFileObject = FileObject;
104 Irp->RequestorMode = PreviousMode;
105 Irp->UserIosb = IoStatusBlock;
106 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
107 Irp->UserEvent = Event;
108 KeResetEvent( Event );
109 Irp->UserBuffer = Buffer;
110 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
111 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
112
113 IoStack = IoGetNextIrpStackLocation(Irp);
114
115 IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
116 IoStack->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
117 IoStack->Flags = 0;
118 IoStack->Control = 0;
119 IoStack->DeviceObject = DeviceObject;
120 IoStack->FileObject = FileObject;
121
122 if (WatchTree)
123 {
124 IoStack->Flags = SL_WATCH_TREE;
125 }
126
127 IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
128 IoStack->Parameters.NotifyDirectory.Length = BufferSize;
129
130 Status = IoCallDriver(FileObject->DeviceObject,Irp);
131
132 /* FIXME: Should we wait here or not for synchronously opened files? */
133
134 return Status;
135 }
136
137
138 /*
139 * @implemented
140 */
141 NTSTATUS
142 STDCALL
143 NtQueryDirectoryFile(
144 IN HANDLE FileHandle,
145 IN HANDLE PEvent OPTIONAL,
146 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
147 IN PVOID ApcContext OPTIONAL,
148 OUT PIO_STATUS_BLOCK IoStatusBlock,
149 OUT PVOID FileInformation,
150 IN ULONG Length,
151 IN FILE_INFORMATION_CLASS FileInformationClass,
152 IN BOOLEAN ReturnSingleEntry,
153 IN PUNICODE_STRING FileName OPTIONAL,
154 IN BOOLEAN RestartScan
155 )
156 /*
157 * FUNCTION: Queries a directory file.
158 * ARGUMENTS:
159 * FileHandle = Handle to a directory file
160 * EventHandle = Handle to the event signaled on completion
161 * ApcRoutine = Asynchroneous procedure callback, called on completion
162 * ApcContext = Argument to the apc.
163 * IoStatusBlock = Caller supplies storage for extended status information.
164 * FileInformation = Caller supplies storage for the resulting information.
165 *
166 * FileNameInformation FILE_NAMES_INFORMATION
167 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
168 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
169 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
170 *
171 * Length = Size of the storage supplied
172 * FileInformationClass = Indicates the type of information requested.
173 * ReturnSingleEntry = Specify true if caller only requests the first
174 * directory found.
175 * FileName = Initial directory name to query, that may contain wild
176 * cards.
177 * RestartScan = Number of times the action should be repeated
178 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
179 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
180 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
181 */
182 {
183 PIRP Irp;
184 PDEVICE_OBJECT DeviceObject;
185 PFILE_OBJECT FileObject;
186 PIO_STACK_LOCATION IoStack;
187 KPROCESSOR_MODE PreviousMode;
188 NTSTATUS Status = STATUS_SUCCESS;
189
190 DPRINT("NtQueryDirectoryFile()\n");
191
192 PAGED_CODE();
193
194 PreviousMode = ExGetPreviousMode();
195
196 if(PreviousMode != KernelMode)
197 {
198 _SEH_TRY
199 {
200 ProbeForWrite(IoStatusBlock,
201 sizeof(IO_STATUS_BLOCK),
202 sizeof(ULONG));
203 ProbeForWrite(FileInformation,
204 Length,
205 sizeof(ULONG));
206 }
207 _SEH_HANDLE
208 {
209 Status = _SEH_GetExceptionCode();
210 }
211 _SEH_END;
212
213 if(!NT_SUCCESS(Status))
214 {
215 return Status;
216 }
217 }
218
219 Status = ObReferenceObjectByHandle(FileHandle,
220 FILE_LIST_DIRECTORY,
221 IoFileObjectType,
222 PreviousMode,
223 (PVOID *)&FileObject,
224 NULL);
225
226 if (Status != STATUS_SUCCESS)
227 {
228 return(Status);
229 }
230 DeviceObject = FileObject->DeviceObject;
231
232 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
233 if (Irp==NULL)
234 {
235 ObDereferenceObject(FileObject);
236 return STATUS_UNSUCCESSFUL;
237 }
238
239 /* Trigger FileObject/Event dereferencing */
240 Irp->Tail.Overlay.OriginalFileObject = FileObject;
241 Irp->RequestorMode = PreviousMode;
242 Irp->UserIosb = IoStatusBlock;
243 Irp->UserEvent = &FileObject->Event;
244 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
245 KeResetEvent( &FileObject->Event );
246 Irp->UserBuffer=FileInformation;
247 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
248 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
249
250 IoStack = IoGetNextIrpStackLocation(Irp);
251
252 IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
253 IoStack->MinorFunction = IRP_MN_QUERY_DIRECTORY;
254 IoStack->Flags = 0;
255 IoStack->Control = 0;
256 IoStack->DeviceObject = DeviceObject;
257 IoStack->FileObject = FileObject;
258
259 if (RestartScan)
260 {
261 IoStack->Flags = IoStack->Flags | SL_RESTART_SCAN;
262 }
263 if (ReturnSingleEntry)
264 {
265 IoStack->Flags = IoStack->Flags | SL_RETURN_SINGLE_ENTRY;
266 }
267 if (((PFILE_DIRECTORY_INFORMATION)FileInformation)->FileIndex != 0)
268 {
269 IoStack->Flags = IoStack->Flags | SL_INDEX_SPECIFIED;
270 }
271
272 IoStack->Parameters.QueryDirectory.FileInformationClass =
273 FileInformationClass;
274 IoStack->Parameters.QueryDirectory.FileName = FileName;
275 IoStack->Parameters.QueryDirectory.Length = Length;
276
277 Status = IoCallDriver(FileObject->DeviceObject,Irp);
278 if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
279 {
280 KeWaitForSingleObject(&FileObject->Event,
281 Executive,
282 PreviousMode,
283 FileObject->Flags & FO_ALERTABLE_IO,
284 NULL);
285 Status = IoStatusBlock->Status;
286 }
287
288 return(Status);
289 }
290
291 /* EOF */