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