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 LONG BufferLength
= 0;
25 PUNICODE_STRING SearchPattern
= NULL
;
26 FILE_INFORMATION_CLASS FileInformationClass
;
29 BOOLEAN First
= FALSE
;
30 PLIST_ENTRY CurrentEntry
;
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
;
43 Stack
= IoGetCurrentIrpStackLocation(Irp
);
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
;
51 DPRINT("SearchPattern: %p '%wZ'\n", SearchPattern
, SearchPattern
);
53 /* Determine Buffer for result */
56 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
60 Buffer
= Irp
->UserBuffer
;
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
)
69 if (SearchPattern
!= NULL
)
71 Ccb
->u
.Directory
.SearchPattern
.Buffer
=
72 ExAllocatePool(NonPagedPool
, SearchPattern
->Length
+ sizeof(WCHAR
));
73 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
75 return STATUS_INSUFFICIENT_RESOURCES
;
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;
87 Ccb
->u
.Directory
.SearchPattern
.Buffer
=
88 ExAllocatePool(NonPagedPool
, 2 * sizeof(WCHAR
));
89 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
91 return STATUS_INSUFFICIENT_RESOURCES
;
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;
100 DPRINT("Search pattern: '%wZ'\n", &Ccb
->u
.Directory
.SearchPattern
);
102 /* Determine the file index */
103 if (First
|| (Stack
->Flags
& SL_RESTART_SCAN
))
106 } else if ((Stack
->Flags
& SL_INDEX_SPECIFIED
) == 0)
108 FileIndex
= Ccb
->u
.Directory
.FileIndex
+ 1;
110 DPRINT("FileIndex: %lu\n", FileIndex
);
112 DPRINT("Buffer = %p tofind = %wZ\n", Buffer
, &Ccb
->u
.Directory
.SearchPattern
);
114 switch (FileInformationClass
)
116 case FileDirectoryInformation
:
117 InfoSize
= sizeof(FILE_DIRECTORY_INFORMATION
) - sizeof(WCHAR
);
120 case FileFullDirectoryInformation
:
121 InfoSize
= sizeof(FILE_FULL_DIR_INFORMATION
) - sizeof(WCHAR
);
124 case FileBothDirectoryInformation
:
125 InfoSize
= sizeof(FILE_BOTH_DIR_INFORMATION
) - sizeof(WCHAR
);
128 case FileNamesInformation
:
129 InfoSize
= sizeof(FILE_NAMES_INFORMATION
) - sizeof(WCHAR
);
133 DPRINT1("Invalid information class: %lu\n", FileInformationClass
);
134 return STATUS_INVALID_INFO_CLASS
;
140 CurrentEntry
= Vcb
->PipeListHead
.Flink
;
141 while (CurrentEntry
!= &Vcb
->PipeListHead
&&
143 Status
== STATUS_SUCCESS
)
145 /* Get the FCB of the next pipe */
146 PipeFcb
= CONTAINING_RECORD(CurrentEntry
,
150 /* Make sure it is a pipe FCB */
151 ASSERT(PipeFcb
->Type
== FCB_PIPE
);
153 DPRINT("PipeName: %wZ\n", &PipeFcb
->PipeName
);
155 if (FsRtlIsNameInExpression(&Ccb
->u
.Directory
.SearchPattern
,
160 DPRINT("Found pipe: %wZ\n", &PipeFcb
->PipeName
);
162 if (PipeIndex
>= FileIndex
)
164 /* Determine whether or not the full pipe name fits into the buffer */
165 if (InfoSize
+ PipeFcb
->PipeName
.Length
> BufferLength
)
167 NameLength
= BufferLength
- InfoSize
;
168 Status
= STATUS_BUFFER_OVERFLOW
;
172 NameLength
= PipeFcb
->PipeName
.Length
;
173 Status
= STATUS_SUCCESS
;
176 /* Initialize the information struct */
177 RtlZeroMemory(Buffer
, InfoSize
);
179 switch (FileInformationClass
)
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
,
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
,
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
,
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
,
231 /* Should never happen! */
236 *Size
= InfoSize
+ NameLength
;
238 Ccb
->u
.Directory
.FileIndex
= PipeIndex
;
241 // if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
242 // return STATUS_SUCCESS;
250 CurrentEntry
= CurrentEntry
->Flink
;
254 Status
= STATUS_NO_MORE_FILES
;
261 NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject
,
264 PIO_STACK_LOCATION IoStack
;
265 PFILE_OBJECT FileObject
;
271 DPRINT("NpfsDirectoryControl() called\n");
273 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
275 FileObject
= IoStack
->FileObject
;
277 if (NpfsGetCcb(FileObject
, &Ccb
) != CCB_DIRECTORY
)
279 Status
= STATUS_INVALID_PARAMETER
;
281 Irp
->IoStatus
.Status
= Status
;
282 Irp
->IoStatus
.Information
= 0;
284 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
291 switch (IoStack
->MinorFunction
)
293 case IRP_MN_QUERY_DIRECTORY
:
294 Status
= NpfsQueryDirectory(Ccb
,
299 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
300 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
301 Status
= STATUS_NOT_IMPLEMENTED
;
305 DPRINT1("NPFS: MinorFunction %d\n", IoStack
->MinorFunction
);
306 Status
= STATUS_INVALID_DEVICE_REQUEST
;
310 Irp
->IoStatus
.Status
= Status
;
311 Irp
->IoStatus
.Information
= Size
;
313 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);