3 * Copyright (C) 2002, 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: services/fs/cdfs/dirctl.c
23 * PURPOSE: CDROM (ISO 9660) filesystem driver
24 * PROGRAMMER: Art Yerkes
29 /* INCLUDES *****************************************************************/
36 /* FUNCTIONS ****************************************************************/
38 #define ROUND_DOWN(N, S) (((N) / (S)) * (S))
39 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
41 /* FUNCTIONS ****************************************************************/
44 * FUNCTION: Retrieves the file name, be it in short or long file name format
47 CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt
,
50 PLARGE_INTEGER StreamOffset
,
57 PDIR_RECORD Record
= *Ptr
;
60 if (*CurrentOffset
>= DirLength
)
61 return(STATUS_NO_MORE_ENTRIES
);
63 if (*CurrentOffset
== 0)
66 Record
= (PDIR_RECORD
)*Block
;
67 while (Index
< *pIndex
)
69 (*Ptr
) = (PVOID
)((ULONG_PTR
)(*Ptr
) + Record
->RecordLength
);
70 (*CurrentOffset
) += Record
->RecordLength
;
72 if ((ULONG_PTR
)(*Ptr
) - (ULONG_PTR
)(*Block
) >= BLOCKSIZE
|| Record
->RecordLength
== 0)
74 DPRINT("Map next sector\n");
75 CcUnpinData(*Context
);
76 StreamOffset
->QuadPart
+= BLOCKSIZE
;
77 *CurrentOffset
= ROUND_UP(*CurrentOffset
, BLOCKSIZE
);
78 if (!CcMapData(DeviceExt
->StreamFileObject
,
83 DPRINT("CcMapData() failed\n");
84 return(STATUS_UNSUCCESSFUL
);
87 Record
= (PDIR_RECORD
)*Ptr
;
89 if (*CurrentOffset
>= DirLength
)
90 return(STATUS_NO_MORE_ENTRIES
);
96 if ((ULONG_PTR
)(*Ptr
) - (ULONG_PTR
)(*Block
) >= BLOCKSIZE
|| Record
->RecordLength
== 0)
98 DPRINT("Map next sector\n");
99 CcUnpinData(*Context
);
100 StreamOffset
->QuadPart
+= BLOCKSIZE
;
101 *CurrentOffset
= ROUND_UP(*CurrentOffset
, BLOCKSIZE
);
102 if (!CcMapData(DeviceExt
->StreamFileObject
,
107 DPRINT("CcMapData() failed\n");
108 return(STATUS_UNSUCCESSFUL
);
111 Record
= (PDIR_RECORD
)*Ptr
;
114 if (*CurrentOffset
>= DirLength
)
115 return STATUS_NO_MORE_ENTRIES
;
117 DPRINT("Index %lu RecordLength %lu Offset %lu\n",
118 *pIndex
, Record
->RecordLength
, *CurrentOffset
);
120 if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 0)
124 else if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 1)
130 if (DeviceExt
->CdInfo
.JolietLevel
== 0)
134 for (i
= 0; i
< Record
->FileIdLength
&& Record
->FileId
[i
] != ';'; i
++)
135 Name
[i
] = (WCHAR
)Record
->FileId
[i
];
140 CdfsSwapString(Name
, Record
->FileId
, Record
->FileIdLength
);
144 DPRINT("Name '%S'\n", Name
);
148 return(STATUS_SUCCESS
);
153 * FUNCTION: Find a file
156 CdfsFindFile(PDEVICE_EXTENSION DeviceExt
,
159 PUNICODE_STRING FileToFind
,
164 WCHAR ShortNameBuffer
[13];
165 UNICODE_STRING TempString
;
166 UNICODE_STRING ShortName
;
167 UNICODE_STRING LongName
;
168 UNICODE_STRING FileToFindUpcase
;
175 PVOID Context
= NULL
;
178 LARGE_INTEGER StreamOffset
, OffsetOfEntry
;
180 DPRINT("FindFile(Parent %p, FileToFind '%wZ', DirIndex: %u)\n",
181 Parent
, FileToFind
, pDirIndex
? *pDirIndex
: 0);
182 DPRINT("FindFile: old Pathname %p, old Objectname %p)\n",
183 Fcb
->PathName
, Fcb
->ObjectName
);
188 if (FileToFind
== NULL
|| FileToFind
->Length
== 0)
190 RtlInitUnicodeString(&TempString
, L
".");
191 FileToFind
= &TempString
;
196 if (Parent
->Entry
.ExtentLocationL
== DeviceExt
->CdInfo
.RootStart
)
208 StreamOffset
.QuadPart
= (LONGLONG
)DeviceExt
->CdInfo
.RootStart
* (LONGLONG
)BLOCKSIZE
;
209 DirSize
= DeviceExt
->CdInfo
.RootSize
;
212 if (FileToFind
->Buffer
[0] == 0 ||
213 (FileToFind
->Buffer
[0] == '\\' && FileToFind
->Buffer
[1] == 0) ||
214 (FileToFind
->Buffer
[0] == '.' && FileToFind
->Buffer
[1] == 0))
216 /* it's root : complete essentials fields then return ok */
217 RtlZeroMemory(Fcb
, sizeof(FCB
));
219 Fcb
->PathNameBuffer
[0] = '\\';
220 Fcb
->ObjectName
= &Fcb
->PathNameBuffer
[1];
221 Fcb
->Entry
.ExtentLocationL
= DeviceExt
->CdInfo
.RootStart
;
222 Fcb
->Entry
.DataLengthL
= DeviceExt
->CdInfo
.RootSize
;
223 Fcb
->Entry
.FileFlags
= 0x02; //FILE_ATTRIBUTE_DIRECTORY;
224 Fcb
->PathName
.Length
= sizeof(WCHAR
);
225 Fcb
->PathName
.MaximumLength
= sizeof(Fcb
->PathNameBuffer
);
226 Fcb
->PathName
.Buffer
= Fcb
->PathNameBuffer
;
232 DPRINT("CdfsFindFile: new Pathname %wZ, new Objectname %S)\n",&Fcb
->PathName
, Fcb
->ObjectName
);
233 return STATUS_SUCCESS
;
238 StreamOffset
.QuadPart
= (LONGLONG
)Parent
->Entry
.ExtentLocationL
* (LONGLONG
)BLOCKSIZE
;
239 DirSize
= Parent
->Entry
.DataLengthL
;
242 DPRINT("StreamOffset %I64d DirSize %u\n", StreamOffset
.QuadPart
, DirSize
);
244 if (pDirIndex
&& (*pDirIndex
))
245 DirIndex
= *pDirIndex
;
247 if (pOffset
&& (*pOffset
))
250 StreamOffset
.QuadPart
+= ROUND_DOWN(Offset
, BLOCKSIZE
);
253 if (!CcMapData(DeviceExt
->StreamFileObject
, &StreamOffset
,
254 BLOCKSIZE
, TRUE
, &Context
, &Block
))
256 DPRINT("CcMapData() failed\n");
257 return STATUS_UNSUCCESSFUL
;
260 Record
= (PDIR_RECORD
) ((ULONG_PTR
)Block
+ Offset
% BLOCKSIZE
);
263 Offset
+= Record
->RecordLength
;
264 Record
= (PDIR_RECORD
)((ULONG_PTR
)Record
+ Record
->RecordLength
);
267 /* Upper case the expression for FsRtlIsNameInExpression */
268 Status
= RtlUpcaseUnicodeString(&FileToFindUpcase
, FileToFind
, TRUE
);
269 if (!NT_SUCCESS(Status
))
276 DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n",
277 Record
->RecordLength
, Record
->ExtAttrRecordLength
, Record
->FileIdLength
);
279 Status
= CdfsGetEntryName
280 (DeviceExt
, &Context
, &Block
, &StreamOffset
,
281 DirSize
, (PVOID
*)&Record
, name
, &DirIndex
, &Offset
);
283 if (Status
== STATUS_NO_MORE_ENTRIES
)
287 else if (Status
== STATUS_UNSUCCESSFUL
)
289 /* Note: the directory cache has already been unpinned */
290 RtlFreeUnicodeString(&FileToFindUpcase
);
294 DPRINT("Name '%S'\n", name
);
296 RtlInitUnicodeString(&LongName
, name
);
297 ShortName
.Length
= 0;
298 ShortName
.MaximumLength
= 26;
299 ShortName
.Buffer
= ShortNameBuffer
;
301 OffsetOfEntry
.QuadPart
= StreamOffset
.QuadPart
+ Offset
;
302 CdfsShortNameCacheGet(Parent
, &OffsetOfEntry
, &LongName
, &ShortName
);
304 DPRINT("ShortName '%wZ'\n", &ShortName
);
306 if (FsRtlIsNameInExpression(&FileToFindUpcase
, &LongName
, TRUE
, NULL
) ||
307 FsRtlIsNameInExpression(&FileToFindUpcase
, &ShortName
, TRUE
, NULL
))
309 if (Parent
->PathName
.Buffer
[0])
311 len
= Parent
->PathName
.Length
/ sizeof(WCHAR
);
312 memcpy(Fcb
->PathName
.Buffer
, Parent
->PathName
.Buffer
, Parent
->PathName
.Length
);
313 Fcb
->PathName
.Length
= Parent
->PathName
.Length
;
314 Fcb
->ObjectName
=&Fcb
->PathName
.Buffer
[len
];
315 if (len
!= 1 || Fcb
->PathName
.Buffer
[0] != '\\')
317 Fcb
->ObjectName
[0] = '\\';
318 Fcb
->ObjectName
= &Fcb
->ObjectName
[1];
323 Fcb
->ObjectName
=Fcb
->PathName
.Buffer
;
324 Fcb
->ObjectName
[0]='\\';
325 Fcb
->ObjectName
=&Fcb
->ObjectName
[1];
328 DPRINT("PathName '%wZ' ObjectName '%S'\n", &Fcb
->PathName
, Fcb
->ObjectName
);
330 memcpy(&Fcb
->Entry
, Record
, sizeof(DIR_RECORD
));
331 wcsncpy(Fcb
->ObjectName
, name
, min(wcslen(name
) + 1,
332 MAX_PATH
- (Fcb
->PathName
.Length
/ sizeof(WCHAR
)) + wcslen(Fcb
->ObjectName
)));
334 /* Copy short name */
335 Fcb
->ShortNameU
.Length
= ShortName
.Length
;
336 Fcb
->ShortNameU
.MaximumLength
= ShortName
.Length
;
337 Fcb
->ShortNameU
.Buffer
= Fcb
->ShortNameBuffer
;
338 memcpy(Fcb
->ShortNameBuffer
, ShortName
.Buffer
, ShortName
.Length
);
341 *pDirIndex
= DirIndex
;
345 DPRINT("FindFile: new Pathname %wZ, new Objectname %S, DirIndex %u\n",
346 &Fcb
->PathName
, Fcb
->ObjectName
, DirIndex
);
348 RtlFreeUnicodeString(&FileToFindUpcase
);
349 CcUnpinData(Context
);
351 return STATUS_SUCCESS
;
354 Offset
+= Record
->RecordLength
;
355 Record
= (PDIR_RECORD
)((ULONG_PTR
)Record
+ Record
->RecordLength
);
359 RtlFreeUnicodeString(&FileToFindUpcase
);
360 CcUnpinData(Context
);
363 *pDirIndex
= DirIndex
;
368 return STATUS_UNSUCCESSFUL
;
373 CdfsGetNameInformation(PFCB Fcb
,
374 PDEVICE_EXTENSION DeviceExt
,
375 PFILE_NAMES_INFORMATION Info
,
380 DPRINT("CdfsGetNameInformation() called\n");
382 UNREFERENCED_PARAMETER(DeviceExt
);
384 Length
= wcslen(Fcb
->ObjectName
) * sizeof(WCHAR
);
385 if ((sizeof(FILE_NAMES_INFORMATION
) + Length
) > BufferLength
)
386 return(STATUS_BUFFER_OVERFLOW
);
388 Info
->FileNameLength
= Length
;
389 Info
->NextEntryOffset
=
390 ROUND_UP(sizeof(FILE_NAMES_INFORMATION
) + Length
, sizeof(ULONG
));
391 RtlCopyMemory(Info
->FileName
, Fcb
->ObjectName
, Length
);
395 return(STATUS_SUCCESS
);
400 CdfsGetDirectoryInformation(PFCB Fcb
,
401 PDEVICE_EXTENSION DeviceExt
,
402 PFILE_DIRECTORY_INFORMATION Info
,
407 DPRINT("CdfsGetDirectoryInformation() called\n");
409 UNREFERENCED_PARAMETER(DeviceExt
);
411 Length
= wcslen(Fcb
->ObjectName
) * sizeof(WCHAR
);
412 if ((sizeof (FILE_DIRECTORY_INFORMATION
) + Length
) > BufferLength
)
413 return(STATUS_BUFFER_OVERFLOW
);
415 Info
->FileNameLength
= Length
;
416 Info
->NextEntryOffset
=
417 ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION
) + Length
, sizeof(ULONG
));
418 RtlCopyMemory(Info
->FileName
, Fcb
->ObjectName
, Length
);
420 /* Convert file times */
421 CdfsDateTimeToSystemTime(Fcb
,
422 &Info
->CreationTime
);
423 Info
->LastWriteTime
= Info
->CreationTime
;
424 Info
->ChangeTime
= Info
->CreationTime
;
426 /* Convert file flags */
427 CdfsFileFlagsToAttributes(Fcb
,
428 &Info
->FileAttributes
);
429 if (CdfsFCBIsDirectory(Fcb
))
431 Info
->EndOfFile
.QuadPart
= 0;
432 Info
->AllocationSize
.QuadPart
= 0;
436 Info
->EndOfFile
.QuadPart
= Fcb
->Entry
.DataLengthL
;
438 /* Make AllocSize a rounded up multiple of the sector size */
439 Info
->AllocationSize
.QuadPart
= ROUND_UP(Fcb
->Entry
.DataLengthL
, BLOCKSIZE
);
444 return(STATUS_SUCCESS
);
449 CdfsGetFullDirectoryInformation(PFCB Fcb
,
450 PDEVICE_EXTENSION DeviceExt
,
451 PFILE_FULL_DIR_INFORMATION Info
,
456 DPRINT("CdfsGetFullDirectoryInformation() called\n");
458 UNREFERENCED_PARAMETER(DeviceExt
);
460 Length
= wcslen(Fcb
->ObjectName
) * sizeof(WCHAR
);
461 if ((sizeof (FILE_FULL_DIR_INFORMATION
) + Length
) > BufferLength
)
462 return(STATUS_BUFFER_OVERFLOW
);
464 Info
->FileNameLength
= Length
;
465 Info
->NextEntryOffset
=
466 ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION
) + Length
, sizeof(ULONG
));
467 RtlCopyMemory(Info
->FileName
, Fcb
->ObjectName
, Length
);
469 /* Convert file times */
470 CdfsDateTimeToSystemTime(Fcb
,
471 &Info
->CreationTime
);
472 Info
->LastWriteTime
= Info
->CreationTime
;
473 Info
->ChangeTime
= Info
->CreationTime
;
475 /* Convert file flags */
476 CdfsFileFlagsToAttributes(Fcb
,
477 &Info
->FileAttributes
);
479 if (CdfsFCBIsDirectory(Fcb
))
481 Info
->EndOfFile
.QuadPart
= 0;
482 Info
->AllocationSize
.QuadPart
= 0;
486 Info
->EndOfFile
.QuadPart
= Fcb
->Entry
.DataLengthL
;
488 /* Make AllocSize a rounded up multiple of the sector size */
489 Info
->AllocationSize
.QuadPart
= ROUND_UP(Fcb
->Entry
.DataLengthL
, BLOCKSIZE
);
495 return(STATUS_SUCCESS
);
500 CdfsGetBothDirectoryInformation(PFCB Fcb
,
501 PDEVICE_EXTENSION DeviceExt
,
502 PFILE_BOTH_DIR_INFORMATION Info
,
507 DPRINT("CdfsGetBothDirectoryInformation() called\n");
509 UNREFERENCED_PARAMETER(DeviceExt
);
511 Length
= wcslen(Fcb
->ObjectName
) * sizeof(WCHAR
);
512 if ((sizeof (FILE_BOTH_DIR_INFORMATION
) + Length
) > BufferLength
)
513 return(STATUS_BUFFER_OVERFLOW
);
515 Info
->FileNameLength
= Length
;
516 Info
->NextEntryOffset
=
517 ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION
) + Length
, sizeof(ULONG
));
518 RtlCopyMemory(Info
->FileName
, Fcb
->ObjectName
, Length
);
520 /* Convert file times */
521 CdfsDateTimeToSystemTime(Fcb
,
522 &Info
->CreationTime
);
523 Info
->LastWriteTime
= Info
->CreationTime
;
524 Info
->ChangeTime
= Info
->CreationTime
;
526 /* Convert file flags */
527 CdfsFileFlagsToAttributes(Fcb
,
528 &Info
->FileAttributes
);
530 if (CdfsFCBIsDirectory(Fcb
))
532 Info
->EndOfFile
.QuadPart
= 0;
533 Info
->AllocationSize
.QuadPart
= 0;
537 Info
->EndOfFile
.QuadPart
= Fcb
->Entry
.DataLengthL
;
539 /* Make AllocSize a rounded up multiple of the sector size */
540 Info
->AllocationSize
.QuadPart
= ROUND_UP(Fcb
->Entry
.DataLengthL
, BLOCKSIZE
);
546 /* Copy short name */
547 ASSERT(Fcb
->ShortNameU
.Length
/ sizeof(WCHAR
) <= 12);
548 Info
->ShortNameLength
= (CCHAR
)Fcb
->ShortNameU
.Length
;
549 RtlCopyMemory(Info
->ShortName
, Fcb
->ShortNameU
.Buffer
, Fcb
->ShortNameU
.Length
);
551 return(STATUS_SUCCESS
);
556 CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject
,
559 PDEVICE_EXTENSION DeviceExtension
;
560 LONG BufferLength
= 0;
561 PUNICODE_STRING SearchPattern
= NULL
;
562 FILE_INFORMATION_CLASS FileInformationClass
;
564 PUCHAR Buffer
= NULL
;
565 PFILE_NAMES_INFORMATION Buffer0
= NULL
;
569 BOOLEAN First
= FALSE
;
570 PIO_STACK_LOCATION Stack
;
571 PFILE_OBJECT FileObject
;
572 NTSTATUS Status
= STATUS_SUCCESS
;
574 DPRINT("CdfsQueryDirectory() called\n");
576 DeviceExtension
= DeviceObject
->DeviceExtension
;
577 Stack
= IoGetCurrentIrpStackLocation(Irp
);
578 FileObject
= Stack
->FileObject
;
579 TempFcb
.PathName
.Buffer
= TempFcb
.PathNameBuffer
;
580 TempFcb
.PathName
.MaximumLength
= sizeof(TempFcb
.PathNameBuffer
);
582 Ccb
= (PCCB
)FileObject
->FsContext2
;
583 Fcb
= (PFCB
)FileObject
->FsContext
;
585 /* Obtain the callers parameters */
586 BufferLength
= Stack
->Parameters
.QueryDirectory
.Length
;
587 SearchPattern
= Stack
->Parameters
.QueryDirectory
.FileName
;
588 FileInformationClass
=
589 Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
590 FileIndex
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
592 /* Determine Buffer for result */
595 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
599 Buffer
= Irp
->UserBuffer
;
602 /* Allocate search pattern in case:
603 * -> We don't have one already in context
604 * -> We have been given an input pattern
605 * -> The pattern length is not null
606 * -> The pattern buffer is not null
607 * Otherwise, we'll fall later and allocate a match all (*) pattern
609 if (SearchPattern
!= NULL
&&
610 SearchPattern
->Length
!= 0 && SearchPattern
->Buffer
!= NULL
)
612 if (Ccb
->DirectorySearchPattern
.Buffer
== NULL
)
615 Ccb
->DirectorySearchPattern
.Buffer
=
616 ExAllocatePoolWithTag(NonPagedPool
, SearchPattern
->Length
+ sizeof(WCHAR
), TAG_CCB
);
617 if (Ccb
->DirectorySearchPattern
.Buffer
== NULL
)
619 return STATUS_INSUFFICIENT_RESOURCES
;
621 Ccb
->DirectorySearchPattern
.MaximumLength
= SearchPattern
->Length
+ sizeof(WCHAR
);
622 RtlCopyUnicodeString(&Ccb
->DirectorySearchPattern
, SearchPattern
);
623 Ccb
->DirectorySearchPattern
.Buffer
[SearchPattern
->Length
/ sizeof(WCHAR
)] = 0;
626 else if (Ccb
->DirectorySearchPattern
.Buffer
== NULL
)
629 Ccb
->DirectorySearchPattern
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
, 2 * sizeof(WCHAR
), TAG_CCB
);
630 if (Ccb
->DirectorySearchPattern
.Buffer
== NULL
)
632 return STATUS_INSUFFICIENT_RESOURCES
;
635 Ccb
->DirectorySearchPattern
.Length
= sizeof(WCHAR
);
636 Ccb
->DirectorySearchPattern
.MaximumLength
= 2 * sizeof(WCHAR
);
637 Ccb
->DirectorySearchPattern
.Buffer
[0] = L
'*';
638 Ccb
->DirectorySearchPattern
.Buffer
[1] = 0;
640 DPRINT("Search pattern '%wZ'\n", &Ccb
->DirectorySearchPattern
);
642 /* Determine directory index */
643 if (Stack
->Flags
& SL_INDEX_SPECIFIED
)
645 Ccb
->Entry
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
646 Ccb
->Offset
= Ccb
->CurrentByteOffset
.u
.LowPart
;
648 else if (First
|| (Stack
->Flags
& SL_RESTART_SCAN
))
653 DPRINT("Buffer = %p tofind = %wZ\n", Buffer
, &Ccb
->DirectorySearchPattern
);
655 TempFcb
.ObjectName
= TempFcb
.PathName
.Buffer
;
656 while (Status
== STATUS_SUCCESS
&& BufferLength
> 0)
658 Status
= CdfsFindFile(DeviceExtension
,
661 &Ccb
->DirectorySearchPattern
,
664 DPRINT("Found %S, Status=%x, entry %x\n", TempFcb
.ObjectName
, Status
, Ccb
->Entry
);
666 if (NT_SUCCESS(Status
))
668 switch (FileInformationClass
)
670 case FileNameInformation
:
671 Status
= CdfsGetNameInformation(&TempFcb
,
673 (PFILE_NAMES_INFORMATION
)Buffer
,
677 case FileDirectoryInformation
:
678 Status
= CdfsGetDirectoryInformation(&TempFcb
,
680 (PFILE_DIRECTORY_INFORMATION
)Buffer
,
684 case FileFullDirectoryInformation
:
685 Status
= CdfsGetFullDirectoryInformation(&TempFcb
,
687 (PFILE_FULL_DIR_INFORMATION
)Buffer
,
691 case FileBothDirectoryInformation
:
692 Status
= CdfsGetBothDirectoryInformation(&TempFcb
,
694 (PFILE_BOTH_DIR_INFORMATION
)Buffer
,
699 Status
= STATUS_INVALID_INFO_CLASS
;
702 if (Status
== STATUS_BUFFER_OVERFLOW
)
706 Buffer0
->NextEntryOffset
= 0;
715 Buffer0
->NextEntryOffset
= 0;
720 Status
= STATUS_NO_SUCH_FILE
;
724 Status
= STATUS_NO_MORE_FILES
;
729 Buffer0
= (PFILE_NAMES_INFORMATION
)Buffer
;
730 Buffer0
->FileIndex
= FileIndex
++;
733 if (Stack
->Flags
& SL_RETURN_SINGLE_ENTRY
)
737 BufferLength
-= Buffer0
->NextEntryOffset
;
738 Buffer
+= Buffer0
->NextEntryOffset
;
743 Buffer0
->NextEntryOffset
= 0;
748 Status
= STATUS_SUCCESS
;
756 CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject
,
759 PIO_STACK_LOCATION Stack
;
762 DPRINT("CdfsDirectoryControl() called\n");
763 FsRtlEnterFileSystem();
765 Stack
= IoGetCurrentIrpStackLocation(Irp
);
767 switch (Stack
->MinorFunction
)
769 case IRP_MN_QUERY_DIRECTORY
:
770 Status
= CdfsQueryDirectory(DeviceObject
,
774 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
775 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
776 Status
= STATUS_NOT_IMPLEMENTED
;
780 DPRINT1("CDFS: MinorFunction %u\n", Stack
->MinorFunction
);
781 Status
= STATUS_INVALID_DEVICE_REQUEST
;
785 Irp
->IoStatus
.Status
= Status
;
786 Irp
->IoStatus
.Information
= 0;
788 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
789 FsRtlExitFileSystem();