[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
41 Stack = IoGetCurrentIrpStackLocation(Irp);
42
43 /* Obtain the callers parameters */
44 BufferLength = Stack->Parameters.QueryDirectory.Length;
45 SearchPattern = Stack->Parameters.QueryDirectory.FileName;
46 FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass;
47 FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
48
49 DPRINT("SearchPattern: %p '%wZ'\n", SearchPattern, SearchPattern);
50
51 /* Determine Buffer for result */
52 if (Irp->MdlAddress)
53 {
54 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
55 }
56 else
57 {
58 Buffer = Irp->UserBuffer;
59 }
60
61 /* Build the search pattern string */
62 DPRINT("Ccb->u.Directory.SearchPattern.Buffer: %p\n", Ccb->u.Directory.SearchPattern.Buffer);
63 if (Ccb->u.Directory.SearchPattern.Buffer == NULL)
64 {
65 First = TRUE;
66
67 if (SearchPattern != NULL)
68 {
69 Ccb->u.Directory.SearchPattern.Buffer =
70 ExAllocatePool(NonPagedPool, SearchPattern->Length + sizeof(WCHAR));
71 if (Ccb->u.Directory.SearchPattern.Buffer == NULL)
72 {
73 return STATUS_INSUFFICIENT_RESOURCES;
74 }
75
76 Ccb->u.Directory.SearchPattern.Length = SearchPattern->Length;
77 Ccb->u.Directory.SearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
78 RtlCopyMemory(Ccb->u.Directory.SearchPattern.Buffer,
79 SearchPattern->Buffer,
80 SearchPattern->Length);
81 Ccb->u.Directory.SearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0;
82 }
83 else
84 {
85 Ccb->u.Directory.SearchPattern.Buffer =
86 ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
87 if (Ccb->u.Directory.SearchPattern.Buffer == NULL)
88 {
89 return STATUS_INSUFFICIENT_RESOURCES;
90 }
91
92 Ccb->u.Directory.SearchPattern.Length = sizeof(WCHAR);
93 Ccb->u.Directory.SearchPattern.MaximumLength = 2 * sizeof(WCHAR);
94 Ccb->u.Directory.SearchPattern.Buffer[0] = L'*';
95 Ccb->u.Directory.SearchPattern.Buffer[1] = 0;
96 }
97 }
98 DPRINT("Search pattern: '%wZ'\n", &Ccb->u.Directory.SearchPattern);
99
100 /* Determine the file index */
101 if (First || (Stack->Flags & SL_RESTART_SCAN))
102 {
103 FileIndex = 0;
104 } else if ((Stack->Flags & SL_INDEX_SPECIFIED) == 0)
105 {
106 FileIndex = Ccb->u.Directory.FileIndex + 1;
107 }
108 DPRINT("FileIndex: %lu\n", FileIndex);
109
110 DPRINT("Buffer = %p tofind = %wZ\n", Buffer, &Ccb->u.Directory.SearchPattern);
111
112 PipeIndex = 0;
113
114 Vcb = Ccb->Fcb->Vcb;
115 CurrentEntry = Vcb->PipeListHead.Flink;
116 while (CurrentEntry != &Vcb->PipeListHead && Found == FALSE)
117 {
118 /* Get the FCB of the next pipe */
119 PipeFcb = CONTAINING_RECORD(CurrentEntry,
120 NPFS_FCB,
121 PipeListEntry);
122
123 /* Make sure it is a pipe FCB */
124 ASSERT(PipeFcb->Type == FCB_PIPE);
125
126 DPRINT("PipeName: %wZ\n", &PipeFcb->PipeName);
127
128 if (FsRtlIsNameInExpression(&Ccb->u.Directory.SearchPattern,
129 &PipeFcb->PipeName,
130 TRUE,
131 NULL))
132 {
133 DPRINT("Found pipe: %wZ\n", &PipeFcb->PipeName);
134
135 if (PipeIndex >= FileIndex)
136 {
137 RtlZeroMemory(Buffer, BufferLength);
138
139 switch (FileInformationClass)
140 {
141 case FileDirectoryInformation:
142 DirectoryBuffer = (PFILE_DIRECTORY_INFORMATION)Buffer;
143 DirectoryBuffer->NextEntryOffset = 0;
144 DirectoryBuffer->FileIndex = PipeIndex;
145 DirectoryBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
146 DirectoryBuffer->EndOfFile.QuadPart = PipeFcb->CurrentInstances;
147 DirectoryBuffer->AllocationSize.LowPart = PipeFcb->MaximumInstances;
148 DirectoryBuffer->FileNameLength = PipeFcb->PipeName.Length;
149 RtlCopyMemory(DirectoryBuffer->FileName,
150 PipeFcb->PipeName.Buffer,
151 PipeFcb->PipeName.Length);
152 *Size = sizeof(FILE_DIRECTORY_INFORMATION) + PipeFcb->PipeName.Length - sizeof(WCHAR);
153 Status = STATUS_SUCCESS;
154 break;
155
156 case FileFullDirectoryInformation:
157 FullDirBuffer = (PFILE_FULL_DIR_INFORMATION)Buffer;
158 FullDirBuffer->NextEntryOffset = 0;
159 FullDirBuffer->FileIndex = PipeIndex;
160 FullDirBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
161 FullDirBuffer->EndOfFile.QuadPart = PipeFcb->CurrentInstances;
162 FullDirBuffer->AllocationSize.LowPart = PipeFcb->MaximumInstances;
163 FullDirBuffer->FileNameLength = PipeFcb->PipeName.Length;
164 RtlCopyMemory(FullDirBuffer->FileName,
165 PipeFcb->PipeName.Buffer,
166 PipeFcb->PipeName.Length);
167 *Size = sizeof(FILE_FULL_DIR_INFORMATION) + PipeFcb->PipeName.Length - sizeof(WCHAR);
168 Status = STATUS_SUCCESS;
169 break;
170
171 case FileBothDirectoryInformation:
172 BothDirBuffer = (PFILE_BOTH_DIR_INFORMATION)Buffer;
173 BothDirBuffer->NextEntryOffset = 0;
174 BothDirBuffer->FileIndex = PipeIndex;
175 BothDirBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
176 BothDirBuffer->EndOfFile.QuadPart = PipeFcb->CurrentInstances;
177 BothDirBuffer->AllocationSize.LowPart = PipeFcb->MaximumInstances;
178 BothDirBuffer->FileNameLength = PipeFcb->PipeName.Length;
179 RtlCopyMemory(BothDirBuffer->FileName,
180 PipeFcb->PipeName.Buffer,
181 PipeFcb->PipeName.Length);
182 *Size = sizeof(FILE_BOTH_DIR_INFORMATION) + PipeFcb->PipeName.Length - sizeof(WCHAR);
183 Status = STATUS_SUCCESS;
184 break;
185
186 case FileNamesInformation:
187 NamesBuffer = (PFILE_NAMES_INFORMATION)Buffer;
188 NamesBuffer->NextEntryOffset = 0;
189 NamesBuffer->FileIndex = PipeIndex;
190 NamesBuffer->FileNameLength = PipeFcb->PipeName.Length;
191 RtlCopyMemory(NamesBuffer->FileName,
192 PipeFcb->PipeName.Buffer,
193 PipeFcb->PipeName.Length);
194 *Size = sizeof(FILE_NAMES_INFORMATION) + PipeFcb->PipeName.Length - sizeof(WCHAR);
195 Status = STATUS_SUCCESS;
196 break;
197
198 default:
199 DPRINT1("Invalid information class: %lu\n", FileInformationClass);
200 Status = STATUS_INVALID_INFO_CLASS;
201 break;
202 }
203
204 Ccb->u.Directory.FileIndex = PipeIndex;
205 Found = TRUE;
206
207 // if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
208 // return STATUS_SUCCESS;
209
210 break;
211 }
212
213 PipeIndex++;
214 }
215
216 CurrentEntry = CurrentEntry->Flink;
217 }
218
219 if (Found == FALSE)
220 Status = STATUS_NO_MORE_FILES;
221
222 return Status;
223 }
224
225
226 NTSTATUS NTAPI
227 NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
228 PIRP Irp)
229 {
230 PIO_STACK_LOCATION IoStack;
231 PFILE_OBJECT FileObject;
232 PNPFS_CCB Ccb;
233 PNPFS_FCB Fcb;
234 NTSTATUS Status;
235 ULONG Size = 0;
236
237 DPRINT("NpfsDirectoryControl() called\n");
238
239 IoStack = IoGetCurrentIrpStackLocation(Irp);
240
241 FileObject = IoStack->FileObject;
242
243 if (NpfsGetCcb(FileObject, &Ccb) != CCB_DIRECTORY)
244 {
245 Status = STATUS_INVALID_PARAMETER;
246
247 Irp->IoStatus.Status = Status;
248 Irp->IoStatus.Information = 0;
249
250 IoCompleteRequest(Irp, IO_NO_INCREMENT);
251
252 return Status;
253 }
254
255 Fcb = Ccb->Fcb;
256
257 switch (IoStack->MinorFunction)
258 {
259 case IRP_MN_QUERY_DIRECTORY:
260 Status = NpfsQueryDirectory(Ccb,
261 Irp,
262 &Size);
263 break;
264
265 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
266 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
267 Status = STATUS_NOT_IMPLEMENTED;
268 break;
269
270 default:
271 DPRINT1("NPFS: MinorFunction %d\n", IoStack->MinorFunction);
272 Status = STATUS_INVALID_DEVICE_REQUEST;
273 break;
274 }
275
276 Irp->IoStatus.Status = Status;
277 Irp->IoStatus.Information = Size;
278
279 IoCompleteRequest(Irp, IO_NO_INCREMENT);
280
281 return Status;
282 }
283
284 /* EOF */