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 KeLockMutex(&Vcb
->PipeListLock
);
148 CurrentEntry
= Vcb
->PipeListHead
.Flink
;
149 while (CurrentEntry
!= &Vcb
->PipeListHead
&&
150 Status
== STATUS_SUCCESS
)
152 /* Get the FCB of the next pipe */
153 PipeFcb
= CONTAINING_RECORD(CurrentEntry
,
157 /* Make sure it is a pipe FCB */
158 ASSERT(PipeFcb
->Type
== FCB_PIPE
);
160 DPRINT("PipeName: %wZ\n", &PipeFcb
->PipeName
);
162 if (FsRtlIsNameInExpression(&Ccb
->u
.Directory
.SearchPattern
,
167 DPRINT("Found pipe: %wZ\n", &PipeFcb
->PipeName
);
169 if (PipeIndex
>= FileIndex
)
171 /* Determine whether or not the full pipe name fits into the buffer */
172 if (InfoSize
+ PipeFcb
->PipeName
.Length
> BufferLength
)
174 NameLength
= BufferLength
- InfoSize
;
175 Status
= STATUS_BUFFER_OVERFLOW
;
179 NameLength
= PipeFcb
->PipeName
.Length
;
180 Status
= STATUS_SUCCESS
;
183 /* Initialize the information struct */
184 RtlZeroMemory(&Buffer
[CurrentOffset
], InfoSize
);
186 switch (FileInformationClass
)
188 case FileDirectoryInformation
:
189 DirectoryBuffer
= (PFILE_DIRECTORY_INFORMATION
)&Buffer
[CurrentOffset
];
190 DirectoryBuffer
->FileIndex
= PipeIndex
;
191 DirectoryBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
192 DirectoryBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
193 DirectoryBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
194 DirectoryBuffer
->FileNameLength
= NameLength
;
195 RtlCopyMemory(DirectoryBuffer
->FileName
,
196 PipeFcb
->PipeName
.Buffer
,
200 case FileFullDirectoryInformation
:
201 FullDirBuffer
= (PFILE_FULL_DIR_INFORMATION
)&Buffer
[CurrentOffset
];
202 FullDirBuffer
->FileIndex
= PipeIndex
;
203 FullDirBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
204 FullDirBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
205 FullDirBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
206 FullDirBuffer
->FileNameLength
= NameLength
;
207 RtlCopyMemory(FullDirBuffer
->FileName
,
208 PipeFcb
->PipeName
.Buffer
,
212 case FileBothDirectoryInformation
:
213 BothDirBuffer
= (PFILE_BOTH_DIR_INFORMATION
)&Buffer
[CurrentOffset
];
214 BothDirBuffer
->NextEntryOffset
= 0;
215 BothDirBuffer
->FileIndex
= PipeIndex
;
216 BothDirBuffer
->FileAttributes
= FILE_ATTRIBUTE_NORMAL
;
217 BothDirBuffer
->EndOfFile
.QuadPart
= PipeFcb
->CurrentInstances
;
218 BothDirBuffer
->AllocationSize
.LowPart
= PipeFcb
->MaximumInstances
;
219 BothDirBuffer
->FileNameLength
= NameLength
;
220 RtlCopyMemory(BothDirBuffer
->FileName
,
221 PipeFcb
->PipeName
.Buffer
,
225 case FileNamesInformation
:
226 NamesBuffer
= (PFILE_NAMES_INFORMATION
)&Buffer
[CurrentOffset
];
227 NamesBuffer
->FileIndex
= PipeIndex
;
228 NamesBuffer
->FileNameLength
= NameLength
;
229 RtlCopyMemory(NamesBuffer
->FileName
,
230 PipeFcb
->PipeName
.Buffer
,
235 /* Should never happen! */
240 DPRINT("CurrentOffset: %lu\n", CurrentOffset
);
242 /* Store the current pipe index in the CCB */
243 Ccb
->u
.Directory
.FileIndex
= PipeIndex
;
245 /* Get the pointer to the previous entries NextEntryOffset */
246 NextEntryOffset
= (PULONG
)&Buffer
[LastOffset
];
248 /* Set the previous entries NextEntryOffset */
249 *NextEntryOffset
= CurrentOffset
- LastOffset
;
251 /* Return the used buffer size */
252 *Size
= CurrentOffset
+ InfoSize
+ NameLength
;
254 /* Leave, if there is no space left in the buffer */
255 if (Status
== STATUS_BUFFER_OVERFLOW
)
257 KeUnlockMutex(&Vcb
->PipeListLock
);
261 /* Leave, if we should return only one entry */
262 if (Stack
->Flags
& SL_RETURN_SINGLE_ENTRY
)
264 KeUnlockMutex(&Vcb
->PipeListLock
);
265 return STATUS_SUCCESS
;
268 /* Store the current offset for the next round */
269 LastOffset
= CurrentOffset
;
271 /* Set the offset for the next entry */
272 CurrentOffset
+= ROUND_UP(InfoSize
+ NameLength
, sizeof(ULONG
));
278 CurrentEntry
= CurrentEntry
->Flink
;
280 KeUnlockMutex(&Vcb
->PipeListLock
);
282 /* Return STATUS_NO_MORE_FILES if no matching pipe name was found */
283 if (CurrentOffset
== 0)
284 Status
= STATUS_NO_MORE_FILES
;
291 NpfsDirectoryControl(PDEVICE_OBJECT DeviceObject
,
294 PIO_STACK_LOCATION IoStack
;
295 PFILE_OBJECT FileObject
;
301 DPRINT("NpfsDirectoryControl() called\n");
303 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
305 FileObject
= IoStack
->FileObject
;
307 if (NpfsGetCcb(FileObject
, &Ccb
) != CCB_DIRECTORY
)
309 Status
= STATUS_INVALID_PARAMETER
;
311 Irp
->IoStatus
.Status
= Status
;
312 Irp
->IoStatus
.Information
= 0;
314 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
321 switch (IoStack
->MinorFunction
)
323 case IRP_MN_QUERY_DIRECTORY
:
324 Status
= NpfsQueryDirectory(Ccb
,
329 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
330 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
331 Status
= STATUS_NOT_IMPLEMENTED
;
335 DPRINT1("NPFS: MinorFunction %d\n", IoStack
->MinorFunction
);
336 Status
= STATUS_INVALID_DEVICE_REQUEST
;
340 Irp
->IoStatus
.Status
= Status
;
341 Irp
->IoStatus
.Information
= Size
;
343 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);