--- /dev/null
+/* $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;
+}
+
+
}
#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;
return STATUS_SUCCESS;
}
-NTSTATUS FsdGetFileDirectoryInformation(PVfatFCB pFcb,
+NTSTATUS FsdGetFileDirectoryInformation(PVFATFCB pFcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
{
return STATUS_SUCCESS;
}
-NTSTATUS FsdGetFileFullDirectoryInformation(PVfatFCB pFcb,
+NTSTATUS FsdGetFileFullDirectoryInformation(PVFATFCB pFcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_FULL_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
{
return STATUS_SUCCESS;
}
-NTSTATUS FsdGetFileBothInformation(PVfatFCB pFcb,
+NTSTATUS FsdGetFileBothInformation(PVFATFCB pFcb,
PDEVICE_EXTENSION DeviceExt,
PFILE_BOTH_DIRECTORY_INFORMATION pInfo,ULONG BufferLength)
{
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;
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 ?
*/
{
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++)
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);
*/
{
WCHAR DirName[MAX_PATH],*FileName,*PathFileName;
- VfatFCB DirFcb,FileFcb;
+ VFATFCB DirFcb,FileFcb;
FATDirEntry FatEntry;
NTSTATUS status;
FILE_OBJECT FileObject;
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
,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;
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;
--- /dev/null
+/*
+ * $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);
+}
+
--- /dev/null
+/* $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;
+}
+
+
+
-/* $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
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION DeviceExt;
- IoCreateDevice(VFATDriverObject,
+ IoCreateDevice(VfatDriverObject,
sizeof(DEVICE_EXTENSION),
NULL,
FILE_DEVICE_FILE_SYSTEM,
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 =
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:
{
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)
{
}
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);
-# $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
- $(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
$(CP) $(TARGET).sys ../../../$(DIST_DIR)/drivers/$(TARGET).sys
endif
-$(TARGET).sys: $(OBJECTS)
+$(TARGET).sys: $(OBJECTS) $(LIBS)
$(CC) \
-specs=../../svc_specs \
-mdll \
-Wl,--defsym,_etext=etext \
-Wl,--base-file,base.tmp \
-Wl,"-h vfatfs.sys" \
- $(OBJECTS)
+ $(OBJECTS) $(LIBS)
- $(RM) junk.tmp
$(DLLTOOL) \
--dllname $(TARGET).sys \
-specs=../../svc_specs \
-mdll \
-o $(TARGET).sys \
- $(OBJECTS)
+ $(OBJECTS) $(LIBS)
- $(RM) temp.exp
+WARNINGS_ARE_ERRORS = yes
include ../../../rules.mak
--- /dev/null
+/* $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);
+}
+
+
--- /dev/null
+/* $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);
+}
+
-/* $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;
typedef struct
{
- ERESOURCE Resource;
+ ERESOURCE DirResource;
+ ERESOURCE FatResource;
+
+ KSPIN_LOCK FcbListLock;
+ LIST_ENTRY FcbListHead;
+
PDEVICE_OBJECT StorageDevice;
BootSector *Boot;
int rootDirectorySectors, FATStart, rootStart, dataStart;
ULONG BytesPerCluster;
ULONG FatType;
unsigned char* FAT;
+
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
typedef struct _FSRTL_COMMON_FCB_HEADER{
ERESOURCE PagingIoResource;
} SFsdNTRequiredFCB, *PtrSFsdNTRequiredFCB;
-struct _VfatFCB;
-typedef struct _VfatFCB
+typedef struct _VFATFCB
{
SFsdNTRequiredFCB NTRequiredFCB;
FATDirEntry entry;
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))
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);
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);
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);
--- /dev/null
+/* $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;
+}
+
+
/*
* 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)
"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;
}
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 */
#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))
-/* $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
* 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;
}
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)
{
DWORD pName;
PWORD pHint;
- DPRINT("ImportModule->Directory->dwRVAModuleName %s\n",
+ DPRINT1("ImportModule->Directory->dwRVAModuleName %s\n",
(PCHAR)(ImageBase + ImportModuleDirectory->dwRVAModuleName));
Status = LdrLoadDll(&Module,
*/
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;
}
-; $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
;
WRITE_PORT_UCHAR
WRITE_PORT_ULONG
WRITE_PORT_USHORT
-
+InsertTailList
+RemoveEntryList
-; $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
;
WRITE_PORT_UCHAR
WRITE_PORT_ULONG
WRITE_PORT_USHORT
+InsertTailList
+RemoveEntryList
-/* $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
*
"_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"