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