Put in updated version of bitops header
authorDavid Welch <welch@cwcom.net>
Sat, 11 Dec 1999 21:14:49 +0000 (21:14 +0000)
committerDavid Welch <welch@cwcom.net>
Sat, 11 Dec 1999 21:14:49 +0000 (21:14 +0000)
Corrected bug in loader with mapping sections with zero VirtualSize
Corrected bug in the vfat driver that accessed freed memory
General cleanup of the vfat driver

svn path=/trunk/; revision=857

17 files changed:
reactos/drivers/fs/vfat/create.c [new file with mode: 0644]
reactos/drivers/fs/vfat/dir.c
reactos/drivers/fs/vfat/dirwr.c
reactos/drivers/fs/vfat/fat.c [new file with mode: 0644]
reactos/drivers/fs/vfat/finfo.c [new file with mode: 0644]
reactos/drivers/fs/vfat/iface.c
reactos/drivers/fs/vfat/makefile
reactos/drivers/fs/vfat/rw.c [new file with mode: 0644]
reactos/drivers/fs/vfat/string.c [new file with mode: 0644]
reactos/drivers/fs/vfat/vfat.h
reactos/drivers/fs/vfat/volume.c [new file with mode: 0644]
reactos/include/internal/bitops.h
reactos/include/ntdll/ntdll.h
reactos/lib/ntdll/ldr/utils.c
reactos/ntoskrnl/ntoskrnl.def
reactos/ntoskrnl/ntoskrnl.edf
reactos/ntoskrnl/rtl/interlck.c

diff --git a/reactos/drivers/fs/vfat/create.c b/reactos/drivers/fs/vfat/create.c
new file mode 100644 (file)
index 0000000..88082c0
--- /dev/null
@@ -0,0 +1,658 @@
+/* $Id: create.c,v 1.1 1999/12/11 21:14:48 dwelch Exp $
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/vfat/create.c
+ * PURPOSE:          VFAT Filesystem
+ * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
+
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <wchar.h>
+#include <internal/string.h>
+#include <ddk/ntddk.h>
+#include <ddk/cctypes.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "vfat.h"
+
+/* FUNCTIONS ****************************************************************/
+
+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)
+/*
+ * FUNCTION: Determine if the given directory entry is a vol entry
+ */
+{
+   if( (((FATDirEntry *)Block)[Offset].Attrib)==0x28 ) return TRUE;
+   else return FALSE;
+}
+
+BOOLEAN IsDeletedEntry(PVOID Block, ULONG Offset)
+/*
+ * FUNCTION: Determines if the given entry is a deleted one
+ */
+{
+   /* Checks special character */
+
+   return ((((FATDirEntry *)Block)[Offset].Filename[0] == 0xe5));
+}
+
+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;
+   
+   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]!=' ')
+     {
+       RtlCatAnsiToUnicode(Name,".",1);
+     }
+   RtlCatAnsiToUnicode(Name,test[Offset].Ext,3);
+      
+   *_Offset = Offset;
+   
+   return(TRUE);
+}
+
+NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, PVPB Vpb)
+/*
+ * FUNCTION: Read the volume label
+ */
+{
+   ULONG i = 0;
+   ULONG 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 (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);
+       }
+     }
+     // not found in this sector, try next :
+
+     /* directory can be fragmented although it is best to keep them
+        unfragmented */
+     StartingSector++;
+     if (DeviceExt->FatType ==FAT32)
+     {
+       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);
+       }
+     }
+   }
+   *(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)
+     {
+       CHECKPOINT;
+        TempStr[0] = (WCHAR)'.';
+       TempStr[1] = 0;
+       FileToFind=(PWSTR)&TempStr;
+     }
+   if (Parent != NULL)
+     {
+       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);
+         }
+     }
+   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))
+              {
+                 if(StartSector) *StartSector=StartingSector;
+                 if(Entry) *Entry=i;
+                 ExFreePool(block);
+                 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);
+                      if(StartSector) *StartSector=StartingSector;
+                      if(Entry) *Entry=i;
+                      ExFreePool(block);
+                      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);
+              }
+         }
+     }
+   if(StartSector) *StartSector=StartingSector;
+   if(Entry) *Entry=i;
+   ExFreePool(block);
+   return(STATUS_UNSUCCESSFUL);
+}
+
+
+NTSTATUS FsdCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
+/*
+ * FUNCTION: Closes a file
+ */
+{
+   PVFATFCB pFcb;
+   PVFATCCB pCcb;
+   KIRQL oldIrql;
+   
+   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)
+   {
+      KeAcquireSpinLock(&DeviceExt->FcbListLock, &oldIrql);
+      RemoveEntryList(&pFcb->FcbListEntry);
+      KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
+      ExFreePool(pFcb);
+   }
+   ExFreePool(pCcb);
+   return STATUS_SUCCESS;
+}
+
+NTSTATUS FsdOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, 
+                    PWSTR FileName)
+/*
+ * FUNCTION: Opens a file
+ */
+{
+   PWSTR current = NULL;
+   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;
+   PLIST_ENTRY current_entry;
+   KIRQL oldIrql;
+   
+   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
+  */
+   CHECKPOINT;
+   
+   KeAcquireSpinLock(&DeviceExt->FcbListLock, &oldIrql);
+   current_entry = DeviceExt->FcbListHead.Flink;
+   while (current_entry != &DeviceExt->FcbListHead)
+     {
+       Fcb = CONTAINING_RECORD(current_entry, VFATFCB, FcbListEntry);
+
+       DPRINT("Scanning %x\n", Fcb);
+       DPRINT("Scanning %w\n", Fcb->PathName);
+       
+       if (DeviceExt==Fcb->pDevExt
+           && wstrcmpi(FileName,Fcb->PathName))
+         {
+            Fcb->RefCount++;
+            KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
+            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);
+         }
+       
+       current_entry = current_entry->Flink;
+     }
+   KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
+   
+ CHECKPOINT; 
+
+ string = FileName;
+ ParentFcb = NULL;
+ Fcb = ExAllocatePool(NonPagedPool, sizeof(VFATFCB));
+ memset(Fcb,0,sizeof(VFATFCB));
+ Fcb->ObjectName=Fcb->PathName;
+ next = &string[0];   
+   
+   CHECKPOINT;
+   while (next!=NULL)
+   {
+      CHECKPOINT;
+     *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)
+       {
+          CHECKPOINT;
+          if (Fcb != NULL)
+            ExFreePool(Fcb);
+          if (ParentFcb != NULL)
+            ExFreePool(ParentFcb);
+          if(AbsFileName)
+             ExFreePool(AbsFileName);
+           return(Status);
+       }
+      Temp = Fcb;
+CHECKPOINT;
+      if (ParentFcb == NULL)
+       {
+          CHECKPOINT;
+          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
+   
+   KeAcquireSpinLock(&DeviceExt->FcbListLock, &oldIrql);
+   InsertTailList(&DeviceExt->FcbListHead, &ParentFcb->FcbListEntry);
+   KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
+   
+   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);
+   CHECKPOINT;
+   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))
+   {
+      /* DeviceObject 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->DirResource, 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);
+   ExReleaseResourceLite(&DeviceExt->DirResource);
+   
+   return Status;
+}
+
+
index 18c0cc4..06ba5d3 100644 (file)
@@ -62,7 +62,7 @@ unsigned long vfat_wstrlen(PWSTR s)
 }
 #define DWORD_ROUND_UP(x) ( (((ULONG)(x))%32) ? ((((ULONG)x)&(~0x1f))+0x20) : ((ULONG)x) )
 
-NTSTATUS FsdGetFileNameInformation(PVfatFCB pFcb,
+NTSTATUS FsdGetFileNameInformation(PVFATFCB pFcb,
          PFILE_NAMES_INFORMATION pInfo,ULONG BufferLength)
 {
  ULONG Length;
@@ -76,7 +76,7 @@ NTSTATUS FsdGetFileNameInformation(PVfatFCB pFcb,
   return STATUS_SUCCESS;
 }
 
-NTSTATUS FsdGetFileDirectoryInformation(PVfatFCB pFcb,
+NTSTATUS FsdGetFileDirectoryInformation(PVFATFCB pFcb,
           PDEVICE_EXTENSION DeviceExt,
           PFILE_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
 {
@@ -109,7 +109,7 @@ NTSTATUS FsdGetFileDirectoryInformation(PVfatFCB pFcb,
   return STATUS_SUCCESS;
 }
 
-NTSTATUS FsdGetFileFullDirectoryInformation(PVfatFCB pFcb,
+NTSTATUS FsdGetFileFullDirectoryInformation(PVFATFCB pFcb,
           PDEVICE_EXTENSION DeviceExt,
           PFILE_FULL_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
 {
@@ -142,7 +142,7 @@ NTSTATUS FsdGetFileFullDirectoryInformation(PVfatFCB pFcb,
   return STATUS_SUCCESS;
 }
 
-NTSTATUS FsdGetFileBothInformation(PVfatFCB pFcb,
+NTSTATUS FsdGetFileBothInformation(PVFATFCB pFcb,
           PDEVICE_EXTENSION DeviceExt,
           PFILE_BOTH_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
 {
@@ -193,9 +193,9 @@ NTSTATUS DoQuery(PDEVICE_OBJECT DeviceObject, PIRP Irp,PIO_STACK_LOCATION Stack)
  unsigned char *Buffer = NULL;
  PFILE_NAMES_INFORMATION Buffer0 = NULL;
  PFILE_OBJECT pFileObject = NULL;
- PVfatFCB pFcb;
- VfatFCB tmpFcb;
- PVfatCCB pCcb;
+ PVFATFCB pFcb;
+ VFATFCB tmpFcb;
+ PVFATCCB pCcb;
  PDEVICE_EXTENSION DeviceExt;
  WCHAR star[5],*pCharPattern;
  unsigned long OldEntry,OldSector;
@@ -206,7 +206,7 @@ NTSTATUS DoQuery(PDEVICE_OBJECT DeviceObject, PIRP Irp,PIO_STACK_LOCATION Stack)
   FileInformationClass = Stack->Parameters.QueryDirectory.FileInformationClass;
   FileIndex = Stack->Parameters.QueryDirectory.FileIndex;
   pFileObject = Stack->FileObject;
-  pCcb =(PVfatCCB)pFileObject->FsContext2;
+  pCcb =(PVFATCCB)pFileObject->FsContext2;
   pFcb = pCcb->pFcb;
   if(Stack->Flags & SL_RESTART_SCAN)
   {//FIXME : what is really use of RestartScan ?
index 4bbbec2..e0ef794 100644 (file)
@@ -25,17 +25,17 @@ NTSTATUS updEntry(PDEVICE_EXTENSION DeviceExt,PFILE_OBJECT pFileObject)
 */
 {
  WCHAR DirName[MAX_PATH],*FileName,*PathFileName;
- VfatFCB FileFcb;
+ VFATFCB FileFcb;
  ULONG Sector=0,Entry=0;
  PUCHAR Buffer;
  FATDirEntry * pEntries;
  NTSTATUS status;
  FILE_OBJECT FileObject;
- PVfatCCB pDirCcb;
- PVfatFCB pDirFcb,pFcb;
+ PVFATCCB pDirCcb;
+ PVFATFCB pDirFcb,pFcb;
  short i,posCar,NameLen;
    PathFileName=pFileObject->FileName.Buffer;
-   pFcb=((PVfatCCB)pFileObject->FsContext2)->pFcb;
+   pFcb=((PVFATCCB)pFileObject->FsContext2)->pFcb;
    //find last \ in PathFileName
    posCar=-1;
    for(i=0;PathFileName[i];i++)
@@ -52,7 +52,7 @@ NTSTATUS updEntry(PDEVICE_EXTENSION DeviceExt,PFILE_OBJECT pFileObject)
    memset(&FileObject,0,sizeof(FILE_OBJECT));
 DPRINT("open directory %w for update of entry %w\n",DirName,FileName);
    status=FsdOpenFile(DeviceExt,&FileObject,DirName);
-   pDirCcb=(PVfatCCB)FileObject.FsContext2;
+   pDirCcb=(PVFATCCB)FileObject.FsContext2;
    assert(pDirCcb);
    pDirFcb=pDirCcb->pFcb;
    assert(pDirFcb);
@@ -79,7 +79,7 @@ NTSTATUS addEntry(PDEVICE_EXTENSION DeviceExt
 */
 {
  WCHAR DirName[MAX_PATH],*FileName,*PathFileName;
- VfatFCB DirFcb,FileFcb;
+ VFATFCB DirFcb,FileFcb;
  FATDirEntry FatEntry;
  NTSTATUS status;
  FILE_OBJECT FileObject;
@@ -89,9 +89,11 @@ NTSTATUS addEntry(PDEVICE_EXTENSION DeviceExt
  short nbSlots=0,nbFree=0,i,j,posCar,NameLen;
  PUCHAR Buffer,Buffer2;
  BOOLEAN needTilde=FALSE,needLong=FALSE;
- PVfatFCB newFCB;
- PVfatCCB newCCB;
+ PVFATFCB newFCB;
+ PVFATCCB newCCB;
  ULONG CurrentCluster;
+   KIRQL oldIrql;
+   
    PathFileName=pFileObject->FileName.Buffer;
    DPRINT("addEntry: Pathname=%w\n",PathFileName);
    //find last \ in PathFileName
@@ -297,19 +299,25 @@ DPRINT("i=%d,j=%d,%d,%d\n",i,j,pEntry->Filename[i],FileName[i]);
           ,sizeof(FATDirEntry)*(nbSlots+1),Offset);
    }
    DPRINT("write entry offset %d status=%x\n",Offset,status);
-   newCCB = ExAllocatePool(NonPagedPool,sizeof(VfatCCB));
-   newFCB = ExAllocatePool(NonPagedPool,sizeof(VfatFCB));
-   memset(newCCB,0,sizeof(VfatCCB));
-   memset(newFCB,0,sizeof(VfatFCB));
+   newCCB = ExAllocatePool(NonPagedPool,sizeof(VFATCCB));
+   newFCB = ExAllocatePool(NonPagedPool,sizeof(VFATFCB));
+   memset(newCCB,0,sizeof(VFATCCB));
+   memset(newFCB,0,sizeof(VFATFCB));
    newCCB->pFcb=newFCB;
    newCCB->PtrFileObject=pFileObject;
    newFCB->RefCount++;
-   //FIXME : initialize all fields in FCB and CCB
-   newFCB->nextFcb=pFirstFcb;
+   
+   /* 
+    * FIXME : initialize all fields in FCB and CCB
+    */
+   KeAcquireSpinLock(&DeviceExt->FcbListLock, &oldIrql);
+   InsertTailList(&DeviceExt->FcbListHead, &newFCB->FcbListEntry);
+   KeReleaseSpinLock(&DeviceExt->FcbListLock, oldIrql);
+   
+   
    memcpy(&newFCB->entry,pEntry,sizeof(FATDirEntry));
 DPRINT("new : entry=%11.11s\n",newFCB->entry.Filename);
 DPRINT("new : entry=%11.11s\n",pEntry->Filename);
-   pFirstFcb=newFCB;
    vfat_wcsncpy(newFCB->PathName,PathFileName,MAX_PATH);
    newFCB->ObjectName=newFCB->PathName+(PathFileName-FileName);
    newFCB->pDevExt=DeviceExt;
@@ -322,9 +330,9 @@ DPRINT("new : entry=%11.11s\n",pEntry->Filename);
      status=FsdWriteFile(DeviceExt,pFileObject,pEntry
           ,sizeof(FATDirEntry),0L);
      pEntry->FirstCluster
-            =((VfatCCB *)(FileObject.FsContext2))->pFcb->entry.FirstCluster;
+            =((VFATCCB *)(FileObject.FsContext2))->pFcb->entry.FirstCluster;
      pEntry->FirstClusterHigh
-            =((VfatCCB *)(FileObject.FsContext2))->pFcb->entry.FirstClusterHigh;
+            =((VFATCCB *)(FileObject.FsContext2))->pFcb->entry.FirstClusterHigh;
      memcpy(pEntry->Filename,"..         ",11);
      if(pEntry->FirstCluster==1 && DeviceExt->FatType!=FAT32)
        pEntry->FirstCluster=0;
diff --git a/reactos/drivers/fs/vfat/fat.c b/reactos/drivers/fs/vfat/fat.c
new file mode 100644 (file)
index 0000000..a825d00
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * $Id: fat.c,v 1.1 1999/12/11 21:14:48 dwelch Exp $
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/vfat/fat.c
+ * PURPOSE:          VFAT Filesystem
+ * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
+ *
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <wchar.h>
+#include <internal/string.h>
+#include <ddk/ntddk.h>
+#include <ddk/cctypes.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "vfat.h"
+
+/* 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);
+}
+
+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);
+}
+
+ULONG GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
+/*
+ * FUNCTION: Retrieve the next cluster depending on the FAT type
+ */
+{
+   ULONG NextCluster;
+   
+   DPRINT("GetNextCluster(DeviceExt %x, CurrentCluster %x)\n",
+           DeviceExt,CurrentCluster);
+   
+   ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
+   
+   if (DeviceExt->FatType == FAT16)
+     {
+       NextCluster = Fat16GetNextCluster(DeviceExt, CurrentCluster);
+     }
+   else if (DeviceExt->FatType == FAT32)
+     {
+       NextCluster = Fat32GetNextCluster(DeviceExt, CurrentCluster);
+     }
+   else
+     {
+       NextCluster = Fat12GetNextCluster(DeviceExt, CurrentCluster);
+     }
+   
+   ExReleaseResourceLite(&DeviceExt->FatResource);
+   
+   return(NextCluster);
+}
+
+ULONG FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt)
+/*
+ * FUNCTION: Finds the first available cluster in a FAT16 table
+ */
+{
+   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;
+}
+
+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;
+}
+
+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++)
+     {
+       if(Block[i]==0)
+       {
+         ExFreePool(Block);
+         return (i+sector*128);
+       }
+     }
+   }
+   /* 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;
+   
+   ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
+   
+   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)
+         ulCount++;
+   }
+   
+   ExReleaseResourceLite(&DeviceExt->FatResource);
+   
+   return ulCount;
+}
+
+ULONG FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
+/*
+ * FUNCTION: Counts free clusters in a FAT16 table
+ */
+{
+   PUSHORT Block;
+   ULONG ulCount = 0;
+   ULONG i;
+   
+   ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
+   
+   Block=(PUSHORT)DeviceExt->FAT;
+   for(i=2;i<(DeviceExt->Boot->FATSectors*256);i++)
+     {
+       if(Block[i]==0)
+         ulCount++;
+     }
+   
+   ExReleaseResourceLite(&DeviceExt->FatResource);
+   
+   return ulCount;
+}
+
+ULONG FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt)
+/*
+ * FUNCTION: Counts free clusters in a FAT32 table
+ */
+{
+   ULONG sector;
+   PULONG Block;
+   ULONG ulCount = 0;
+   ULONG i;
+   
+   ExAcquireResourceSharedLite(&DeviceExt->FatResource, TRUE);
+   
+   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);
+   ExReleaseResourceLite(&DeviceExt->FatResource);
+   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 VFATLoadCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster)
+/*
+ * FUNCTION: Load a cluster from the physical device
+ */
+{
+   ULONG Sector;
+
+   DPRINT("VFATLoadCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
+         DeviceExt,Buffer,Cluster);
+
+   Sector = ClusterToSector(DeviceExt, Cluster);
+
+   VFATReadSectors(DeviceExt->StorageDevice,
+                  Sector,
+                   DeviceExt->Boot->SectorsPerCluster,
+                  Buffer);
+   DPRINT("Finished VFATReadSectors\n");
+}
+
+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);
+}
+
diff --git a/reactos/drivers/fs/vfat/finfo.c b/reactos/drivers/fs/vfat/finfo.c
new file mode 100644 (file)
index 0000000..f281e84
--- /dev/null
@@ -0,0 +1,249 @@
+/* $Id: finfo.c,v 1.1 1999/12/11 21:14:48 dwelch Exp $
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/vfat/finfo.c
+ * PURPOSE:          VFAT Filesystem
+ * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
+ *
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <wchar.h>
+#include <internal/string.h>
+#include <ddk/ntddk.h>
+#include <ddk/cctypes.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "vfat.h"
+
+/* FUNCTIONS ****************************************************************/
+
+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");
+
+    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;
+}
+
+NTSTATUS VfatSetInformation(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);
+
+   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;
+     }
+   
+   Irp->IoStatus.Status = RC;
+   Irp->IoStatus.Information = 0;
+   IoCompleteRequest(Irp, IO_NO_INCREMENT);
+   
+   return RC;
+}
+
+
+
index 99413ae..1428bae 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: iface.c,v 1.38 1999/12/04 20:58:42 ea Exp $
+/* $Id: iface.c,v 1.39 1999/12/11 21:14:49 dwelch Exp $
  *
  * COPYRIGHT:        See COPYING in the top level directory
  * PROJECT:          ReactOS kernel
  * 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
-
-*/
-
-/* INCLUDES *****************************************************************/
-
-#include <wchar.h>
-#include <internal/string.h>
-#include <ddk/ntddk.h>
-#include <ddk/cctypes.h>
-
-#define NDEBUG
-#include <internal/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);
-}
-
-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);
-}
-
-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));
-}
-
-ULONG FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt)
-/*
- * FUNCTION: Finds the first available cluster in a FAT16 table
- */
-{
- 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;
-}
-
-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;
-}
-
-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++)
-     {
-       if(Block[i]==0)
-       {
-         ExFreePool(Block);
-         return (i+sector*128);
-       }
-     }
-   }
-   /* 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
-     {
-       Entry = (CBlock[FATOffset] >> 4);
-       Entry |= (CBlock[FATOffset + 1] << 4);
-     }
-     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];
-     }
-   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--];
-    }
-  }
-
-  return(src);
-}
-
-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)
-/*
- * FUNCTION: Determine if the given directory entry is a vol entry
- */
-{
-   if( (((FATDirEntry *)Block)[Offset].Attrib)==0x28 ) return TRUE;
-   else return FALSE;
-}
-
-BOOLEAN IsDeletedEntry(PVOID Block, ULONG Offset)
-/*
- * FUNCTION: Determines if the given entry is a deleted one
- */
-{
-   /* Checks special character */
-
-   return ((((FATDirEntry *)Block)[Offset].Filename[0] == 0xe5));
-}
-
-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]!=' ')
-     {
-       RtlCatAnsiToUnicode(Name,".",1);
-     }
-   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);
-}
-
-
-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 (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);
-       }
-     }
-     // not found in this sector, try next :
-
-     /* directory can be fragmented although it is best to keep them
-        unfragmented */
-     StartingSector++;
-     if (DeviceExt->FatType ==FAT32)
-     {
-       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);
-       }
-     }
-   }
-   *(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)
-     {
-CHECKPOINT;
-        TempStr[0] = (WCHAR)'.';
-       TempStr[1] = 0;
-       FileToFind=&TempStr;
-     }
-   if (Parent != NULL)
-     {
-       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);
-     }
-   }
-   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);
-       }
-     }
-   }
-   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;
-}
-
-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)
-/*
- * FUNCTION: Tests if the device contains a filesystem that can be mounted 
- *           by this fsd
- */
-{
-   BootSector* Boot;
-
-   Boot = ExAllocatePool(NonPagedPool,512);
-
-   VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)Boot);
-
-   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;
-     }
-
-   // 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;
-}
-
-void VFATLoadCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster)
-/*
- * FUNCTION: Load a cluster from the physical device
- */
-{
-   ULONG Sector;
-
-   DPRINT("VFATLoadCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
-         DeviceExt,Buffer,Cluster);
-
-   Sector = ClusterToSector(DeviceExt, Cluster);
-
-   VFATReadSectors(DeviceExt->StorageDevice,
-                  Sector,
-                   DeviceExt->Boot->SectorsPerCluster,
-                  Buffer);
-   DPRINT("Finished VFATReadSectors\n");
-}
-
-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);
-}
-
-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 (Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
-     {
-       return(STATUS_FILE_IS_A_DIRECTORY);
-     }
-   
-   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
-    {
-      VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
-      CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
-    }
-       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)
-    {
-      VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
-           ,DeviceExt->Boot->SectorsPerCluster,Buffer);
-      CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
-    }
-    else
-    {
-      VFATLoadCluster(DeviceExt,Buffer,CurrentCluster);
-      CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
-    }
-      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 */
+ *    ??           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
+ *
+ */
 
-   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;
+/* INCLUDES *****************************************************************/
 
-   /* Write the remainder */
+#include <wchar.h>
+#include <internal/string.h>
+#include <ddk/ntddk.h>
+#include <ddk/cctypes.h>
 
-   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);
-}
+#define NDEBUG
+#include <internal/debug.h>
 
-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;
+#include "vfat.h"
 
-   DPRINT("FsdClose(DeviceObject %x, Irp %x)\n",DeviceObject, Irp);
-   
-   Status = FsdCloseFile(DeviceExtension,FileObject);
+/* GLOBALS *****************************************************************/
 
-   Irp->IoStatus.Status = Status;
-   Irp->IoStatus.Information = 0;
-   
-   IoCompleteRequest(Irp, IO_NO_INCREMENT);
-   return(Status);
-}
+static PDRIVER_OBJECT VfatDriverObject;
 
+/* FUNCTIONS ****************************************************************/
 
-NTSTATUS FsdCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+BOOLEAN FsdHasFileSystem(PDEVICE_OBJECT DeviceToMount)
 /*
- * FUNCTION: Create or open a file
+ * FUNCTION: Tests if the device contains a filesystem that can be mounted 
+ *           by this fsd
  */
 {
- PIO_STACK_LOCATION Stack;
- PFILE_OBJECT FileObject;
- NTSTATUS Status=STATUS_SUCCESS;
- PDEVICE_EXTENSION DeviceExt;
- ULONG RequestedDisposition,RequestedOptions;
- PVfatCCB pCcb;
- PVfatFCB pFcb;
+   BootSector* Boot;
 
-   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))
+   Boot = ExAllocatePool(NonPagedPool,512);
+
+   VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)Boot);
+
+   if (strncmp(Boot->SysType,"FAT12",5)==0 ||
+       strncmp(Boot->SysType,"FAT16",5)==0 ||
+       strncmp(((struct _BootSector32 *)(Boot))->SysType,"FAT32",5)==0)
      {
-       Status=STATUS_NOT_A_DIRECTORY;
+       ExFreePool(Boot);
+       return(TRUE);
      }
-     // 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;
+   ExFreePool(Boot);
+   return(FALSE);
 }
 
-
-NTSTATUS FsdWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt,
+                       PDEVICE_OBJECT DeviceToMount)
 /*
- * FUNCTION: Write to a file
+ * FUNCTION: Mounts the device
  */
 {
-   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);
-
-   Length = Stack->Parameters.Write.Length;
-   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
-   Offset = Stack->Parameters.Write.ByteOffset.u.LowPart;
-
-   Status = FsdWriteFile(DeviceExt,FileObject,Buffer,Length,Offset);
-
-   Irp->IoStatus.Status = Status;
-   Irp->IoStatus.Information = Length;
-   IoCompleteRequest(Irp,IO_NO_INCREMENT);
-
-   return(Status);
-}
+   DPRINT("Mounting VFAT device...");
+   DPRINT("DeviceExt %x\n",DeviceExt);
 
-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;
+   DeviceExt->Boot = ExAllocatePool(NonPagedPool,512);
+   VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)DeviceExt->Boot);
    
-   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;
+   DPRINT("DeviceExt->Boot->BytesPerSector %x\n",
+         DeviceExt->Boot->BytesPerSector);
    
-   Status = FsdReadFile(DeviceExt,FileObject,Buffer,Length,Offset,
-                       &LengthRead);
+   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;
    
-   Irp->IoStatus.Status = Status;
-   Irp->IoStatus.Information = LengthRead;
-   IoCompleteRequest(Irp,IO_NO_INCREMENT);
+   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;
+     }
 
-   return(Status);
+   // 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;
 }
 
-
 NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount)
 /*
  * FUNCTION: Mount the filesystem
@@ -1663,7 +122,7 @@ NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount)
    PDEVICE_OBJECT DeviceObject;
    PDEVICE_EXTENSION DeviceExt;
       
-   IoCreateDevice(VFATDriverObject,
+   IoCreateDevice(VfatDriverObject,
                  sizeof(DEVICE_EXTENSION),
                  NULL,
                  FILE_DEVICE_FILE_SYSTEM,
@@ -1678,7 +137,12 @@ NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount)
    DeviceObject->Vpb->Flags |= VPB_MOUNTED;
    DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject,
                                                          DeviceToMount);
-
+   ExInitializeResourceLite(&DeviceExt->DirResource);
+   ExInitializeResourceLite(&DeviceExt->FatResource);
+   
+   KeInitializeSpinLock(&DeviceExt->FcbListLock);
+   InitializeListHead(&DeviceExt->FcbListHead);
+   
    /* read serial number */
    if (DeviceExt->FatType == FAT12 || DeviceExt->FatType == FAT16)
        DeviceObject->Vpb->SerialNumber =
@@ -1726,399 +190,8 @@ NTSTATUS FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
    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");
-
-    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;
-}
-
-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);
-
-   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;
-     }
-   
-   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);
-
-
-    /* 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;
-}
-
-
-NTSTATUS STDCALL
-DriverEntry(PDRIVER_OBJECT _DriverObject, PUNICODE_STRING RegistryPath)
+NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT _DriverObject, 
+                            PUNICODE_STRING RegistryPath)
 /*
  * FUNCTION: Called by the system to initalize the driver
  * ARGUMENTS:
@@ -2129,16 +202,14 @@ DriverEntry(PDRIVER_OBJECT _DriverObject, PUNICODE_STRING RegistryPath)
 {
    PDEVICE_OBJECT DeviceObject;
    NTSTATUS ret;
-   UNICODE_STRING ustr;
-   ANSI_STRING astr;
+   UNICODE_STRING DeviceName;
    
    DbgPrint("VFAT 0.0.6\n");
-   pFirstFcb=NULL;
-   VFATDriverObject = _DriverObject;
+
+   VfatDriverObject = _DriverObject;
    
-   RtlInitAnsiString(&astr,"\\Device\\VFAT");
-   RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE);
-   ret = IoCreateDevice(VFATDriverObject,0,&ustr,
+   RtlInitUnicodeString(&DeviceName, L"\\Device\\Vfat");
+   ret = IoCreateDevice(VfatDriverObject,0,&DeviceName,
                         FILE_DEVICE_FILE_SYSTEM,0,FALSE,&DeviceObject);
    if (ret!=STATUS_SUCCESS)
      {
@@ -2146,22 +217,22 @@ DriverEntry(PDRIVER_OBJECT _DriverObject, PUNICODE_STRING RegistryPath)
      }
 
    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] =
+   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] =
+   VfatDriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
                       FsdQueryInformation;
-   VFATDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
-                      FsdSetInformation;
-   VFATDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
+   VfatDriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] =
+                      VfatSetInformation;
+   VfatDriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
                       FsdDirectoryControl;
-   VFATDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
-                      FsdQueryVolumeInformation;
+   VfatDriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
+                      VfatQueryVolumeInformation;
 
-   VFATDriverObject->DriverUnload = NULL;
+   VfatDriverObject->DriverUnload = NULL;
    
    IoRegisterFileSystem(DeviceObject);
 
index d3cdb8b..725d281 100644 (file)
@@ -1,10 +1,11 @@
-# $Id: makefile,v 1.11 1999/12/04 20:58:44 ea Exp $
+# $Id: makefile,v 1.12 1999/12/11 21:14:49 dwelch Exp $
 #
 #
 TARGET=vfatfs
 
-#OBJECTS = blockdev.o dir.o dirwr.o iface.o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
-OBJECTS = blockdev.o dir.o dirwr.o iface.o ../../../ntoskrnl/ntoskrnl.a
+OBJECTS = blockdev.o dir.o dirwr.o iface.o string.o fat.o rw.o finfo.o \
+          volume.o create.o
+LIBS = ../../../ntoskrnl/ntoskrnl.a
 
 BASE_CFLAGS = -I../../../include
 
@@ -24,7 +25,7 @@ ifeq ($(DOSCLI),yes)
        - $(RM) temp.exp
        - $(RM) $(TARGET).sys
 else
-       - $(RM) blockdev.o dir.o dirwr.o iface.o $(TARGET).coff junk.tmp base.tmp temp.exp $(TARGET).sys
+       - $(RM) $(OBJECTS) $(TARGET).coff junk.tmp base.tmp temp.exp $(TARGET).sys
 endif
 
 .phony: clean
@@ -47,7 +48,7 @@ else
        $(CP) $(TARGET).sys ../../../$(DIST_DIR)/drivers/$(TARGET).sys
 endif
 
-$(TARGET).sys: $(OBJECTS)
+$(TARGET).sys: $(OBJECTS) $(LIBS)
        $(CC) \
                -specs=../../svc_specs \
                -mdll \
@@ -57,7 +58,7 @@ $(TARGET).sys: $(OBJECTS)
                -Wl,--defsym,_etext=etext \
                -Wl,--base-file,base.tmp \
                -Wl,"-h vfatfs.sys" \
-               $(OBJECTS)
+               $(OBJECTS) $(LIBS)
        - $(RM) junk.tmp
        $(DLLTOOL) \
                --dllname $(TARGET).sys \
@@ -74,8 +75,9 @@ $(TARGET).sys: $(OBJECTS)
                -specs=../../svc_specs \
                -mdll \
                -o $(TARGET).sys \
-               $(OBJECTS)
+               $(OBJECTS) $(LIBS)
        - $(RM) temp.exp
 
 
+WARNINGS_ARE_ERRORS = yes
 include ../../../rules.mak
diff --git a/reactos/drivers/fs/vfat/rw.c b/reactos/drivers/fs/vfat/rw.c
new file mode 100644 (file)
index 0000000..24ad20d
--- /dev/null
@@ -0,0 +1,385 @@
+/* $Id: rw.c,v 1.1 1999/12/11 21:14:49 dwelch Exp $
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/vfat/rw.c
+ * PURPOSE:          VFAT Filesystem
+ * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
+ *
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <wchar.h>
+#include <internal/string.h>
+#include <ddk/ntddk.h>
+#include <ddk/cctypes.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "vfat.h"
+
+/* FUNCTIONS ****************************************************************/
+
+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 (Fcb->entry.Attrib & FILE_ATTRIBUTE_DIRECTORY)
+     {
+       return(STATUS_FILE_IS_A_DIRECTORY);
+     }
+   
+   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
+    {
+      VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
+      CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
+    }
+       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)
+    {
+      VFATReadSectors(DeviceExt->StorageDevice,CurrentCluster
+           ,DeviceExt->Boot->SectorsPerCluster,Buffer);
+      CurrentCluster += DeviceExt->Boot->SectorsPerCluster;
+    }
+    else
+    {
+      VFATLoadCluster(DeviceExt,Buffer,CurrentCluster);
+      CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster);
+    }
+      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 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);
+
+   Length = Stack->Parameters.Write.Length;
+   Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+   Offset = Stack->Parameters.Write.ByteOffset.u.LowPart;
+
+   Status = FsdWriteFile(DeviceExt,FileObject,Buffer,Length,Offset);
+
+   Irp->IoStatus.Status = Status;
+   Irp->IoStatus.Information = Length;
+   IoCompleteRequest(Irp,IO_NO_INCREMENT);
+
+   return(Status);
+}
+
+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);
+}
+
+
diff --git a/reactos/drivers/fs/vfat/string.c b/reactos/drivers/fs/vfat/string.c
new file mode 100644 (file)
index 0000000..2e5b4f3
--- /dev/null
@@ -0,0 +1,178 @@
+/* $Id: string.c,v 1.1 1999/12/11 21:14:49 dwelch Exp $
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/vfat/string.c
+ * PURPOSE:          VFAT Filesystem
+ * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
+ *
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <wchar.h>
+#include <internal/string.h>
+#include <ddk/ntddk.h>
+#include <ddk/cctypes.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "vfat.h"
+
+/* FUNCTIONS ****************************************************************/
+
+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];
+     }
+   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(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--];
+    }
+  }
+
+  return(src);
+}
+
+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);
+}
+
index 911576e..c151b38 100644 (file)
@@ -1,9 +1,4 @@
-/* $Id: vfat.h,v 1.14 1999/12/04 20:58:44 ea Exp $ */
-
-#include <wchar.h>
-
-
-
+/* $Id: vfat.h,v 1.15 1999/12/11 21:14:49 dwelch Exp $ */
 
 struct _BootSector { 
   unsigned char  magic0, res0, magic1;
@@ -77,7 +72,12 @@ typedef struct _slot slot;
 
 typedef struct
 {
-  ERESOURCE Resource;
+   ERESOURCE DirResource;
+   ERESOURCE FatResource;
+   
+   KSPIN_LOCK FcbListLock;
+   LIST_ENTRY FcbListHead;
+   
    PDEVICE_OBJECT StorageDevice;
    BootSector *Boot;
    int rootDirectorySectors, FATStart, rootStart, dataStart;
@@ -85,6 +85,7 @@ typedef struct
    ULONG BytesPerCluster;
    ULONG FatType;
    unsigned char* FAT;
+   
 } DEVICE_EXTENSION, *PDEVICE_EXTENSION;
 
 typedef struct _FSRTL_COMMON_FCB_HEADER{
@@ -105,8 +106,7 @@ typedef struct _SFsdNTRequiredFCB {
   ERESOURCE               PagingIoResource;
 } SFsdNTRequiredFCB, *PtrSFsdNTRequiredFCB;
 
-struct _VfatFCB;
-typedef struct _VfatFCB
+typedef struct _VFATFCB
 {
   SFsdNTRequiredFCB     NTRequiredFCB;
    FATDirEntry entry;
@@ -114,20 +114,20 @@ typedef struct _VfatFCB
    WCHAR PathName[MAX_PATH];// path+filename 260 max
    long RefCount;
    PDEVICE_EXTENSION pDevExt;
-   struct _VfatFCB * nextFcb, *prevFcb;
-   struct _VfatFCB * parentFcb;
-} VfatFCB, *PVfatFCB;
+   LIST_ENTRY FcbListEntry;
+   struct _VFATFCB * parentFcb;
+} VFATFCB, *PVFATFCB;
 
-typedef struct
+typedef struct _VFATCCB
 {
-  VfatFCB *   pFcb;
+  VFATFCB *   pFcb;
   LIST_ENTRY     NextCCB;
   PFILE_OBJECT   PtrFileObject;
   LARGE_INTEGER  CurrentByteOffset;
   ULONG StartSector; // for DirectoryControl
   ULONG StartEntry;  //for DirectoryControl
 //    PSTRING DirectorySearchPattern;// for DirectoryControl ?
-} VfatCCB, *PVfatCCB;
+} VFATCCB, *PVFATCCB;
 
 
 #define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry))
@@ -147,9 +147,6 @@ typedef struct __DOSDATE
    WORD Year:5;
 } DOSDATE, *PDOSDATE;
 
-
-extern PVfatFCB pFirstFcb;
-
 // functions called by i/o manager :
 NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT _DriverObject,PUNICODE_STRING RegistryPath);
 NTSTATUS FsdDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
@@ -176,10 +173,10 @@ BOOLEAN VFATWriteSectors(IN PDEVICE_OBJECT pDeviceObject,
 BOOL FsdDosDateTimeToFileTime(WORD wDosDate,WORD wDosTime, TIME *FileTime);
 
 //internal functions in iface.c :
-NTSTATUS FindFile(PDEVICE_EXTENSION DeviceExt, PVfatFCB Fcb,
-          PVfatFCB Parent, PWSTR FileToFind,ULONG *StartSector,ULONG *Entry);
+NTSTATUS FindFile(PDEVICE_EXTENSION DeviceExt, PVFATFCB Fcb,
+          PVFATFCB Parent, PWSTR FileToFind,ULONG *StartSector,ULONG *Entry);
 NTSTATUS FsdCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject);
-NTSTATUS FsdGetStandardInformation(PVfatFCB FCB, PDEVICE_OBJECT DeviceObject,
+NTSTATUS FsdGetStandardInformation(PVFATFCB FCB, PDEVICE_OBJECT DeviceObject,
                                    PFILE_STANDARD_INFORMATION StandardInfo);
 NTSTATUS FsdOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, 
              PWSTR FileName);
@@ -200,7 +197,41 @@ NTSTATUS addEntry(PDEVICE_EXTENSION DeviceExt
 NTSTATUS updEntry(PDEVICE_EXTENSION DeviceExt,PFILE_OBJECT pFileObject);
 
 
-//FIXME : following defines must be removed
-//FIXME   when this functions will work.
-#define ExAcquireResourceExclusiveLite(x,y) {}
-#define ExReleaseResourceForThreadLite(x,y) {}
+
+
+/*
+ * String functions
+ */
+void RtlAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length);
+void RtlCatAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length);
+void vfat_initstr(wchar_t *wstr, ULONG wsize);
+wchar_t * vfat_wcsncat(wchar_t * dest, const wchar_t * src,size_t wstart, size_t wcount);
+wchar_t * vfat_wcsncpy(wchar_t * dest, const wchar_t *src,size_t wcount);
+wchar_t * vfat_movstr(wchar_t *src, ULONG dpos, ULONG spos, ULONG len);
+BOOLEAN wstrcmpi(PWSTR s1, PWSTR s2);
+BOOLEAN wstrcmpjoki(PWSTR s1, PWSTR s2);
+
+/*
+ * functions from fat.c
+ */
+ULONG ClusterToSector(PDEVICE_EXTENSION DeviceExt, ULONG Cluster);
+ULONG GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster);
+VOID VFATLoadCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster);
+ULONG FAT12CountAvailableClusters(PDEVICE_EXTENSION DeviceExt);
+ULONG FAT16CountAvailableClusters(PDEVICE_EXTENSION DeviceExt);
+ULONG FAT32CountAvailableClusters(PDEVICE_EXTENSION DeviceExt);
+
+/*
+ * functions from volume.c
+ */
+NTSTATUS VfatQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+
+/*
+ * functions from finfo.c
+ */
+NTSTATUS VfatSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+
+/*
+ * From create.c
+ */
+NTSTATUS ReadVolumeLabel(PDEVICE_EXTENSION DeviceExt, PVPB Vpb);
diff --git a/reactos/drivers/fs/vfat/volume.c b/reactos/drivers/fs/vfat/volume.c
new file mode 100644 (file)
index 0000000..03b05de
--- /dev/null
@@ -0,0 +1,189 @@
+/* $Id: volume.c,v 1.1 1999/12/11 21:14:49 dwelch Exp $
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             services/fs/vfat/volume.c
+ * PURPOSE:          VFAT Filesystem
+ * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include <wchar.h>
+#include <internal/string.h>
+#include <ddk/ntddk.h>
+#include <ddk/cctypes.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "vfat.h"
+
+/* FUNCTIONS ****************************************************************/
+
+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);
+
+
+    /* 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 VfatQueryVolumeInformation(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;
+}
+
+
index 460c270..08df0f2 100644 (file)
@@ -4,9 +4,6 @@
 /*
  * Copyright 1992, Linus Torvalds.
  */
-/*
- * Reused for the ReactOS kernel by David Welch (1998)
- */
 
 /*
  * These have to be done with inline assembly: that way the bit-setting
 
 #ifdef __SMP__
 #define LOCK_PREFIX "lock ; "
-#define SMPVOL volatile
 #else
 #define LOCK_PREFIX ""
-#define SMPVOL
 #endif
 
+/*
+ * Function prototypes to keep gcc -Wall happy
+ */
+extern void set_bit(int nr, volatile void * addr);
+extern void clear_bit(int nr, volatile void * addr);
+extern void change_bit(int nr, volatile void * addr);
+extern int test_and_set_bit(int nr, volatile void * addr);
+extern int test_and_clear_bit(int nr, volatile void * addr);
+extern int test_and_change_bit(int nr, volatile void * addr);
+extern int __constant_test_bit(int nr, const volatile void * addr);
+extern int __test_bit(int nr, volatile void * addr);
+extern int find_first_zero_bit(void * addr, unsigned size);
+extern int find_next_zero_bit (void * addr, int size, int offset);
+extern unsigned long ffz(unsigned long word);
+
 /*
  * Some hacks to defeat gcc over-optimizations..
  */
 struct __dummy { unsigned long a[100]; };
-#define ADDR (*(struct __dummy *) addr)
-#define CONST_ADDR (*(const struct __dummy *) addr)
+#define ADDR (*(volatile struct __dummy *) addr)
+#define CONST_ADDR (*(volatile const struct __dummy *) addr)
 
-extern __inline__ int set_bit(int nr, SMPVOL void * addr)
+extern __inline__ void set_bit(int nr, volatile void * addr)
+{
+       __asm__ __volatile__( LOCK_PREFIX
+               "btsl %1,%0"
+               :"=m" (ADDR)
+               :"Ir" (nr));
+}
+
+extern __inline__ void clear_bit(int nr, volatile void * addr)
+{
+       __asm__ __volatile__( LOCK_PREFIX
+               "btrl %1,%0"
+               :"=m" (ADDR)
+               :"Ir" (nr));
+}
+
+extern __inline__ void change_bit(int nr, volatile void * addr)
+{
+       __asm__ __volatile__( LOCK_PREFIX
+               "btcl %1,%0"
+               :"=m" (ADDR)
+               :"Ir" (nr));
+}
+
+extern __inline__ int test_and_set_bit(int nr, volatile void * addr)
 {
        int oldbit;
 
-       __asm__ __volatile__(LOCK_PREFIX
+       __asm__ __volatile__( LOCK_PREFIX
                "btsl %2,%1\n\tsbbl %0,%0"
                :"=r" (oldbit),"=m" (ADDR)
-               :"ir" (nr));
+               :"Ir" (nr));
        return oldbit;
 }
 
-extern __inline__ int clear_bit(int nr, SMPVOL void * addr)
+extern __inline__ int test_and_clear_bit(int nr, volatile void * addr)
 {
        int oldbit;
 
-       __asm__ __volatile__(LOCK_PREFIX
+       __asm__ __volatile__( LOCK_PREFIX
                "btrl %2,%1\n\tsbbl %0,%0"
                :"=r" (oldbit),"=m" (ADDR)
-               :"ir" (nr));
+               :"Ir" (nr));
        return oldbit;
 }
 
-extern __inline__ int change_bit(int nr, SMPVOL void * addr)
+extern __inline__ int test_and_change_bit(int nr, volatile void * addr)
 {
        int oldbit;
 
-       __asm__ __volatile__(LOCK_PREFIX
+       __asm__ __volatile__( LOCK_PREFIX
                "btcl %2,%1\n\tsbbl %0,%0"
                :"=r" (oldbit),"=m" (ADDR)
-               :"ir" (nr));
+               :"Ir" (nr));
        return oldbit;
 }
 
 /*
  * This routine doesn't need to be atomic.
  */
-extern __inline__ int test_bit(int nr, const SMPVOL void * addr)
+extern __inline__ int __constant_test_bit(int nr, const volatile void * addr)
 {
-       return ((1UL << (nr & 31)) & (((const unsigned int *) addr)[nr >> 5])) != 0;
+       return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
+}
+
+extern __inline__ int __test_bit(int nr, volatile void * addr)
+{
+       int oldbit;
+
+       __asm__ __volatile__(
+               "btl %2,%1\n\tsbbl %0,%0"
+               :"=r" (oldbit)
+               :"m" (ADDR),"Ir" (nr));
+       return oldbit;
 }
 
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ __constant_test_bit((nr),(addr)) : \
+ __test_bit((nr),(addr)))
+
 /*
  * Find-bit routines..
  */
 extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
 {
+       int d0, d1, d2;
        int res;
 
        if (!size)
@@ -92,9 +143,8 @@ extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
                "1:\tsubl %%ebx,%%edi\n\t"
                "shll $3,%%edi\n\t"
                "addl %%edi,%%edx"
-               :"=d" (res)
-               :"c" ((size + 31) >> 5), "D" (addr), "b" (addr)
-               :"ax", "cx", "di");
+               :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+               :"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
        return res;
 }
 
@@ -137,4 +187,50 @@ extern __inline__ unsigned long ffz(unsigned long word)
        return word;
 }
 
+#ifdef __KERNEL__
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+
+extern __inline__ int ffs(int x)
+{
+       int r;
+
+       __asm__("bsfl %1,%0\n\t"
+               "jnz 1f\n\t"
+               "movl $-1,%0\n"
+               "1:" : "=r" (r) : "g" (x));
+       return r+1;
+}
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
+
+#ifdef __KERNEL__
+
+#define ext2_set_bit                 test_and_set_bit
+#define ext2_clear_bit               test_and_clear_bit
+#define ext2_test_bit                test_bit
+#define ext2_find_first_zero_bit     find_first_zero_bit
+#define ext2_find_next_zero_bit      find_next_zero_bit
+
+/* Bitmap functions for the minix filesystem.  */
+#define minix_set_bit(nr,addr) test_and_set_bit(nr,addr)
+#define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
 #endif /* _I386_BITOPS_H */
index 3d0dde7..d34ef02 100644 (file)
@@ -8,6 +8,8 @@ extern void dprintf(char* fmt,...);
 #define DPRINT(args...) do { dprintf("(NTDLL:%s:%d) ",__FILE__,__LINE__); dprintf(args); } while(0);
 #endif
 
+#define DPRINT1(args...) do { dprintf("(NTDLL:%s:%d) ",__FILE__,__LINE__); dprintf(args); } while(0);
+
 #define ROUNDUP(a,b)   ((((a)+(b)-1)/(b))*(b))
 #define ROUNDDOWN(a,b) (((a)/(b))*(b))
 
index 21ac80f..27d64e9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: utils.c,v 1.18 1999/12/09 19:14:45 ekohl Exp $
+/* $Id: utils.c,v 1.19 1999/12/11 21:14:47 dwelch Exp $
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -367,49 +367,50 @@ static NTSTATUS LdrFindDll(PDLL* Dll, PCHAR Name)
  * NOTE
  *
  */
-NTSTATUS
-LdrMapSections (
-       HANDLE                  ProcessHandle,
-       PVOID                   ImageBase,
-       HANDLE                  SectionHandle,
-       PIMAGE_NT_HEADERS       NTHeaders
-       )
+NTSTATUS LdrMapSections(HANDLE                 ProcessHandle,
+                       PVOID                   ImageBase,
+                       HANDLE                  SectionHandle,
+                       PIMAGE_NT_HEADERS       NTHeaders)
 {
-       ULONG           i;
-       NTSTATUS        Status;
-
-
-       for (   i = 0;
-               (i < NTHeaders->FileHeader.NumberOfSections);
-               i++
-               )
-       {
-               PIMAGE_SECTION_HEADER   Sections;
-               LARGE_INTEGER           Offset;
-               ULONG                   Base;
+   ULONG               i;
+   NTSTATUS    Status;
+   
+   
+   for (i = 0; (i < NTHeaders->FileHeader.NumberOfSections); i++)
+     {
+       PIMAGE_SECTION_HEADER   Sections;
+       LARGE_INTEGER           Offset; 
+       ULONG                   Base;
+       ULONG Size;
        
-               Sections = (PIMAGE_SECTION_HEADER) SECHDROFFSET(ImageBase);
-               Base = (ULONG) (Sections[i].VirtualAddress + ImageBase);
-               Offset.u.LowPart = Sections[i].PointerToRawData;
-               Offset.u.HighPart = 0;
-               Status = ZwMapViewOfSection(
-                               SectionHandle,
-                               ProcessHandle,
-                               (PVOID *) & Base,
-                               0,
-                               Sections[i].Misc.VirtualSize,
-                               & Offset,
-                               (PULONG) & Sections[i].Misc.VirtualSize,
-                               0,
-                               MEM_COMMIT,
-                               PAGE_READWRITE
-                               );
-               if (!NT_SUCCESS(Status))
-               {
-                       return Status;
-               }
-       }
-       return STATUS_SUCCESS;
+       Sections = (PIMAGE_SECTION_HEADER) SECHDROFFSET(ImageBase);
+       Base = (ULONG) (Sections[i].VirtualAddress + ImageBase);
+       Offset.u.LowPart = Sections[i].PointerToRawData;
+       Offset.u.HighPart = 0;
+       
+       Size = max(Sections[i].Misc.VirtualSize, Sections[i].SizeOfRawData);
+       
+       DPRINT("Mapping section %d offset %x base %x size %x\n",
+               i, Offset.u.LowPart, Base, Sections[i].Misc.VirtualSize);
+       DPRINT("Size %x\n", Sections[i].SizeOfRawData);
+       
+       Status = ZwMapViewOfSection(SectionHandle,
+                                   ProcessHandle,
+                                   (PVOID*)&Base,
+                                   0,
+                                   Size,
+                                   &Offset,
+                                   (PULONG)&Size,
+                                   0,
+                                   MEM_COMMIT,
+                                   PAGE_READWRITE);
+       if (!NT_SUCCESS(Status))
+         {
+            DPRINT("Failed to map section");
+            return(Status);
+         }
+     }
+   return STATUS_SUCCESS;
 }
 
 
@@ -697,14 +698,17 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
    PDLL                                Module;
    NTSTATUS                    Status;
    
+   DPRINT1("LdrFixupImports(NTHeaders %x, ImageBase %x)\n", NTHeaders, 
+          ImageBase);
    
    /*
     * Process each import module.
     */
    ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)(
-                            ImageBase + NTHeaders->OptionalHeader
-                            .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
+                              ImageBase + NTHeaders->OptionalHeader
+                                .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
                             .VirtualAddress);
+   DPRINT1("ImportModuleDirectory %x\n", ImportModuleDirectory);
    
    while (ImportModuleDirectory->dwRVAModuleName)
      {
@@ -713,7 +717,7 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS   NTHeaders,
        DWORD   pName;
        PWORD   pHint;
        
-       DPRINT("ImportModule->Directory->dwRVAModuleName %s\n",
+       DPRINT1("ImportModule->Directory->dwRVAModuleName %s\n",
               (PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName));
        
        Status = LdrLoadDll(&Module,
@@ -734,61 +738,61 @@ static NTSTATUS LdrFixupImports(PIMAGE_NT_HEADERS NTHeaders,
         */
        if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
          {
-                       FunctionNameList = (PULONG) (
-                                                    ImageBase
-                                                    + ImportModuleDirectory->dwRVAFunctionNameList
-                               );
-               }
-               else
-               {
-                       FunctionNameList = (PULONG) (
-                               ImageBase
-                               + ImportModuleDirectory->dwRVAFunctionAddressList
-                               );
-               }
-               /*
-                * Walk through function list and fixup addresses.
-                */
-               while (*FunctionNameList != 0L)
-               {
-                       if ((*FunctionNameList) & 0x80000000)
-                       {
-                               Ordinal = (*FunctionNameList) & 0x7fffffff;
+            FunctionNameList = (PULONG) (
+                                         ImageBase
+                                         + ImportModuleDirectory->dwRVAFunctionNameList
+                                         );
+         }
+       else
+         {
+            FunctionNameList = (PULONG) (
+                                         ImageBase
+                                         + ImportModuleDirectory->dwRVAFunctionAddressList
+                                         );
+         }
+       /*
+        * Walk through function list and fixup addresses.
+        */
+       while (*FunctionNameList != 0L)
+         {
+            if ((*FunctionNameList) & 0x80000000)
+              {
+                 Ordinal = (*FunctionNameList) & 0x7fffffff;
                                *ImportAddressList = 
-                                       LdrGetExportByOrdinal(
-                                               Module,
-                                               Ordinal
-                                               );
-                       }
-                       else
-                       {
-                               pName = (DWORD) (
-                                               ImageBase
-                                               + *FunctionNameList
-                                               + 2
+                   LdrGetExportByOrdinal(
+                                         Module,
+                                         Ordinal
+                                         );
+              }
+            else
+              {
+                 pName = (DWORD) (
+                                  ImageBase
+                                  + *FunctionNameList
+                                  + 2
+                                  );
+                 pHint = (PWORD) (
+                                  ImageBase
+                                  + *FunctionNameList
                                                );
-                               pHint = (PWORD) (
-                                               ImageBase
-                                               + *FunctionNameList
-                                               );
-
-                               *ImportAddressList =
-                                       LdrGetExportByName(
+                 
+                 *ImportAddressList =
+                   LdrGetExportByName(
                                                Module,
-                                               (PUCHAR) pName
-                                               );
-                               if ((*ImportAddressList) == NULL)
-                               {
+                                      (PUCHAR) pName
+                                      );
+                 if ((*ImportAddressList) == NULL)
+                   {
                                   dprintf("Failed to import %s\n", pName);
-                                       return STATUS_UNSUCCESSFUL;
-                               }
-                       }
+                      return STATUS_UNSUCCESSFUL;
+                   }
+              }
                        ImportAddressList++;
-                       FunctionNameList++;
-               }
-               ImportModuleDirectory++;
-       }
-       return STATUS_SUCCESS;
+            FunctionNameList++;
+         }
+       ImportModuleDirectory++;
+     }
+   return STATUS_SUCCESS;
 }
 
 
index 1cc4fc6..48efb2e 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: ntoskrnl.def,v 1.31 1999/12/02 20:53:52 dwelch Exp $
+; $Id: ntoskrnl.def,v 1.32 1999/12/11 21:14:47 dwelch Exp $
 ;
 ; reactos/ntoskrnl/ntoskrnl.def
 ;
@@ -505,4 +505,5 @@ WRITE_PORT_BUFFER_USHORT
 WRITE_PORT_UCHAR
 WRITE_PORT_ULONG
 WRITE_PORT_USHORT
-
+InsertTailList
+RemoveEntryList
index d8df857..e638ee0 100644 (file)
@@ -1,4 +1,4 @@
-; $Id: ntoskrnl.edf,v 1.18 1999/12/02 20:53:53 dwelch Exp $
+; $Id: ntoskrnl.edf,v 1.19 1999/12/11 21:14:48 dwelch Exp $
 ;
 ; reactos/ntoskrnl/ntoskrnl.def
 ;
@@ -503,3 +503,5 @@ WRITE_PORT_BUFFER_USHORT
 WRITE_PORT_UCHAR
 WRITE_PORT_ULONG
 WRITE_PORT_USHORT
+InsertTailList
+RemoveEntryList
index 4c00d32..5dc9afe 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: interlck.c,v 1.5 1999/12/10 17:04:37 dwelch Exp $
+/* $Id: interlck.c,v 1.6 1999/12/11 21:14:48 dwelch Exp $
  *
  * reactos/ntoskrnl/rtl/interlck.c
  *
@@ -112,13 +112,11 @@ __asm__(
        "_InterlockedExchange@8:\n\t"
        "pushl %ebp\n\t"
        "movl  %esp,%ebp\n\t"
-       "pushl %eax\n\t"
        "pushl %ebx\n\t"
        "movl  12(%ebp),%eax\n\t"
        "movl  8(%ebp),%ebx\n\t"
        "xchgl %eax,(%ebx)\n\t"
        "popl  %ebx\n\t"
-       "popl  %eax\n\t"
        "movl  %ebp,%esp\n\t"
        "popl  %ebp\n\t"
        "ret $8\n\t"