Added media change support (untested).
authorEric Kohl <eric.kohl@reactos.org>
Fri, 26 Apr 2002 23:21:28 +0000 (23:21 +0000)
committerEric Kohl <eric.kohl@reactos.org>
Fri, 26 Apr 2002 23:21:28 +0000 (23:21 +0000)
Added directory listing (works only on the root directory).

svn path=/trunk/; revision=2872

reactos/drivers/fs/cdfs/common.c
reactos/drivers/fs/cdfs/dirctl.c
reactos/drivers/fs/cdfs/fcb.c
reactos/drivers/fs/cdfs/fsctl.c

index c3b5680..98a2b1e 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: common.c,v 1.2 2002/04/15 20:39:49 ekohl Exp $
+/* $Id: common.c,v 1.3 2002/04/26 23:21:28 ekohl Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -93,6 +93,19 @@ CdfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
 
   if (!NT_SUCCESS(Status))
     {
+      if (Status == STATUS_VERIFY_REQUIRED)
+        {
+         PDEVICE_OBJECT DeviceToVerify;
+         NTSTATUS NewStatus;
+
+         DPRINT1("STATUS_VERIFY_REQUIRED\n");
+         DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
+         IoSetDeviceToVerify(PsGetCurrentThread(), NULL);
+
+         NewStatus = IoVerifyVolume(DeviceToVerify, FALSE);
+         DPRINT1("IoVerifyVolume() retuned (Status %lx)\n", NewStatus);
+        }
+
       DPRINT("CdfsReadSectors() failed (Status %x)\n", Status);
       DPRINT("(DeviceObject %x, DiskSector %x, Buffer %x, Offset 0x%I64x)\n",
             DeviceObject, DiskSector, Buffer,
index a77729f..4190877 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: dirctl.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $
+/* $Id: dirctl.c,v 1.2 2002/04/26 23:21:28 ekohl Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -30,7 +30,7 @@
 
 #include <ddk/ntddk.h>
 
-//#define NDEBUG
+#define NDEBUG
 #include <debug.h>
 
 #include "cdfs.h"
 
 /* FUNCTIONS ****************************************************************/
 
-/* HACK -- NEEDS FIXING */
-#if 0
-int
-FsdExtractDirectoryEntry(PDEVICE_EXTENSION DeviceExt,
-                        FsdFcbEntry *parent,
-                        FsdFcbEntry *fill_in,
-                        int entry_to_get)
+
+static BOOLEAN
+wstrcmpjoki(PWSTR s1, PWSTR s2)
+/*
+ * FUNCTION: Compare two wide character strings, s2 with jokers (* or ?)
+ * return TRUE if s1 like s2
+ */
 {
-  switch( entry_to_get )
+  while ((*s2=='*')||(*s2=='?')||(towlower(*s1)==towlower(*s2)))
     {
-      case 0:
-       wcscpy( fill_in->name, L"." );
-       fill_in->extent_start = parent->extent_start;
-       fill_in->byte_count = parent->byte_count;
-       break;
+      if ((*s1)==0 && (*s2)==0)
+        return(TRUE);
 
-      case 1:
-       wcscpy( fill_in->name, L".." );
-       fill_in->extent_start = parent->extent_start;
-       fill_in->byte_count = parent->byte_count;
-       break;
+      if(*s2=='*')
+       {
+         s2++;
+         while (*s1)
+           if (wstrcmpjoki(s1,s2))
+             return TRUE;
+           else
+             s1++;
+       }
+      else
+       {
+         s1++;
+         s2++;
+       }
+    }
 
-      case 2:
-       wcscpy( fill_in->name, L"readme.txt" );
-       fill_in->extent_start = 0x190;
-       fill_in->byte_count = 0x800;
-       break;
+  if ((*s2)=='.')
+    {
+      for (;((*s2)=='.')||((*s2)=='*')||((*s2)=='?');s2++)
+       ;
+    }
 
-      default:
-       return 1;
+  if ((*s1)==0 && (*s2)==0)
+    return(TRUE);
+
+  return(FALSE);
+}
+
+
+static void
+CdfsSwapString(PWCHAR Out,
+              PUCHAR In,
+              ULONG Count)
+{
+  PUCHAR t = (PUCHAR)Out;
+  ULONG i;
+
+  for (i = 0; i < Count; i += 2)
+    {
+      t[i] = In[i+1];
+      t[i+1] = In[i];
     }
+  t[i] = 0;
+  t[i+1] = 0;
+}
+
+
+static VOID
+CdfsDateTimeToFileTime(PFCB Fcb,
+                      TIME *FileTime)
+{
+  TIME_FIELDS TimeFields;
 
-  return 0;
+  TimeFields.Milliseconds = 0;
+  TimeFields.Second = Fcb->Entry.Second;
+  TimeFields.Minute = Fcb->Entry.Minute;
+  TimeFields.Hour = Fcb->Entry.Hour;
+
+  TimeFields.Day = Fcb->Entry.Day;
+  TimeFields.Month = Fcb->Entry.Month;
+  TimeFields.Year = Fcb->Entry.Year + 1900;
+
+  RtlTimeFieldsToTime(&TimeFields,
+                     (PLARGE_INTEGER)FileTime);
 }
+
+
+NTSTATUS
+CdfsGetEntryName(PDEVICE_EXTENSION DeviceExt,
+                PVOID Block,
+                ULONG BlockLength,
+                PVOID *Ptr,
+                PWSTR Name,
+                PULONG pIndex,
+                PULONG pIndex2)
+/*
+ * FUNCTION: Retrieves the file name, be it in short or long file name format
+ */
+{
+  PDIR_RECORD Record;
+  NTSTATUS Status;
+  ULONG Index = 0;
+  ULONG Offset = 0;
+
+  Record = (PDIR_RECORD)Block;
+  while(Index < *pIndex)
+    {
+      Offset = Offset + Record->RecordLength;
+
+      Record = (PDIR_RECORD)(Block + Offset);
+      if (Record->RecordLength == 0)
+       {
+         Offset = ROUND_UP(Offset, 2048);
+         Record = (PDIR_RECORD)(Block + Offset);
+       }
+
+      if (Offset >= BlockLength)
+       return(STATUS_NO_MORE_ENTRIES);
+
+      Index++;
+    }
+
+  DPRINT("Index %lu  RecordLength %lu  Offset %lu\n",
+        Index, Record->RecordLength, Offset);
+
+  if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
+    {
+      wcscpy(Name, L".");
+    }
+  else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
+    {
+      wcscpy(Name, L"..");
+    }
+  else
+    {
+      if (DeviceExt->CdInfo.JolietLevel == 0)
+       {
+         ULONG i;
+
+         for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
+           Name[i] = (WCHAR)Record->FileId[i];
+         Name[i] = 0;
+       }
+      else
+       {
+         CdfsSwapString(Name, Record->FileId, Record->FileIdLength);
+       }
+    }
+
+  DPRINT("Name '%S'\n", Name);
+
+  *Ptr = Record;
+
+  *pIndex = Index;
+
+  return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+CdfsFindFile(PDEVICE_EXTENSION DeviceExt,
+            PFCB Fcb,
+            PFCB Parent,
+            PWSTR FileToFind,
+            PULONG pDirIndex,
+            PULONG pDirIndex2)
+/*
+ * FUNCTION: Find a file
+ */
+{
+  WCHAR name[256];
+  char * block;
+  WCHAR TempStr[2];
+  NTSTATUS Status;
+  ULONG len;
+  ULONG DirIndex;
+  ULONG Offset;
+  ULONG FirstSector;
+  ULONG Read;
+  BOOLEAN IsRoot;
+  LARGE_INTEGER FileOffset;
+  PVOID Context = NULL;
+
+  ULONG DirSize;
+  ULONG BufferSize;
+  ULONG SectorCount;
+  PUCHAR Ptr;
+  PDIR_RECORD Record;
+
+  DPRINT("FindFile(Parent %x, FileToFind '%S', DirIndex: %d)\n", Parent, FileToFind, pDirIndex ? *pDirIndex : 0);
+  DPRINT("FindFile: old Pathname %x, old Objectname %x)\n",Fcb->PathName, Fcb->ObjectName);
+
+  IsRoot = FALSE;
+  DirIndex = 0;
+  if (wcslen (FileToFind) == 0)
+    {
+      CHECKPOINT;
+      TempStr[0] = (WCHAR) '.';
+      TempStr[1] = 0;
+      FileToFind = (PWSTR)&TempStr;
+    }
+
+  if (Parent)
+    {
+      FirstSector = Parent->Entry.ExtentLocationL;
+      if (FirstSector == DeviceExt->CdInfo.RootStart)
+       {
+         IsRoot = TRUE;
+       }
+    }
+  else
+    {
+      IsRoot = TRUE;
+    }
+
+  if (IsRoot == TRUE)
+    {
+      FirstSector = DeviceExt->CdInfo.RootStart;
+      DirSize = DeviceExt->CdInfo.RootSize;
+
+
+      if (FileToFind[0] == 0 || (FileToFind[0] == '\\' && FileToFind[1] == 0)
+         || (FileToFind[0] == '.' && FileToFind[1] == 0))
+       {
+         /* it's root : complete essentials fields then return ok */
+         RtlZeroMemory(Fcb, sizeof(FCB));
+
+         Fcb->PathName[0]='\\';
+         Fcb->ObjectName = &Fcb->PathName[1];
+         Fcb->Entry.ExtentLocationL = DeviceExt->CdInfo.RootStart;
+         Fcb->Entry.DataLengthL = DeviceExt->CdInfo.RootSize;
+         Fcb->Entry.FileFlags = 0x02; //FILE_ATTRIBUTE_DIRECTORY;
+
+         if (pDirIndex)
+           *pDirIndex = 0;
+         if (pDirIndex2)
+           *pDirIndex2 = 0;
+         DPRINT("CdfsFindFile: new Pathname %S, new Objectname %S)\n",Fcb->PathName, Fcb->ObjectName);
+         return (STATUS_SUCCESS);
+       }
+    }
+  else
+    {
+      FirstSector = Parent->Entry.ExtentLocationL;
+      DirSize = Parent->Entry.DataLengthL;
+    }
+
+  DPRINT("FirstSector %lu  DirSize %lu\n", FirstSector, DirSize);
+
+  if (pDirIndex && (*pDirIndex))
+    DirIndex = *pDirIndex;
+
+  BufferSize = ROUND_UP(DirSize, BLOCKSIZE);
+  SectorCount = BufferSize / BLOCKSIZE;
+
+  DPRINT("FirstSector %lu  DirSize %lu  BufferSize %lu  SectorCount %lu\n",
+        FirstSector, DirSize, BufferSize, SectorCount);
+
+  block = ExAllocatePool(NonPagedPool, BufferSize);
+
+  Status = CdfsReadSectors(DeviceExt->StorageDevice,
+                          FirstSector,
+                          SectorCount,
+                          block);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Reading directory extent failed (Status %lx)\n", Status);
+      ExFreePool(block);
+      return(Status);
+    }
+
+  Ptr = (PUCHAR)block;
+  while(TRUE)
+    {
+      Record = (PDIR_RECORD)Ptr;
+      if (Record->RecordLength == 0)
+       {
+         DPRINT1("Stopped!\n");
+         break;
+       }
+       
+      DPRINT("RecordLength %u  ExtAttrRecordLength %u  NameLength %u\n",
+            Record->RecordLength, Record->ExtAttrRecordLength, Record->FileIdLength);
+
+      Status = CdfsGetEntryName(DeviceExt, block, DirSize, (PVOID*)&Ptr, name, &DirIndex, pDirIndex2);
+      if (Status == STATUS_NO_MORE_ENTRIES)
+       {
+         break;
+       }
+
+//      DPRINT("Name '%S'\n", name);
+
+      if (wstrcmpjoki(name, FileToFind)) /* || wstrcmpjoki (name2, FileToFind)) */
+       {
+         if (Parent && Parent->PathName)
+           {
+             len = wcslen(Parent->PathName);
+             memcpy(Fcb->PathName, Parent->PathName, len*sizeof(WCHAR));
+             Fcb->ObjectName=&Fcb->PathName[len];
+             if (len != 1 || Fcb->PathName[0] != '\\')
+               {
+                 Fcb->ObjectName[0] = '\\';
+                 Fcb->ObjectName = &Fcb->ObjectName[1];
+               }
+           }
+         else
+           {
+             Fcb->ObjectName=Fcb->PathName;
+             Fcb->ObjectName[0]='\\';
+             Fcb->ObjectName=&Fcb->ObjectName[1];
+           }
+
+         DPRINT("PathName '%S'  ObjectName '%S'\n", Fcb->PathName, Fcb->ObjectName);
+
+         memcpy(&Fcb->Entry, Ptr, sizeof(DIR_RECORD));
+         wcsncpy(Fcb->ObjectName, name, MAX_PATH);
+         if (pDirIndex)
+           *pDirIndex = DirIndex;
+
+         DPRINT("FindFile: new Pathname %S, new Objectname %S, DirIndex %d\n",Fcb->PathName, Fcb->ObjectName, DirIndex);
+
+         ExFreePool(block);
+
+         return(STATUS_SUCCESS);
+       }
+
+
+      Ptr = Ptr + Record->RecordLength;
+      DirIndex++;
+
+      if (((ULONG)Ptr - (ULONG)block) >= DirSize)
+       {
+         DPRINT("Stopped!\n");
+         break;
+       }
+    }
+
+  ExFreePool(block);
+
+  if (pDirIndex)
+    *pDirIndex = DirIndex;
+
+  return(STATUS_UNSUCCESSFUL);
+}
+
+
+static NTSTATUS
+CdfsGetBothInformation(PFCB Fcb,
+                      PDEVICE_EXTENSION DeviceExt,
+                      PFILE_BOTH_DIRECTORY_INFORMATION Info,
+                      ULONG BufferLength)
+{
+//  short i;
+//  ULONGLONG AllocSize;
+  ULONG Length;
+
+  DPRINT("FileBothDirectoryInformation() called\n");
+
+  Length = wcslen(Fcb->ObjectName) * sizeof(WCHAR);
+  if ((sizeof (FILE_BOTH_DIRECTORY_INFORMATION) + Length) > BufferLength)
+    return(STATUS_BUFFER_OVERFLOW);
+
+  Info->FileNameLength = Length;
+  Info->NextEntryOffset =
+    ROUND_UP(sizeof(FILE_BOTH_DIRECTORY_INFORMATION) + Length, 4);
+  memcpy(Info->FileName, Fcb->ObjectName, Length);
+
+//  Info->FileIndex=;
+
+  /* Convert file times */
+  CdfsDateTimeToFileTime(Fcb,
+                        &Info->CreationTime);
+  CdfsDateTimeToFileTime(Fcb,
+                        &Info->LastAccessTime);
+  CdfsDateTimeToFileTime(Fcb,
+                        &Info->LastWriteTime);
+  CdfsDateTimeToFileTime(Fcb,
+                        &Info->ChangeTime);
+
+  Info->EndOfFile.QuadPart = Fcb->Entry.DataLengthL;
+
+  /* Make AllocSize a rounded up multiple of the sector size */
+//  AllocSize = ((Fcb->Entry.DataLengthL + BLOCKSIZE - 1) /
+//            BLOCKSIZE) * BLOCKSIZE;
+//  Info->AllocationSize.QuadPart = AllocSize;
+  Info->AllocationSize.QuadPart = ROUND_UP(Fcb->Entry.DataLengthL, BLOCKSIZE);
+
+  /* FIXME: Convert file flags to file attributes */
+  Info->FileAttributes = (Fcb->Entry.FileFlags & 0x02) ? FILE_ATTRIBUTE_DIRECTORY : 0;
+  Info->EaSize = 0;
+
+  /* FIXME: Copy or create a short file name */
+#if 0
+  for (i = 0; i < 8 && (pFcb->entry.Filename[i] != ' '); i++)
+    pInfo->ShortName[i] = pFcb->entry.Filename[i];
+  pInfo->ShortNameLength = i;
+  pInfo->ShortName[i] = '.';
+  for (i = 0; i < 3 && (pFcb->entry.Ext[i] != ' '); i++)
+    pInfo->ShortName[i + 1 + pInfo->ShortNameLength] = pFcb->entry.Ext[i];
+  if (i)
+    pInfo->ShortNameLength += (i + 1);
+  pInfo->ShortNameLength *= sizeof(WCHAR);
 #endif
 
+  Info->ShortName[0] = 0;
+  Info->ShortNameLength = 0;
+
+  return STATUS_SUCCESS;
+}
+
+
+
+static NTSTATUS
+CdfsQueryDirectory(PDEVICE_OBJECT DeviceObject,
+                  PIRP Irp)
+{
+  PDEVICE_EXTENSION DeviceExtension;
+  LONG BufferLength = 0;
+  PUNICODE_STRING SearchPattern = NULL;
+  FILE_INFORMATION_CLASS FileInformationClass;
+  ULONG FileIndex = 0;
+  PUCHAR Buffer = NULL;
+  PFILE_NAMES_INFORMATION Buffer0 = NULL;
+  PFCB Fcb;
+  PCCB Ccb;
+  FCB TempFcb;
+  BOOLEAN First = FALSE;
+  PIO_STACK_LOCATION Stack;
+  PFILE_OBJECT FileObject;
+  NTSTATUS Status = STATUS_SUCCESS;
+
+  DPRINT("CdfsQueryDirectory() called\n");
+
+  DeviceExtension = DeviceObject->DeviceExtension;
+  Stack = IoGetCurrentIrpStackLocation(Irp);
+  FileObject = Stack->FileObject;
+
+  Ccb = (PCCB)FileObject->FsContext2;
+  Fcb = Ccb->Fcb;
+
+  /* Obtain the callers parameters */
+  BufferLength = Stack->Parameters.QueryDirectory.Length;
+  SearchPattern = Stack->Parameters.QueryDirectory.FileName;
+  FileInformationClass =
+    Stack->Parameters.QueryDirectory.FileInformationClass;
+  FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
+
+
+  if (SearchPattern != NULL)
+    {
+      if (!Ccb->DirectorySearchPattern)
+       {
+         First = TRUE;
+         Ccb->DirectorySearchPattern =
+           ExAllocatePool(NonPagedPool, SearchPattern->Length + sizeof(WCHAR));
+         if (!Ccb->DirectorySearchPattern)
+           {
+             return(STATUS_INSUFFICIENT_RESOURCES);
+           }
+
+         memcpy(Ccb->DirectorySearchPattern,
+                SearchPattern->Buffer,
+                SearchPattern->Length);
+         Ccb->DirectorySearchPattern[SearchPattern->Length / sizeof(WCHAR)] = 0;
+       }
+    }
+  else if (!Ccb->DirectorySearchPattern)
+    {
+      First = TRUE;
+      Ccb->DirectorySearchPattern = ExAllocatePool(NonPagedPool, 2 * sizeof(WCHAR));
+      if (!Ccb->DirectorySearchPattern)
+       {
+         return(STATUS_INSUFFICIENT_RESOURCES);
+       }
+      Ccb->DirectorySearchPattern[0] = L'*';
+      Ccb->DirectorySearchPattern[1] = 0;
+    }
+  DPRINT("Search pattern '%S'\n", Ccb->DirectorySearchPattern);
+
+  /* Determine directory index */
+  if (Stack->Flags & SL_INDEX_SPECIFIED)
+    {
+      Ccb->Entry = Ccb->CurrentByteOffset.u.LowPart;
+    }
+  else if (First || (Stack->Flags & SL_RESTART_SCAN))
+    {
+      Ccb->Entry = 0;
+    }
+
+  /* Determine Buffer for result */
+  if (Irp->MdlAddress)
+    {
+      Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+    }
+  else
+    {
+      Buffer = Irp->UserBuffer;
+    }
+  DPRINT("Buffer=%x tofind=%S\n", Buffer, Ccb->DirectorySearchPattern);
+
+  TempFcb.ObjectName = TempFcb.PathName;
+  while (Status == STATUS_SUCCESS && BufferLength > 0)
+    {
+      Status = CdfsFindFile(DeviceExtension,
+                           &TempFcb,
+                           Fcb,
+                           Ccb->DirectorySearchPattern,
+                           &Ccb->Entry,
+                           NULL);
+      DPRINT("Found %S, Status=%x, entry %x\n", TempFcb.ObjectName, Status, Ccb->Entry);
+
+      if (NT_SUCCESS(Status))
+       {
+         switch (FileInformationClass)
+           {
+             case FileNameInformation:
+               DPRINT1("FileNameInformation\n");
+//             Status = VfatGetFileNameInformation(&TempFcb,
+//                         (PFILE_NAMES_INFORMATION) Buffer, BufferLength);
+//             break;
+
+             case FileDirectoryInformation:
+               DPRINT1("FileDirectoryInformation\n");
+//             Status = VfatGetFileDirectoryInformation(&TempFcb, DeviceExtension,
+//                              (PFILE_DIRECTORY_INFORMATION) Buffer, BufferLength);
+               break;
+
+             case FileFullDirectoryInformation:
+               DPRINT1("FileFullDirecrotyInformation\n");
+//             Status = CdfsGetFullDirectoryInformation(&TempFcb,
+//                                                      DeviceExtension,
+//                             (PFILE_FULL_DIRECTORY_INFORMATION)Buffer, BufferLength);
+               break;
+
+             case FileBothDirectoryInformation:
+               Status = CdfsGetBothInformation(&TempFcb,
+                                               DeviceExtension,
+                                               (PFILE_BOTH_DIRECTORY_INFORMATION)Buffer,
+                                               BufferLength);
+               break;
+
+             default:
+               Status = STATUS_INVALID_INFO_CLASS;
+           }
+
+         if (Status == STATUS_BUFFER_OVERFLOW)
+           {
+             if (Buffer0)
+               {
+                 Buffer0->NextEntryOffset = 0;
+               }
+             break;
+           }
+       }
+      else
+       {
+         if (Buffer0)
+           {
+             Buffer0->NextEntryOffset = 0;
+           }
+
+         if (First)
+           {
+             Status = STATUS_NO_SUCH_FILE;
+           }
+         else
+           {
+             Status = STATUS_NO_MORE_FILES;
+           }
+         break;
+       }
+
+      Buffer0 = (PFILE_NAMES_INFORMATION)Buffer;
+      Buffer0->FileIndex = FileIndex++;
+      Ccb->Entry++;
+
+      if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
+       {
+         break;
+       }
+      BufferLength -= Buffer0->NextEntryOffset;
+      Buffer += Buffer0->NextEntryOffset;
+    }
+
+  if (Buffer0)
+    {
+      Buffer0->NextEntryOffset = 0;
+    }
+
+  if (FileIndex > 0)
+    {
+      Status = STATUS_SUCCESS;
+    }
+
+  return(Status);
+}
+
+
 
 NTSTATUS STDCALL
 CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
@@ -88,9 +643,18 @@ CdfsDirectoryControl(PDEVICE_OBJECT DeviceObject,
 
   switch (Stack->MinorFunction)
     {
+      case IRP_MN_QUERY_DIRECTORY:
+       Status = CdfsQueryDirectory(DeviceObject,
+                                   Irp);
+       break;
+
+      case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
+       DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
+       Status = STATUS_NOT_IMPLEMENTED;
+       break;
 
       default:
-       DPRINT("CDFS: MinorFunction %d\n", Stack->MinorFunction);
+       DPRINT1("CDFS: MinorFunction %d\n", Stack->MinorFunction);
        Status = STATUS_INVALID_DEVICE_REQUEST;
        break;
     }
index 3597ba7..e095820 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: fcb.c,v 1.2 2002/04/15 20:39:49 ekohl Exp $
+/* $Id: fcb.c,v 1.3 2002/04/26 23:21:28 ekohl Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -283,7 +283,7 @@ vfatMakeFCBFromDirEntry(PVCB  vcb,
                        PVFATFCB  directoryFCB,
                        PWSTR  longName,
                        PFAT_DIR_ENTRY  dirEntry,
-            ULONG dirIndex,
+                       ULONG dirIndex,
                        PVFATFCB * fileFCB)
 {
   PVFATFCB  rcFCB;
index 9d411b5..2c2a053 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: fsctl.c,v 1.1 2002/04/15 20:39:49 ekohl Exp $
+/* $Id: fsctl.c,v 1.2 2002/04/26 23:21:28 ekohl Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
@@ -118,6 +118,8 @@ CdfsGetSVDData(PUCHAR Buffer,
       JolietLevel = 3;
     }
 
+  /* Don't support Joliet yet! */
+//#if 0
   Vcb->CdInfo.JolietLevel = JolietLevel;
 
   if (JolietLevel != 0)
@@ -128,6 +130,7 @@ CdfsGetSVDData(PUCHAR Buffer,
       DPRINT1("RootStart: %lu\n", Svd->RootDirRecord.ExtentLocationL);
       DPRINT1("RootSize: %lu\n", Svd->RootDirRecord.DataLengthL);
     }
+//#endif
 }
 
 
@@ -199,41 +202,47 @@ CdfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
 }
 
 
-static BOOLEAN
+static NTSTATUS
 CdfsHasFileSystem(PDEVICE_OBJECT DeviceToMount)
 /*
  * FUNCTION: Tests if the device contains a filesystem that can be mounted 
  * by this fsd
  */
 {
-  PUCHAR bytebuf; // [CDFS_BASIC_SECTOR];
+  PUCHAR Buffer;
   NTSTATUS Status;
-  int ret;
 
-  bytebuf = ExAllocatePool( NonPagedPool, CDFS_BASIC_SECTOR );
-  if( !bytebuf ) return FALSE;
+  Buffer = ExAllocatePool(NonPagedPool,
+                         CDFS_BASIC_SECTOR);
+  if (Buffer == NULL)
+    {
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
 
   DPRINT1("CDFS: Checking on mount of device %08x\n", DeviceToMount);
 
   Status = CdfsReadSectors(DeviceToMount,
                           CDFS_PRIMARY_DESCRIPTOR_LOCATION,
                           1,
-                          bytebuf);
-  bytebuf[6] = 0;
-  DPRINT1( "CD-identifier: [%.5s]\n", bytebuf + 1 );
-
-  ret = 
-    Status == STATUS_SUCCESS &&
-    bytebuf[0] == 1 &&
-    bytebuf[1] == 'C' &&
-    bytebuf[2] == 'D' &&
-    bytebuf[3] == '0' &&
-    bytebuf[4] == '0' &&
-    bytebuf[5] == '1';
-
-  ExFreePool( bytebuf );
-
-  return ret;
+                          Buffer);
+  if (!NT_SUCCESS(Status))
+    {
+      return(Status);
+    }
+
+  Buffer[6] = 0;
+  DPRINT1("CD-identifier: [%.5s]\n", Buffer + 1);
+
+  Status = (Buffer[0] == 1 &&
+           Buffer[1] == 'C' &&
+           Buffer[2] == 'D' &&
+           Buffer[3] == '0' &&
+           Buffer[4] == '0' &&
+           Buffer[5] == '1') ? STATUS_SUCCESS : STATUS_UNRECOGNIZED_VOLUME;
+
+  ExFreePool(Buffer);
+
+  return(Status);
 }
 
 
@@ -260,9 +269,9 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
   Stack = IoGetCurrentIrpStackLocation(Irp);
   DeviceToMount = Stack->Parameters.MountVolume.DeviceObject;
 
-  if (CdfsHasFileSystem(DeviceToMount) == FALSE)
+  Status = CdfsHasFileSystem(DeviceToMount);
+  if (!NT_SUCCESS(Status))
     {
-      Status = STATUS_UNRECOGNIZED_VOLUME;
       goto ByeBye;
     }
 
@@ -358,6 +367,106 @@ ByeBye:
        IoDeleteDevice(NewDeviceObject);
     }
 
+  DPRINT1("CdfsMountVolume() done (Status: %lx)\n", Status);
+
+  return(Status);
+}
+
+
+static NTSTATUS
+CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
+               PIRP Irp)
+{
+  PDEVICE_OBJECT DeviceToVerify;
+  PIO_STACK_LOCATION Stack;
+  PUCHAR Buffer;
+  ULONG Sector;
+  ULONG i;
+  NTSTATUS Status;
+
+  union
+    {
+      ULONG Value;
+      UCHAR Part[4];
+    } Serial;
+
+  DPRINT1("CdfsVerifyVolume() called\n");
+
+  if (DeviceObject != CdfsGlobalData->DeviceObject)
+    {
+      return(STATUS_INVALID_DEVICE_REQUEST);
+    }
+
+  Stack = IoGetCurrentIrpStackLocation(Irp);
+  DeviceToVerify = Stack->Parameters.VerifyVolume.DeviceObject;
+
+  Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION;
+
+  Buffer = ExAllocatePool(NonPagedPool,
+                         CDFS_BASIC_SECTOR);
+  if (Buffer == NULL)
+    {
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  Status = STATUS_WRONG_VOLUME;
+
+  do
+    {
+      /* Read the Primary Volume Descriptor (PVD) */
+      Status = CdfsReadSectors(DeviceToVerify,
+                              Sector,
+                              1,
+                              Buffer);
+      if (!NT_SUCCESS(Status))
+       {
+         goto ByeBye;
+       }
+
+      if (Buffer[0] == 1 &&
+         Buffer[1] == 'C' &&
+         Buffer[2] == 'D' &&
+         Buffer[3] == '0' &&
+         Buffer[4] == '0' &&
+         Buffer[5] == '1')
+       {
+         break;
+       }
+
+      Sector++;
+    }
+  while (Buffer[0] != 255);
+
+  if (Buffer[0] == 255)
+    goto ByeBye;
+
+
+  /* Calculate the volume serial number */
+  Serial.Value = 0;
+  for (i = 0; i < 2048; i += 4)
+    {
+      /* DON'T optimize this to ULONG!!! (breaks overflow) */
+      Serial.Part[0] += Buffer[i+3];
+      Serial.Part[1] += Buffer[i+2];
+      Serial.Part[2] += Buffer[i+1];
+      Serial.Part[3] += Buffer[i+0];
+    }
+
+  DPRINT1("Current serial number %08lx  Vpb serial number %08lx\n",
+         Serial.Value, DeviceToVerify->Vpb->SerialNumber);
+
+  if (Serial.Value == DeviceToVerify->Vpb->SerialNumber)
+    Status = STATUS_SUCCESS;
+
+ByeBye:
+
+  ExFreePool(Buffer);
+
+
+//  Status = STATUS_INVALID_DEVICE_REQUEST;
+
+  DPRINT1("CdfsVerifyVolume() done (Status: %lx)\n", Status);
+
   return(Status);
 }
 
@@ -369,7 +478,7 @@ CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
   PIO_STACK_LOCATION Stack;
   NTSTATUS Status;
 
-  DPRINT1("CdfsFileSystemControl() called\n");
+  DPRINT("CdfsFileSystemControl() called\n");
 
   Stack = IoGetCurrentIrpStackLocation(Irp);
 
@@ -386,8 +495,8 @@ CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
        break;
 
       case IRP_MN_VERIFY_VOLUME:
-       DPRINT("CDFS: IRP_MN_VERIFY_VOLUME\n");
-       Status = STATUS_INVALID_DEVICE_REQUEST;
+       DPRINT1("CDFS: IRP_MN_VERIFY_VOLUME\n");
+       Status = CdfsVerifyVolume(DeviceObject, Irp);
        break;
 
       default: