90b918009276e181abd521198c186af2edaa450e
[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 NTSTATUS Status;
42 PIO_STACK_LOCATION IoStack;
43 KPROCESSOR_MODE PreviousMode;
44
45 DPRINT("NtNotifyChangeDirectoryFile()\n");
46
47 PreviousMode = ExGetPreviousMode();
48
49 Status = ObReferenceObjectByHandle(FileHandle,
50 FILE_LIST_DIRECTORY,
51 IoFileObjectType,
52 PreviousMode,
53 (PVOID *)&FileObject,
54 NULL);
55
56 if (Status != STATUS_SUCCESS)
57 {
58 return(Status);
59 }
60 DeviceObject = FileObject->DeviceObject;
61
62 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
63 if (Irp==NULL)
64 {
65 ObDereferenceObject(FileObject);
66 return STATUS_UNSUCCESSFUL;
67 }
68
69 if (Event == NULL)
70 {
71 Event = &FileObject->Event;
72 }
73
74 /* Trigger FileObject/Event dereferencing */
75 Irp->Tail.Overlay.OriginalFileObject = FileObject;
76 Irp->RequestorMode = PreviousMode;
77 Irp->UserIosb = IoStatusBlock;
78 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
79 Irp->UserEvent = Event;
80 KeResetEvent( Event );
81 Irp->UserBuffer = Buffer;
82 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
83 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
84
85 IoStack = IoGetNextIrpStackLocation(Irp);
86
87 IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
88 IoStack->MinorFunction = IRP_MN_NOTIFY_CHANGE_DIRECTORY;
89 IoStack->Flags = 0;
90 IoStack->Control = 0;
91 IoStack->DeviceObject = DeviceObject;
92 IoStack->FileObject = FileObject;
93
94 if (WatchTree)
95 {
96 IoStack->Flags = SL_WATCH_TREE;
97 }
98
99 IoStack->Parameters.NotifyDirectory.CompletionFilter = CompletionFilter;
100 IoStack->Parameters.NotifyDirectory.Length = BufferSize;
101
102 Status = IoCallDriver(FileObject->DeviceObject,Irp);
103
104 /* FIXME: Should we wait here or not for synchronously opened files? */
105
106 return Status;
107 }
108
109
110 /*
111 * @implemented
112 */
113 NTSTATUS
114 STDCALL
115 NtQueryDirectoryFile(
116 IN HANDLE FileHandle,
117 IN HANDLE PEvent OPTIONAL,
118 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
119 IN PVOID ApcContext OPTIONAL,
120 OUT PIO_STATUS_BLOCK IoStatusBlock,
121 OUT PVOID FileInformation,
122 IN ULONG Length,
123 IN FILE_INFORMATION_CLASS FileInformationClass,
124 IN BOOLEAN ReturnSingleEntry,
125 IN PUNICODE_STRING FileName OPTIONAL,
126 IN BOOLEAN RestartScan
127 )
128 /*
129 * FUNCTION: Queries a directory file.
130 * ARGUMENTS:
131 * FileHandle = Handle to a directory file
132 * EventHandle = Handle to the event signaled on completion
133 * ApcRoutine = Asynchroneous procedure callback, called on completion
134 * ApcContext = Argument to the apc.
135 * IoStatusBlock = Caller supplies storage for extended status information.
136 * FileInformation = Caller supplies storage for the resulting information.
137 *
138 * FileNameInformation FILE_NAMES_INFORMATION
139 * FileDirectoryInformation FILE_DIRECTORY_INFORMATION
140 * FileFullDirectoryInformation FILE_FULL_DIRECTORY_INFORMATION
141 * FileBothDirectoryInformation FILE_BOTH_DIR_INFORMATION
142 *
143 * Length = Size of the storage supplied
144 * FileInformationClass = Indicates the type of information requested.
145 * ReturnSingleEntry = Specify true if caller only requests the first
146 * directory found.
147 * FileName = Initial directory name to query, that may contain wild
148 * cards.
149 * RestartScan = Number of times the action should be repeated
150 * RETURNS: Status [ STATUS_SUCCESS, STATUS_ACCESS_DENIED, STATUS_INSUFFICIENT_RESOURCES,
151 * STATUS_INVALID_PARAMETER, STATUS_INVALID_DEVICE_REQUEST, STATUS_BUFFER_OVERFLOW,
152 * STATUS_INVALID_INFO_CLASS, STATUS_NO_SUCH_FILE, STATUS_NO_MORE_FILES ]
153 */
154 {
155 PIRP Irp;
156 PDEVICE_OBJECT DeviceObject;
157 PFILE_OBJECT FileObject;
158 NTSTATUS Status;
159 PIO_STACK_LOCATION IoStack;
160 KPROCESSOR_MODE PreviousMode;
161
162 DPRINT("NtQueryDirectoryFile()\n");
163
164 PreviousMode = ExGetPreviousMode();
165
166 Status = ObReferenceObjectByHandle(FileHandle,
167 FILE_LIST_DIRECTORY,
168 IoFileObjectType,
169 PreviousMode,
170 (PVOID *)&FileObject,
171 NULL);
172
173 if (Status != STATUS_SUCCESS)
174 {
175 return(Status);
176 }
177 DeviceObject = FileObject->DeviceObject;
178
179 Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
180 if (Irp==NULL)
181 {
182 ObDereferenceObject(FileObject);
183 return STATUS_UNSUCCESSFUL;
184 }
185
186 /* Trigger FileObject/Event dereferencing */
187 Irp->Tail.Overlay.OriginalFileObject = FileObject;
188 Irp->RequestorMode = PreviousMode;
189 Irp->UserIosb = IoStatusBlock;
190 Irp->UserEvent = &FileObject->Event;
191 Irp->Tail.Overlay.Thread = PsGetCurrentThread();
192 KeResetEvent( &FileObject->Event );
193 Irp->UserBuffer=FileInformation;
194 Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
195 Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
196
197 IoStack = IoGetNextIrpStackLocation(Irp);
198
199 IoStack->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
200 IoStack->MinorFunction = IRP_MN_QUERY_DIRECTORY;
201 IoStack->Flags = 0;
202 IoStack->Control = 0;
203 IoStack->DeviceObject = DeviceObject;
204 IoStack->FileObject = FileObject;
205
206 if (RestartScan)
207 {
208 IoStack->Flags = IoStack->Flags | SL_RESTART_SCAN;
209 }
210 if (ReturnSingleEntry)
211 {
212 IoStack->Flags = IoStack->Flags | SL_RETURN_SINGLE_ENTRY;
213 }
214 if (((PFILE_DIRECTORY_INFORMATION)FileInformation)->FileIndex != 0)
215 {
216 IoStack->Flags = IoStack->Flags | SL_INDEX_SPECIFIED;
217 }
218
219 IoStack->Parameters.QueryDirectory.FileInformationClass =
220 FileInformationClass;
221 IoStack->Parameters.QueryDirectory.FileName = FileName;
222 IoStack->Parameters.QueryDirectory.Length = Length;
223
224 Status = IoCallDriver(FileObject->DeviceObject,Irp);
225 if (Status==STATUS_PENDING && !(FileObject->Flags & FO_SYNCHRONOUS_IO))
226 {
227 KeWaitForSingleObject(&FileObject->Event,
228 Executive,
229 PreviousMode,
230 FileObject->Flags & FO_ALERTABLE_IO,
231 NULL);
232 Status = IoStatusBlock->Status;
233 }
234
235 return(Status);
236 }
237
238 /* EOF */