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.
19 /* $Id: dirctl.c 57791 2012-12-02 21:04:31Z pschweitzer $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/fs/cdfs/dirctl.c
24 * PURPOSE: CDROM (ISO 9660) filesystem driver
25 * PROGRAMMER: Art Yerkes
30 /* INCLUDES *****************************************************************/
37 /* FUNCTIONS ****************************************************************/
39 #define ROUND_DOWN(N, S) (((N) / (S)) * (S))
40 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
42 /* FUNCTIONS ****************************************************************/
45 * FUNCTION: Retrieves the file name, be it in short or long file name format
48 CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt
,
51 PLARGE_INTEGER StreamOffset
,
58 PDIR_RECORD Record
= *Ptr
;
61 if (*CurrentOffset
>= DirLength
)
62 return(STATUS_NO_MORE_ENTRIES
);
64 if (*CurrentOffset
== 0)
67 Record
= (PDIR_RECORD
)*Block
;
68 while (Index
< *pIndex
)
70 (*Ptr
) = (PVOID
)((ULONG_PTR
)(*Ptr
) + Record
->RecordLength
);
71 (*CurrentOffset
) += Record
->RecordLength
;
73 if ((ULONG_PTR
)(*Ptr
) - (ULONG_PTR
)(*Block
) >= BLOCKSIZE
|| Record
->RecordLength
== 0)
75 DPRINT("Map next sector\n");
76 CcUnpinData(*Context
);
77 StreamOffset
->QuadPart
+= BLOCKSIZE
;
78 *CurrentOffset
= ROUND_UP(*CurrentOffset
, BLOCKSIZE
);
79 if (!CcMapData(DeviceExt
->StreamFileObject
,
84 DPRINT("CcMapData() failed\n");
85 return(STATUS_UNSUCCESSFUL
);
88 Record
= (PDIR_RECORD
)*Ptr
;
90 if (*CurrentOffset
>= DirLength
)
91 return(STATUS_NO_MORE_ENTRIES
);
97 if ((ULONG_PTR
)(*Ptr
) - (ULONG_PTR
)(*Block
) >= BLOCKSIZE
|| Record
->RecordLength
== 0)
99 DPRINT("Map next sector\n");
100 CcUnpinData(*Context
);
101 StreamOffset
->QuadPart
+= BLOCKSIZE
;
102 *CurrentOffset
= ROUND_UP(*CurrentOffset
, BLOCKSIZE
);
103 if (!CcMapData(DeviceExt
->StreamFileObject
,
108 DPRINT("CcMapData() failed\n");
109 return(STATUS_UNSUCCESSFUL
);
112 Record
= (PDIR_RECORD
)*Ptr
;
115 if (*CurrentOffset
>= DirLength
)
116 return STATUS_NO_MORE_ENTRIES
;
118 DPRINT("Index %lu RecordLength %lu Offset %lu\n",
119 *pIndex
, Record
->RecordLength
, *CurrentOffset
);
121 if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 0)
125 else if (Record
->FileIdLength
== 1 && Record
->FileId
[0] == 1)
131 if (DeviceExt
->CdInfo
.JolietLevel
== 0)
135 for (i
= 0; i
< Record
->FileIdLength
&& Record
->FileId
[i
] != ';'; i
++)
136 Name
[i
] = (WCHAR
)Record
->FileId
[i
];
141 CdfsSwapString(Name
, Record
->FileId
, Record
->FileIdLength
);
145 DPRINT("Name '%S'\n", Name
);
149 return(STATUS_SUCCESS
);
154 * FUNCTION: Find a file
157 CdfsFindFile(PDEVICE_EXTENSION DeviceExt
,
160 PUNICODE_STRING FileToFind
,
165 WCHAR ShortNameBuffer
[13];
166 UNICODE_STRING TempString
;
167 UNICODE_STRING ShortName
;
168 UNICODE_STRING LongName
;
169 UNICODE_STRING FileToFindUpcase
;
176 PVOID Context
= NULL
;
179 LARGE_INTEGER StreamOffset
, OffsetOfEntry
;
181 DPRINT("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
182 Parent
, FileToFind
, pDirIndex
? *pDirIndex
: 0);
183 DPRINT("FindFile: old Pathname %x, old Objectname %x)\n",
184 Fcb
->PathName
, Fcb
->ObjectName
);
189 if (FileToFind
== NULL
|| FileToFind
->Length
== 0)
191 RtlInitUnicodeString(&TempString
, L
".");
192 FileToFind
= &TempString
;
197 if (Parent
->Entry
.ExtentLocationL
== DeviceExt
->CdInfo
.RootStart
)
209 StreamOffset
.QuadPart
= (LONGLONG
)DeviceExt
->CdInfo
.RootStart
* (LONGLONG
)BLOCKSIZE
;
210 DirSize
= DeviceExt
->CdInfo
.RootSize
;
213 if (FileToFind
->Buffer
[0] == 0 ||
214 (FileToFind
->Buffer
[0] == '\\' && FileToFind
->Buffer
[1] == 0) ||
215 (FileToFind
->Buffer
[0] == '.' && FileToFind
->Buffer
[1] == 0))
217 /* it's root : complete essentials fields then return ok */
218 RtlZeroMemory(Fcb
, sizeof(FCB
));
220 Fcb
->PathName
[0] = '\\';
221 Fcb
->ObjectName
= &Fcb
->PathName
[1];
222 Fcb
->Entry
.ExtentLocationL
= DeviceExt
->CdInfo
.RootStart
;
223 Fcb
->Entry
.DataLengthL
= DeviceExt
->CdInfo
.RootSize
;
224 Fcb
->Entry
.FileFlags
= 0x02; //FILE_ATTRIBUTE_DIRECTORY;
230 DPRINT("CdfsFindFile: new Pathname %S, new Objectname %S)\n",Fcb
->PathName
, Fcb
->ObjectName
);
231 return STATUS_SUCCESS
;
236 StreamOffset
.QuadPart
= (LONGLONG
)Parent
->Entry
.ExtentLocationL
* (LONGLONG
)BLOCKSIZE
;
237 DirSize
= Parent
->Entry
.DataLengthL
;
240 DPRINT("StreamOffset %I64u DirSize %lu\n", StreamOffset
.QuadPart
, DirSize
);
242 if (pDirIndex
&& (*pDirIndex
))
243 DirIndex
= *pDirIndex
;
245 if (pOffset
&& (*pOffset
))
248 StreamOffset
.QuadPart
+= ROUND_DOWN(Offset
, BLOCKSIZE
);
251 if (!CcMapData(DeviceExt
->StreamFileObject
, &StreamOffset
,
252 BLOCKSIZE
, TRUE
, &Context
, &Block
))
254 DPRINT("CcMapData() failed\n");
255 return STATUS_UNSUCCESSFUL
;
258 Record
= (PDIR_RECORD
) ((ULONG_PTR
)Block
+ Offset
% BLOCKSIZE
);
261 Offset
+= Record
->RecordLength
;
262 Record
= (PDIR_RECORD
)((ULONG_PTR
)Record
+ Record
->RecordLength
);
265 /* Upper case the expression for FsRtlIsNameInExpression */
266 Status
= RtlUpcaseUnicodeString(&FileToFindUpcase
, FileToFind
, TRUE
);
267 if (!NT_SUCCESS(Status
))
274 DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n",
275 Record
->RecordLength
, Record
->ExtAttrRecordLength
, Record
->FileIdLength
);
277 Status
= CdfsGetEntryName
278 (DeviceExt
, &Context
, &Block
, &StreamOffset
,
279 DirSize
, (PVOID
*)&Record
, name
, &DirIndex
, &Offset
);
281 if (Status
== STATUS_NO_MORE_ENTRIES
)
285 else if (Status
== STATUS_UNSUCCESSFUL
)
287 /* Note: the directory cache has already been unpinned */
288 RtlFreeUnicodeString(&FileToFindUpcase
);
292 DPRINT("Name '%S'\n", name
);
294 RtlInitUnicodeString(&LongName
, name
);
295 ShortName
.Length
= 0;
296 ShortName
.MaximumLength
= 26;
297 ShortName
.Buffer
= ShortNameBuffer
;
299 OffsetOfEntry
.QuadPart
= StreamOffset
.QuadPart
+ Offset
;
300 CdfsShortNameCacheGet(Parent
, &OffsetOfEntry
, &LongName
, &ShortName
);
302 DPRINT("ShortName '%wZ'\n", &ShortName
);
304 if (FsRtlIsNameInExpression(&FileToFindUpcase
, &LongName
, TRUE
, NULL
) ||
305 FsRtlIsNameInExpression(&FileToFindUpcase
, &ShortName
, TRUE
, NULL
))
307 if (Parent
&& Parent
->PathName
)
309 len
= wcslen(Parent
->PathName
);
310 memcpy(Fcb
->PathName
, Parent
->PathName
, len
*sizeof(WCHAR
));
311 Fcb
->ObjectName
=&Fcb
->PathName
[len
];
312 if (len
!= 1 || Fcb
->PathName
[0] != '\\')
314 Fcb
->ObjectName
[0] = '\\';
315 Fcb
->ObjectName
= &Fcb
->ObjectName
[1];
320 Fcb
->ObjectName
=Fcb
->PathName
;
321 Fcb
->ObjectName
[0]='\\';
322 Fcb
->ObjectName
=&Fcb
->ObjectName
[1];
325 DPRINT("PathName '%S' ObjectName '%S'\n", Fcb
->PathName
, Fcb
->ObjectName
);
327 memcpy(&Fcb
->Entry
, Record
, sizeof(DIR_RECORD
));
328 wcsncpy(Fcb
->ObjectName
, name
, min(wcslen(name
) + 1,
329 MAX_PATH
- wcslen(Fcb
->PathName
) + wcslen(Fcb
->ObjectName
)));
331 /* Copy short name */
332 Fcb
->ShortNameU
.Length
= ShortName
.Length
;
333 Fcb
->ShortNameU
.MaximumLength
= ShortName
.Length
;
334 Fcb
->ShortNameU
.Buffer
= Fcb
->ShortNameBuffer
;
335 memcpy(Fcb
->ShortNameBuffer
, ShortName
.Buffer
, ShortName
.Length
);
338 *pDirIndex
= DirIndex
;
342 DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",
343 Fcb
->PathName
, Fcb
->ObjectName
, DirIndex
);
345 RtlFreeUnicodeString(&FileToFindUpcase
);
346 CcUnpinData(Context
);
348 return STATUS_SUCCESS
;
351 Offset
+= Record
->RecordLength
;
352 Record
= (PDIR_RECORD
)((ULONG_PTR
)Record
+ Record
->RecordLength
);
356 RtlFreeUnicodeString(&FileToFindUpcase
);
357 CcUnpinData(Context
);
360 *pDirIndex
= DirIndex
;
365 return STATUS_UNSUCCESSFUL
;
370 CdfsGetNameInformation(PFCB Fcb
,
371 PDEVICE_EXTENSION DeviceExt
,
372 PFILE_NAMES_INFORMATION Info
,
377 DPRINT("CdfsGetNameInformation() called\n");
379 Length
= wcslen(Fcb
->ObjectName
) * sizeof(WCHAR
);
380 if ((sizeof(FILE_NAMES_INFORMATION
) + Length
) > BufferLength
)
381 return(STATUS_BUFFER_OVERFLOW
);
383 Info
->FileNameLength
= Length
;
384 Info
->NextEntryOffset
=
385 ROUND_UP(sizeof(FILE_NAMES_INFORMATION
) + Length
, sizeof(ULONG
));
386 RtlCopyMemory(Info
->FileName
, Fcb
->ObjectName
, Length
);
390 return(STATUS_SUCCESS
);
395 CdfsGetDirectoryInformation(PFCB Fcb
,
396 PDEVICE_EXTENSION DeviceExt
,
397 PFILE_DIRECTORY_INFORMATION Info
,
402 DPRINT("CdfsGetDirectoryInformation() called\n");
404 Length
= wcslen(Fcb
->ObjectName
) * sizeof(WCHAR
);
405 if ((sizeof (FILE_DIRECTORY_INFORMATION
) + Length
) > BufferLength
)
406 return(STATUS_BUFFER_OVERFLOW
);
408 Info
->FileNameLength
= Length
;
409 Info
->NextEntryOffset
=
410 ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION
) + Length
, sizeof(ULONG
));
411 RtlCopyMemory(Info
->FileName
, Fcb
->ObjectName
, Length
);
413 /* Convert file times */
414 CdfsDateTimeToSystemTime(Fcb
,
415 &Info
->CreationTime
);
416 Info
->LastWriteTime
= Info
->CreationTime
;
417 Info
->ChangeTime
= Info
->CreationTime
;
419 /* Convert file flags */
420 CdfsFileFlagsToAttributes(Fcb
,
421 &Info
->FileAttributes
);
422 if (CdfsFCBIsDirectory(Fcb
))
424 Info
->EndOfFile
.QuadPart
= 0;
425 Info
->AllocationSize
.QuadPart
= 0;
429 Info
->EndOfFile
.QuadPart
= Fcb
->Entry
.DataLengthL
;
431 /* Make AllocSize a rounded up multiple of the sector size */
432 Info
->AllocationSize
.QuadPart
= ROUND_UP(Fcb
->Entry
.DataLengthL
, BLOCKSIZE
);
437 return(STATUS_SUCCESS
);
442 CdfsGetFullDirectoryInformation(PFCB Fcb
,
443 PDEVICE_EXTENSION DeviceExt
,
444 PFILE_FULL_DIR_INFORMATION Info
,
449 DPRINT("CdfsGetFullDirectoryInformation() called\n");
451 Length
= wcslen(Fcb
->ObjectName
) * sizeof(WCHAR
);
452 if ((sizeof (FILE_FULL_DIR_INFORMATION
) + Length
) > BufferLength
)
453 return(STATUS_BUFFER_OVERFLOW
);
455 Info
->FileNameLength
= Length
;
456 Info
->NextEntryOffset
=
457 ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION
) + Length
, sizeof(ULONG
));
458 RtlCopyMemory(Info
->FileName
, Fcb
->ObjectName
, Length
);
460 /* Convert file times */
461 CdfsDateTimeToSystemTime(Fcb
,
462 &Info
->CreationTime
);
463 Info
->LastWriteTime
= Info
->CreationTime
;
464 Info
->ChangeTime
= Info
->CreationTime
;
466 /* Convert file flags */
467 CdfsFileFlagsToAttributes(Fcb
,
468 &Info
->FileAttributes
);
470 if (CdfsFCBIsDirectory(Fcb
))
472 Info
->EndOfFile
.QuadPart
= 0;
473 Info
->AllocationSize
.QuadPart
= 0;
477 Info
->EndOfFile
.QuadPart
= Fcb
->Entry
.DataLengthL
;
479 /* Make AllocSize a rounded up multiple of the sector size */
480 Info
->AllocationSize
.QuadPart
= ROUND_UP(Fcb
->Entry
.DataLengthL
, BLOCKSIZE
);
486 return(STATUS_SUCCESS
);
491 CdfsGetBothDirectoryInformation(PFCB Fcb
,
492 PDEVICE_EXTENSION DeviceExt
,
493 PFILE_BOTH_DIR_INFORMATION Info
,
498 DPRINT("CdfsGetBothDirectoryInformation() called\n");
500 Length
= wcslen(Fcb
->ObjectName
) * sizeof(WCHAR
);
501 if ((sizeof (FILE_BOTH_DIR_INFORMATION
) + Length
) > BufferLength
)
502 return(STATUS_BUFFER_OVERFLOW
);
504 Info
->FileNameLength
= Length
;
505 Info
->NextEntryOffset
=
506 ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION
) + Length
, sizeof(ULONG
));
507 RtlCopyMemory(Info
->FileName
, Fcb
->ObjectName
, Length
);
509 /* Convert file times */
510 CdfsDateTimeToSystemTime(Fcb
,
511 &Info
->CreationTime
);
512 Info
->LastWriteTime
= Info
->CreationTime
;
513 Info
->ChangeTime
= Info
->CreationTime
;
515 /* Convert file flags */
516 CdfsFileFlagsToAttributes(Fcb
,
517 &Info
->FileAttributes
);
519 if (CdfsFCBIsDirectory(Fcb
))
521 Info
->EndOfFile
.QuadPart
= 0;
522 Info
->AllocationSize
.QuadPart
= 0;
526 Info
->EndOfFile
.QuadPart
= Fcb
->Entry
.DataLengthL
;
528 /* Make AllocSize a rounded up multiple of the sector size */
529 Info
->AllocationSize
.QuadPart
= ROUND_UP(Fcb
->Entry
.DataLengthL
, BLOCKSIZE
);
535 /* Copy short name */
536 ASSERT(Fcb
->ShortNameU
.Length
/ sizeof(WCHAR
) <= 12);
537 Info
->ShortNameLength
= (CCHAR
)Fcb
->ShortNameU
.Length
;
538 RtlCopyMemory(Info
->ShortName
, Fcb
->ShortNameU
.Buffer
, Fcb
->ShortNameU
.Length
);
540 return(STATUS_SUCCESS
);
545 CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject
,
548 PDEVICE_EXTENSION DeviceExtension
;
549 LONG BufferLength
= 0;
550 PUNICODE_STRING SearchPattern
= NULL
;
551 FILE_INFORMATION_CLASS FileInformationClass
;
553 PUCHAR Buffer
= NULL
;
554 PFILE_NAMES_INFORMATION Buffer0
= NULL
;
558 BOOLEAN First
= FALSE
;
559 PIO_STACK_LOCATION Stack
;
560 PFILE_OBJECT FileObject
;
561 NTSTATUS Status
= STATUS_SUCCESS
;
563 DPRINT("CdfsQueryDirectory() called\n");
565 DeviceExtension
= DeviceObject
->DeviceExtension
;
566 Stack
= IoGetCurrentIrpStackLocation(Irp
);
567 FileObject
= Stack
->FileObject
;
569 Ccb
= (PCCB
)FileObject
->FsContext2
;
570 Fcb
= (PFCB
)FileObject
->FsContext
;
572 /* Obtain the callers parameters */
573 BufferLength
= Stack
->Parameters
.QueryDirectory
.Length
;
574 SearchPattern
= Stack
->Parameters
.QueryDirectory
.FileName
;
575 FileInformationClass
=
576 Stack
->Parameters
.QueryDirectory
.FileInformationClass
;
577 FileIndex
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
579 /* Determine Buffer for result */
582 Buffer
= MmGetSystemAddressForMdl(Irp
->MdlAddress
);
586 Buffer
= Irp
->UserBuffer
;
589 /* Allocate search pattern in case:
590 * -> We don't have one already in context
591 * -> We have been given an input pattern
592 * -> The pattern length is not null
593 * -> The pattern buffer is not null
594 * Otherwise, we'll fall later and allocate a match all (*) pattern
596 if (SearchPattern
!= NULL
&&
597 SearchPattern
->Length
!= 0 && SearchPattern
->Buffer
!= NULL
)
599 if (Ccb
->DirectorySearchPattern
.Buffer
== NULL
)
602 Ccb
->DirectorySearchPattern
.Buffer
=
603 ExAllocatePoolWithTag(NonPagedPool
, SearchPattern
->Length
+ sizeof(WCHAR
), TAG_CCB
);
604 if (Ccb
->DirectorySearchPattern
.Buffer
== NULL
)
606 return STATUS_INSUFFICIENT_RESOURCES
;
608 Ccb
->DirectorySearchPattern
.MaximumLength
= SearchPattern
->Length
+ sizeof(WCHAR
);
609 RtlCopyUnicodeString(&Ccb
->DirectorySearchPattern
, SearchPattern
);
610 Ccb
->DirectorySearchPattern
.Buffer
[SearchPattern
->Length
/ sizeof(WCHAR
)] = 0;
613 else if (Ccb
->DirectorySearchPattern
.Buffer
== NULL
)
616 Ccb
->DirectorySearchPattern
.Buffer
= ExAllocatePoolWithTag(NonPagedPool
, 2 * sizeof(WCHAR
), TAG_CCB
);
617 if (Ccb
->DirectorySearchPattern
.Buffer
== NULL
)
619 return STATUS_INSUFFICIENT_RESOURCES
;
622 Ccb
->DirectorySearchPattern
.Length
= sizeof(WCHAR
);
623 Ccb
->DirectorySearchPattern
.MaximumLength
= 2 * sizeof(WCHAR
);
624 Ccb
->DirectorySearchPattern
.Buffer
[0] = L
'*';
625 Ccb
->DirectorySearchPattern
.Buffer
[1] = 0;
627 DPRINT("Search pattern '%wZ'\n", &Ccb
->DirectorySearchPattern
);
629 /* Determine directory index */
630 if (Stack
->Flags
& SL_INDEX_SPECIFIED
)
632 Ccb
->Entry
= Stack
->Parameters
.QueryDirectory
.FileIndex
;
633 Ccb
->Offset
= Ccb
->CurrentByteOffset
.u
.LowPart
;
635 else if (First
|| (Stack
->Flags
& SL_RESTART_SCAN
))
640 DPRINT("Buffer = %p tofind = %wZ\n", Buffer
, &Ccb
->DirectorySearchPattern
);
642 TempFcb
.ObjectName
= TempFcb
.PathName
;
643 while (Status
== STATUS_SUCCESS
&& BufferLength
> 0)
645 Status
= CdfsFindFile(DeviceExtension
,
648 &Ccb
->DirectorySearchPattern
,
651 DPRINT("Found %S, Status=%x, entry %x\n", TempFcb
.ObjectName
, Status
, Ccb
->Entry
);
653 if (NT_SUCCESS(Status
))
655 switch (FileInformationClass
)
657 case FileNameInformation
:
658 Status
= CdfsGetNameInformation(&TempFcb
,
660 (PFILE_NAMES_INFORMATION
)Buffer
,
664 case FileDirectoryInformation
:
665 Status
= CdfsGetDirectoryInformation(&TempFcb
,
667 (PFILE_DIRECTORY_INFORMATION
)Buffer
,
671 case FileFullDirectoryInformation
:
672 Status
= CdfsGetFullDirectoryInformation(&TempFcb
,
674 (PFILE_FULL_DIR_INFORMATION
)Buffer
,
678 case FileBothDirectoryInformation
:
679 Status
= CdfsGetBothDirectoryInformation(&TempFcb
,
681 (PFILE_BOTH_DIR_INFORMATION
)Buffer
,
686 Status
= STATUS_INVALID_INFO_CLASS
;
689 if (Status
== STATUS_BUFFER_OVERFLOW
)
693 Buffer0
->NextEntryOffset
= 0;
702 Buffer0
->NextEntryOffset
= 0;
707 Status
= STATUS_NO_SUCH_FILE
;
711 Status
= STATUS_NO_MORE_FILES
;
716 Buffer0
= (PFILE_NAMES_INFORMATION
)Buffer
;
717 Buffer0
->FileIndex
= FileIndex
++;
720 if (Stack
->Flags
& SL_RETURN_SINGLE_ENTRY
)
724 BufferLength
-= Buffer0
->NextEntryOffset
;
725 Buffer
+= Buffer0
->NextEntryOffset
;
730 Buffer0
->NextEntryOffset
= 0;
735 Status
= STATUS_SUCCESS
;
744 CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject
,
747 PIO_STACK_LOCATION Stack
;
750 DPRINT("CdfsDirectoryControl() called\n");
751 FsRtlEnterFileSystem();
753 Stack
= IoGetCurrentIrpStackLocation(Irp
);
755 switch (Stack
->MinorFunction
)
757 case IRP_MN_QUERY_DIRECTORY
:
758 Status
= CdfsQueryDirectory(DeviceObject
,
762 case IRP_MN_NOTIFY_CHANGE_DIRECTORY
:
763 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
764 Status
= STATUS_NOT_IMPLEMENTED
;
768 DPRINT1("CDFS: MinorFunction %d\n", Stack
->MinorFunction
);
769 Status
= STATUS_INVALID_DEVICE_REQUEST
;
773 Irp
->IoStatus
.Status
= Status
;
774 Irp
->IoStatus
.Information
= 0;
776 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
777 FsRtlExitFileSystem();