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
9 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
19 NpfsQueryDirectory(PNPFS_CCB Ccb
,
23 PIO_STACK_LOCATION Stack
;
24 ULONG BufferLength
= 0;
25 PUNICODE_STRING SearchPattern
= NULL
;
26 FILE_INFORMATION_CLASS FileInformationClass
;
29 BOOLEAN First
= FALSE
;
30 PLIST_ENTRY CurrentEntry
;
34 NTSTATUS Status
= STATUS_SUCCESS
;
35 PFILE_NAMES_INFORMATION NamesBuffer
;
36 PFILE_DIRECTORY_INFORMATION DirectoryBuffer
;
37 PFILE_FULL_DIR_INFORMATION FullDirBuffer
;
38 PFILE_BOTH_DIR_INFORMATION BothDirBuffer
;
41 ULONG CurrentOffset
= 0;
43 PULONG NextEntryOffset
;
45 Stack
= IoGetCurrentIrpStackLocation(Irp
);
47 /* Obtain the callers parameters */
48 BufferLength
= Stack
->Parameters
.QueryDirectory
.Length
;
49 SearchPattern
= Stack
->Parameters
.QueryDirectory
.FileName
;
50 FileInformationClass
= Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
51 FileIndex
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
53 DPRINT("SearchPattern: %p '%wZ'\n", SearchPattern
, SearchPattern
);
55 /* Determine Buffer for result */
58 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
62 Buffer
= Irp
->UserBuffer
;
65 /* Build the search pattern string */
66 DPRINT("Ccb->u.Directory.SearchPattern.Buffer: %p\n", Ccb
->u
.Directory
.SearchPattern
.Buffer
);
67 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
71 if (SearchPattern
!= NULL
)
73 Ccb
->u
.Directory
.SearchPattern
.Buffer
=
74 ExAllocatePoolWithTag(NonPagedPool
,
75 SearchPattern
->Length
+ sizeof(WCHAR
),
77 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
79 return STATUS_INSUFFICIENT_RESOURCES
;
82 Ccb
->u
.Directory
.SearchPattern
.Length
= SearchPattern
->Length
;
83 Ccb
->u
.Directory
.SearchPattern
.MaximumLength
= SearchPattern
->Length
+ sizeof(WCHAR
);
84 RtlCopyMemory(Ccb
->u
.Directory
.SearchPattern
.Buffer
,
85 SearchPattern
->Buffer
,
86 SearchPattern
->Length
);
87 Ccb
->u
.Directory
.SearchPattern
.Buffer
[SearchPattern
->Length
/ sizeof(WCHAR
)] = 0;
91 Ccb
->u
.Directory
.SearchPattern
.Buffer
=
92 ExAllocatePoolWithTag(NonPagedPool
,
95 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
97 return STATUS_INSUFFICIENT_RESOURCES
;
100 Ccb
->u
.Directory
.SearchPattern
.Length
= sizeof(WCHAR
);
101 Ccb
->u
.Directory
.SearchPattern
.MaximumLength
= 2 * sizeof(WCHAR
);
102 Ccb
->u
.Directory
.SearchPattern
.Buffer
[0] = L
'*';
103 Ccb
->u
.Directory
.SearchPattern
.Buffer
[1] = 0;
106 DPRINT("Search pattern: '%wZ'\n", &Ccb
->u
.Directory
.SearchPattern
);
108 /* Determine the file index */
109 if (First
|| (Stack
->Flags
& SL_RESTART_SCAN
))
113 else if ((Stack
->Flags
& SL_INDEX_SPECIFIED
) == 0)
115 FileIndex
= Ccb
->u
.Directory
.FileIndex
+ 1;
117 DPRINT("FileIndex: %lu\n", FileIndex
);
119 DPRINT("Buffer = %p tofind = %wZ\n", Buffer
, &Ccb
->u
.Directory
.SearchPattern
);
121 switch (FileInformationClass
)
123 case FileDirectoryInformation
:
124 InfoSize
= sizeof(FILE_DIRECTORY_INFORMATION
) - sizeof(WCHAR
);
127 case FileFullDirectoryInformation
:
128 InfoSize
= sizeof(FILE_FULL_DIR_INFORMATION
) - sizeof(WCHAR
);
131 case FileBothDirectoryInformation
:
132 InfoSize
= sizeof(FILE_BOTH_DIR_INFORMATION
) - sizeof(WCHAR
);
135 case FileNamesInformation
:
136 InfoSize
= sizeof(FILE_NAMES_INFORMATION
) - sizeof(WCHAR
);
140 DPRINT1("Invalid information class: %lu\n", FileInformationClass
);
141 return STATUS_INVALID_INFO_CLASS
;
147 CurrentEntry
= Vcb
->PipeListHead
.Flink
;
148 while (CurrentEntry
!= &Vcb
->PipeListHead
&&
149 Status
== STATUS_SUCCESS
)
151 /* Get the FCB of the next pipe */
152 PipeFcb
= CONTAINING_RECORD(CurrentEntry
,
156 /* Make sure it is a pipe FCB */
157 ASSERT(PipeFcb
->Type
== FCB_PIPE
);
159 DPRINT("PipeName: %wZ\n", &PipeFcb
->PipeName
);
161 if (FsRtlIsNameInExpression(&Ccb
->u
.Directory
.SearchPattern
,
166 DPRINT("Found pipe: %wZ\n", &PipeFcb
->PipeName
);
168 if (PipeIndex
>= FileIndex
)
170 /* Determine whether or not the full pipe name fits into the buffer */
171 if (InfoSize
+ PipeFcb
->PipeName
.Length
> BufferLength
)
173 NameLength
= BufferLength
- InfoSize
;
174 Status
= STATUS_BUFFER_OVERFLOW
;
178 NameLength
= PipeFcb
->PipeName
.Length
;
179 Status
= STATUS_SUCCESS
;
182 /* Initialize the information struct */
183 RtlZeroMemory(&Buffer
[CurrentOffset
], InfoSize
);
185 switch (FileInformationClass
)
187 case FileDirectoryInformation
:
188 DirectoryBuffer
= (PFILE_DIRECTORY_INFORMATION
)&Buffer
[CurrentOffset
];
189 DirectoryBuffer
->FileIndex
= PipeIndex
;
190 DirectoryBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
191 DirectoryBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
192 DirectoryBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
193 DirectoryBuffer
->FileNameLength
= NameLength
;
194 RtlCopyMemory(DirectoryBuffer
->FileName
,
195 PipeFcb
->PipeName
.Buffer
,
199 case FileFullDirectoryInformation
:
200 FullDirBuffer
= (PFILE_FULL_DIR_INFORMATION
)&Buffer
[CurrentOffset
];
201 FullDirBuffer
->FileIndex
= PipeIndex
;
202 FullDirBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
203 FullDirBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
204 FullDirBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
205 FullDirBuffer
->FileNameLength
= NameLength
;
206 RtlCopyMemory(FullDirBuffer
->FileName
,
207 PipeFcb
->PipeName
.Buffer
,
211 case FileBothDirectoryInformation
:
212 BothDirBuffer
= (PFILE_BOTH_DIR_INFORMATION
)&Buffer
[CurrentOffset
];
213 BothDirBuffer
->NextEntryOffset
= 0;
214 BothDirBuffer
->FileIndex
= PipeIndex
;
215 BothDirBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
216 BothDirBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
217 BothDirBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
218 BothDirBuffer
->FileNameLength
= NameLength
;
219 RtlCopyMemory(BothDirBuffer
->FileName
,
220 PipeFcb
->PipeName
.Buffer
,
224 case FileNamesInformation
:
225 NamesBuffer
= (PFILE_NAMES_INFORMATION
)&Buffer
[CurrentOffset
];
226 NamesBuffer
->FileIndex
= PipeIndex
;
227 NamesBuffer
->FileNameLength
= NameLength
;
228 RtlCopyMemory(NamesBuffer
->FileName
,
229 PipeFcb
->PipeName
.Buffer
,
234 /* Should never happen! */
239 DPRINT("CurrentOffset: %lu\n", CurrentOffset
);
241 /* Store the current pipe index in the CCB */
242 Ccb
->u
.Directory
.FileIndex
= PipeIndex
;
244 /* Get the pointer to the previous entries NextEntryOffset */
245 NextEntryOffset
= (PULONG
)&Buffer
[LastOffset
];
247 /* Set the previous entries NextEntryOffset */
248 *NextEntryOffset
= CurrentOffset
- LastOffset
;
250 /* Return the used buffer size */
251 *Size
= CurrentOffset
+ InfoSize
+ NameLength
;
253 /* Leave, if there is no space left in the buffer */
254 if (Status
== STATUS_BUFFER_OVERFLOW
)
257 /* Leave, if we should return only one entry */
258 if (Stack
->Flags
& SL_RETURN_SINGLE_ENTRY
)
259 return STATUS_SUCCESS
;
261 /* Store the current offset for the next round */
262 LastOffset
= CurrentOffset
;
264 /* Set the offset for the next entry */
265 CurrentOffset
+= ROUND_UP(InfoSize
+ NameLength
, sizeof(ULONG
));
271 CurrentEntry
= CurrentEntry
->Flink
;
274 /* Return STATUS_NO_MORE_FILES if no matching pipe name was found */
275 if (CurrentOffset
== 0)
276 Status
= STATUS_NO_MORE_FILES
;
283 NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject
,
286 PIO_STACK_LOCATION IoStack
;
287 PFILE_OBJECT FileObject
;
293 DPRINT("NpfsDirectoryControl() called\n");
295 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
297 FileObject
= IoStack
->FileObject
;
299 if (NpfsGetCcb(FileObject
, &Ccb
) != CCB_DIRECTORY
)
301 Status
= STATUS_INVALID_PARAMETER
;
303 Irp
->IoStatus
.Status
= Status
;
304 Irp
->IoStatus
.Information
= 0;
306 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
313 switch (IoStack
->MinorFunction
)
315 case IRP_MN_QUERY_DIRECTORY
:
316 Status
= NpfsQueryDirectory(Ccb
,
321 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
322 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
323 Status
= STATUS_NOT_IMPLEMENTED
;
327 DPRINT1("NPFS: MinorFunction %d\n", IoStack
->MinorFunction
);
328 Status
= STATUS_INVALID_DEVICE_REQUEST
;
332 Irp
->IoStatus
.Status
= Status
;
333 Irp
->IoStatus
.Information
= Size
;
335 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);