Reworked code for handling of asynchonous i/o requests.
[reactos.git] / reactos / drivers / fs / vfat / iface.c
index 7c2136f..efd37ce 100644 (file)
-/*
+/* $Id: iface.c,v 1.59 2001/11/02 22:47:36 hbirr Exp $
+ *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * FILE:             services/fs/vfat/iface.c
  * PURPOSE:          VFAT Filesystem
  * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
  * UPDATE HISTORY:
-     ??           Created
-     24-10-1998   Fixed bugs in long filename support
-                  Fixed a bug that prevented unsuccessful file open requests being reported
-                  Now works with long filenames that span over a sector boundary
-     28-10-1998   Reads entire FAT into memory
-                  VFatReadSector modified to read in more than one sector at a time
-     7-11-1998    Fixed bug that assumed that directory data could be fragmented
-     8-12-1998    Added FAT32 support
-                  Added initial writability functions
-                  WARNING: DO NOT ATTEMPT TO TEST WRITABILITY FUNCTIONS!!!
-     12-12-1998   Added basic support for FILE_STANDARD_INFORMATION request
-
-*/
+ *    ??           Created
+ *   24-10-1998   Fixed bugs in long filename support
+ *                Fixed a bug that prevented unsuccessful file open requests
+ *                being reported
+ *                Now works with long filenames that span over a sector
+ *                boundary
+ *   28-10-1998   Reads entire FAT into memory
+ *                VFatReadSector modified to read in more than one sector at a
+ *                time
+ *   7-11-1998    Fixed bug that assumed that directory data could be
+ *                fragmented
+ *   8-12-1998    Added FAT32 support
+ *                Added initial writability functions
+ *                WARNING: DO NOT ATTEMPT TO TEST WRITABILITY FUNCTIONS!!!
+ *   12-12-1998   Added basic support for FILE_STANDARD_INFORMATION request
+ *
+ */
 
 /* INCLUDES *****************************************************************/
 
-#include <wchar.h>
-#include <internal/string.h>
 #include <ddk/ntddk.h>
-#include <ddk/cctypes.h>
 
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 #include "vfat.h"
 
-//#include "dbgpool.c"
-
 /* GLOBALS *****************************************************************/
 
-static PDRIVER_OBJECT VFATDriverObject;
-PVfatFCB pFirstFcb;
-
-/* FUNCTIONS ****************************************************************/
-
-ULONG Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
-/*
- * FUNCTION: Retrieve the next FAT32 cluster from the FAT table via a physical
- *           disk read
- */
-{
-   ULONG FATsector;
-   ULONG FATeis;
-   PULONG Block;
-   
-   Block = ExAllocatePool(NonPagedPool,1024);
-   FATsector=CurrentCluster/(512/sizeof(ULONG));
-   FATeis=CurrentCluster-(FATsector*(512/sizeof(ULONG)));
-   VFATReadSectors(DeviceExt->StorageDevice
-        ,(ULONG)(DeviceExt->FATStart+FATsector), 1,(UCHAR*) Block);
-   CurrentCluster = Block[FATeis];
-   if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff)
-    CurrentCluster = 0xffffffff;
-   ExFreePool(Block);
-   return(CurrentCluster);
-}
-
-ULONG Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
-/*
- * FUNCTION: Retrieve the next FAT16 cluster from the FAT table from the
- *           in-memory FAT
- */
-{
-   PUSHORT Block;
-   Block=(PUSHORT)DeviceExt->FAT;
-   CurrentCluster = Block[CurrentCluster];
-   if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
-     CurrentCluster = 0xffffffff;
-   DPRINT("Returning %x\n",CurrentCluster);
-   return(CurrentCluster);
-}
+#define  CACHEPAGESIZE(pDeviceExt) ((pDeviceExt)->BytesPerCluster > PAGESIZE ? \
+                  (pDeviceExt)->BytesPerCluster : PAGESIZE)
 
-ULONG Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
-/*
- * FUNCTION: Retrieve the next FAT12 cluster from the FAT table from the
- *           in-memory FAT
- */
-{
- unsigned char* CBlock;
- ULONG FATOffset;
- ULONG Entry;
-   CBlock = DeviceExt->FAT;
-   FATOffset = (CurrentCluster * 12)/ 8;//first byte containing value
-   if ((CurrentCluster % 2) == 0)
-   {
-    Entry = CBlock[FATOffset];
-    Entry |= ((CBlock[FATOffset+1] & 0xf)<<8);
-   }
-   else
-   {
-    Entry = (CBlock[FATOffset] >> 4);
-    Entry |= (CBlock[FATOffset+1] << 4);
-   }
-   DPRINT("Entry %x\n",Entry);
-   if (Entry >= 0xff8 && Entry <= 0xfff)
-    Entry = 0xffffffff;
-   DPRINT("Returning %x\n",Entry);
-   return(Entry);
-}
+static PDRIVER_OBJECT VfatDriverObject;
 
-ULONG GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
-/*
- * FUNCTION: Retrieve the next cluster depending on the FAT type
- */
-{
-   
-   DPRINT("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n",
-           DeviceExt,CurrentCluster);
-   if (DeviceExt->FatType == FAT16)
-       return(Fat16GetNextCluster(DeviceExt, CurrentCluster));
-   else if (DeviceExt->FatType == FAT32)
-       return(Fat32GetNextCluster(DeviceExt, CurrentCluster));
-   else
-       return(Fat12GetNextCluster(DeviceExt, CurrentCluster));
-}
+/* FUNCTIONS ****************************************************************/
 
-ULONG FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt)
+static NTSTATUS
+VfatHasFileSystem(PDEVICE_OBJECT DeviceToMount,
+                 PBOOLEAN RecognizedFS)
 /*
- * FUNCTION: Finds the first available cluster in a FAT16 table
+ * FUNCTION: Tests if the device contains a filesystem that can be mounted
+ *           by this fsd
  */
 {
- PUSHORT Block;
- int i;
-   Block=(PUSHORT)DeviceExt->FAT;
-   for(i=2;i<(DeviceExt->Boot->FATSectors*256) ;i++)
-     if(Block[i]==0)
-       return (i);
-   /* Give an error message (out of disk space) if we reach here) */
-   return 0;
-}
+   BootSector *Boot;
+   NTSTATUS Status;
 
-ULONG FAT12FindAvailableCluster(PDEVICE_EXTENSION DeviceExt)
-/*
- * FUNCTION: Finds the first available cluster in a FAT12 table
- */
-{
- ULONG FATOffset;
- ULONG Entry;
- PUCHAR CBlock=DeviceExt->FAT;
- ULONG i;
-   for(i=2;i<((DeviceExt->Boot->FATSectors*512*8)/12) ;i++)
-   {
-     FATOffset = (i * 12)/8;
-     if ((i % 2) == 0)
-     {
-       Entry = CBlock[FATOffset];
-       Entry |= ((CBlock[FATOffset + 1] & 0xf)<<8);
-     }
-     else
-     {
-       Entry = (CBlock[FATOffset] >> 4);
-       Entry |= (CBlock[FATOffset + 1] << 4);
-     }
-     if(Entry==0)
-         return (i);
-   }
-   /* Give an error message (out of disk space) if we reach here) */
-   DbgPrint("Disk full, %d clusters used\n",i);
-   return 0;
-}
+   Boot = ExAllocatePool(NonPagedPool, 512);
 
-ULONG FAT32FindAvailableCluster(PDEVICE_EXTENSION DeviceExt)
-/*
- * FUNCTION: Finds the first available cluster in a FAT32 table
- */
-{
- ULONG sector;
- PULONG Block;
- int i;
-   Block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
-   for(sector=0
-       ;sector<  ((struct _BootSector32*)(DeviceExt->Boot))->FATSectors32
-       ;sector++)
-   {
-     VFATReadSectors(DeviceExt->StorageDevice
-        ,(ULONG)(DeviceExt->FATStart+sector), 1,(UCHAR*) Block);
-
-     for(i=0; i<512; i++)
+   Status = VfatReadSectors(DeviceToMount, 0, 1, (UCHAR *) Boot);
+   if (!NT_SUCCESS(Status))
      {
-       if(Block[i]==0)
-       {
-         ExFreePool(Block);
-         return (i+sector*128);
-       }
+       return(Status);
      }
-   }
-   /* Give an error message (out of disk space) if we reach here) */
-   ExFreePool(Block);
-   return 0;
-}
 
-ULONG FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
-/*
- * FUNCTION: Counts free cluster in a FAT12 table
- */
-{
-   ULONG FATOffset;
-   ULONG Entry;
-   PUCHAR CBlock=DeviceExt->FAT;
-   ULONG ulCount = 0;
-   ULONG i;
-
-   for(i=2;i<((DeviceExt->Boot->FATSectors*512*8)/12) ;i++)
-   {
-     FATOffset = (i * 12)/8;
-     if ((i % 2) == 0)
-     {
-       Entry = CBlock[FATOffset];
-       Entry |= ((CBlock[FATOffset + 1] & 0xf)<<8);
-     }
-     else
+   DPRINT1("Boot->SysType %.5s\n", Boot->SysType);
+   if (strncmp(Boot->SysType, "FAT12", 5) == 0 ||
+       strncmp(Boot->SysType, "FAT16", 5) == 0 ||
+       strncmp(((struct _BootSector32 *) (Boot))->SysType, "FAT32", 5) == 0)
      {
-       Entry = (CBlock[FATOffset] >> 4);
-       Entry |= (CBlock[FATOffset + 1] << 4);
+       *RecognizedFS = TRUE;
      }
-     if(Entry==0)
-         ulCount++;
-   }
-   return ulCount;
-}
-
-ULONG FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
-/*
- * FUNCTION: Counts free clusters in a FAT16 table
- */
-{
-   PUSHORT Block;
-   ULONG ulCount = 0;
-   ULONG i;
-
-   Block=(PUSHORT)DeviceExt->FAT;
-   for(i=2;i<(DeviceExt->Boot->FATSectors*256) ;i++)
-     if(Block[i]==0)
-       ulCount++;
-   return ulCount;
-}
-
-ULONG FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
-/*
- * FUNCTION: Counts free clusters in a FAT32 table
- */
-{
-   ULONG sector;
-   PULONG Block;
-   ULONG ulCount = 0;
-   ULONG i;
-
-   Block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
-   for(sector=0
-       ;sector<  ((struct _BootSector32*)(DeviceExt->Boot))->FATSectors32
-       ;sector++)
-   {
-     VFATReadSectors(DeviceExt->StorageDevice
-        ,(ULONG)(DeviceExt->FATStart+sector), 1,(UCHAR*) Block);
-
-     for(i=0; i<512; i++)
-     {
-       if(Block[i]==0)
-         ulCount++;
-     }
-   }
-   /* Give an error message (out of disk space) if we reach here) */
-   ExFreePool(Block);
-   return ulCount;
-}
-
-void  FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
-                        ULONG NewValue)
-/*
- * FUNCTION: Writes a cluster to the FAT12 physical and in-memory tables
- */
-{
- ULONG FATsector;
- ULONG FATOffset;
- PUCHAR CBlock=DeviceExt->FAT;
- int i;
-   FATOffset = (ClusterToWrite * 12)/8;
-   if ((ClusterToWrite % 2) == 0)
-   {
-     CBlock[FATOffset]=NewValue;
-     CBlock[FATOffset + 1] &=0xf0;
-     CBlock[FATOffset + 1]
-         |= (NewValue&0xf00)>>8;
-   }
-   else
-   {
-     CBlock[FATOffset] &=0x0f;
-     CBlock[FATOffset]
-         |= (NewValue&0xf)<<4;
-     CBlock[FATOffset+1]=NewValue>>4;
-   }
-   /* Write the changed FAT sector(s) to disk */
-   FATsector=FATOffset/BLOCKSIZE;
-   for(i=0;i<DeviceExt->Boot->FATCount;i++)
-   {
-      if( (FATOffset%BLOCKSIZE)==(BLOCKSIZE-1))//entry is on 2 sectors
-      {
-        VFATWriteSectors(DeviceExt->StorageDevice,
-                   DeviceExt->FATStart+FATsector
-                   +i*DeviceExt->Boot->FATSectors,
-                       2,
-                   CBlock+FATsector*512);
-      }
-      else
-      {
-        VFATWriteSectors(DeviceExt->StorageDevice,
-                   DeviceExt->FATStart+FATsector
-                   +i*DeviceExt->Boot->FATSectors,
-                       1,
-                   CBlock+FATsector*512);
-      }
-   }
-}
-
-void  FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
-                        ULONG NewValue)
-/*
- * FUNCTION: Writes a cluster to the FAT16 physical and in-memory tables
- */
-{
- ULONG FATsector;
- PUSHORT Block;
-DbgPrint("FAT16WriteCluster %u : %u\n",ClusterToWrite,NewValue);
-   Block=(PUSHORT)DeviceExt->FAT;
-   FATsector=ClusterToWrite/(512/sizeof(USHORT));
-
-   /* Update the in-memory FAT */
-   Block[ClusterToWrite] = NewValue;
-   /* Write the changed FAT sector to disk */
-   VFATWriteSectors(DeviceExt->StorageDevice,
-                   DeviceExt->FATStart+FATsector,
-                    1,
-                   (UCHAR *)Block);
-}
-
-void  FAT32WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
-                        ULONG NewValue)
-/*
- * FUNCTION: Writes a cluster to the FAT32 physical tables
- */
-{
- ULONG FATsector;
- ULONG FATeis;
- PUSHORT Block;
-DbgPrint("FAT32WriteCluster %u : %u\n",ClusterToWrite,NewValue);
-   Block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
-   FATsector=ClusterToWrite/128;
-   FATeis=ClusterToWrite-(FATsector*128);
-   /* load sector, change value, then rewrite sector */
-   VFATReadSectors(DeviceExt->StorageDevice,
-                   DeviceExt->FATStart+FATsector,
-                    1,
-                   (UCHAR *)Block);
-   Block[FATeis] = NewValue;
-   VFATWriteSectors(DeviceExt->StorageDevice,
-                   DeviceExt->FATStart+FATsector,
-                    1,
-                   (UCHAR *)Block);
-   ExFreePool(Block);
-}
-
-void  WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
-                   ULONG NewValue)
-/*
- * FUNCTION: Write a changed FAT entry
- */
-{
-   if(DeviceExt->FatType==FAT16)
-     FAT16WriteCluster(DeviceExt, ClusterToWrite, NewValue);
-   else if(DeviceExt->FatType==FAT32)
-     FAT32WriteCluster(DeviceExt, ClusterToWrite, NewValue);
    else
-     FAT12WriteCluster(DeviceExt, ClusterToWrite, NewValue);
-}
-
-ULONG GetNextWriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
-/*
- * FUNCTION: Determines the next cluster to be written
- */
-{
- ULONG LastCluster, NewCluster;
-   DPRINT("GetNextWriteCluster(DeviceExt %x, CurrentCluster %x)\n",
-           DeviceExt,CurrentCluster);
-
-   /* Find out what was happening in the last cluster's AU */
-   LastCluster=GetNextCluster(DeviceExt,CurrentCluster);
-   /* Check to see if we must append or overwrite */
-   if (LastCluster==0xffffffff)
-   {//we are after last existing cluster : we must add one to file
-        /* Append */
-        /* Firstly, find the next available open allocation unit */
-        if(DeviceExt->FatType == FAT16)
-           NewCluster = FAT16FindAvailableCluster(DeviceExt);
-        else if(DeviceExt->FatType == FAT32)
-           NewCluster = FAT32FindAvailableCluster(DeviceExt);
-        else
-           NewCluster = FAT12FindAvailableCluster(DeviceExt);
-        /* Mark the new AU as the EOF */
-        WriteCluster(DeviceExt, NewCluster, 0xFFFFFFFF);
-        /* Now, write the AU of the LastCluster with the value of the newly
-           found AU */
-        if(CurrentCluster)
-          WriteCluster(DeviceExt, CurrentCluster, NewCluster);
-        /* Return NewCluster as CurrentCluster */
-        return NewCluster;
-   }
-   else
-   {
-        /* Overwrite: Return LastCluster as CurrentCluster */
-        return LastCluster;
-   }
-}
-
-ULONG ClusterToSector(PDEVICE_EXTENSION DeviceExt,
-                             unsigned long Cluster)
-/*
- * FUNCTION: Converts the cluster number to a sector number for this physical
- *           device
- */
-{
-  return DeviceExt->dataStart+((Cluster-2)*DeviceExt->Boot->SectorsPerCluster);
-}
-
-void RtlAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length)
-/*
- * FUNCTION: Convert an ANSI string to it's Unicode equivalent
- */
-{
-   int i;
-   
-   for (i=0; (i<Length && Source[i] != ' '); i++)
      {
-       Dest[i] = Source[i];
+       *RecognizedFS = FALSE;
      }
-   Dest[i]=0;
-}
-
-void RtlCatAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length)
-/*
- * FUNCTION: Appends a converted ANSI to Unicode string to the end of an
- *           existing Unicode string
- */
-{
-   ULONG i;
-   
-   while((*Dest)!=0)
-     {
-       Dest++;
-     }
-   for (i=0; (i<Length && Source[i] != ' '); i++)
-     {
-       Dest[i] = Source[i];
-     }
-   Dest[i]=0;
-}
-
-void vfat_initstr(wchar_t *wstr, ULONG wsize)
-/*
- * FUNCTION: Initialize a string for use with a long file name
- */
-{
-  int i;
-  wchar_t nc=0;
-  for(i=0; i<wsize; i++)
-  {
-    *wstr=nc;
-    wstr++;
-  }
-  wstr=wstr-wsize;
-}
-
-wchar_t * vfat_wcsncat(wchar_t * dest, const wchar_t * src,size_t wstart, size_t wcount)
-/*
- * FUNCTION: Append a string for use with a long file name
- */
-{
-   int i;
-
-   dest+=wstart;
-   for(i=0; i<wcount; i++)
-   {
-     *dest=src[i];
-     dest++;
-   }
-   dest=dest-(wcount+wstart);
-
-   return dest;
-}
-
-wchar_t * vfat_wcsncpy(wchar_t * dest, const wchar_t *src,size_t wcount)
-/*
- * FUNCTION: Copy a string for use with long file names
- */
-{
- int i;
-   
-   for (i=0;i<wcount;i++)
-   {
-     dest[i]=src[i];
-     if(!dest[i]) break;
-   }
-   return(dest);
-}
-
-wchar_t * vfat_movstr(const wchar_t *src, ULONG dpos,
-                      ULONG spos, ULONG len)
-/*
- * FUNCTION: Move the characters in a string to a new position in the same
- *           string
- */
-{
- int i;
 
-  if(dpos<=spos)
-  {
-    for(i=0; i<len; i++)
-    {
-      src[dpos++]=src[spos++];
-    }
-  }
-  else
-  {
-    dpos+=len-1;
-    spos+=len-1;
-    for(i=0; i<len; i++)
-    {
-      src[dpos--]=src[spos--];
-    }
-  }
+   ExFreePool(Boot);
 
-  return(src);
+   return(STATUS_SUCCESS);
 }
 
-BOOLEAN IsLastEntry(PVOID Block, ULONG Offset)
-/*
- * FUNCTION: Determine if the given directory entry is the last
- */
-{
-   return(((FATDirEntry *)Block)[Offset].Filename[0] == 0);
-}
 
-BOOLEAN IsVolEntry(PVOID Block, ULONG Offset)
+static NTSTATUS
+VfatMountDevice(PDEVICE_EXTENSION DeviceExt,
+               PDEVICE_OBJECT DeviceToMount)
 /*
- * FUNCTION: Determine if the given directory entry is a vol entry
+ * FUNCTION: Mounts the device
  */
 {
-   if( (((FATDirEntry *)Block)[Offset].Attrib)==0x28 ) return TRUE;
-   else return FALSE;
-}
+   NTSTATUS Status;
 
-BOOLEAN IsDeletedEntry(PVOID Block, ULONG Offset)
-/*
- * FUNCTION: Determines if the given entry is a deleted one
- */
-{
-   /* Checks special character */
+   DPRINT("Mounting VFAT device...");
+   DPRINT("DeviceExt %x\n", DeviceExt);
 
-   return ((((FATDirEntry *)Block)[Offset].Filename[0] == 0xe5));
-}
+   DeviceExt->Boot = ExAllocatePool(NonPagedPool, 512);
 
-BOOLEAN GetEntryName(PVOID Block, PULONG _Offset, PWSTR Name, PULONG _jloop,
-  PDEVICE_EXTENSION DeviceExt, ULONG * _StartingSector)
-/*
- * FUNCTION: Retrieves the file name, be it in short or long file name format
- */
-{
-   FATDirEntry* test;
-   slot* test2;
-   ULONG Offset = *_Offset;
-   ULONG StartingSector = *_StartingSector;
-   ULONG jloop = *_jloop;
-   ULONG cpos;
-   WCHAR tmp[256];
-   
-   test = (FATDirEntry *)Block;
-   test2 = (slot *)Block;
-   
-   *Name = 0;
-
-   if (IsDeletedEntry(Block,Offset))
-     {
-       return(FALSE);
-     }
-   
-   if(test2[Offset].attr == 0x0f) 
-     {
-        vfat_initstr(Name, 256);
-       vfat_wcsncpy(Name,test2[Offset].name0_4,5);
-       vfat_wcsncat(Name,test2[Offset].name5_10,5,6);
-       vfat_wcsncat(Name,test2[Offset].name11_12,11,2);
-
-        cpos=0;
-        while((test2[Offset].id!=0x41) && (test2[Offset].id!=0x01) &&
-             (test2[Offset].attr>0)) 
-         {
-            Offset++;
-             if(Offset==ENTRIES_PER_SECTOR) {
-               Offset=0;
-               StartingSector++;//FIXME : nor always the next sector
-               jloop++;
-               VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,Block);
-               test2 = (slot *)Block;
-             }
-             cpos++;
-             vfat_movstr(Name, 13, 0, cpos*13);
-             vfat_wcsncpy(Name, test2[Offset].name0_4, 5);
-             vfat_wcsncat(Name,test2[Offset].name5_10,5,6);
-             vfat_wcsncat(Name,test2[Offset].name11_12,11,2);
-
-          }
-
-       if (IsDeletedEntry(Block,Offset+1))
-         {
-            Offset++;
-            *_Offset = Offset;
-             *_jloop = jloop;
-             *_StartingSector = StartingSector;
-            return(FALSE);
-         }
-       
-       *_Offset = Offset;
-        *_jloop = jloop;
-        *_StartingSector = StartingSector;
-       
-       return(TRUE);
-     }   
-      
-   RtlAnsiToUnicode(Name,test[Offset].Filename,8);
-   if (test[Offset].Ext[0]!=' ')
+   Status = VfatReadSectors(DeviceToMount, 0, 1, (UCHAR *) DeviceExt->Boot);
+   if (!NT_SUCCESS(Status))
      {
-       RtlCatAnsiToUnicode(Name,".",1);
+       return(Status);
      }
-   RtlCatAnsiToUnicode(Name,test[Offset].Ext,3);
-      
-   *_Offset = Offset;
-   
-   return(TRUE);
-}
-
-BOOLEAN wstrcmpi(PWSTR s1, PWSTR s2)
-/*
- * FUNCTION: Compare to wide character strings
- * return TRUE if s1==s2
- */
-{
-   while (towlower(*s1)==towlower(*s2))
-     {
-       if ((*s1)==0 && (*s2)==0)
-         {
-            return(TRUE);
-         }
-       
-       s1++;
-       s2++;   
-     }
-   return(FALSE);
-}
-BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2)
-/*
- * FUNCTION: Compare to wide character strings, s2 with jokers (* or ?)
- * return TRUE if s1 like s2
- */
-{
-   while ((*s2=='?')||(towlower(*s1)==towlower(*s2)))
-   {
-      if ((*s1)==0 && (*s2)==0)
-        return(TRUE);
-      s1++;
-      s2++;    
-   }
-   if(*s2=='*')
-   {
-     s2++;
-     while (*s1)
-       if (wstrcmpjoki(s1,s2)) return TRUE;
-       else s1++;
-   }
-   if ((*s1)==0 && (*s2)==0)
-        return(TRUE);
-   return(FALSE);
-}
 
+   DeviceExt->FATStart = DeviceExt->Boot->ReservedSectors;
+   DeviceExt->rootDirectorySectors =
+     (DeviceExt->Boot->RootEntries * 32) / DeviceExt->Boot->BytesPerSector;
+   DeviceExt->rootStart =
+     DeviceExt->FATStart +
+     DeviceExt->Boot->FATCount * DeviceExt->Boot->FATSectors;
+   DeviceExt->dataStart =
+     DeviceExt->rootStart + DeviceExt->rootDirectorySectors;
+   DeviceExt->BytesPerSector = DeviceExt->Boot->BytesPerSector;
+   DeviceExt->FATEntriesPerSector = DeviceExt->Boot->BytesPerSector / 32;
+   DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
+     DeviceExt->Boot->BytesPerSector;
 
-NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
-/*
- * FUNCTION: Read the volume label
- */
-{
-   ULONG i, j;
-   ULONG Size;
-   char* block;
-   ULONG StartingSector;
-   ULONG NextCluster;
-
-   Size = DeviceExt->rootDirectorySectors;//FIXME : in fat32, no limit
-   StartingSector = DeviceExt->rootStart;
-   NextCluster=0;
-
-   block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
-   DPRINT("FindFile : start at sector %lx, entry %ld\n",StartingSector,i);
-   for (j=0; j<Size; j++)
-   {
-     VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,block);
-
-     for (i=0; i<ENTRIES_PER_SECTOR; i++)
+   if (DeviceExt->BytesPerCluster >= PAGESIZE && 
+       (DeviceExt->BytesPerCluster % PAGESIZE) != 0)
      {
-       if (IsVolEntry((PVOID)block,i))
-       {
-         FATDirEntry *test = (FATDirEntry *)block;
-
-         /* copy volume label */
-         RtlAnsiToUnicode(Vpb->VolumeLabel,test[i].Filename,8);
-         RtlCatAnsiToUnicode(Vpb->VolumeLabel,test[i].Ext,3);
-         Vpb->VolumeLabelLength = wcslen(Vpb->VolumeLabel);
-
-         ExFreePool(block);
-         return(STATUS_SUCCESS);
-       }
-       if (IsLastEntry((PVOID)block,i))
-       {
-         *(Vpb->VolumeLabel) = 0;
-         Vpb->VolumeLabelLength = 0;
-         ExFreePool(block);
-         return(STATUS_UNSUCCESSFUL);
-       }
+       DbgPrint("Invalid cluster size\n");
+       KeBugCheck(0);
      }
-     // not found in this sector, try next :
-
-     /* directory can be fragmented although it is best to keep them
-        unfragmented */
-     StartingSector++;
-     if (DeviceExt->FatType ==FAT32)
+   else if (DeviceExt->BytesPerCluster < PAGESIZE &&
+           (PAGESIZE % DeviceExt->BytesPerCluster) != 0)
      {
-       if(StartingSector==ClusterToSector(DeviceExt,NextCluster+1))
-       {
-         NextCluster = GetNextCluster(DeviceExt,NextCluster);
-         if (NextCluster == 0||NextCluster==0xffffffff)
-         {
-           *(Vpb->VolumeLabel) = 0;
-           Vpb->VolumeLabelLength = 0;
-           ExFreePool(block);
-           return(STATUS_UNSUCCESSFUL);
-         }
-         StartingSector = ClusterToSector(DeviceExt,NextCluster);
-       }
+       DbgPrint("Invalid cluster size2\n");
+       KeBugCheck(0);
      }
-   }
-   *(Vpb->VolumeLabel) = 0;
-   Vpb->VolumeLabelLength = 0;
-   ExFreePool(block);
-   return(STATUS_UNSUCCESSFUL);
-}
-
 
-NTSTATUS FindFile(PDEVICE_EXTENSION DeviceExt, PVfatFCB Fcb,
-          PVfatFCB Parent, PWSTR FileToFind,ULONG *StartSector,ULONG *Entry)
-/*
- * FUNCTION: Find a file
- */
-{
- ULONG i, j;
- ULONG Size;
- char* block;
- WCHAR name[256];
- ULONG StartingSector;
- ULONG NextCluster;
-   WCHAR TempStr[2];
-   
-   DPRINT("FindFile(Parent %x, FileToFind '%w')\n",Parent,FileToFind);
-   
-   if (wcslen(FileToFind)==0)
+   if (strncmp (DeviceExt->Boot->SysType, "FAT12", 5) == 0)
      {
-CHECKPOINT;
-        TempStr[0] = (WCHAR)'.';
-       TempStr[1] = 0;
-       FileToFind=&TempStr;
+       DbgPrint("FAT12\n");
+       DeviceExt->FatType = FAT12;
      }
-   if (Parent != NULL)
+   else if (strncmp
+           (((struct _BootSector32 *) (DeviceExt->Boot))->SysType, "FAT32",
+           5) == 0)
      {
-       DPRINT("Parent->entry.FirstCluster %d\n",Parent->entry.FirstCluster);
-     }
-
-DPRINT("FindFile '%w'\n", FileToFind);
-   if (Parent == NULL||Parent->entry.FirstCluster==1)
-   {
-CHECKPOINT;
-     Size = DeviceExt->rootDirectorySectors;//FIXME : in fat32, no limit
-     StartingSector = DeviceExt->rootStart;
-     NextCluster=0;
-     if(FileToFind[0]==0 ||(FileToFind[0]=='\\' && FileToFind[1]==0) ||
-       (FileToFind[0]=='.' && FileToFind[1]==0))
-     {// it's root : complete essentials fields then return ok
-CHECKPOINT;
-       memset(Fcb,0,sizeof(VfatFCB));
-       memset(Fcb->entry.Filename,' ',11);
-       Fcb->entry.FileSize=DeviceExt->rootDirectorySectors*BLOCKSIZE;
-       Fcb->entry.Attrib=FILE_ATTRIBUTE_DIRECTORY;
-       if (DeviceExt->FatType == FAT32)
-         Fcb->entry.FirstCluster=2;
-       else
-         Fcb->entry.FirstCluster=1;//FIXME : is 1 the good value for mark root?
-       if(StartSector)
-         *StartSector=StartingSector;
-       if(Entry)
-         *Entry=0;
-       return(STATUS_SUCCESS);
+       DbgPrint("FAT32\n");
+       DeviceExt->FatType = FAT32;
+       DeviceExt->rootDirectorySectors = DeviceExt->Boot->SectorsPerCluster;
+       DeviceExt->dataStart = DeviceExt->FATStart + DeviceExt->Boot->FATCount
+         * ((struct _BootSector32 *) (DeviceExt->Boot))->FATSectors32;
+       DeviceExt->rootStart = ClusterToSector (DeviceExt,
+         ((struct _BootSector32 *)(DeviceExt->Boot))->RootCluster);
      }
-   }
    else
-   {
-     DPRINT("Parent->entry.FileSize %x\n",Parent->entry.FileSize);
-       
-     Size = ULONG_MAX;
-     if (DeviceExt->FatType == FAT32)
-       NextCluster = Parent->entry.FirstCluster
-               +Parent->entry.FirstClusterHigh*65536;
-     else
-       NextCluster = Parent->entry.FirstCluster;
-     StartingSector = ClusterToSector(DeviceExt, NextCluster);
-     if(Parent->entry.FirstCluster==1 && DeviceExt->FatType!=FAT32)
-     {// read of root directory in FAT16 or FAT12
-       StartingSector=DeviceExt->rootStart;
-     }
-   }
-CHECKPOINT;
-   block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
-CHECKPOINT;
-   if (StartSector && (*StartSector)) StartingSector=*StartSector;
-   i=(Entry)?(*Entry):0;
-   DPRINT("FindFile : start at sector %lx, entry %ld\n",StartingSector,i);
-   for (j=0; j<Size; j++)
-   {
-     VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,block);
-
-     for (i=(Entry)?(*Entry):0; i<ENTRIES_PER_SECTOR; i++)
-     {
-       if (IsVolEntry((PVOID)block,i))
-          continue;
-       if (IsLastEntry((PVOID)block,i))
-       {
-         ExFreePool(block);
-         if(StartSector) *StartSector=StartingSector;
-         if(Entry) *Entry=i;
-         return(STATUS_UNSUCCESSFUL);
-       }
-       if (GetEntryName((PVOID)block,&i,name,&j,DeviceExt,&StartingSector))
-       {
-        DPRINT("Comparing '%w' '%w'\n",name,FileToFind);
-         if (wstrcmpjoki(name,FileToFind))
-         {
-           /* In the case of a long filename, the firstcluster is stored in
-                         the next record -- where it's short name is */
-           if(((FATDirEntry *)block)[i].Attrib==0x0f) i++;
-           if( i==(ENTRIES_PER_SECTOR))
-           {// entry is in next sector
-             StartingSector++;
-             //FIXME : treat case of next sector fragmented
-             VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,block);
-             i=0;
-           }
-           memcpy(&Fcb->entry,&((FATDirEntry *)block)[i],
-                          sizeof(FATDirEntry));
-           vfat_wcsncpy(Fcb->ObjectName,name,MAX_PATH);
-           ExFreePool(block);
-           if(StartSector) *StartSector=StartingSector;
-           if(Entry) *Entry=i;
-           return(STATUS_SUCCESS);
-         }
-       }
-     }
-     // not found in this sector, try next :
-
-     /* directory can be fragmented although it is best to keep them
-        unfragmented */
-     if(Entry) *Entry=0;
-     StartingSector++;
-     if ((Parent != NULL && Parent->entry.FirstCluster!=1)
-           || DeviceExt->FatType ==FAT32)
      {
-       if(StartingSector==ClusterToSector(DeviceExt,NextCluster+1))
-       {
-         NextCluster = GetNextCluster(DeviceExt,NextCluster);
-         if (NextCluster == 0||NextCluster==0xffffffff)
-         {
-           if(StartSector) *StartSector=StartingSector;
-           if(Entry) *Entry=i;
-           ExFreePool(block);
-           return(STATUS_UNSUCCESSFUL);
-         }
-         StartingSector = ClusterToSector(DeviceExt,NextCluster);
-       }
+       DbgPrint("FAT16\n");
+       DeviceExt->FatType = FAT16;
      }
-   }
-   ExFreePool(block);
-   if(StartSector) *StartSector=StartingSector;
-   if(Entry) *Entry=i;
-   return(STATUS_UNSUCCESSFUL);
-}
-
 
-NTSTATUS FsdCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
-/*
- * FUNCTION: Closes a file
- */
-{
- PVfatFCB pFcb;
- PVfatCCB pCcb;
-   
-   DPRINT("FsdCloseFile(DeviceExt %x, FileObject %x)\n",
-           DeviceExt,FileObject);
-  
- //FIXME : update entry in directory ?
-   pCcb = (PVfatCCB)(FileObject->FsContext2);
-   
-   DPRINT("pCcb %x\n",pCcb);
-   if (pCcb == NULL)
-     {
-       return(STATUS_SUCCESS);
-     }
-   
-   pFcb = pCcb->pFcb;
-   
-   pFcb->RefCount--;
-   if(pFcb->RefCount<=0)
-   {
-     if(pFcb->prevFcb)
-       pFcb->prevFcb->nextFcb=pFcb->nextFcb;
-     else
-       pFirstFcb=pFcb->nextFcb;
-     if(pFcb->nextFcb)
-       pFcb->nextFcb->prevFcb=pFcb->prevFcb;
-     ExFreePool(pFcb);
-   }
-   ExFreePool(pCcb);
-   return STATUS_SUCCESS;
+   return(STATUS_SUCCESS);
 }
 
-NTSTATUS FsdOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, 
-                    PWSTR FileName)
-/*
- * FUNCTION: Opens a file
- */
-{
- PWSTR current;
- PWSTR next;
- PWSTR string;
- PVfatFCB ParentFcb;
- PVfatFCB Fcb,pRelFcb;
- PVfatFCB Temp;
- PVfatCCB newCCB,pRelCcb;
- NTSTATUS Status;
- PFILE_OBJECT pRelFileObject;
- PWSTR AbsFileName=NULL;
- short i,j;
-
-   DPRINT("FsdOpenFile(%08lx, %08lx, %w)\n", 
-          DeviceExt,
-          FileObject,
-          FileName);
-   
-  //FIXME : treat relative name
-   if(FileObject->RelatedFileObject)
-   {
-DbgPrint("try related for %w\n",FileName);
-     pRelFileObject=FileObject->RelatedFileObject;
-     pRelCcb=pRelFileObject->FsContext2;
-     assert(pRelCcb);
-     pRelFcb=pRelCcb->pFcb;
-     assert(pRelFcb);
-     // verify related object is a directory and target name don't start with \.
-     if( !(pRelFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
-         || (FileName[0]!= '\\') )
-     {
-       Status=STATUS_INVALID_PARAMETER;
-       return Status;
-     }
-     // construct absolute path name
-     AbsFileName=ExAllocatePool(NonPagedPool,MAX_PATH);
-     for (i=0;pRelFcb->PathName[i];i++)
-       AbsFileName[i]=pRelFcb->PathName[i];
-     AbsFileName[i++]='\\';
-     for (j=0;FileName[j]&&i<MAX_PATH;j++)
-       AbsFileName[i++]=FileName[j];
-     assert(i<MAX_PATH);
-     AbsFileName[i]=0;
-     FileName=AbsFileName;
-   }
-   // try first to find an existing FCB in memory
-   for (Fcb=pFirstFcb;Fcb; Fcb=Fcb->nextFcb)
-   {
-     if (DeviceExt==Fcb->pDevExt
-          && wstrcmpi(FileName,Fcb->PathName))
-     {
-        Fcb->RefCount++;
-        FileObject->FsContext =(PVOID) &Fcb->NTRequiredFCB;
-        newCCB = ExAllocatePool(NonPagedPool,sizeof(VfatCCB));
-        memset(newCCB,0,sizeof(VfatCCB));
-        FileObject->FsContext2 = newCCB;
-        newCCB->pFcb=Fcb;
-        newCCB->PtrFileObject=FileObject;
-        if(AbsFileName)ExFreePool(AbsFileName);
-        return(STATUS_SUCCESS);
-     }
-   }
-   string = FileName;
-   ParentFcb = NULL;
-   Fcb = ExAllocatePool(NonPagedPool, sizeof(VfatFCB));
-   memset(Fcb,0,sizeof(VfatFCB));
-   Fcb->ObjectName=Fcb->PathName;
-   next = &string[0];   
-
-   while (next!=NULL)
-   {
-     *next = '\\';
-     current = next+1;
-     next = wcschr(next+1,'\\');
-     if (next!=NULL)
-       {
-          *next=0;
-       }
-      DPRINT("current '%w'\n",current);
-      Status = FindFile(DeviceExt,Fcb,ParentFcb,current,NULL,NULL);
-      if (Status != STATUS_SUCCESS)
-       {
-          if (Fcb != NULL)
-            ExFreePool(Fcb);
-          if (ParentFcb != NULL)
-            ExFreePool(ParentFcb);
-          if(AbsFileName)
-             ExFreePool(AbsFileName);
-           return(Status);
-       }
-      Temp = Fcb;
-CHECKPOINT;
-      if (ParentFcb == NULL)
-       {
-          Fcb = ExAllocatePool(NonPagedPool,sizeof(VfatFCB));
-          memset(Fcb,0,sizeof(VfatFCB));
-          Fcb->ObjectName=Fcb->PathName;
-       }
-      else
-        Fcb = ParentFcb;
-CHECKPOINT;
-      ParentFcb = Temp;
-   }
-CHECKPOINT;
- FileObject->FsContext =(PVOID) &ParentFcb->NTRequiredFCB;
- newCCB = ExAllocatePool(NonPagedPool,sizeof(VfatCCB));
- memset(newCCB,0,sizeof(VfatCCB));
- FileObject->FsContext2 = newCCB;
- newCCB->pFcb=ParentFcb;
- newCCB->PtrFileObject=FileObject;
- ParentFcb->RefCount++;
- //FIXME : initialize all fields in FCB and CCB
- ParentFcb->nextFcb=pFirstFcb;
- pFirstFcb=ParentFcb;
-   vfat_wcsncpy(ParentFcb->PathName,FileName,MAX_PATH);
- ParentFcb->ObjectName=ParentFcb->PathName+(current-FileName);
- ParentFcb->pDevExt=DeviceExt;
- DPRINT("file open, fcb=%x\n",ParentFcb);
- DPRINT("FileSize %d\n",ParentFcb->entry.FileSize);
- if(Fcb) ExFreePool(Fcb);
- if(AbsFileName)ExFreePool(AbsFileName);
-   return(STATUS_SUCCESS);
- }
- BOOLEAN FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount)
+
+static NTSTATUS
+VfatMount (PVFAT_IRP_CONTEXT IrpContext)
 /*
- * FUNCTION: Tests if the device contains a filesystem that can be mounted 
- *           by this fsd
+ * FUNCTION: Mount the filesystem
  */
 {
-   BootSector* Boot;
+  PDEVICE_OBJECT DeviceObject = NULL;
+  PDEVICE_EXTENSION DeviceExt = NULL;
+  BOOLEAN RecognizedFS;
+  NTSTATUS Status;
+  PVFATFCB Fcb = NULL;
+  PVFATCCB Ccb = NULL;
 
-   Boot = ExAllocatePool(NonPagedPool,512);
+  DPRINT1("VfatMount(IrpContext %x)\n", IrpContext);
 
-   VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)Boot);
+  assert (IrpContext);
 
-   if (strncmp(Boot->SysType,"FAT12",5)==0 ||
-       strncmp(Boot->SysType,"FAT16",5)==0 ||
-       strncmp(((struct _BootSector32 *)(Boot))->SysType,"FAT32",5)==0)
-     {
-       ExFreePool(Boot);
-       return(TRUE);
-     }
-   ExFreePool(Boot);
-   return(FALSE);
-}
-
-NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt,
-                       PDEVICE_OBJECT DeviceToMount)
-/*
- * FUNCTION: Mounts the device
- */
-{
-   DPRINT("Mounting VFAT device...");
-   DPRINT("DeviceExt %x\n",DeviceExt);
-
-   DeviceExt->Boot = ExAllocatePool(NonPagedPool,512);
-   VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)DeviceExt->Boot);
-   
-   DPRINT("DeviceExt->Boot->BytesPerSector %x\n",
-         DeviceExt->Boot->BytesPerSector);
-   
-   DeviceExt->FATStart=DeviceExt->Boot->ReservedSectors;
-   DeviceExt->rootDirectorySectors=
-     (DeviceExt->Boot->RootEntries*32)/DeviceExt->Boot->BytesPerSector;
-   DeviceExt->rootStart=
-     DeviceExt->FATStart+DeviceExt->Boot->FATCount*DeviceExt->Boot->FATSectors;
-   DeviceExt->dataStart=DeviceExt->rootStart+DeviceExt->rootDirectorySectors;
-   DeviceExt->FATEntriesPerSector=DeviceExt->Boot->BytesPerSector/32;
-   DeviceExt->BytesPerCluster = DeviceExt->Boot->SectorsPerCluster *
-                                DeviceExt->Boot->BytesPerSector;
-   
-   if (strncmp(DeviceExt->Boot->SysType,"FAT12",5)==0)
-     {
-       DeviceExt->FatType = FAT12;
-     }
-   else if (strncmp(((struct _BootSector32 *)(DeviceExt->Boot))->SysType,"FAT32",5)==0)
-     {
-      DeviceExt->FatType = FAT32;
-      DeviceExt->rootDirectorySectors=DeviceExt->Boot->SectorsPerCluster;
-      DeviceExt->rootStart=
-             DeviceExt->FATStart+DeviceExt->Boot->FATCount
-             * ((struct _BootSector32 *)( DeviceExt->Boot))->FATSectors32;
-      DeviceExt->dataStart=DeviceExt->rootStart;
-        }
-   else
-     {
-       DeviceExt->FatType = FAT16;
-     }
+  if (IrpContext->DeviceObject != VfatDriverObject->DeviceObject)
+  {
+     // Only allowed on the main device object
+     Status = STATUS_INVALID_DEVICE_REQUEST;
+     goto ByeBye;
+  }
 
-   // with FAT32 it's not a good idea to load always fat in memory
-   // because on a 8GB partition with 2 KO clusters, the fat = 8 MO
-   if(DeviceExt->FatType!=FAT32)
-   {
-    DeviceExt->FAT = ExAllocatePool(NonPagedPool, BLOCKSIZE*DeviceExt->Boot->FATSectors);
-    VFATReadSectors(DeviceToMount, DeviceExt->FATStart, DeviceExt->Boot->FATSectors, (UCHAR *)DeviceExt->FAT);
-   }
-   return STATUS_SUCCESS;
-}
+  Status = VfatHasFileSystem (IrpContext->Stack->Parameters.Mount.DeviceObject, &RecognizedFS);
+  if (!NT_SUCCESS(Status))
+  {
+     goto ByeBye;
+  }
 
-void VFATLoadCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster)
-/*
- * FUNCTION: Load a cluster from the physical device
- */
-{
-   ULONG Sector;
+  if (RecognizedFS == FALSE)
+  {
+     DPRINT("VFAT: Unrecognized Volume\n");
+     Status = STATUS_UNRECOGNIZED_VOLUME;
+     goto ByeBye;
+  }
 
-   DPRINT("VFATLoadCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
-         DeviceExt,Buffer,Cluster);
+  DPRINT("VFAT: Recognized volume\n");
 
-   Sector = ClusterToSector(DeviceExt, Cluster);
+  Status = IoCreateDevice(VfatDriverObject,
+                         sizeof (DEVICE_EXTENSION),
+                         NULL,
+                         FILE_DEVICE_FILE_SYSTEM,
+                         0,
+                         FALSE,
+                         &DeviceObject);
+  if (!NT_SUCCESS(Status))
+  {
+    goto ByeBye;
+  }
 
-   VFATReadSectors(DeviceExt->StorageDevice,
-                  Sector,
-                   DeviceExt->Boot->SectorsPerCluster,
-                  Buffer);
-   DPRINT("Finished VFATReadSectors\n");
-}
+  DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
+  DeviceExt = (PVOID) DeviceObject->DeviceExtension;
+  RtlZeroMemory(DeviceExt, sizeof(DEVICE_EXTENSION));
 
-void VFATWriteCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster)
-/*
- * FUNCTION: Write a cluster to the physical device
- */
-{
-   ULONG Sector;
-   DPRINT("VFATWriteCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
-         DeviceExt,Buffer,Cluster);
-   
-   Sector = ClusterToSector(DeviceExt, Cluster);
-   
-   VFATWriteSectors(DeviceExt->StorageDevice,
-                   Sector,
-                    DeviceExt->Boot->SectorsPerCluster,
-                   Buffer);
-}
+  /* use same vpb as device disk */
+  DeviceObject->Vpb = IrpContext->Stack->Parameters.Mount.DeviceObject->Vpb;
+  Status = VfatMountDevice(DeviceExt, IrpContext->Stack->Parameters.Mount.DeviceObject);
+  if (!NT_SUCCESS(Status))
+  {
+    /* FIXME: delete device object */
+    goto ByeBye;
+  }
 
-NTSTATUS FsdReadFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
-                    PVOID Buffer, ULONG Length, ULONG ReadOffset,
-                    PULONG LengthRead)
-/*
- * FUNCTION: Reads data from a file
- */
-{
-   ULONG CurrentCluster;
-   ULONG FileOffset;
-   ULONG FirstCluster;
-   PVfatFCB  Fcb;
-   PVOID Temp;
-   ULONG TempLength;
-   
-   /* PRECONDITION */
-   assert(DeviceExt != NULL);
-   assert(DeviceExt->BytesPerCluster != 0);
-   assert(FileObject != NULL);
-   assert(FileObject->FsContext != NULL);
-
-   DPRINT("FsdReadFile(DeviceExt %x, FileObject %x, Buffer %x, "
-           "Length %d, ReadOffset %d)\n",DeviceExt,FileObject,Buffer,
-           Length,ReadOffset);
-   
-   Fcb = ((PVfatCCB)(FileObject->FsContext2))->pFcb;
-   if (DeviceExt->FatType == FAT32)
-       CurrentCluster = Fcb->entry.FirstCluster
-                +Fcb->entry.FirstClusterHigh*65536;
-   else
-       CurrentCluster = Fcb->entry.FirstCluster;
-   FirstCluster=CurrentCluster;
-   DPRINT("DeviceExt->BytesPerCluster %x\n",DeviceExt->BytesPerCluster);
-   
-   if (ReadOffset >= Fcb->entry.FileSize
-       && !(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
-     {
-       return(STATUS_END_OF_FILE);
-     }
-   if ((ReadOffset + Length) > Fcb->entry.FileSize
-       && !(Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
-     {
-       Length = Fcb->entry.FileSize - ReadOffset;
-     }
-   *LengthRead = 0;
-   /* FIXME: optimize by remembering the last cluster read and using if possible */
-   Temp = ExAllocatePool(NonPagedPool,DeviceExt->BytesPerCluster);
-   if(!Temp) return STATUS_UNSUCCESSFUL;
-   if (FirstCluster==1)
-   {  //root of FAT16 or FAT12
-     CurrentCluster=DeviceExt->rootStart+ReadOffset
-              /(DeviceExt->BytesPerCluster)*DeviceExt->Boot->SectorsPerCluster;
-   }
-   else
-     for (FileOffset=0; FileOffset < ReadOffset / DeviceExt->BytesPerCluster
-           ; FileOffset++)
-     {
-       CurrentCluster = GetNextCluster(DeviceExt,CurrentCluster);
-     }
-   CHECKPOINT;
-   if ((ReadOffset % DeviceExt->BytesPerCluster)!=0)
-   {
-    if (FirstCluster==1)
-    {
-      VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
-           ,DeviceExt->Boot->SectorsPerCluster,Temp);
-      CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
-    }
-    else
+#if 1
+  DbgPrint("BytesPerSector:     %d\n", DeviceExt->Boot->BytesPerSector);
+  DbgPrint("SectorsPerCluster:  %d\n", DeviceExt->Boot->SectorsPerCluster);
+  DbgPrint("ReservedSectors:    %d\n", DeviceExt->Boot->ReservedSectors);
+  DbgPrint("FATCount:           %d\n", DeviceExt->Boot->FATCount);
+  DbgPrint("RootEntries:        %d\n", DeviceExt->Boot->RootEntries);
+  DbgPrint("Sectors:            %d\n", DeviceExt->Boot->Sectors);
+  DbgPrint("FATSectors:         %d\n", DeviceExt->Boot->FATSectors);
+  DbgPrint("SectorsPerTrack:    %d\n", DeviceExt->Boot->SectorsPerTrack);
+  DbgPrint("Heads:              %d\n", DeviceExt->Boot->Heads);
+  DbgPrint("HiddenSectors:      %d\n", DeviceExt->Boot->HiddenSectors);
+  DbgPrint("SectorsHuge:        %d\n", DeviceExt->Boot->SectorsHuge);
+  DbgPrint("RootStart:          %d\n", DeviceExt->rootStart);
+  DbgPrint("DataStart:          %d\n", DeviceExt->dataStart);
+  if (DeviceExt->FatType == FAT32)
     {
-      VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
-      CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
+      DbgPrint("FATSectors32:       %d\n",
+              ((struct _BootSector32*)(DeviceExt->Boot))->FATSectors32);
+      DbgPrint("RootCluster:        %d\n",
+              ((struct _BootSector32*)(DeviceExt->Boot))->RootCluster);
+      DbgPrint("FSInfoSector:       %d\n",
+              ((struct _BootSector32*)(DeviceExt->Boot))->FSInfoSector);
+      DbgPrint("BootBackup:         %d\n",
+              ((struct _BootSector32*)(DeviceExt->Boot))->BootBackup);
     }
-       TempLength = min(Length,DeviceExt->BytesPerCluster -
-                        (ReadOffset % DeviceExt->BytesPerCluster));
-       
-       memcpy(Buffer, Temp + ReadOffset % DeviceExt->BytesPerCluster,
-              TempLength);
-       
-       (*LengthRead) = (*LengthRead) + TempLength;
-       Length = Length - TempLength;
-       Buffer = Buffer + TempLength;        
-     }
-   CHECKPOINT;
-   while (Length >= DeviceExt->BytesPerCluster)
-   {
-    if (FirstCluster==1)
+#endif
+  DeviceObject->Vpb->Flags |= VPB_MOUNTED;
+  DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject, IrpContext->Stack->Parameters.Mount.DeviceObject);
+
+  DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
+  Fcb = vfatNewFCB(NULL);
+  if (Fcb == NULL)
+  {
+    Status = STATUS_INSUFFICIENT_RESOURCES;
+    goto ByeBye;
+  }
+  Ccb = ExAllocatePoolWithTag (NonPagedPool, sizeof (VFATCCB), TAG_CCB);
+  if (Ccb == NULL)
+  {
+    Status =  STATUS_INSUFFICIENT_RESOURCES;
+    goto ByeBye;
+  }
+  memset(Ccb, 0, sizeof (VFATCCB));
+  DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
+  DeviceExt->FATFileObject->FsContext = (PVOID) &Fcb->RFCB;
+  DeviceExt->FATFileObject->FsContext2 = Ccb;
+  DeviceExt->FATFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers;
+  Ccb->pFcb = Fcb;
+  Ccb->PtrFileObject = DeviceExt->FATFileObject;
+  Fcb->FileObject = DeviceExt->FATFileObject;
+  Fcb->pDevExt = (PDEVICE_EXTENSION)DeviceExt->StorageDevice;
+
+  Fcb->Flags = FCB_IS_FAT;
+
+  if (DeviceExt->Boot->Sectors != 0)
+  {
+    DeviceExt->NumberOfClusters = (DeviceExt->Boot->Sectors - DeviceExt->dataStart)
+                                    / DeviceExt->Boot->SectorsPerCluster + 2;
+  }
+  else
+  {
+    DeviceExt->NumberOfClusters = (DeviceExt->Boot->SectorsHuge - DeviceExt->dataStart)
+                                    / DeviceExt->Boot->SectorsPerCluster + 2;
+  }
+  if (DeviceExt->FatType == FAT32)
+  {
+    Fcb->RFCB.FileSize.QuadPart = ((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32 * BLOCKSIZE;
+    Fcb->RFCB.ValidDataLength.QuadPart = ((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32 * BLOCKSIZE;
+    Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(((struct _BootSector32 *)DeviceExt->Boot)->FATSectors32 * BLOCKSIZE, CACHEPAGESIZE(DeviceExt));
+    Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, CACHEPAGESIZE(DeviceExt));
+  }
+  else
+  {
+    if (DeviceExt->FatType == FAT16)
     {
-      VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
-           ,DeviceExt->Boot->SectorsPerCluster,Buffer);
-      CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
+      Fcb->RFCB.FileSize.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE;
+      Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE;
+      Fcb->RFCB.AllocationSize.QuadPart = ROUND_UP(DeviceExt->Boot->FATSectors * BLOCKSIZE, CACHEPAGESIZE(DeviceExt));
+      Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, CACHEPAGESIZE(DeviceExt));
     }
     else
     {
-      VFATLoadCluster(DeviceExt,Buffer,CurrentCluster);
-      CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
+      Fcb->RFCB.FileSize.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE;
+      Fcb->RFCB.ValidDataLength.QuadPart = DeviceExt->Boot->FATSectors * BLOCKSIZE;
+      Fcb->RFCB.AllocationSize.QuadPart = 2 * PAGESIZE;
+      Status = CcRosInitializeFileCache(DeviceExt->FATFileObject, &Fcb->RFCB.Bcb, 2 * PAGESIZE);
     }
-      if (CurrentCluster == 0xffffffff)
-       {
-          ExFreePool(Temp);
-          return(STATUS_SUCCESS);
-       }
-       
-       (*LengthRead) = (*LengthRead) + DeviceExt->BytesPerCluster;
-       Buffer = Buffer + DeviceExt->BytesPerCluster;
-       Length = Length - DeviceExt->BytesPerCluster;
-     }
-   CHECKPOINT;
-   if (Length > 0)
-     {
-       (*LengthRead) = (*LengthRead) + Length;
-       if (FirstCluster==1)
-         {
-            VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
-                            ,DeviceExt->Boot->SectorsPerCluster,Temp);
-            CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
-         }
-       else
-         {
-            VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
-            CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
-         }
-       memcpy(Buffer, Temp, Length);
-     }
-   ExFreePool(Temp);
-   return(STATUS_SUCCESS);
-}
-
-NTSTATUS FsdWriteFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
-                     PVOID Buffer, ULONG Length, ULONG WriteOffset)
-/*
- * FUNCTION: Writes data to file
- */
-{
-   ULONG CurrentCluster;
-   ULONG FileOffset;
-   ULONG FirstCluster;
-   PVfatFCB  Fcb;
-   PVfatCCB pCcb;
-   PVOID Temp;
-   ULONG TempLength,Length2=Length;
-
-   /* Locate the first cluster of the file */
-   assert(FileObject);
-   pCcb=(PVfatCCB)(FileObject->FsContext2);
-   assert(pCcb);
-   Fcb = pCcb->pFcb;
-   assert(Fcb);
-   if (DeviceExt->FatType == FAT32)
-       CurrentCluster = Fcb->entry.FirstCluster+Fcb->entry.FirstClusterHigh*65536;
-   else
-       CurrentCluster = Fcb->entry.FirstCluster;
-   FirstCluster=CurrentCluster;
-   /* Allocate a buffer to hold 1 cluster of data */
-
-   Temp = ExAllocatePool(NonPagedPool,DeviceExt->BytesPerCluster);
-   assert(Temp);
-
-   /* Find the cluster according to the offset in the file */
-
-   if (CurrentCluster==1)
-   {  //root of FAT16 or FAT12
-     CurrentCluster=DeviceExt->rootStart+WriteOffset
-          /DeviceExt->BytesPerCluster*DeviceExt->Boot->SectorsPerCluster;
-   }
-   else
-   if (CurrentCluster==0)
-   {// file of size 0 : allocate first cluster
-     CurrentCluster=GetNextWriteCluster(DeviceExt,0);
-     if (DeviceExt->FatType == FAT32)
-     {
-       Fcb->entry.FirstClusterHigh=CurrentCluster>>16;
-       Fcb->entry.FirstCluster=CurrentCluster;
-     }
-     else
-       Fcb->entry.FirstCluster=CurrentCluster;
-   }
-   else
-     for (FileOffset=0; FileOffset < WriteOffset / DeviceExt->BytesPerCluster; FileOffset++)
-     {
-       CurrentCluster = GetNextCluster(DeviceExt,CurrentCluster);
-     }
-   CHECKPOINT;
-
-   /*
-      If the offset in the cluster doesn't fall on the cluster boundary then
-      we have to write only from the specified offset
-   */
-
-   if ((WriteOffset % DeviceExt->BytesPerCluster)!=0)
-   {
-   CHECKPOINT;
-     TempLength = min(Length,DeviceExt->BytesPerCluster -
-                        (WriteOffset % DeviceExt->BytesPerCluster));
-     /* Read in the existing cluster data */
-     if (FirstCluster==1)
-       VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
-           ,DeviceExt->Boot->SectorsPerCluster,Temp);
-     else
-       VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
-
-     /* Overwrite the last parts of the data as necessary */
-     memcpy(Temp + (WriteOffset % DeviceExt->BytesPerCluster), Buffer,
-              TempLength);
-
-     /* Write the cluster back */
-     if (FirstCluster==1)
-     {
-       VFATWriteSectors(DeviceExt->StorageDevice,CurrentCluster
-           ,DeviceExt->Boot->SectorsPerCluster,Temp);
-       CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
-     }
-     else
-     {
-       VFATWriteCluster(DeviceExt,Temp,CurrentCluster);
-       CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
-     }
-     Length2 -= TempLength;
-     Buffer = Buffer + TempLength;
-   }
-   CHECKPOINT;
-
-   /* Write the buffer in chunks of 1 cluster */
-
-   while (Length2 >= DeviceExt->BytesPerCluster)
-   {
-   CHECKPOINT;
-     if (CurrentCluster == 0)
-     {
-        ExFreePool(Temp);
-        return(STATUS_UNSUCCESSFUL);
-     }
-     if (FirstCluster==1)
-     {
-       VFATWriteSectors(DeviceExt->StorageDevice,CurrentCluster
-           ,DeviceExt->Boot->SectorsPerCluster,Buffer);
-       CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
-     }
-     else
-     {
-       VFATWriteCluster(DeviceExt,Buffer,CurrentCluster);
-       CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
-     }
-     Buffer = Buffer + DeviceExt->BytesPerCluster;
-     Length2 -= DeviceExt->BytesPerCluster;
-   }
-   CHECKPOINT;
-
-   /* Write the remainder */
-
-   if (Length2 > 0)
-   {
-   CHECKPOINT;
-     if (CurrentCluster == 0)
-     {
-        ExFreePool(Temp);
-        return(STATUS_UNSUCCESSFUL);
-     }
-   CHECKPOINT;
-     /* Read in the existing cluster data */
-     if (FirstCluster==1)
-       VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
-           ,DeviceExt->Boot->SectorsPerCluster,Temp);
-     else
-       VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
-   CHECKPOINT;
-     memcpy(Temp, Buffer, Length2);
-   CHECKPOINT;
-     if (FirstCluster==1)
-     {
-       VFATWriteSectors(DeviceExt->StorageDevice,CurrentCluster
-           ,DeviceExt->Boot->SectorsPerCluster,Temp);
-     }
-     else
-       VFATWriteCluster(DeviceExt,Temp,CurrentCluster);
-   }
-   CHECKPOINT;
-//FIXME : set  last write time and date
-   if(Fcb->entry.FileSize<WriteOffset+Length
-       && !(Fcb->entry.Attrib &FILE_ATTRIBUTE_DIRECTORY))
-   {
-     Fcb->entry.FileSize=WriteOffset+Length;
-     // update entry in directory
-     updEntry(DeviceExt,FileObject);
-   }
-   ExFreePool(Temp);
-   return(STATUS_SUCCESS);
-}
-
-NTSTATUS FsdClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-/*
- * FUNCTION: Close a file
- */
-{
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
-   PFILE_OBJECT FileObject = Stack->FileObject;
-   PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
-   NTSTATUS Status;
-
-   DPRINT("FsdClose(DeviceObject %x, Irp %x)\n",DeviceObject, Irp);
-   
-   Status = FsdCloseFile(DeviceExtension,FileObject);
-
-   Irp->IoStatus.Status = Status;
-   Irp->IoStatus.Information = 0;
-   
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
-   return(Status);
-}
-
-
-NTSTATUS FsdCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-/*
- * FUNCTION: Create or open a file
- */
-{
- PIO_STACK_LOCATION Stack;
- PFILE_OBJECT FileObject;
- NTSTATUS Status=STATUS_SUCCESS;
- PDEVICE_EXTENSION DeviceExt;
- ULONG RequestedDisposition,RequestedOptions;
- PVfatCCB pCcb;
- PVfatFCB pFcb;
-
-   assert(DeviceObject);
-   assert(Irp);
-   if(DeviceObject->Size==sizeof(DEVICE_OBJECT))
-   {// DevieObject represent FileSystem instead of  logical volume
-     DbgPrint("FsdCreate called with file system\n");
-     Irp->IoStatus.Status=Status;
-     Irp->IoStatus.Information=FILE_OPENED;
-     IoCompleteRequest(Irp,IO_NO_INCREMENT);
-     return(Status);
-   }
-   Stack = IoGetCurrentIrpStackLocation(Irp);
-   assert(Stack);
-   RequestedDisposition = ((Stack->Parameters.Create.Options>>24)&0xff);
-   RequestedOptions=Stack->Parameters.Create.Options&FILE_VALID_OPTION_FLAGS;
-   FileObject = Stack->FileObject;
-   DeviceExt = DeviceObject->DeviceExtension;
-   assert(DeviceExt);
-   ExAcquireResourceExclusiveLite(&(DeviceExt->Resource),TRUE);
-   Status = FsdOpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer);
-CHECKPOINT;
-   Irp->IoStatus.Information = 0;
-   if(!NT_SUCCESS(Status))
-   {
-      if(RequestedDisposition==FILE_CREATE
-         ||RequestedDisposition==FILE_OPEN_IF
-         ||RequestedDisposition==FILE_OVERWRITE_IF)
-      {
-CHECKPOINT;
-         Status=addEntry(DeviceExt,FileObject,RequestedOptions
-             ,(Stack->Parameters.Create.FileAttributes & FILE_ATTRIBUTE_VALID_FLAGS));
-         if(NT_SUCCESS(Status))
-           Irp->IoStatus.Information = FILE_CREATED;
-         // FIXME set size if AllocationSize requested
-         // FIXME set extended attributes ?
-         // FIXME set share access
-         // IoSetShareAccess(DesiredAccess,ShareAccess,FileObject
-         //   ,((PVfatCCB)(FileObject->FsContext2))->pFcb->FCBShareAccess);
-      }
-   }
-   else
-   {
-     if(RequestedDisposition==FILE_CREATE)
-     {
-       Irp->IoStatus.Information = FILE_EXISTS;
-       Status=STATUS_OBJECT_NAME_COLLISION;
-     }
-     pCcb=FileObject->FsContext2;
-     pFcb=pCcb->pFcb;
-     if( (RequestedOptions&FILE_NON_DIRECTORY_FILE)
-         && (pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
-     {
-       Status=STATUS_FILE_IS_A_DIRECTORY;
-     }
-     if( (RequestedOptions&FILE_DIRECTORY_FILE)
-         && !(pFcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY))
-     {
-       Status=STATUS_NOT_A_DIRECTORY;
-     }
-     // FIXME : test share access
-     // FIXME : test write access if requested
-     if(!NT_SUCCESS(Status))
-       FsdCloseFile(DeviceExt,FileObject);
-     else Irp->IoStatus.Information = FILE_OPENED;
-     // FIXME : make supersed or overwrite if requested
-   }
-CHECKPOINT;   
-   Irp->IoStatus.Status = Status;
-   
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
-   ExReleaseResourceForThreadLite(&(DeviceExt->Resource),ExGetCurrentResourceThread());
-   return Status;
-}
-
+  }
+  if (!NT_SUCCESS (Status))
+  {
+     DbgPrint ("CcRosInitializeFileCache failed\n");
+     goto ByeBye;
+  }
 
-NTSTATUS FsdWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-/*
- * FUNCTION: Write to a file
- */
-{
-   ULONG Length;
-   PVOID Buffer;
-   ULONG Offset;
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
-   PFILE_OBJECT FileObject = Stack->FileObject;
-   PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
-   NTSTATUS Status;
-   
-   DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
+  DeviceExt->LastAvailableCluster = 0;
+  ExInitializeResourceLite(&DeviceExt->DirResource);
+  ExInitializeResourceLite(&DeviceExt->FatResource);
 
-   Length = Stack->Parameters.Write.Length;
-   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
-   Offset = Stack->Parameters.Write.ByteOffset.u.LowPart;
+  KeInitializeSpinLock(&DeviceExt->FcbListLock);
+  InitializeListHead(&DeviceExt->FcbListHead);
 
-   Status = FsdWriteFile(DeviceExt,FileObject,Buffer,Length,Offset);
+  /* read serial number */
+  if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16)
+    DeviceObject->Vpb->SerialNumber =
+      ((struct _BootSector *) (DeviceExt->Boot))->VolumeID;
+  else if (DeviceExt->FatType == FAT32)
+    DeviceObject->Vpb->SerialNumber =
+      ((struct _BootSector32 *) (DeviceExt->Boot))->VolumeID;
 
-   Irp->IoStatus.Status = Status;
-   Irp->IoStatus.Information = Length;
-   IoCompleteRequest(Irp,IO_NO_INCREMENT);
+  /* read volume label */
+  ReadVolumeLabel(DeviceExt,  DeviceObject->Vpb);
+  Status = STATUS_SUCCESS;
 
-   return(Status);
-}
+ByeBye:
 
-NTSTATUS FsdRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-/*
- * FUNCTION: Read from a file
- */
-{
-   ULONG Length;
-   PVOID Buffer;
-   ULONG Offset;
-   PIO_STACK_LOCATION Stack;
-   PFILE_OBJECT FileObject;
-   PDEVICE_EXTENSION DeviceExt;
-   NTSTATUS Status;
-   ULONG LengthRead;
-   
-   DPRINT("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp);
-
-   /* Precondition / Initialization */
-   assert(Irp != NULL);
-   Stack = IoGetCurrentIrpStackLocation(Irp);
-   assert(Stack != NULL);
-   FileObject = Stack->FileObject;
-   assert(FileObject != NULL);
-   DeviceExt = DeviceObject->DeviceExtension;
-   assert(DeviceExt != NULL);
-
-   Length = Stack->Parameters.Read.Length;
-   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
-   Offset = Stack->Parameters.Read.ByteOffset.u.LowPart;
-   
-   Status = FsdReadFile(DeviceExt,FileObject,Buffer,Length,Offset,
-                       &LengthRead);
-   
-   Irp->IoStatus.Status = Status;
-   Irp->IoStatus.Information = LengthRead;
-   IoCompleteRequest(Irp,IO_NO_INCREMENT);
-
-   return(Status);
+  if (!NT_SUCCESS(Status))
+  {
+     // cleanup
+     if (DeviceExt && DeviceExt->FATFileObject)
+        ObDereferenceObject (DeviceExt->FATFileObject);
+     if (Fcb)
+        ExFreePool(Fcb);
+     if (Ccb)
+        ExFreePool(Ccb);
+     if (DeviceObject)
+       IoDeleteDevice(DeviceObject);
+  }
+  return Status;
 }
 
 
-NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount)
-/*
- * FUNCTION: Mount the filesystem
- */
-{
-   PDEVICE_OBJECT DeviceObject;
-   PDEVICE_EXTENSION DeviceExt;
-      
-   IoCreateDevice(VFATDriverObject,
-                 sizeof(DEVICE_EXTENSION),
-                 NULL,
-                 FILE_DEVICE_FILE_SYSTEM,
-                 0,
-                 FALSE,
-                 &DeviceObject);
-   DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
-   DeviceExt = (PVOID)DeviceObject->DeviceExtension;
-   // use same vpb as device disk
-   DeviceObject->Vpb=DeviceToMount->Vpb;
-   FsdMountDevice(DeviceExt,DeviceToMount);
-   DeviceObject->Vpb->Flags |= VPB_MOUNTED;
-   DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
-                                                         DeviceToMount);
-
-   /* read serial number */
-   if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16)
-       DeviceObject->Vpb->SerialNumber =
-         ((struct _BootSector *)(DeviceExt->Boot))->VolumeID;
-   else if (DeviceExt->FatType == FAT32)
-       DeviceObject->Vpb->SerialNumber =
-         ((struct _BootSector32 *)(DeviceExt->Boot))->VolumeID;
-
-   /* read volume label */
-   ReadVolumeLabel (DeviceExt, DeviceObject->Vpb);
-
-   return(STATUS_SUCCESS);
-}
-
-NTSTATUS FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
 /*
  * FUNCTION: File system control
  */
 {
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
-//   PVPB      vpb = Stack->Parameters.Mount.Vpb;
-   PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
+
    NTSTATUS Status;
 
-//   DPRINT("VFAT FSC\n");
-   DbgPrint("VFAT FSC\n");
+   DPRINT1("VfatFileSystemControl(IrpContext %x)\n", IrpContext);
 
-   /* FIXME: should make sure that this is actually a mount request!  */
+   assert (IrpContext);
 
-   if (FsdHasFileSystem(DeviceToMount))
+   switch (IrpContext->MinorFunction)
      {
-       Status = FsdMount(DeviceToMount);
-     }
-   else
-     {
-        DPRINT("VFAT: Unrecognized Volume\n");
-       Status = STATUS_UNRECOGNIZED_VOLUME;
-     }
-   DPRINT("VFAT File system successfully mounted\n");
-
-   Irp->IoStatus.Status = Status;
-   Irp->IoStatus.Information = 0;
-
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
-   return(Status);
-}
-
-NTSTATUS FsdGetStandardInformation(PVfatFCB FCB, PDEVICE_OBJECT DeviceObject,
-                                   PFILE_STANDARD_INFORMATION StandardInfo)
-/*
- * FUNCTION: Retrieve the standard file information
- */
-{
-  PDEVICE_EXTENSION DeviceExtension;
-  unsigned long AllocSize;
-
-  DeviceExtension = DeviceObject->DeviceExtension;
-  /* PRECONDITION */
-  assert(DeviceExtension != NULL);
-  assert(DeviceExtension->BytesPerCluster != 0);
-  assert(StandardInfo != NULL);
-  assert(FCB != NULL);
-
-  RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION));
-
-  /* Make allocsize a rounded up multiple of BytesPerCluster */
-  AllocSize = ((FCB->entry.FileSize +  DeviceExtension->BytesPerCluster - 1) /
-              DeviceExtension->BytesPerCluster) *
-              DeviceExtension->BytesPerCluster;
-
-  StandardInfo->AllocationSize = RtlConvertUlongToLargeInteger(AllocSize);
-  StandardInfo->EndOfFile      = RtlConvertUlongToLargeInteger(FCB->entry.FileSize);
-  StandardInfo->NumberOfLinks  = 0;
-  StandardInfo->DeletePending  = FALSE;
-  if((FCB->entry.Attrib & 0x10)>0) {
-    StandardInfo->Directory    = TRUE;
-  } else {
-    StandardInfo->Directory    = FALSE;
-  }
-
-  return STATUS_SUCCESS;
-}
-
-NTSTATUS FsdSetPositionInformation(PFILE_OBJECT FileObject,
-                                  PVfatFCB FCB,
-                                  PDEVICE_OBJECT DeviceObject,
-                                   PFILE_POSITION_INFORMATION PositionInfo)
- {
-    DPRINT("FsdSetPositionInformation()\n");
-    
-    DPRINT("PositionInfo %x\n", PositionInfo);
-    DPRINT("Setting position %d\n", PositionInfo->CurrentByteOffset.u.LowPart);
-    memcpy(&FileObject->CurrentByteOffset,&PositionInfo->CurrentByteOffset,
-          sizeof(LARGE_INTEGER));
-    
-    return(STATUS_SUCCESS);
- }
-NTSTATUS FsdGetPositionInformation(PFILE_OBJECT FileObject,
-                                  PVfatFCB FCB,
-                                  PDEVICE_OBJECT DeviceObject,
-                                   PFILE_POSITION_INFORMATION PositionInfo)
- {
-    DPRINT("FsdGetPositionInformation()\n");
-    
-    memcpy(&PositionInfo->CurrentByteOffset, &FileObject->CurrentByteOffset,
-          sizeof(LARGE_INTEGER));
-    DPRINT("Getting position %x\n", PositionInfo->CurrentByteOffset.u.LowPart);
-    return(STATUS_SUCCESS);
- }
-
-NTSTATUS FsdGetBasicInformation(PFILE_OBJECT FileObject,
-                                PVfatFCB FCB,
-                                PDEVICE_OBJECT DeviceObject,
-                                PFILE_BASIC_INFORMATION BasicInfo)
-{
-    DPRINT("FsdGetBasicInformation()\n");
+       case IRP_MN_USER_FS_REQUEST:
+          DPRINT1("VFAT FSC: IRP_MN_USER_FS_REQUEST\n");
+          Status = STATUS_INVALID_DEVICE_REQUEST;
+          break;
 
-    FsdDosDateTimeToFileTime(FCB->entry.CreationDate,FCB->entry.CreationTime,
-        &BasicInfo->CreationTime);
-    FsdDosDateTimeToFileTime(FCB->entry.AccessDate,0,
-        &BasicInfo->LastAccessTime);
-    FsdDosDateTimeToFileTime(FCB->entry.UpdateDate,FCB->entry.UpdateTime,
-        &BasicInfo->LastWriteTime);
-    FsdDosDateTimeToFileTime(FCB->entry.UpdateDate,FCB->entry.UpdateTime,
-        &BasicInfo->ChangeTime);
-
-    BasicInfo->FileAttributes = FCB->entry.Attrib;
-
-    DPRINT("Getting attributes %x\n", BasicInfo->FileAttributes);
-
-    return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS FsdSetDispositionInformation(PFILE_OBJECT FileObject,
-                                      PVfatFCB FCB,
-                                      PDEVICE_OBJECT DeviceObject,
-                                      PFILE_DISPOSITION_INFORMATION DispositionInfo)
-{
-    DPRINT("FsdSetDispositionInformation()\n");
-
-    FileObject->DeletePending = DispositionInfo->DeleteFile;
-   
-    return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS FsdQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-/*
- * FUNCTION: Retrieve the specified file information
- */
-{
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
-   FILE_INFORMATION_CLASS FileInformationClass =
-     Stack->Parameters.QueryFile.FileInformationClass;
-   PFILE_OBJECT FileObject = NULL;
-   PVfatFCB FCB = NULL;
-//   PVfatCCB CCB = NULL;
-
-   NTSTATUS RC = STATUS_SUCCESS;
-   void *SystemBuffer;
-
-   /* PRECONDITION */
-   assert(DeviceObject != NULL);
-   assert(Irp != NULL);
-
-   /* INITIALIZATION */
-   Stack = IoGetCurrentIrpStackLocation(Irp);
-   FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
-   FileObject = Stack->FileObject;
-//   CCB = (PVfatCCB)(FileObject->FsContext2);
-//   FCB = CCB->Buffer; // Should be CCB->FCB???
-   FCB = ((PVfatCCB)(FileObject->FsContext2))->pFcb;
-
-  // FIXME : determine Buffer for result :
-  if (Irp->MdlAddress) 
-    SystemBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
-  else
-    SystemBuffer = Irp->UserBuffer;
-//   SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
-
-   switch(FileInformationClass) {
-      case FileStandardInformation:
-         RC = FsdGetStandardInformation(FCB, DeviceObject, SystemBuffer);
-      break;
-      case FilePositionInformation:
-         RC = FsdGetPositionInformation(FileObject,
-                                       FCB, 
-                                       DeviceObject, 
-                                       SystemBuffer);
-      break;
-      case FileBasicInformation:
-         RC = FsdGetBasicInformation(FileObject,
-                                     FCB, 
-                                     DeviceObject, 
-                                     SystemBuffer);
-      break;
-      default:
-       RC=STATUS_NOT_IMPLEMENTED;
-   }
-
-   Irp->IoStatus.Status = RC;
-   Irp->IoStatus.Information = 0;
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-   return RC;
-}
+       case IRP_MN_MOUNT_VOLUME:
+          Status = VfatMount(IrpContext);
+          break;
 
-NTSTATUS FsdSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-/*
- * FUNCTION: Retrieve the specified file information
- */
-{
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
-   FILE_INFORMATION_CLASS FileInformationClass;
-   PFILE_OBJECT FileObject = NULL;
-   PVfatFCB FCB = NULL;
-//   PVfatCCB CCB = NULL;   
-   NTSTATUS RC = STATUS_SUCCESS;
-   PVOID SystemBuffer;
-
-   /* PRECONDITION */
-   assert(DeviceObject != NULL);
-   assert(Irp != NULL);
-   
-   DPRINT("FsdSetInformation(DeviceObject %x, Irp %x)\n",
-           DeviceObject,Irp);
-   
-   /* INITIALIZATION */
-   Stack = IoGetCurrentIrpStackLocation(Irp);
-   FileInformationClass = Stack->Parameters.SetFile.FileInformationClass;
-   FileObject = Stack->FileObject;
-   FCB = ((PVfatCCB)(FileObject->FsContext2))->pFcb;
-
-   // FIXME : determine Buffer for result :
-  if (Irp->MdlAddress) 
-     SystemBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
-   else
-     SystemBuffer = Irp->UserBuffer;
-   //   SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
-   
-   DPRINT("FileInformationClass %d\n",FileInformationClass);
-   DPRINT("SystemBuffer %x\n",SystemBuffer);
+       case IRP_MN_VERIFY_VOLUME:
+          DPRINT1("VFAT FSC: IRP_MN_VERIFY_VOLUME\n");
+          Status = STATUS_INVALID_DEVICE_REQUEST;
+          break;
 
-   switch(FileInformationClass) 
-     {
-      case FilePositionInformation:
-       RC = FsdSetPositionInformation(FileObject,
-                                      FCB, 
-                                      DeviceObject, 
-                                      SystemBuffer);
-       break;
-      case FileDispositionInformation:
-        RC = FsdSetDispositionInformation(FileObject,
-                                          FCB, 
-                                          DeviceObject, 
-                                          SystemBuffer);
-        break;
-      default:
-       RC = STATUS_NOT_IMPLEMENTED;
+       default:
+          DPRINT1("VFAT FSC: MinorFunction %d\n", IrpContext->MinorFunction);
+          Status = STATUS_INVALID_DEVICE_REQUEST;
+          break;
      }
-   
-   Irp->IoStatus.Status = RC;
-   Irp->IoStatus.Information = 0;
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
-   
-   return RC;
-}
-
-
-
-NTSTATUS FsdGetFsVolumeInformation(PFILE_OBJECT FileObject,
-                                   PVfatFCB FCB,
-                                   PDEVICE_OBJECT DeviceObject,
-                                   PFILE_FS_VOLUME_INFORMATION FsVolumeInfo)
-{
-    DPRINT("FsdGetFsVolumeInformation()\n");
-    DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
-
-    if (!FsVolumeInfo)
-        return(STATUS_SUCCESS);
 
+   IrpContext->Irp->IoStatus.Status = Status;
+   IrpContext->Irp->IoStatus.Information = 0;
 
-    /* valid entries */
-    FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
-    FsVolumeInfo->VolumeLabelLength  = DeviceObject->Vpb->VolumeLabelLength;
-    wcscpy (FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel);
-
-    /* dummy entries */
-    FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
-    FsVolumeInfo->SupportsObjects = FALSE;
-
-    DPRINT("Finished FsdGetFsVolumeInformation()\n");
-
-    return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS FsdGetFsAttributeInformation(PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo)
-{
-    DPRINT("FsdGetFsAttributeInformation()\n");
-    DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
-
-    if (!FsAttributeInfo)
-        return(STATUS_SUCCESS);
-
-    FsAttributeInfo->FileSystemAttributes = FS_CASE_IS_PRESERVED;
-    FsAttributeInfo->MaximumComponentNameLength = 255;
-    FsAttributeInfo->FileSystemNameLength = 3;
-    wcscpy (FsAttributeInfo->FileSystemName, L"FAT");
-
-    DPRINT("Finished FsdGetFsAttributeInformation()\n");
-
-    return(STATUS_SUCCESS);
-}
-
-NTSTATUS FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
-                                 PFILE_FS_SIZE_INFORMATION FsSizeInfo)
-{
-    PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
-
-    DPRINT("FsdGetFsSizeInformation()\n");
-    DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
-
-    if (!FsSizeInfo)
-        return(STATUS_SUCCESS);
-
-    if (DeviceExt->FatType == FAT32)
-    {
-        struct _BootSector32 *BootSect = (struct _BootSector32 *)DeviceExt->Boot;
-
-        if (BootSect->Sectors)
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->Sectors;
-        else
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->SectorsHuge;
-
-        FsSizeInfo->AvailableAllocationUnits.QuadPart =
-            FAT32CountAvailableClusters(DeviceExt);
-
-        FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
-        FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
-    }
-    else
-    {
-        struct _BootSector *BootSect = (struct _BootSector *)DeviceExt->Boot;
-
-        if (BootSect->Sectors)
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->Sectors;
-        else
-            FsSizeInfo->TotalAllocationUnits.QuadPart = BootSect->SectorsHuge;
-
-        if (DeviceExt->FatType == FAT16)
-            FsSizeInfo->AvailableAllocationUnits.QuadPart =
-                FAT16CountAvailableClusters(DeviceExt);
-        else
-            FsSizeInfo->AvailableAllocationUnits.QuadPart =
-                FAT12CountAvailableClusters(DeviceExt);
-
-        FsSizeInfo->SectorsPerAllocationUnit = BootSect->SectorsPerCluster;
-        FsSizeInfo->BytesPerSector = BootSect->BytesPerSector;
-    }
-
-    DPRINT("Finished FsdGetFsSizeInformation()\n");
-
-    return(STATUS_SUCCESS);
-}
-
-
-NTSTATUS FsdQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
-/*
- * FUNCTION: Retrieve the specified file information
- */
-{
-   PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
-   FILE_INFORMATION_CLASS FileInformationClass =
-     Stack->Parameters.QueryVolume.FileInformationClass;
-   PFILE_OBJECT FileObject = NULL;
-   PVfatFCB FCB = NULL;
-//   PVfatCCB CCB = NULL;
-
-   NTSTATUS RC = STATUS_SUCCESS;
-   void *SystemBuffer;
-
-   /* PRECONDITION */
-   assert(DeviceObject != NULL);
-   assert(Irp != NULL);
-
-   DPRINT("FsdQueryVolumeInformation(DeviceObject %x, Irp %x)\n",
-          DeviceObject,Irp);
-
-   /* INITIALIZATION */
-   Stack = IoGetCurrentIrpStackLocation(Irp);
-   FileInformationClass = Stack->Parameters.QueryVolume.FileInformationClass;
-   FileObject = Stack->FileObject;
-//   CCB = (PVfatCCB)(FileObject->FsContext2);
-//   FCB = CCB->Buffer; // Should be CCB->FCB???
-   FCB = ((PVfatCCB)(FileObject->FsContext2))->pFcb;
-
-  // FIXME : determine Buffer for result :
-  if (Irp->MdlAddress) 
-    SystemBuffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
-  else
-    SystemBuffer = Irp->UserBuffer;
-//   SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
-
-   DPRINT("FileInformationClass %d\n",FileInformationClass);
-   DPRINT("SystemBuffer %x\n",SystemBuffer);
-
-   switch (FileInformationClass)
-   {
-      case FileFsVolumeInformation:
-         RC = FsdGetFsVolumeInformation(FileObject,
-                                        FCB,
-                                        DeviceObject,
-                                        SystemBuffer);
-         break;
-
-      case FileFsAttributeInformation:
-         RC = FsdGetFsAttributeInformation(SystemBuffer);
-         break;
-
-      case FileFsSizeInformation:
-         RC = FsdGetFsSizeInformation(DeviceObject, SystemBuffer);
-         break;
-
-      default:
-         RC=STATUS_NOT_IMPLEMENTED;
-   }
-
-   Irp->IoStatus.Status = RC;
-   Irp->IoStatus.Information = 0;
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-   return RC;
+   IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
+   return (Status);
 }
 
 
 NTSTATUS STDCALL
-DriverEntry(PDRIVER_OBJECT _DriverObject, PUNICODE_STRING RegistryPath)
+DriverEntry(PDRIVER_OBJECT _DriverObject,
+           PUNICODE_STRING RegistryPath)
 /*
  * FUNCTION: Called by the system to initalize the driver
  * ARGUMENTS:
@@ -2122,43 +401,52 @@ DriverEntry(PDRIVER_OBJECT _DriverObject, PUNICODE_STRING RegistryPath)
  */
 {
    PDEVICE_OBJECT DeviceObject;
-   NTSTATUS ret;
-   UNICODE_STRING ustr;
-   ANSI_STRING astr;
-   
+   UNICODE_STRING DeviceName;
+   NTSTATUS Status;
+
    DbgPrint("VFAT 0.0.6\n");
-   pFirstFcb=NULL;
-   VFATDriverObject = _DriverObject;
-   
-   RtlInitAnsiString(&astr,"\\Device\\VFAT");
-   RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE);
-   ret = IoCreateDevice(VFATDriverObject,0,&ustr,
-                        FILE_DEVICE_FILE_SYSTEM,0,FALSE,&DeviceObject);
-   if (ret!=STATUS_SUCCESS)
+
+   VfatDriverObject = _DriverObject;
+
+   RtlInitUnicodeString(&DeviceName,
+                       L"\\Device\\Vfat");
+   Status = IoCreateDevice(VfatDriverObject,
+                          0,
+                          &DeviceName,
+                          FILE_DEVICE_FILE_SYSTEM,
+                          0,
+                          FALSE,
+                          &DeviceObject);
+   if (!NT_SUCCESS(Status))
      {
-       return(ret);
+       return (Status);
      }
 
    DeviceObject->Flags = DO_DIRECT_IO;
-   VFATDriverObject->MajorFunction[IRP_MJ_CLOSE] = FsdClose;
-   VFATDriverObject->MajorFunction[IRP_MJ_CREATE] = FsdCreate;
-   VFATDriverObject->MajorFunction[IRP_MJ_READ] = FsdRead;
-   VFATDriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite;
-   VFATDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
-                      FsdFileSystemControl;
-   VFATDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
-                      FsdQueryInformation;
-   VFATDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
-                      FsdSetInformation;
-   VFATDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
-                      FsdDirectoryControl;
-   VFATDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
-                      FsdQueryVolumeInformation;
-
-   VFATDriverObject->DriverUnload = NULL;
-   
+   VfatDriverObject->MajorFunction[IRP_MJ_CLOSE] = VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_CREATE] = VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_READ] = VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_WRITE] = VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
+     VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
+     VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
+     VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
+     VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
+     VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] =
+     VfatBuildRequest;
+   VfatDriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = VfatShutdown;
+   VfatDriverObject->MajorFunction[IRP_MJ_CLEANUP] = VfatBuildRequest;
+
+   VfatDriverObject->DriverUnload = NULL;
+
    IoRegisterFileSystem(DeviceObject);
 
-   return(STATUS_SUCCESS);
+   return STATUS_SUCCESS;
 }
 
+/* EOF */