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