Create a branch for audio work
[reactos.git] / drivers / filesystems / cdfs / dirctl.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2004 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id$
20 *
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
26 * Eric Kohl
27 * UPDATE HISTORY:
28 */
29
30 /* INCLUDES *****************************************************************/
31
32 #include "cdfs.h"
33
34 #define NDEBUG
35 #include <debug.h>
36
37 /* FUNCTIONS ****************************************************************/
38
39 #define ROUND_DOWN(N, S) (((N) / (S)) * (S))
40 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
41
42 /* FUNCTIONS ****************************************************************/
43
44 /*
45 * FUNCTION: Retrieves the file name, be it in short or long file name format
46 */
47 static NTSTATUS
48 CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt,
49 PVOID *Context,
50 PVOID *Block,
51 PLARGE_INTEGER StreamOffset,
52 ULONG DirLength,
53 PVOID *Ptr,
54 PWSTR Name,
55 PULONG pIndex,
56 PULONG CurrentOffset)
57 {
58 PDIR_RECORD Record = *Ptr;
59 ULONG Index;
60
61 if (*CurrentOffset >= DirLength)
62 return(STATUS_NO_MORE_ENTRIES);
63
64 if (*CurrentOffset == 0)
65 {
66 Index = 0;
67 Record = (PDIR_RECORD)*Block;
68 while (Index < *pIndex)
69 {
70 (*Ptr) = (PVOID)((ULONG_PTR)(*Ptr) + Record->RecordLength);
71 (*CurrentOffset) += Record->RecordLength;
72 Record = *Ptr;
73 if ((ULONG_PTR)(*Ptr) - (ULONG_PTR)(*Block) >= BLOCKSIZE || Record->RecordLength == 0)
74 {
75 DPRINT("Map next sector\n");
76 CcUnpinData(*Context);
77 StreamOffset->QuadPart += BLOCKSIZE;
78 *CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE);
79 if (!CcMapData(DeviceExt->StreamFileObject,
80 StreamOffset,
81 BLOCKSIZE, TRUE,
82 Context, Block))
83 {
84 DPRINT("CcMapData() failed\n");
85 return(STATUS_UNSUCCESSFUL);
86 }
87 *Ptr = *Block;
88 Record = (PDIR_RECORD)*Ptr;
89 }
90 if (*CurrentOffset >= DirLength)
91 return(STATUS_NO_MORE_ENTRIES);
92
93 Index++;
94 }
95 }
96
97 if ((ULONG_PTR)(*Ptr) - (ULONG_PTR)(*Block) >= BLOCKSIZE || Record->RecordLength == 0)
98 {
99 DPRINT("Map next sector\n");
100 CcUnpinData(*Context);
101 StreamOffset->QuadPart += BLOCKSIZE;
102 *CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE);
103 if (!CcMapData(DeviceExt->StreamFileObject,
104 StreamOffset,
105 BLOCKSIZE, TRUE,
106 Context, Block))
107 {
108 DPRINT("CcMapData() failed\n");
109 return(STATUS_UNSUCCESSFUL);
110 }
111 *Ptr = *Block;
112 Record = (PDIR_RECORD)*Ptr;
113 }
114
115 if (*CurrentOffset >= DirLength)
116 return STATUS_NO_MORE_ENTRIES;
117
118 DPRINT("Index %lu RecordLength %lu Offset %lu\n",
119 *pIndex, Record->RecordLength, *CurrentOffset);
120
121 if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
122 {
123 wcscpy(Name, L".");
124 }
125 else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
126 {
127 wcscpy(Name, L"..");
128 }
129 else
130 {
131 if (DeviceExt->CdInfo.JolietLevel == 0)
132 {
133 ULONG i;
134
135 for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
136 Name[i] = (WCHAR)Record->FileId[i];
137 Name[i] = 0;
138 }
139 else
140 {
141 CdfsSwapString(Name, Record->FileId, Record->FileIdLength);
142 }
143 }
144
145 DPRINT("Name '%S'\n", Name);
146
147 *Ptr = Record;
148
149 return(STATUS_SUCCESS);
150 }
151
152
153 /*
154 * FUNCTION: Find a file
155 */
156 static NTSTATUS
157 CdfsFindFile(PDEVICE_EXTENSION DeviceExt,
158 PFCB Fcb,
159 PFCB Parent,
160 PUNICODE_STRING FileToFind,
161 PULONG pDirIndex,
162 PULONG pOffset)
163 {
164 WCHAR name[256];
165 WCHAR ShortNameBuffer[13];
166 UNICODE_STRING TempString;
167 UNICODE_STRING ShortName;
168 UNICODE_STRING LongName;
169 UNICODE_STRING FileToFindUpcase;
170 PVOID Block;
171 NTSTATUS Status;
172 ULONG len;
173 ULONG DirIndex;
174 ULONG Offset = 0;
175 BOOLEAN IsRoot;
176 PVOID Context = NULL;
177 ULONG DirSize;
178 PDIR_RECORD Record;
179 LARGE_INTEGER StreamOffset, OffsetOfEntry;
180
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);
185
186 IsRoot = FALSE;
187 DirIndex = 0;
188
189 if (FileToFind == NULL || FileToFind->Length == 0)
190 {
191 RtlInitUnicodeString(&TempString, L".");
192 FileToFind = &TempString;
193 }
194
195 if (Parent)
196 {
197 if (Parent->Entry.ExtentLocationL == DeviceExt->CdInfo.RootStart)
198 {
199 IsRoot = TRUE;
200 }
201 }
202 else
203 {
204 IsRoot = TRUE;
205 }
206
207 if (IsRoot == TRUE)
208 {
209 StreamOffset.QuadPart = (LONGLONG)DeviceExt->CdInfo.RootStart * (LONGLONG)BLOCKSIZE;
210 DirSize = DeviceExt->CdInfo.RootSize;
211
212
213 if (FileToFind->Buffer[0] == 0 ||
214 (FileToFind->Buffer[0] == '\\' && FileToFind->Buffer[1] == 0) ||
215 (FileToFind->Buffer[0] == '.' && FileToFind->Buffer[1] == 0))
216 {
217 /* it's root : complete essentials fields then return ok */
218 RtlZeroMemory(Fcb, sizeof(FCB));
219
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;
225
226 if (pDirIndex)
227 *pDirIndex = 0;
228 if (pOffset)
229 *pOffset = 0;
230 DPRINT("CdfsFindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName);
231 return STATUS_SUCCESS;
232 }
233 }
234 else
235 {
236 StreamOffset.QuadPart = (LONGLONG)Parent->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
237 DirSize = Parent->Entry.DataLengthL;
238 }
239
240 DPRINT("StreamOffset %I64u DirSize %lu\n", StreamOffset.QuadPart, DirSize);
241
242 if (pDirIndex && (*pDirIndex))
243 DirIndex = *pDirIndex;
244
245 if (pOffset && (*pOffset))
246 {
247 Offset = *pOffset;
248 StreamOffset.QuadPart += ROUND_DOWN(Offset, BLOCKSIZE);
249 }
250
251 if (!CcMapData(DeviceExt->StreamFileObject, &StreamOffset,
252 BLOCKSIZE, TRUE, &Context, &Block))
253 {
254 DPRINT("CcMapData() failed\n");
255 return STATUS_UNSUCCESSFUL;
256 }
257
258 Record = (PDIR_RECORD) ((ULONG_PTR)Block + Offset % BLOCKSIZE);
259 if (Offset)
260 {
261 Offset += Record->RecordLength;
262 Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength);
263 }
264
265 /* Upper case the expression for FsRtlIsNameInExpression */
266 Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFind, TRUE);
267 if (!NT_SUCCESS(Status))
268 {
269 return Status;
270 }
271
272 while(TRUE)
273 {
274 DPRINT("RecordLength %u ExtAttrRecordLength %u NameLength %u\n",
275 Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
276
277 Status = CdfsGetEntryName
278 (DeviceExt, &Context, &Block, &StreamOffset,
279 DirSize, (PVOID*)&Record, name, &DirIndex, &Offset);
280
281 if (Status == STATUS_NO_MORE_ENTRIES)
282 {
283 break;
284 }
285 else if (Status == STATUS_UNSUCCESSFUL)
286 {
287 /* Note: the directory cache has already been unpinned */
288 RtlFreeUnicodeString(&FileToFindUpcase);
289 return Status;
290 }
291
292 DPRINT("Name '%S'\n", name);
293
294 RtlInitUnicodeString(&LongName, name);
295 ShortName.Length = 0;
296 ShortName.MaximumLength = 26;
297 ShortName.Buffer = ShortNameBuffer;
298
299 OffsetOfEntry.QuadPart = StreamOffset.QuadPart + Offset;
300 CdfsShortNameCacheGet(Parent, &OffsetOfEntry, &LongName, &ShortName);
301
302 DPRINT("ShortName '%wZ'\n", &ShortName);
303
304 if (FsRtlIsNameInExpression(&FileToFindUpcase, &LongName, TRUE, NULL) ||
305 FsRtlIsNameInExpression(&FileToFindUpcase, &ShortName, TRUE, NULL))
306 {
307 if (Parent && Parent->PathName)
308 {
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] != '\\')
313 {
314 Fcb->ObjectName[0] = '\\';
315 Fcb->ObjectName = &Fcb->ObjectName[1];
316 }
317 }
318 else
319 {
320 Fcb->ObjectName=Fcb->PathName;
321 Fcb->ObjectName[0]='\\';
322 Fcb->ObjectName=&Fcb->ObjectName[1];
323 }
324
325 DPRINT("PathName '%S' ObjectName '%S'\n", Fcb->PathName, Fcb->ObjectName);
326
327 memcpy(&Fcb->Entry, Record, sizeof(DIR_RECORD));
328 wcsncpy(Fcb->ObjectName, name, MAX_PATH);
329
330 /* Copy short name */
331 Fcb->ShortNameU.Length = ShortName.Length;
332 Fcb->ShortNameU.MaximumLength = ShortName.Length;
333 Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer;
334 memcpy(Fcb->ShortNameBuffer, ShortName.Buffer, ShortName.Length);
335
336 if (pDirIndex)
337 *pDirIndex = DirIndex;
338 if (pOffset)
339 *pOffset = Offset;
340
341 DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",
342 Fcb->PathName, Fcb->ObjectName, DirIndex);
343
344 RtlFreeUnicodeString(&FileToFindUpcase);
345 CcUnpinData(Context);
346
347 return STATUS_SUCCESS;
348 }
349
350 Offset += Record->RecordLength;
351 Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength);
352 DirIndex++;
353 }
354
355 RtlFreeUnicodeString(&FileToFindUpcase);
356 CcUnpinData(Context);
357
358 if (pDirIndex)
359 *pDirIndex = DirIndex;
360
361 if (pOffset)
362 *pOffset = Offset;
363
364 return STATUS_UNSUCCESSFUL;
365 }
366
367
368 static NTSTATUS
369 CdfsGetNameInformation(PFCB Fcb,
370 PDEVICE_EXTENSION DeviceExt,
371 PFILE_NAMES_INFORMATION Info,
372 ULONG BufferLength)
373 {
374 ULONG Length;
375
376 DPRINT("CdfsGetNameInformation() called\n");
377
378 Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
379 if ((sizeof(FILE_NAMES_INFORMATION) + Length) > BufferLength)
380 return(STATUS_BUFFER_OVERFLOW);
381
382 Info->FileNameLength = Length;
383 Info->NextEntryOffset =
384 ROUND_UP(sizeof(FILE_NAMES_INFORMATION) + Length, sizeof(ULONG));
385 RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
386
387 // Info->FileIndex=;
388
389 return(STATUS_SUCCESS);
390 }
391
392
393 static NTSTATUS
394 CdfsGetDirectoryInformation(PFCB Fcb,
395 PDEVICE_EXTENSION DeviceExt,
396 PFILE_DIRECTORY_INFORMATION Info,
397 ULONG BufferLength)
398 {
399 ULONG Length;
400
401 DPRINT("CdfsGetDirectoryInformation() called\n");
402
403 Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
404 if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
405 return(STATUS_BUFFER_OVERFLOW);
406
407 Info->FileNameLength = Length;
408 Info->NextEntryOffset =
409 ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) + Length, sizeof(ULONG));
410 RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
411
412 /* Convert file times */
413 CdfsDateTimeToSystemTime(Fcb,
414 &Info->CreationTime);
415 Info->LastWriteTime = Info->CreationTime;
416 Info->ChangeTime = Info->CreationTime;
417
418 /* Convert file flags */
419 CdfsFileFlagsToAttributes(Fcb,
420 &Info->FileAttributes);
421 if (CdfsFCBIsDirectory(Fcb))
422 {
423 Info->EndOfFile.QuadPart = 0;
424 Info->AllocationSize.QuadPart = 0;
425 }
426 else
427 {
428 Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
429
430 /* Make AllocSize a rounded up multiple of the sector size */
431 Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
432 }
433
434 // Info->FileIndex=;
435
436 return(STATUS_SUCCESS);
437 }
438
439
440 static NTSTATUS
441 CdfsGetFullDirectoryInformation(PFCB Fcb,
442 PDEVICE_EXTENSION DeviceExt,
443 PFILE_FULL_DIR_INFORMATION Info,
444 ULONG BufferLength)
445 {
446 ULONG Length;
447
448 DPRINT("CdfsGetFullDirectoryInformation() called\n");
449
450 Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
451 if ((sizeof (FILE_FULL_DIR_INFORMATION) + Length) > BufferLength)
452 return(STATUS_BUFFER_OVERFLOW);
453
454 Info->FileNameLength = Length;
455 Info->NextEntryOffset =
456 ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION) + Length, sizeof(ULONG));
457 RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
458
459 /* Convert file times */
460 CdfsDateTimeToSystemTime(Fcb,
461 &Info->CreationTime);
462 Info->LastWriteTime = Info->CreationTime;
463 Info->ChangeTime = Info->CreationTime;
464
465 /* Convert file flags */
466 CdfsFileFlagsToAttributes(Fcb,
467 &Info->FileAttributes);
468
469 if (CdfsFCBIsDirectory(Fcb))
470 {
471 Info->EndOfFile.QuadPart = 0;
472 Info->AllocationSize.QuadPart = 0;
473 }
474 else
475 {
476 Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
477
478 /* Make AllocSize a rounded up multiple of the sector size */
479 Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
480 }
481
482 // Info->FileIndex=;
483 Info->EaSize = 0;
484
485 return(STATUS_SUCCESS);
486 }
487
488
489 static NTSTATUS
490 CdfsGetBothDirectoryInformation(PFCB Fcb,
491 PDEVICE_EXTENSION DeviceExt,
492 PFILE_BOTH_DIR_INFORMATION Info,
493 ULONG BufferLength)
494 {
495 ULONG Length;
496
497 DPRINT("CdfsGetBothDirectoryInformation() called\n");
498
499 Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
500 if ((sizeof (FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength)
501 return(STATUS_BUFFER_OVERFLOW);
502
503 Info->FileNameLength = Length;
504 Info->NextEntryOffset =
505 ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, sizeof(ULONG));
506 RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
507
508 /* Convert file times */
509 CdfsDateTimeToSystemTime(Fcb,
510 &Info->CreationTime);
511 Info->LastWriteTime = Info->CreationTime;
512 Info->ChangeTime = Info->CreationTime;
513
514 /* Convert file flags */
515 CdfsFileFlagsToAttributes(Fcb,
516 &Info->FileAttributes);
517
518 if (CdfsFCBIsDirectory(Fcb))
519 {
520 Info->EndOfFile.QuadPart = 0;
521 Info->AllocationSize.QuadPart = 0;
522 }
523 else
524 {
525 Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
526
527 /* Make AllocSize a rounded up multiple of the sector size */
528 Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
529 }
530
531 // Info->FileIndex=;
532 Info->EaSize = 0;
533
534 /* Copy short name */
535 ASSERT(Fcb->ShortNameU.Length / sizeof(WCHAR) <= 12);
536 Info->ShortNameLength = Fcb->ShortNameU.Length;
537 RtlCopyMemory(Info->ShortName, Fcb->ShortNameU.Buffer, Fcb->ShortNameU.Length);
538
539 return(STATUS_SUCCESS);
540 }
541
542
543 static NTSTATUS
544 CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject,
545 PIRP Irp)
546 {
547 PDEVICE_EXTENSION DeviceExtension;
548 LONG BufferLength = 0;
549 PUNICODE_STRING SearchPattern = NULL;
550 FILE_INFORMATION_CLASS FileInformationClass;
551 ULONG FileIndex = 0;
552 PUCHAR Buffer = NULL;
553 PFILE_NAMES_INFORMATION Buffer0 = NULL;
554 PFCB Fcb;
555 PCCB Ccb;
556 FCB TempFcb;
557 BOOLEAN First = FALSE;
558 PIO_STACK_LOCATION Stack;
559 PFILE_OBJECT FileObject;
560 NTSTATUS Status = STATUS_SUCCESS;
561
562 DPRINT("CdfsQueryDirectory() called\n");
563
564 DeviceExtension = DeviceObject->DeviceExtension;
565 Stack = IoGetCurrentIrpStackLocation(Irp);
566 FileObject = Stack->FileObject;
567
568 Ccb = (PCCB)FileObject->FsContext2;
569 Fcb = (PFCB)FileObject->FsContext;
570
571 /* Obtain the callers parameters */
572 BufferLength = Stack->Parameters.QueryDirectory.Length;
573 SearchPattern = Stack->Parameters.QueryDirectory.FileName;
574 FileInformationClass =
575 Stack->Parameters.QueryDirectory.FileInformationClass;
576 FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
577
578 /* Determine Buffer for result */
579 if (Irp->MdlAddress)
580 {
581 Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
582 }
583 else
584 {
585 Buffer = Irp->UserBuffer;
586 }
587
588 if (SearchPattern != NULL)
589 {
590 if (Ccb->DirectorySearchPattern.Buffer == NULL)
591 {
592 First = TRUE;
593 Ccb->DirectorySearchPattern.Buffer =
594 ExAllocatePoolWithTag(NonPagedPool, SearchPattern->Length + sizeof(WCHAR), TAG_CCB);
595 if (Ccb->DirectorySearchPattern.Buffer == NULL)
596 {
597 return STATUS_INSUFFICIENT_RESOURCES;
598 }
599 Ccb->DirectorySearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
600 RtlCopyUnicodeString(&Ccb->DirectorySearchPattern, SearchPattern);
601 Ccb->DirectorySearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0;
602 }
603 }
604 else if (Ccb->DirectorySearchPattern.Buffer == NULL)
605 {
606 First = TRUE;
607 Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), TAG_CCB);
608 if (Ccb->DirectorySearchPattern.Buffer == NULL)
609 {
610 return STATUS_INSUFFICIENT_RESOURCES;
611 }
612
613 Ccb->DirectorySearchPattern.Length = sizeof(WCHAR);
614 Ccb->DirectorySearchPattern.MaximumLength = 2 * sizeof(WCHAR);
615 Ccb->DirectorySearchPattern.Buffer[0] = L'*';
616 Ccb->DirectorySearchPattern.Buffer[1] = 0;
617 }
618 DPRINT("Search pattern '%wZ'\n", &Ccb->DirectorySearchPattern);
619
620 /* Determine directory index */
621 if (Stack->Flags & SL_INDEX_SPECIFIED)
622 {
623 Ccb->Entry = Stack->Parameters.QueryDirectory.FileIndex;
624 Ccb->Offset = Ccb->CurrentByteOffset.u.LowPart;
625 }
626 else if (First || (Stack->Flags & SL_RESTART_SCAN))
627 {
628 Ccb->Entry = 0;
629 Ccb->Offset = 0;
630 }
631 DPRINT("Buffer = %p tofind = %wZ\n", Buffer, &Ccb->DirectorySearchPattern);
632
633 TempFcb.ObjectName = TempFcb.PathName;
634 while (Status == STATUS_SUCCESS && BufferLength > 0)
635 {
636 Status = CdfsFindFile(DeviceExtension,
637 &TempFcb,
638 Fcb,
639 &Ccb->DirectorySearchPattern,
640 &Ccb->Entry,
641 &Ccb->Offset);
642 DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry);
643
644 if (NT_SUCCESS(Status))
645 {
646 switch (FileInformationClass)
647 {
648 case FileNameInformation:
649 Status = CdfsGetNameInformation(&TempFcb,
650 DeviceExtension,
651 (PFILE_NAMES_INFORMATION)Buffer,
652 BufferLength);
653 break;
654
655 case FileDirectoryInformation:
656 Status = CdfsGetDirectoryInformation(&TempFcb,
657 DeviceExtension,
658 (PFILE_DIRECTORY_INFORMATION)Buffer,
659 BufferLength);
660 break;
661
662 case FileFullDirectoryInformation:
663 Status = CdfsGetFullDirectoryInformation(&TempFcb,
664 DeviceExtension,
665 (PFILE_FULL_DIR_INFORMATION)Buffer,
666 BufferLength);
667 break;
668
669 case FileBothDirectoryInformation:
670 Status = CdfsGetBothDirectoryInformation(&TempFcb,
671 DeviceExtension,
672 (PFILE_BOTH_DIR_INFORMATION)Buffer,
673 BufferLength);
674 break;
675
676 default:
677 Status = STATUS_INVALID_INFO_CLASS;
678 }
679
680 if (Status == STATUS_BUFFER_OVERFLOW)
681 {
682 if (Buffer0)
683 {
684 Buffer0->NextEntryOffset = 0;
685 }
686 break;
687 }
688 }
689 else
690 {
691 if (Buffer0)
692 {
693 Buffer0->NextEntryOffset = 0;
694 }
695
696 if (First)
697 {
698 Status = STATUS_NO_SUCH_FILE;
699 }
700 else
701 {
702 Status = STATUS_NO_MORE_FILES;
703 }
704 break;
705 }
706
707 Buffer0 = (PFILE_NAMES_INFORMATION)Buffer;
708 Buffer0->FileIndex = FileIndex++;
709 Ccb->Entry++;
710
711 if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
712 {
713 break;
714 }
715 BufferLength -= Buffer0->NextEntryOffset;
716 Buffer += Buffer0->NextEntryOffset;
717 }
718
719 if (Buffer0)
720 {
721 Buffer0->NextEntryOffset = 0;
722 }
723
724 if (FileIndex > 0)
725 {
726 Status = STATUS_SUCCESS;
727 }
728
729 return(Status);
730 }
731
732
733
734 NTSTATUS NTAPI
735 CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
736 PIRP Irp)
737 {
738 PIO_STACK_LOCATION Stack;
739 NTSTATUS Status;
740
741 DPRINT("CdfsDirectoryControl() called\n");
742 FsRtlEnterFileSystem();
743
744 Stack = IoGetCurrentIrpStackLocation(Irp);
745
746 switch (Stack->MinorFunction)
747 {
748 case IRP_MN_QUERY_DIRECTORY:
749 Status = CdfsQueryDirectory(DeviceObject,
750 Irp);
751 break;
752
753 case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
754 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
755 Status = STATUS_NOT_IMPLEMENTED;
756 break;
757
758 default:
759 DPRINT1("CDFS: MinorFunction %d\n", Stack->MinorFunction);
760 Status = STATUS_INVALID_DEVICE_REQUEST;
761 break;
762 }
763
764 Irp->IoStatus.Status = Status;
765 Irp->IoStatus.Information = 0;
766
767 IoCompleteRequest(Irp, IO_NO_INCREMENT);
768 FsRtlExitFileSystem();
769
770 return(Status);
771 }
772
773 /* EOF */