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 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 ExAllocatePool(NonPagedPool
, SearchPattern
->Length
+ sizeof(WCHAR
));
75 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
77 return STATUS_INSUFFICIENT_RESOURCES
;
80 Ccb
->u
.Directory
.SearchPattern
.Length
= SearchPattern
->Length
;
81 Ccb
->u
.Directory
.SearchPattern
.MaximumLength
= SearchPattern
->Length
+ sizeof(WCHAR
);
82 RtlCopyMemory(Ccb
->u
.Directory
.SearchPattern
.Buffer
,
83 SearchPattern
->Buffer
,
84 SearchPattern
->Length
);
85 Ccb
->u
.Directory
.SearchPattern
.Buffer
[SearchPattern
->Length
/ sizeof(WCHAR
)] = 0;
89 Ccb
->u
.Directory
.SearchPattern
.Buffer
=
90 ExAllocatePool(NonPagedPool
, 2 * sizeof(WCHAR
));
91 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
93 return STATUS_INSUFFICIENT_RESOURCES
;
96 Ccb
->u
.Directory
.SearchPattern
.Length
= sizeof(WCHAR
);
97 Ccb
->u
.Directory
.SearchPattern
.MaximumLength
= 2 * sizeof(WCHAR
);
98 Ccb
->u
.Directory
.SearchPattern
.Buffer
[0] = L
'*';
99 Ccb
->u
.Directory
.SearchPattern
.Buffer
[1] = 0;
102 DPRINT("Search pattern: '%wZ'\n", &Ccb
->u
.Directory
.SearchPattern
);
104 /* Determine the file index */
105 if (First
|| (Stack
->Flags
& SL_RESTART_SCAN
))
109 else if ((Stack
->Flags
& SL_INDEX_SPECIFIED
) == 0)
111 FileIndex
= Ccb
->u
.Directory
.FileIndex
+ 1;
113 DPRINT("FileIndex: %lu\n", FileIndex
);
115 DPRINT("Buffer = %p tofind = %wZ\n", Buffer
, &Ccb
->u
.Directory
.SearchPattern
);
117 switch (FileInformationClass
)
119 case FileDirectoryInformation
:
120 InfoSize
= sizeof(FILE_DIRECTORY_INFORMATION
) - sizeof(WCHAR
);
123 case FileFullDirectoryInformation
:
124 InfoSize
= sizeof(FILE_FULL_DIR_INFORMATION
) - sizeof(WCHAR
);
127 case FileBothDirectoryInformation
:
128 InfoSize
= sizeof(FILE_BOTH_DIR_INFORMATION
) - sizeof(WCHAR
);
131 case FileNamesInformation
:
132 InfoSize
= sizeof(FILE_NAMES_INFORMATION
) - sizeof(WCHAR
);
136 DPRINT1("Invalid information class: %lu\n", FileInformationClass
);
137 return STATUS_INVALID_INFO_CLASS
;
143 CurrentEntry
= Vcb
->PipeListHead
.Flink
;
144 while (CurrentEntry
!= &Vcb
->PipeListHead
&&
145 Status
== STATUS_SUCCESS
)
147 /* Get the FCB of the next pipe */
148 PipeFcb
= CONTAINING_RECORD(CurrentEntry
,
152 /* Make sure it is a pipe FCB */
153 ASSERT(PipeFcb
->Type
== FCB_PIPE
);
155 DPRINT("PipeName: %wZ\n", &PipeFcb
->PipeName
);
157 if (FsRtlIsNameInExpression(&Ccb
->u
.Directory
.SearchPattern
,
162 DPRINT("Found pipe: %wZ\n", &PipeFcb
->PipeName
);
164 if (PipeIndex
>= FileIndex
)
166 /* Determine whether or not the full pipe name fits into the buffer */
167 if (InfoSize
+ PipeFcb
->PipeName
.Length
> BufferLength
)
169 NameLength
= BufferLength
- InfoSize
;
170 Status
= STATUS_BUFFER_OVERFLOW
;
174 NameLength
= PipeFcb
->PipeName
.Length
;
175 Status
= STATUS_SUCCESS
;
178 /* Initialize the information struct */
179 RtlZeroMemory(&Buffer
[CurrentOffset
], InfoSize
);
181 switch (FileInformationClass
)
183 case FileDirectoryInformation
:
184 DirectoryBuffer
= (PFILE_DIRECTORY_INFORMATION
)&Buffer
[CurrentOffset
];
185 DirectoryBuffer
->FileIndex
= PipeIndex
;
186 DirectoryBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
187 DirectoryBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
188 DirectoryBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
189 DirectoryBuffer
->FileNameLength
= NameLength
;
190 RtlCopyMemory(DirectoryBuffer
->FileName
,
191 PipeFcb
->PipeName
.Buffer
,
195 case FileFullDirectoryInformation
:
196 FullDirBuffer
= (PFILE_FULL_DIR_INFORMATION
)&Buffer
[CurrentOffset
];
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
[CurrentOffset
];
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
[CurrentOffset
];
222 NamesBuffer
->FileIndex
= PipeIndex
;
223 NamesBuffer
->FileNameLength
= NameLength
;
224 RtlCopyMemory(NamesBuffer
->FileName
,
225 PipeFcb
->PipeName
.Buffer
,
230 /* Should never happen! */
235 DPRINT("CurrentOffset: %lu\n", CurrentOffset
);
237 /* Store the current pipe index in the CCB */
238 Ccb
->u
.Directory
.FileIndex
= PipeIndex
;
240 /* Get the pointer to the previous entries NextEntryOffset */
241 NextEntryOffset
= (PULONG
)&Buffer
[LastOffset
];
243 /* Set the previous entries NextEntryOffset */
244 *NextEntryOffset
= CurrentOffset
- LastOffset
;
246 /* Return the used buffer size */
247 *Size
= CurrentOffset
+ InfoSize
+ NameLength
;
249 /* Leave, if there is no space left in the buffer */
250 if (Status
== STATUS_BUFFER_OVERFLOW
)
253 /* Leave, if we should return only one entry */
254 if (Stack
->Flags
& SL_RETURN_SINGLE_ENTRY
)
255 return STATUS_SUCCESS
;
257 /* Store the current offset for the next round */
258 LastOffset
= CurrentOffset
;
260 /* Set the offset for the next entry */
261 CurrentOffset
+= ROUND_UP(InfoSize
+ NameLength
, sizeof(ULONG
));
267 CurrentEntry
= CurrentEntry
->Flink
;
270 /* Return STATUS_NO_MORE_FILES if no matching pipe name was found */
271 if (CurrentOffset
== 0)
272 Status
= STATUS_NO_MORE_FILES
;
279 NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject
,
282 PIO_STACK_LOCATION IoStack
;
283 PFILE_OBJECT FileObject
;
289 DPRINT("NpfsDirectoryControl() called\n");
291 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
293 FileObject
= IoStack
->FileObject
;
295 if (NpfsGetCcb(FileObject
, &Ccb
) != CCB_DIRECTORY
)
297 Status
= STATUS_INVALID_PARAMETER
;
299 Irp
->IoStatus
.Status
= Status
;
300 Irp
->IoStatus
.Information
= 0;
302 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
309 switch (IoStack
->MinorFunction
)
311 case IRP_MN_QUERY_DIRECTORY
:
312 Status
= NpfsQueryDirectory(Ccb
,
317 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
318 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
319 Status
= STATUS_NOT_IMPLEMENTED
;
323 DPRINT1("NPFS: MinorFunction %d\n", IoStack
->MinorFunction
);
324 Status
= STATUS_INVALID_DEVICE_REQUEST
;
328 Irp
->IoStatus
.Status
= Status
;
329 Irp
->IoStatus
.Information
= Size
;
331 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);