[CMAKE]
[reactos.git] / drivers / filesystems / npfs / dirctl.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/filesastems/npfs/dirctl.c
5 * PURPOSE: Named pipe filesystem
6 * PROGRAMMER: Eric Kohl
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "npfs.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* FUNCTIONS *****************************************************************/
17
18 static NTSTATUS
19 NpfsQueryDirectory(PNPFS_CCB Ccb,
20 PIRP Irp,
21 PULONG Size)
22 {
23 PIO_STACK_LOCATION Stack;
24 LONG BufferLength = 0;
25 PUNICODE_STRING SearchPattern = NULL;
26 FILE_INFORMATION_CLASS FileInformationClass;
27 ULONG FileIndex = 0;
28 PUCHAR Buffer = NULL;
29 BOOLEAN First = FALSE;
30 PLIST_ENTRY CurrentEntry;
31 PNPFS_VCB Vcb;
32 PNPFS_FCB PipeFcb;
33 ULONG PipeIndex;
34 BOOLEAN Found = FALSE;
35 NTSTATUS Status = STATUS_SUCCESS;
36 PFILE_NAMES_INFORMATION NamesBuffer;
37 PFILE_DIRECTORY_INFORMATION DirectoryBuffer;
38 PFILE_FULL_DIR_INFORMATION FullDirBuffer;
39 PFILE_BOTH_DIR_INFORMATION BothDirBuffer;
40 ULONG InfoSize = 0;
41 ULONG NameLength;
42
43 Stack = IoGetCurrentIrpStackLocation(Irp);
44
45 /* Obtain the callers parameters */
46 BufferLength = Stack->Parameters.QueryDirectory.Length;
47 SearchPattern = Stack->Parameters.QueryDirectory.FileName;
48 FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass;
49 FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
50
51 DPRINT("SearchPattern: %p '%wZ'\n", SearchPattern, SearchPattern);
52
53 /* Determine Buffer for result */
54 if (Irp->MdlAddress)
55 {
56 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
57 }
58 else
59 {
60 Buffer = Irp->UserBuffer;
61 }
62
63 /* Build the search pattern string */
64 DPRINT("Ccb->u.Directory.SearchPattern.Buffer: %p\n", Ccb->u.Directory.SearchPattern.Buffer);
65 if (Ccb->u.Directory.SearchPattern.Buffer == NULL)
66 {
67 First = TRUE;
68
69 if (SearchPattern != NULL)
70 {
71 Ccb->u.Directory.SearchPattern.Buffer =
72 ExAllocatePool(NonPagedPool, SearchPattern->Length + sizeof(WCHAR));
73 if (Ccb->u.Directory.SearchPattern.Buffer == NULL)
74 {
75 return STATUS_INSUFFICIENT_RESOURCES;
76 }
77
78 Ccb->u.Directory.SearchPattern.Length = SearchPattern->Length;
79 Ccb->u.Directory.SearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
80 RtlCopyMemory(Ccb->u.Directory.SearchPattern.Buffer,
81 SearchPattern->Buffer,
82 SearchPattern->Length);
83 Ccb->u.Directory.SearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0;
84 }
85 else
86 {
87 Ccb->u.Directory.SearchPattern.Buffer =
88 ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
89 if (Ccb->u.Directory.SearchPattern.Buffer == NULL)
90 {
91 return STATUS_INSUFFICIENT_RESOURCES;
92 }
93
94 Ccb->u.Directory.SearchPattern.Length = sizeof(WCHAR);
95 Ccb->u.Directory.SearchPattern.MaximumLength = 2 * sizeof(WCHAR);
96 Ccb->u.Directory.SearchPattern.Buffer[0] = L'*';
97 Ccb->u.Directory.SearchPattern.Buffer[1] = 0;
98 }
99 }
100 DPRINT("Search pattern: '%wZ'\n", &Ccb->u.Directory.SearchPattern);
101
102 /* Determine the file index */
103 if (First || (Stack->Flags & SL_RESTART_SCAN))
104 {
105 FileIndex = 0;
106 } else if ((Stack->Flags & SL_INDEX_SPECIFIED) == 0)
107 {
108 FileIndex = Ccb->u.Directory.FileIndex + 1;
109 }
110 DPRINT("FileIndex: %lu\n", FileIndex);
111
112 DPRINT("Buffer = %p tofind = %wZ\n", Buffer, &Ccb->u.Directory.SearchPattern);
113
114 switch (FileInformationClass)
115 {
116 case FileDirectoryInformation:
117 InfoSize = sizeof(FILE_DIRECTORY_INFORMATION) - sizeof(WCHAR);
118 break;
119
120 case FileFullDirectoryInformation:
121 InfoSize = sizeof(FILE_FULL_DIR_INFORMATION) - sizeof(WCHAR);
122 break;
123
124 case FileBothDirectoryInformation:
125 InfoSize = sizeof(FILE_BOTH_DIR_INFORMATION) - sizeof(WCHAR);
126 break;
127
128 case FileNamesInformation:
129 InfoSize = sizeof(FILE_NAMES_INFORMATION) - sizeof(WCHAR);
130 break;
131
132 default:
133 DPRINT1("Invalid information class: %lu\n", FileInformationClass);
134 return STATUS_INVALID_INFO_CLASS;
135 }
136
137 PipeIndex = 0;
138
139 Vcb = Ccb->Fcb->Vcb;
140 CurrentEntry = Vcb->PipeListHead.Flink;
141 while (CurrentEntry != &Vcb->PipeListHead &&
142 Found == FALSE &&
143 Status == STATUS_SUCCESS)
144 {
145 /* Get the FCB of the next pipe */
146 PipeFcb = CONTAINING_RECORD(CurrentEntry,
147 NPFS_FCB,
148 PipeListEntry);
149
150 /* Make sure it is a pipe FCB */
151 ASSERT(PipeFcb->Type == FCB_PIPE);
152
153 DPRINT("PipeName: %wZ\n", &PipeFcb->PipeName);
154
155 if (FsRtlIsNameInExpression(&Ccb->u.Directory.SearchPattern,
156 &PipeFcb->PipeName,
157 TRUE,
158 NULL))
159 {
160 DPRINT("Found pipe: %wZ\n", &PipeFcb->PipeName);
161
162 if (PipeIndex >= FileIndex)
163 {
164 /* Determine whether or not the full pipe name fits into the buffer */
165 if (InfoSize + PipeFcb->PipeName.Length > BufferLength)
166 {
167 NameLength = BufferLength - InfoSize;
168 Status = STATUS_BUFFER_OVERFLOW;
169 }
170 else
171 {
172 NameLength = PipeFcb->PipeName.Length;
173 Status = STATUS_SUCCESS;
174 }
175
176 /* Initialize the information struct */
177 RtlZeroMemory(Buffer, InfoSize);
178
179 switch (FileInformationClass)
180 {
181 case FileDirectoryInformation:
182 DirectoryBuffer = (PFILE_DIRECTORY_INFORMATION)Buffer;
183 DirectoryBuffer->NextEntryOffset = 0;
184 DirectoryBuffer->FileIndex = PipeIndex;
185 DirectoryBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
186 DirectoryBuffer->EndOfFile.QuadPart = PipeFcb->CurrentInstances;
187 DirectoryBuffer->AllocationSize.LowPart = PipeFcb->MaximumInstances;
188 DirectoryBuffer->FileNameLength = NameLength;
189 RtlCopyMemory(DirectoryBuffer->FileName,
190 PipeFcb->PipeName.Buffer,
191 NameLength);
192 break;
193
194 case FileFullDirectoryInformation:
195 FullDirBuffer = (PFILE_FULL_DIR_INFORMATION)Buffer;
196 FullDirBuffer->NextEntryOffset = 0;
197 FullDirBuffer->FileIndex = PipeIndex;
198 FullDirBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
199 FullDirBuffer->EndOfFile.QuadPart = PipeFcb->CurrentInstances;
200 FullDirBuffer->AllocationSize.LowPart = PipeFcb->MaximumInstances;
201 FullDirBuffer->FileNameLength = NameLength;
202 RtlCopyMemory(FullDirBuffer->FileName,
203 PipeFcb->PipeName.Buffer,
204 NameLength);
205 break;
206
207 case FileBothDirectoryInformation:
208 BothDirBuffer = (PFILE_BOTH_DIR_INFORMATION)Buffer;
209 BothDirBuffer->NextEntryOffset = 0;
210 BothDirBuffer->FileIndex = PipeIndex;
211 BothDirBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
212 BothDirBuffer->EndOfFile.QuadPart = PipeFcb->CurrentInstances;
213 BothDirBuffer->AllocationSize.LowPart = PipeFcb->MaximumInstances;
214 BothDirBuffer->FileNameLength = NameLength;
215 RtlCopyMemory(BothDirBuffer->FileName,
216 PipeFcb->PipeName.Buffer,
217 NameLength);
218 break;
219
220 case FileNamesInformation:
221 NamesBuffer = (PFILE_NAMES_INFORMATION)Buffer;
222 NamesBuffer->NextEntryOffset = 0;
223 NamesBuffer->FileIndex = PipeIndex;
224 NamesBuffer->FileNameLength = NameLength;
225 RtlCopyMemory(NamesBuffer->FileName,
226 PipeFcb->PipeName.Buffer,
227 NameLength);
228 break;
229
230 default:
231 /* Should never happen! */
232 ASSERT(FALSE);
233 break;
234 }
235
236 *Size = InfoSize + NameLength;
237
238 Ccb->u.Directory.FileIndex = PipeIndex;
239 Found = TRUE;
240
241 // if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
242 // return STATUS_SUCCESS;
243
244 break;
245 }
246
247 PipeIndex++;
248 }
249
250 CurrentEntry = CurrentEntry->Flink;
251 }
252
253 if (Found == FALSE)
254 Status = STATUS_NO_MORE_FILES;
255
256 return Status;
257 }
258
259
260 NTSTATUS NTAPI
261 NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
262 PIRP Irp)
263 {
264 PIO_STACK_LOCATION IoStack;
265 PFILE_OBJECT FileObject;
266 PNPFS_CCB Ccb;
267 PNPFS_FCB Fcb;
268 NTSTATUS Status;
269 ULONG Size = 0;
270
271 DPRINT("NpfsDirectoryControl() called\n");
272
273 IoStack = IoGetCurrentIrpStackLocation(Irp);
274
275 FileObject = IoStack->FileObject;
276
277 if (NpfsGetCcb(FileObject, &Ccb) != CCB_DIRECTORY)
278 {
279 Status = STATUS_INVALID_PARAMETER;
280
281 Irp->IoStatus.Status = Status;
282 Irp->IoStatus.Information = 0;
283
284 IoCompleteRequest(Irp, IO_NO_INCREMENT);
285
286 return Status;
287 }
288
289 Fcb = Ccb->Fcb;
290
291 switch (IoStack->MinorFunction)
292 {
293 case IRP_MN_QUERY_DIRECTORY:
294 Status = NpfsQueryDirectory(Ccb,
295 Irp,
296 &Size);
297 break;
298
299 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
300 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
301 Status = STATUS_NOT_IMPLEMENTED;
302 break;
303
304 default:
305 DPRINT1("NPFS: MinorFunction %d\n", IoStack->MinorFunction);
306 Status = STATUS_INVALID_DEVICE_REQUEST;
307 break;
308 }
309
310 Irp->IoStatus.Status = Status;
311 Irp->IoStatus.Information = Size;
312
313 IoCompleteRequest(Irp, IO_NO_INCREMENT);
314
315 return Status;
316 }
317
318 /* EOF */