2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/filesystems/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
= MmGetSystemAddressForMdlSafe(Irp
->MdlAddress
,
63 Buffer
= Irp
->UserBuffer
;
66 /* Build the search pattern string */
67 DPRINT("Ccb->u.Directory.SearchPattern.Buffer: %p\n", Ccb
->u
.Directory
.SearchPattern
.Buffer
);
68 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
72 if (SearchPattern
!= NULL
)
74 Ccb
->u
.Directory
.SearchPattern
.Buffer
=
75 ExAllocatePoolWithTag(NonPagedPool
,
76 SearchPattern
->Length
+ sizeof(WCHAR
),
78 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
80 return STATUS_INSUFFICIENT_RESOURCES
;
83 Ccb
->u
.Directory
.SearchPattern
.Length
= SearchPattern
->Length
;
84 Ccb
->u
.Directory
.SearchPattern
.MaximumLength
= SearchPattern
->Length
+ sizeof(WCHAR
);
85 RtlCopyMemory(Ccb
->u
.Directory
.SearchPattern
.Buffer
,
86 SearchPattern
->Buffer
,
87 SearchPattern
->Length
);
88 Ccb
->u
.Directory
.SearchPattern
.Buffer
[SearchPattern
->Length
/ sizeof(WCHAR
)] = 0;
92 Ccb
->u
.Directory
.SearchPattern
.Buffer
=
93 ExAllocatePoolWithTag(NonPagedPool
,
96 if (Ccb
->u
.Directory
.SearchPattern
.Buffer
== NULL
)
98 return STATUS_INSUFFICIENT_RESOURCES
;
101 Ccb
->u
.Directory
.SearchPattern
.Length
= sizeof(WCHAR
);
102 Ccb
->u
.Directory
.SearchPattern
.MaximumLength
= 2 * sizeof(WCHAR
);
103 Ccb
->u
.Directory
.SearchPattern
.Buffer
[0] = L
'*';
104 Ccb
->u
.Directory
.SearchPattern
.Buffer
[1] = 0;
107 DPRINT("Search pattern: '%wZ'\n", &Ccb
->u
.Directory
.SearchPattern
);
109 /* Determine the file index */
110 if (First
|| (Stack
->Flags
& SL_RESTART_SCAN
))
114 else if ((Stack
->Flags
& SL_INDEX_SPECIFIED
) == 0)
116 FileIndex
= Ccb
->u
.Directory
.FileIndex
+ 1;
118 DPRINT("FileIndex: %lu\n", FileIndex
);
120 DPRINT("Buffer = %p tofind = %wZ\n", Buffer
, &Ccb
->u
.Directory
.SearchPattern
);
122 switch (FileInformationClass
)
124 case FileDirectoryInformation
:
125 InfoSize
= sizeof(FILE_DIRECTORY_INFORMATION
) - sizeof(WCHAR
);
128 case FileFullDirectoryInformation
:
129 InfoSize
= sizeof(FILE_FULL_DIR_INFORMATION
) - sizeof(WCHAR
);
132 case FileBothDirectoryInformation
:
133 InfoSize
= sizeof(FILE_BOTH_DIR_INFORMATION
) - sizeof(WCHAR
);
136 case FileNamesInformation
:
137 InfoSize
= sizeof(FILE_NAMES_INFORMATION
) - sizeof(WCHAR
);
141 DPRINT1("Invalid information class: %lu\n", FileInformationClass
);
142 return STATUS_INVALID_INFO_CLASS
;
148 KeLockMutex(&Vcb
->PipeListLock
);
149 CurrentEntry
= Vcb
->PipeListHead
.Flink
;
150 while (CurrentEntry
!= &Vcb
->PipeListHead
&&
151 Status
== STATUS_SUCCESS
)
153 /* Get the FCB of the next pipe */
154 PipeFcb
= CONTAINING_RECORD(CurrentEntry
,
158 /* Make sure it is a pipe FCB */
159 ASSERT(PipeFcb
->Type
== FCB_PIPE
);
161 DPRINT("PipeName: %wZ\n", &PipeFcb
->PipeName
);
163 if (FsRtlIsNameInExpression(&Ccb
->u
.Directory
.SearchPattern
,
168 DPRINT("Found pipe: %wZ\n", &PipeFcb
->PipeName
);
170 if (PipeIndex
>= FileIndex
)
172 /* Determine whether or not the full pipe name fits into the buffer */
173 if (InfoSize
+ PipeFcb
->PipeName
.Length
> BufferLength
)
175 NameLength
= BufferLength
- InfoSize
;
176 Status
= STATUS_BUFFER_OVERFLOW
;
180 NameLength
= PipeFcb
->PipeName
.Length
;
181 Status
= STATUS_SUCCESS
;
184 /* Initialize the information struct */
185 RtlZeroMemory(&Buffer
[CurrentOffset
], InfoSize
);
187 switch (FileInformationClass
)
189 case FileDirectoryInformation
:
190 DirectoryBuffer
= (PFILE_DIRECTORY_INFORMATION
)&Buffer
[CurrentOffset
];
191 DirectoryBuffer
->FileIndex
= PipeIndex
;
192 DirectoryBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
193 DirectoryBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
194 DirectoryBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
195 DirectoryBuffer
->FileNameLength
= NameLength
;
196 RtlCopyMemory(DirectoryBuffer
->FileName
,
197 PipeFcb
->PipeName
.Buffer
,
201 case FileFullDirectoryInformation
:
202 FullDirBuffer
= (PFILE_FULL_DIR_INFORMATION
)&Buffer
[CurrentOffset
];
203 FullDirBuffer
->FileIndex
= PipeIndex
;
204 FullDirBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
205 FullDirBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
206 FullDirBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
207 FullDirBuffer
->FileNameLength
= NameLength
;
208 RtlCopyMemory(FullDirBuffer
->FileName
,
209 PipeFcb
->PipeName
.Buffer
,
213 case FileBothDirectoryInformation
:
214 BothDirBuffer
= (PFILE_BOTH_DIR_INFORMATION
)&Buffer
[CurrentOffset
];
215 BothDirBuffer
->NextEntryOffset
= 0;
216 BothDirBuffer
->FileIndex
= PipeIndex
;
217 BothDirBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
218 BothDirBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
219 BothDirBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
220 BothDirBuffer
->FileNameLength
= NameLength
;
221 RtlCopyMemory(BothDirBuffer
->FileName
,
222 PipeFcb
->PipeName
.Buffer
,
226 case FileNamesInformation
:
227 NamesBuffer
= (PFILE_NAMES_INFORMATION
)&Buffer
[CurrentOffset
];
228 NamesBuffer
->FileIndex
= PipeIndex
;
229 NamesBuffer
->FileNameLength
= NameLength
;
230 RtlCopyMemory(NamesBuffer
->FileName
,
231 PipeFcb
->PipeName
.Buffer
,
236 /* Should never happen! */
241 DPRINT("CurrentOffset: %lu\n", CurrentOffset
);
243 /* Store the current pipe index in the CCB */
244 Ccb
->u
.Directory
.FileIndex
= PipeIndex
;
246 /* Get the pointer to the previous entries NextEntryOffset */
247 NextEntryOffset
= (PULONG
)&Buffer
[LastOffset
];
249 /* Set the previous entries NextEntryOffset */
250 *NextEntryOffset
= CurrentOffset
- LastOffset
;
252 /* Return the used buffer size */
253 *Size
= CurrentOffset
+ InfoSize
+ NameLength
;
255 /* Leave, if there is no space left in the buffer */
256 if (Status
== STATUS_BUFFER_OVERFLOW
)
258 KeUnlockMutex(&Vcb
->PipeListLock
);
262 /* Leave, if we should return only one entry */
263 if (Stack
->Flags
& SL_RETURN_SINGLE_ENTRY
)
265 KeUnlockMutex(&Vcb
->PipeListLock
);
266 return STATUS_SUCCESS
;
269 /* Store the current offset for the next round */
270 LastOffset
= CurrentOffset
;
272 /* Set the offset for the next entry */
273 CurrentOffset
+= ROUND_UP(InfoSize
+ NameLength
, sizeof(ULONG
));
279 CurrentEntry
= CurrentEntry
->Flink
;
281 KeUnlockMutex(&Vcb
->PipeListLock
);
283 /* Return STATUS_NO_MORE_FILES if no matching pipe name was found */
284 if (CurrentOffset
== 0)
285 Status
= STATUS_NO_MORE_FILES
;
292 NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject
,
295 PIO_STACK_LOCATION IoStack
;
296 PFILE_OBJECT FileObject
;
302 UNREFERENCED_PARAMETER(DeviceObject
);
304 DPRINT("NpfsDirectoryControl() called\n");
306 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
308 FileObject
= IoStack
->FileObject
;
310 if (NpfsGetCcb(FileObject
, &Ccb
) != CCB_DIRECTORY
)
312 Status
= STATUS_INVALID_PARAMETER
;
314 Irp
->IoStatus
.Status
= Status
;
315 Irp
->IoStatus
.Information
= 0;
317 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
324 switch (IoStack
->MinorFunction
)
326 case IRP_MN_QUERY_DIRECTORY
:
327 Status
= NpfsQueryDirectory(Ccb
,
332 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
333 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
334 Status
= STATUS_NOT_IMPLEMENTED
;
338 DPRINT1("NPFS: MinorFunction %d\n", IoStack
->MinorFunction
);
339 Status
= STATUS_INVALID_DEVICE_REQUEST
;
343 Irp
->IoStatus
.Status
= Status
;
344 Irp
->IoStatus
.Information
= Size
;
346 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);