ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dirctl.c
Go to the documentation of this file.
00001 /*
00002 *  ReactOS kernel
00003 *  Copyright (C) 2002, 2004 ReactOS Team
00004 *
00005 *  This program is free software; you can redistribute it and/or modify
00006 *  it under the terms of the GNU General Public License as published by
00007 *  the Free Software Foundation; either version 2 of the License, or
00008 *  (at your option) any later version.
00009 *
00010 *  This program is distributed in the hope that it will be useful,
00011 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 *  GNU General Public License for more details.
00014 *
00015 *  You should have received a copy of the GNU General Public License along
00016 *  with this program; if not, write to the Free Software Foundation, Inc.,
00017 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
00018 */
00019 /* $Id: dirctl.c 54072 2011-10-10 13:37:19Z khornicek $
00020 *
00021 * COPYRIGHT:        See COPYING in the top level directory
00022 * PROJECT:          ReactOS kernel
00023 * FILE:             services/fs/cdfs/dirctl.c
00024 * PURPOSE:          CDROM (ISO 9660) filesystem driver
00025 * PROGRAMMER:       Art Yerkes
00026 *                   Eric Kohl
00027 * UPDATE HISTORY:
00028 */
00029 
00030 /* INCLUDES *****************************************************************/
00031 
00032 #include "cdfs.h"
00033 
00034 #define NDEBUG
00035 #include <debug.h>
00036 
00037 /* FUNCTIONS ****************************************************************/
00038 
00039 #define ROUND_DOWN(N, S) (((N) / (S)) * (S))
00040 #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
00041 
00042 /* FUNCTIONS ****************************************************************/
00043 
00044 /*
00045 * FUNCTION: Retrieves the file name, be it in short or long file name format
00046 */
00047 static NTSTATUS
00048 CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt,
00049                  PVOID *Context,
00050                  PVOID *Block,
00051                  PLARGE_INTEGER StreamOffset,
00052                  ULONG DirLength,
00053                  PVOID *Ptr,
00054                  PWSTR Name,
00055                  PULONG pIndex,
00056                  PULONG CurrentOffset)
00057 {
00058     PDIR_RECORD Record = *Ptr;
00059     ULONG Index;
00060 
00061     if (*CurrentOffset >= DirLength)
00062         return(STATUS_NO_MORE_ENTRIES);
00063 
00064     if (*CurrentOffset == 0)
00065     {
00066         Index = 0;
00067         Record = (PDIR_RECORD)*Block;
00068         while (Index < *pIndex)
00069         {
00070             (*Ptr) = (PVOID)((ULONG_PTR)(*Ptr) + Record->RecordLength);
00071             (*CurrentOffset) += Record->RecordLength;
00072             Record = *Ptr;
00073             if ((ULONG_PTR)(*Ptr) - (ULONG_PTR)(*Block) >= BLOCKSIZE || Record->RecordLength == 0)
00074             {
00075                 DPRINT("Map next sector\n");
00076                 CcUnpinData(*Context);
00077                 StreamOffset->QuadPart += BLOCKSIZE;
00078                 *CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE);
00079                 if (!CcMapData(DeviceExt->StreamFileObject,
00080                     StreamOffset,
00081                     BLOCKSIZE, TRUE,
00082                     Context, Block))
00083                 {
00084                     DPRINT("CcMapData() failed\n");
00085                     return(STATUS_UNSUCCESSFUL);
00086                 }
00087                 *Ptr = *Block;
00088                 Record = (PDIR_RECORD)*Ptr;
00089             }
00090             if (*CurrentOffset >= DirLength)
00091                 return(STATUS_NO_MORE_ENTRIES);
00092 
00093             Index++;
00094         }
00095     }
00096 
00097     if ((ULONG_PTR)(*Ptr) - (ULONG_PTR)(*Block) >= BLOCKSIZE || Record->RecordLength == 0)
00098     {
00099         DPRINT("Map next sector\n");
00100         CcUnpinData(*Context);
00101         StreamOffset->QuadPart += BLOCKSIZE;
00102         *CurrentOffset = ROUND_UP(*CurrentOffset, BLOCKSIZE);
00103         if (!CcMapData(DeviceExt->StreamFileObject,
00104             StreamOffset,
00105             BLOCKSIZE, TRUE,
00106             Context, Block))
00107         {
00108             DPRINT("CcMapData() failed\n");
00109             return(STATUS_UNSUCCESSFUL);
00110         }
00111         *Ptr = *Block;
00112         Record = (PDIR_RECORD)*Ptr;
00113     }
00114 
00115     if (*CurrentOffset >= DirLength)
00116         return STATUS_NO_MORE_ENTRIES;
00117 
00118     DPRINT("Index %lu  RecordLength %lu  Offset %lu\n",
00119         *pIndex, Record->RecordLength, *CurrentOffset);
00120 
00121     if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
00122     {
00123         wcscpy(Name, L".");
00124     }
00125     else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
00126     {
00127         wcscpy(Name, L"..");
00128     }
00129     else
00130     {
00131         if (DeviceExt->CdInfo.JolietLevel == 0)
00132         {
00133             ULONG i;
00134 
00135             for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
00136                 Name[i] = (WCHAR)Record->FileId[i];
00137             Name[i] = 0;
00138         }
00139         else
00140         {
00141             CdfsSwapString(Name, Record->FileId, Record->FileIdLength);
00142         }
00143     }
00144 
00145     DPRINT("Name '%S'\n", Name);
00146 
00147     *Ptr = Record;
00148 
00149     return(STATUS_SUCCESS);
00150 }
00151 
00152 
00153 /*
00154 * FUNCTION: Find a file
00155 */
00156 static NTSTATUS
00157 CdfsFindFile(PDEVICE_EXTENSION DeviceExt,
00158              PFCB Fcb,
00159              PFCB Parent,
00160              PUNICODE_STRING FileToFind,
00161              PULONG pDirIndex,
00162              PULONG pOffset)
00163 {
00164     WCHAR name[256];
00165     WCHAR ShortNameBuffer[13];
00166     UNICODE_STRING TempString;
00167     UNICODE_STRING ShortName;
00168     UNICODE_STRING LongName;
00169     UNICODE_STRING FileToFindUpcase;
00170     PVOID Block;
00171     NTSTATUS Status;
00172     ULONG len;
00173     ULONG DirIndex;
00174     ULONG Offset = 0;
00175     BOOLEAN IsRoot;
00176     PVOID Context = NULL;
00177     ULONG DirSize;
00178     PDIR_RECORD Record;
00179     LARGE_INTEGER StreamOffset, OffsetOfEntry;
00180 
00181     DPRINT("FindFile(Parent %x, FileToFind '%wZ', DirIndex: %d)\n",
00182         Parent, FileToFind, pDirIndex ? *pDirIndex : 0);
00183     DPRINT("FindFile: old Pathname %x, old Objectname %x)\n",
00184         Fcb->PathName, Fcb->ObjectName);
00185 
00186     IsRoot = FALSE;
00187     DirIndex = 0;
00188 
00189     if (FileToFind == NULL || FileToFind->Length == 0)
00190     {
00191         RtlInitUnicodeString(&TempString, L".");
00192         FileToFind = &TempString;
00193     }
00194 
00195     if (Parent)
00196     {
00197         if (Parent->Entry.ExtentLocationL == DeviceExt->CdInfo.RootStart)
00198         {
00199             IsRoot = TRUE;
00200         }
00201     }
00202     else
00203     {
00204         IsRoot = TRUE;
00205     }
00206 
00207     if (IsRoot == TRUE)
00208     {
00209         StreamOffset.QuadPart = (LONGLONG)DeviceExt->CdInfo.RootStart * (LONGLONG)BLOCKSIZE;
00210         DirSize = DeviceExt->CdInfo.RootSize;
00211 
00212 
00213         if (FileToFind->Buffer[0] == 0 ||
00214             (FileToFind->Buffer[0] == '\\' && FileToFind->Buffer[1] == 0) ||
00215             (FileToFind->Buffer[0] == '.' && FileToFind->Buffer[1] == 0))
00216         {
00217             /* it's root : complete essentials fields then return ok */
00218             RtlZeroMemory(Fcb, sizeof(FCB));
00219 
00220             Fcb->PathName[0] = '\\';
00221             Fcb->ObjectName = &Fcb->PathName[1];
00222             Fcb->Entry.ExtentLocationL = DeviceExt->CdInfo.RootStart;
00223             Fcb->Entry.DataLengthL = DeviceExt->CdInfo.RootSize;
00224             Fcb->Entry.FileFlags = 0x02; //FILE_ATTRIBUTE_DIRECTORY;
00225 
00226             if (pDirIndex)
00227                 *pDirIndex = 0;
00228             if (pOffset)
00229                 *pOffset = 0;
00230             DPRINT("CdfsFindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName);
00231             return STATUS_SUCCESS;
00232         }
00233     }
00234     else
00235     {
00236         StreamOffset.QuadPart = (LONGLONG)Parent->Entry.ExtentLocationL * (LONGLONG)BLOCKSIZE;
00237         DirSize = Parent->Entry.DataLengthL;
00238     }
00239 
00240     DPRINT("StreamOffset %I64u  DirSize %lu\n", StreamOffset.QuadPart, DirSize);
00241 
00242     if (pDirIndex && (*pDirIndex))
00243         DirIndex = *pDirIndex;
00244 
00245     if (pOffset && (*pOffset))
00246     {
00247         Offset = *pOffset;
00248         StreamOffset.QuadPart += ROUND_DOWN(Offset, BLOCKSIZE);
00249     }
00250 
00251     if (!CcMapData(DeviceExt->StreamFileObject, &StreamOffset,
00252         BLOCKSIZE, TRUE, &Context, &Block))
00253     {
00254         DPRINT("CcMapData() failed\n");
00255         return STATUS_UNSUCCESSFUL;
00256     }
00257 
00258     Record = (PDIR_RECORD) ((ULONG_PTR)Block + Offset % BLOCKSIZE);
00259     if (Offset)
00260     {
00261         Offset += Record->RecordLength;
00262         Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength);
00263     }
00264 
00265     /* Upper case the expression for FsRtlIsNameInExpression */
00266     Status = RtlUpcaseUnicodeString(&FileToFindUpcase, FileToFind, TRUE);
00267     if (!NT_SUCCESS(Status))
00268     {
00269         return Status;
00270     }
00271 
00272     while(TRUE)
00273     {
00274         DPRINT("RecordLength %u  ExtAttrRecordLength %u  NameLength %u\n",
00275             Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
00276 
00277         Status = CdfsGetEntryName
00278             (DeviceExt, &Context, &Block, &StreamOffset,
00279             DirSize, (PVOID*)&Record, name, &DirIndex, &Offset);
00280 
00281         if (Status == STATUS_NO_MORE_ENTRIES)
00282         {
00283             break;
00284         }
00285         else if (Status == STATUS_UNSUCCESSFUL)
00286         {
00287             /* Note: the directory cache has already been unpinned */
00288             RtlFreeUnicodeString(&FileToFindUpcase);
00289             return Status;
00290         }
00291 
00292         DPRINT("Name '%S'\n", name);
00293 
00294         RtlInitUnicodeString(&LongName, name);
00295         ShortName.Length = 0;
00296         ShortName.MaximumLength = 26;
00297         ShortName.Buffer = ShortNameBuffer;
00298 
00299         OffsetOfEntry.QuadPart = StreamOffset.QuadPart + Offset;
00300         CdfsShortNameCacheGet(Parent, &OffsetOfEntry, &LongName, &ShortName);
00301 
00302         DPRINT("ShortName '%wZ'\n", &ShortName);
00303 
00304         if (FsRtlIsNameInExpression(&FileToFindUpcase, &LongName, TRUE, NULL) ||
00305             FsRtlIsNameInExpression(&FileToFindUpcase, &ShortName, TRUE, NULL))
00306         {
00307             if (Parent && Parent->PathName)
00308             {
00309                 len = wcslen(Parent->PathName);
00310                 memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR));
00311                 Fcb->ObjectName=&Fcb->PathName[len];
00312                 if (len != 1 || Fcb->PathName[0] != '\\')
00313                 {
00314                     Fcb->ObjectName[0] = '\\';
00315                     Fcb->ObjectName = &Fcb->ObjectName[1];
00316                 }
00317             }
00318             else
00319             {
00320                 Fcb->ObjectName=Fcb->PathName;
00321                 Fcb->ObjectName[0]='\\';
00322                 Fcb->ObjectName=&Fcb->ObjectName[1];
00323             }
00324 
00325             DPRINT("PathName '%S'  ObjectName '%S'\n", Fcb->PathName, Fcb->ObjectName);
00326 
00327             memcpy(&Fcb->Entry, Record, sizeof(DIR_RECORD));
00328             wcsncpy(Fcb->ObjectName, name, min(wcslen(name) + 1,
00329                 MAX_PATH - wcslen(Fcb->PathName) + wcslen(Fcb->ObjectName)));
00330 
00331             /* Copy short name */
00332             Fcb->ShortNameU.Length = ShortName.Length;
00333             Fcb->ShortNameU.MaximumLength = ShortName.Length;
00334             Fcb->ShortNameU.Buffer = Fcb->ShortNameBuffer;
00335             memcpy(Fcb->ShortNameBuffer, ShortName.Buffer, ShortName.Length);
00336 
00337             if (pDirIndex)
00338                 *pDirIndex = DirIndex;
00339             if (pOffset)
00340                 *pOffset = Offset;
00341 
00342             DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",
00343                 Fcb->PathName, Fcb->ObjectName, DirIndex);
00344 
00345             RtlFreeUnicodeString(&FileToFindUpcase);
00346             CcUnpinData(Context);
00347 
00348             return STATUS_SUCCESS;
00349         }
00350 
00351         Offset += Record->RecordLength;
00352         Record = (PDIR_RECORD)((ULONG_PTR)Record + Record->RecordLength);
00353         DirIndex++;
00354     }
00355 
00356     RtlFreeUnicodeString(&FileToFindUpcase);
00357     CcUnpinData(Context);
00358 
00359     if (pDirIndex)
00360         *pDirIndex = DirIndex;
00361 
00362     if (pOffset)
00363         *pOffset = Offset;
00364 
00365     return STATUS_UNSUCCESSFUL;
00366 }
00367 
00368 
00369 static NTSTATUS
00370 CdfsGetNameInformation(PFCB Fcb,
00371                        PDEVICE_EXTENSION DeviceExt,
00372                        PFILE_NAMES_INFORMATION Info,
00373                        ULONG BufferLength)
00374 {
00375     ULONG Length;
00376 
00377     DPRINT("CdfsGetNameInformation() called\n");
00378 
00379     Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
00380     if ((sizeof(FILE_NAMES_INFORMATION) + Length) > BufferLength)
00381         return(STATUS_BUFFER_OVERFLOW);
00382 
00383     Info->FileNameLength = Length;
00384     Info->NextEntryOffset =
00385         ROUND_UP(sizeof(FILE_NAMES_INFORMATION) + Length, sizeof(ULONG));
00386     RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
00387 
00388     //  Info->FileIndex=;
00389 
00390     return(STATUS_SUCCESS);
00391 }
00392 
00393 
00394 static NTSTATUS
00395 CdfsGetDirectoryInformation(PFCB Fcb,
00396                             PDEVICE_EXTENSION DeviceExt,
00397                             PFILE_DIRECTORY_INFORMATION Info,
00398                             ULONG BufferLength)
00399 {
00400     ULONG Length;
00401 
00402     DPRINT("CdfsGetDirectoryInformation() called\n");
00403 
00404     Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
00405     if ((sizeof (FILE_DIRECTORY_INFORMATION) + Length) > BufferLength)
00406         return(STATUS_BUFFER_OVERFLOW);
00407 
00408     Info->FileNameLength = Length;
00409     Info->NextEntryOffset =
00410         ROUND_UP(sizeof(FILE_DIRECTORY_INFORMATION) + Length, sizeof(ULONG));
00411     RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
00412 
00413     /* Convert file times */
00414     CdfsDateTimeToSystemTime(Fcb,
00415         &Info->CreationTime);
00416     Info->LastWriteTime = Info->CreationTime;
00417     Info->ChangeTime = Info->CreationTime;
00418 
00419     /* Convert file flags */
00420     CdfsFileFlagsToAttributes(Fcb,
00421         &Info->FileAttributes);
00422     if (CdfsFCBIsDirectory(Fcb))
00423     {
00424         Info->EndOfFile.QuadPart = 0;
00425         Info->AllocationSize.QuadPart = 0;
00426     }
00427     else
00428     {
00429         Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
00430 
00431         /* Make AllocSize a rounded up multiple of the sector size */
00432         Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
00433     }
00434 
00435     //  Info->FileIndex=;
00436 
00437     return(STATUS_SUCCESS);
00438 }
00439 
00440 
00441 static NTSTATUS
00442 CdfsGetFullDirectoryInformation(PFCB Fcb,
00443                                 PDEVICE_EXTENSION DeviceExt,
00444                                 PFILE_FULL_DIR_INFORMATION Info,
00445                                 ULONG BufferLength)
00446 {
00447     ULONG Length;
00448 
00449     DPRINT("CdfsGetFullDirectoryInformation() called\n");
00450 
00451     Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
00452     if ((sizeof (FILE_FULL_DIR_INFORMATION) + Length) > BufferLength)
00453         return(STATUS_BUFFER_OVERFLOW);
00454 
00455     Info->FileNameLength = Length;
00456     Info->NextEntryOffset =
00457         ROUND_UP(sizeof(FILE_FULL_DIR_INFORMATION) + Length, sizeof(ULONG));
00458     RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
00459 
00460     /* Convert file times */
00461     CdfsDateTimeToSystemTime(Fcb,
00462         &Info->CreationTime);
00463     Info->LastWriteTime = Info->CreationTime;
00464     Info->ChangeTime = Info->CreationTime;
00465 
00466     /* Convert file flags */
00467     CdfsFileFlagsToAttributes(Fcb,
00468         &Info->FileAttributes);
00469 
00470     if (CdfsFCBIsDirectory(Fcb))
00471     {
00472         Info->EndOfFile.QuadPart = 0;
00473         Info->AllocationSize.QuadPart = 0;
00474     }
00475     else
00476     {
00477         Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
00478 
00479         /* Make AllocSize a rounded up multiple of the sector size */
00480         Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
00481     }
00482 
00483     //  Info->FileIndex=;
00484     Info->EaSize = 0;
00485 
00486     return(STATUS_SUCCESS);
00487 }
00488 
00489 
00490 static NTSTATUS
00491 CdfsGetBothDirectoryInformation(PFCB Fcb,
00492                                 PDEVICE_EXTENSION DeviceExt,
00493                                 PFILE_BOTH_DIR_INFORMATION Info,
00494                                 ULONG BufferLength)
00495 {
00496     ULONG Length;
00497 
00498     DPRINT("CdfsGetBothDirectoryInformation() called\n");
00499 
00500     Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
00501     if ((sizeof (FILE_BOTH_DIR_INFORMATION) + Length) > BufferLength)
00502         return(STATUS_BUFFER_OVERFLOW);
00503 
00504     Info->FileNameLength = Length;
00505     Info->NextEntryOffset =
00506         ROUND_UP(sizeof(FILE_BOTH_DIR_INFORMATION) + Length, sizeof(ULONG));
00507     RtlCopyMemory(Info->FileName, Fcb->ObjectName, Length);
00508 
00509     /* Convert file times */
00510     CdfsDateTimeToSystemTime(Fcb,
00511         &Info->CreationTime);
00512     Info->LastWriteTime = Info->CreationTime;
00513     Info->ChangeTime = Info->CreationTime;
00514 
00515     /* Convert file flags */
00516     CdfsFileFlagsToAttributes(Fcb,
00517         &Info->FileAttributes);
00518 
00519     if (CdfsFCBIsDirectory(Fcb))
00520     {
00521         Info->EndOfFile.QuadPart = 0;
00522         Info->AllocationSize.QuadPart = 0;
00523     }
00524     else
00525     {
00526         Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
00527 
00528         /* Make AllocSize a rounded up multiple of the sector size */
00529         Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
00530     }
00531 
00532     //  Info->FileIndex=;
00533     Info->EaSize = 0;
00534 
00535     /* Copy short name */
00536     ASSERT(Fcb->ShortNameU.Length / sizeof(WCHAR) <= 12);
00537     Info->ShortNameLength = (CCHAR)Fcb->ShortNameU.Length;
00538     RtlCopyMemory(Info->ShortName, Fcb->ShortNameU.Buffer, Fcb->ShortNameU.Length);
00539 
00540     return(STATUS_SUCCESS);
00541 }
00542 
00543 
00544 static NTSTATUS
00545 CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject,
00546                    PIRP Irp)
00547 {
00548     PDEVICE_EXTENSION DeviceExtension;
00549     LONG BufferLength = 0;
00550     PUNICODE_STRING SearchPattern = NULL;
00551     FILE_INFORMATION_CLASS FileInformationClass;
00552     ULONG FileIndex = 0;
00553     PUCHAR Buffer = NULL;
00554     PFILE_NAMES_INFORMATION Buffer0 = NULL;
00555     PFCB Fcb;
00556     PCCB Ccb;
00557     FCB TempFcb;
00558     BOOLEAN First = FALSE;
00559     PIO_STACK_LOCATION Stack;
00560     PFILE_OBJECT FileObject;
00561     NTSTATUS Status = STATUS_SUCCESS;
00562 
00563     DPRINT("CdfsQueryDirectory() called\n");
00564 
00565     DeviceExtension = DeviceObject->DeviceExtension;
00566     Stack = IoGetCurrentIrpStackLocation(Irp);
00567     FileObject = Stack->FileObject;
00568 
00569     Ccb = (PCCB)FileObject->FsContext2;
00570     Fcb = (PFCB)FileObject->FsContext;
00571 
00572     /* Obtain the callers parameters */
00573     BufferLength = Stack->Parameters.QueryDirectory.Length;
00574     SearchPattern = Stack->Parameters.QueryDirectory.FileName;
00575     FileInformationClass =
00576         Stack->Parameters.QueryDirectory.FileInformationClass;
00577     FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
00578 
00579     /* Determine Buffer for result */
00580     if (Irp->MdlAddress)
00581     {
00582         Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
00583     }
00584     else
00585     {
00586         Buffer = Irp->UserBuffer;
00587     }
00588 
00589     if (SearchPattern != NULL)
00590     {
00591         if (Ccb->DirectorySearchPattern.Buffer == NULL)
00592         {
00593             First = TRUE;
00594             Ccb->DirectorySearchPattern.Buffer =
00595                 ExAllocatePoolWithTag(NonPagedPool, SearchPattern->Length + sizeof(WCHAR), TAG_CCB);
00596             if (Ccb->DirectorySearchPattern.Buffer == NULL)
00597             {
00598                 return STATUS_INSUFFICIENT_RESOURCES;
00599             }
00600             Ccb->DirectorySearchPattern.MaximumLength = SearchPattern->Length + sizeof(WCHAR);
00601             RtlCopyUnicodeString(&Ccb->DirectorySearchPattern, SearchPattern);
00602             Ccb->DirectorySearchPattern.Buffer[SearchPattern->Length / sizeof(WCHAR)] = 0;
00603         }
00604     }
00605     else if (Ccb->DirectorySearchPattern.Buffer == NULL)
00606     {
00607         First = TRUE;
00608         Ccb->DirectorySearchPattern.Buffer = ExAllocatePoolWithTag(NonPagedPool, 2 * sizeof(WCHAR), TAG_CCB);
00609         if (Ccb->DirectorySearchPattern.Buffer == NULL)
00610         {
00611             return STATUS_INSUFFICIENT_RESOURCES;
00612         }
00613 
00614         Ccb->DirectorySearchPattern.Length = sizeof(WCHAR);
00615         Ccb->DirectorySearchPattern.MaximumLength = 2 * sizeof(WCHAR);
00616         Ccb->DirectorySearchPattern.Buffer[0] = L'*';
00617         Ccb->DirectorySearchPattern.Buffer[1] = 0;
00618     }
00619     DPRINT("Search pattern '%wZ'\n", &Ccb->DirectorySearchPattern);
00620 
00621     /* Determine directory index */
00622     if (Stack->Flags & SL_INDEX_SPECIFIED)
00623     {
00624         Ccb->Entry = Stack->Parameters.QueryDirectory.FileIndex;
00625         Ccb->Offset = Ccb->CurrentByteOffset.u.LowPart;
00626     }
00627     else if (First || (Stack->Flags & SL_RESTART_SCAN))
00628     {
00629         Ccb->Entry = 0;
00630         Ccb->Offset = 0;
00631     }
00632     DPRINT("Buffer = %p  tofind = %wZ\n", Buffer, &Ccb->DirectorySearchPattern);
00633 
00634     TempFcb.ObjectName = TempFcb.PathName;
00635     while (Status == STATUS_SUCCESS && BufferLength > 0)
00636     {
00637         Status = CdfsFindFile(DeviceExtension,
00638             &TempFcb,
00639             Fcb,
00640             &Ccb->DirectorySearchPattern,
00641             &Ccb->Entry,
00642             &Ccb->Offset);
00643         DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry);
00644 
00645         if (NT_SUCCESS(Status))
00646         {
00647             switch (FileInformationClass)
00648             {
00649             case FileNameInformation:
00650                 Status = CdfsGetNameInformation(&TempFcb,
00651                     DeviceExtension,
00652                     (PFILE_NAMES_INFORMATION)Buffer,
00653                     BufferLength);
00654                 break;
00655 
00656             case FileDirectoryInformation:
00657                 Status = CdfsGetDirectoryInformation(&TempFcb,
00658                     DeviceExtension,
00659                     (PFILE_DIRECTORY_INFORMATION)Buffer,
00660                     BufferLength);
00661                 break;
00662 
00663             case FileFullDirectoryInformation:
00664                 Status = CdfsGetFullDirectoryInformation(&TempFcb,
00665                     DeviceExtension,
00666                     (PFILE_FULL_DIR_INFORMATION)Buffer,
00667                     BufferLength);
00668                 break;
00669 
00670             case FileBothDirectoryInformation:
00671                 Status = CdfsGetBothDirectoryInformation(&TempFcb,
00672                     DeviceExtension,
00673                     (PFILE_BOTH_DIR_INFORMATION)Buffer,
00674                     BufferLength);
00675                 break;
00676 
00677             default:
00678                 Status = STATUS_INVALID_INFO_CLASS;
00679             }
00680 
00681             if (Status == STATUS_BUFFER_OVERFLOW)
00682             {
00683                 if (Buffer0)
00684                 {
00685                     Buffer0->NextEntryOffset = 0;
00686                 }
00687                 break;
00688             }
00689         }
00690         else
00691         {
00692             if (Buffer0)
00693             {
00694                 Buffer0->NextEntryOffset = 0;
00695             }
00696 
00697             if (First)
00698             {
00699                 Status = STATUS_NO_SUCH_FILE;
00700             }
00701             else
00702             {
00703                 Status = STATUS_NO_MORE_FILES;
00704             }
00705             break;
00706         }
00707 
00708         Buffer0 = (PFILE_NAMES_INFORMATION)Buffer;
00709         Buffer0->FileIndex = FileIndex++;
00710         Ccb->Entry++;
00711 
00712         if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
00713         {
00714             break;
00715         }
00716         BufferLength -= Buffer0->NextEntryOffset;
00717         Buffer += Buffer0->NextEntryOffset;
00718     }
00719 
00720     if (Buffer0)
00721     {
00722         Buffer0->NextEntryOffset = 0;
00723     }
00724 
00725     if (FileIndex > 0)
00726     {
00727         Status = STATUS_SUCCESS;
00728     }
00729 
00730     return(Status);
00731 }
00732 
00733 
00734 
00735 NTSTATUS NTAPI
00736 CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
00737                      PIRP Irp)
00738 {
00739     PIO_STACK_LOCATION Stack;
00740     NTSTATUS Status;
00741 
00742     DPRINT("CdfsDirectoryControl() called\n");
00743     FsRtlEnterFileSystem();
00744 
00745     Stack = IoGetCurrentIrpStackLocation(Irp);
00746 
00747     switch (Stack->MinorFunction)
00748     {
00749     case IRP_MN_QUERY_DIRECTORY:
00750         Status = CdfsQueryDirectory(DeviceObject,
00751             Irp);
00752         break;
00753 
00754     case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
00755         DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
00756         Status = STATUS_NOT_IMPLEMENTED;
00757         break;
00758 
00759     default:
00760         DPRINT1("CDFS: MinorFunction %d\n", Stack->MinorFunction);
00761         Status = STATUS_INVALID_DEVICE_REQUEST;
00762         break;
00763     }
00764 
00765     Irp->IoStatus.Status = Status;
00766     Irp->IoStatus.Information = 0;
00767 
00768     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00769     FsRtlExitFileSystem();
00770 
00771     return(Status);
00772 }
00773 
00774 /* EOF */

Generated on Mon May 28 2012 04:27:21 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.