/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: services/fs/vfat/iface.c * PURPOSE: VFAT Filesystem * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) * UPDATE HISTORY: ?? Created 24-10-1998 Fixed bugs in long filename support Fixed a bug that prevented unsuccessful file open requests being reported Now works with long filenames that span over a sector boundary 28-10-1998 Reads entire FAT into memory VFatReadSector modified to read in more than one sector at a time 7-11-1998 Fixed bug that assumed that directory data could be fragmented 8-12-1998 Added FAT32 support Added initial writability functions WARNING: DO NOT ATTEMPT TO TEST WRITABILITY FUNCTIONS!!! 12-12-1998 Added basic support for FILE_STANDARD_INFORMATION request */ /* INCLUDES *****************************************************************/ #include #include #include #include #define NDEBUG #include #include "vfat.h" #define FAT16 (1) #define FAT12 (2) #define FAT32 (3) typedef struct { PDEVICE_OBJECT StorageDevice; BootSector *Boot; int rootDirectorySectors, FATStart, rootStart, dataStart; int FATEntriesPerSector, FATUnit; ULONG BytesPerCluster; ULONG FatType; unsigned char* FAT; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; typedef struct { FATDirEntry entry; } FCB, *PFCB; #define ENTRIES_PER_SECTOR (BLOCKSIZE / sizeof(FATDirEntry)) /* GLOBALS *****************************************************************/ static PDRIVER_OBJECT DriverObject; /* FUNCTIONS ****************************************************************/ ULONG Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) { ULONG FATsector; ULONG FATeis; PULONG Block; Block = ExAllocatePool(NonPagedPool,1024); FATsector=CurrentCluster/(512/sizeof(ULONG)); FATeis=CurrentCluster-(FATsector*(512/sizeof(ULONG))); VFATReadSectors(DeviceExt->StorageDevice,DeviceExt->FATStart+FATsector, 1, Block); CurrentCluster = Block[FATeis]; if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff) CurrentCluster = 0; ExFreePool(Block); return(CurrentCluster); } ULONG Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) { ULONG FATsector; ULONG FATeis; PUSHORT Block; FATsector=CurrentCluster/(512/sizeof(USHORT)); FATeis=CurrentCluster-(FATsector*256); // VFATReadSectors(DeviceExt->StorageDevice,DeviceExt->FATStart+FATsector, 1, // (UCHAR *)Block); Block = (PUSHORT)(DeviceExt->FAT + (FATsector * BLOCKSIZE)); CurrentCluster = Block[FATeis]; if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff) CurrentCluster = 0; DPRINT("Returning %x\n",CurrentCluster); return(CurrentCluster); } ULONG Fat12GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) { unsigned char* CBlock; ULONG FATsector; ULONG FATOffset; ULONG Entry; FATsector = (CurrentCluster * 12) / (512 * 8); // VFATReadSectors(DeviceExt->StorageDevice,DeviceExt->FATStart // +FATsector,1,CBlock); CBlock = (unsigned char *)(DeviceExt->FAT + (FATsector * BLOCKSIZE)); FATOffset = (CurrentCluster * 12) % (512 * 8); DPRINT("FATSector %d FATOffset %d\n",FATsector,FATOffset); if ((CurrentCluster % 2) == 0) { Entry = CBlock[((FATOffset / 24)*3)]; Entry |= (CBlock[((FATOffset / 24)*3) + 1] & 0xf); } else { Entry = (CBlock[((FATOffset / 24)*3) + 1] >> 4); Entry |= (CBlock[((FATOffset / 24)*3) + 2] << 4); } DPRINT("Entry %x\n",Entry); if (Entry >= 0xff8 && Entry <= 0xfff) Entry = 0; CurrentCluster = Entry; DPRINT("Returning %x\n",CurrentCluster); return(CurrentCluster); } ULONG GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) { 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) { ULONG sector; PUSHORT Block; int i; sector = 0; Block = ExAllocatePool(NonPagedPool,BLOCKSIZE); while(sectorBoot->FATSectors) { memcpy(Block, DeviceExt->FAT+sector*BLOCKSIZE, BLOCKSIZE); for(i=0; i<512; i++) { if(Block[i]==0) { ExFreePool(Block); return i; } } sector++; } /* Give an error message (out of disk space) if we reach here) */ ExFreePool(Block); return 0; } void FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue) { ULONG FATsector; ULONG FATeis; PUSHORT Block; Block = ExAllocatePool(NonPagedPool,BLOCKSIZE); FATsector=ClusterToWrite/(512/sizeof(USHORT)); FATeis=ClusterToWrite-(FATsector*256); /* Update the in-memory FAT */ memcpy(Block, DeviceExt->FAT+FATsector*BLOCKSIZE, BLOCKSIZE); Block[FATeis] = NewValue; memcpy(DeviceExt->FAT+FATsector*BLOCKSIZE, Block, BLOCKSIZE); /* Write the changed FAT sector to disk */ VFATWriteSectors(DeviceExt->StorageDevice, DeviceExt->FATStart+FATsector, DeviceExt->Boot->SectorsPerCluster, (UCHAR *)Block); ExFreePool(Block); } void FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue) { unsigned char* CBlock; ULONG FATsector; ULONG FATOffset; ULONG Entry; CBlock = ExAllocatePool(NonPagedPool,1024); FATsector = (ClusterToWrite * 12) / (512 * 8); memcpy(CBlock,DeviceExt->FAT+FATsector*BLOCKSIZE, BLOCKSIZE); FATOffset = (ClusterToWrite * 12) % (512 * 8); DPRINT("FATSector %d FATOffset %d\n",FATsector,FATOffset); /* Write 12-bit entry if ((CurrentCluster % 2) == 0) { Entry = CBlock[((FATOffset / 24)*3)]; Entry |= (CBlock[((FATOffset / 24)*3) + 1] & 0xf); } else { Entry = (CBlock[((FATOffset / 24)*3) + 1] >> 4); Entry |= (CBlock[((FATOffset / 24)*3) + 2] << 4); } */ ExFreePool(CBlock); } void WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite, ULONG NewValue) { if (DeviceExt->FatType == FAT16) { FAT16WriteCluster(DeviceExt, ClusterToWrite, NewValue); } else { FAT12WriteCluster(DeviceExt, ClusterToWrite, NewValue); } } ULONG GetNextWriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster) { ULONG LastCluster, NewCluster; BOOLEAN EOF = FALSE; DPRINT("GetNextWriteCluster(DeviceExt %x, CurrentCluster %x)\n", DeviceExt,CurrentCluster); /* Find out what was happening in the last cluster's AU */ if (DeviceExt->FatType == FAT16) { LastCluster = Fat16GetNextCluster(DeviceExt, CurrentCluster); if(LastCluster == 0xFFFF) { EOF = TRUE; } } else { LastCluster = Fat12GetNextCluster(DeviceExt, CurrentCluster); if(LastCluster == 0xFFF) { EOF = TRUE; } } /* Check to see if we must append or overwrite */ if (EOF == TRUE) { /* Append */ /* Firstly, find the next available open allocation unit */ NewCluster = FAT16FindAvailableCluster(DeviceExt); /* Mark the new AU as the EOF */ if(DeviceExt->FatType == FAT16) { FAT16WriteCluster(DeviceExt, NewCluster, 0xFFFF); } else { FAT12WriteCluster(DeviceExt, NewCluster, 0xFFF); } /* Now, write the AU of the LastCluster with the value of the newly found AU */ WriteCluster(DeviceExt, LastCluster, NewCluster); /* Return NewCluster as CurrentCluster */ return NewCluster; } else { /* Overwrite: Return LastCluster as CurrentCluster */ return LastCluster; } } unsigned long ClusterToSector(PDEVICE_EXTENSION DeviceExt, unsigned long Cluster) { return DeviceExt->dataStart+((Cluster-2)*DeviceExt->Boot->SectorsPerCluster); } void RtlAnsiToUnicode(PWSTR Dest, PCH Source, ULONG Length) { int i; for (i=0; (i0)) { Offset++; if(Offset==ENTRIES_PER_SECTOR) { Offset=0; StartingSector++; jloop++; VFATReadSectors(DeviceExt->StorageDevice,StartingSector,1,Block); test2 = (slot *)Block; } cpos++; vfat_initstr(tmp, 256); vfat_movstr(tmp, Name, 13, 0, cpos*13); vfat_wcsncpy(Name, tmp, 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); } 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) { DPRINT("s1 '%w' s2 '%w'\n",s1,s2); while (wtolower(*s1)==wtolower(*s2)) { if ((*s1)==0 && (*s2)==0) { return(TRUE); } s1++; s2++; } return(FALSE); } NTSTATUS FindFile(PDEVICE_EXTENSION DeviceExt, PFCB Fcb, PFCB Parent, PWSTR FileToFind) { ULONG i, j; ULONG Size; char* block; WCHAR name[256]; ULONG StartingSector; ULONG NextCluster; DPRINT("FileFile(Parent %x, FileToFind %w)\n",Parent,FileToFind); if (Parent == NULL) { Size = DeviceExt->rootDirectorySectors;//FIXME : in fat32, no limit StartingSector = DeviceExt->rootStart; } 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); } block = ExAllocatePool(NonPagedPool,BLOCKSIZE); for (j=0; jStorageDevice,StartingSector,1,block); for (i=0; iFatType==FAT32) if(((FATDirEntry *)block)[i].FirstCluster==0 &&((FATDirEntry *)block)[i].FirstClusterHigh==0 ) i++; else if(((FATDirEntry *)block)[i].FirstCluster==0) i++; DPRINT("Found it at cluster %u\n", ((FATDirEntry *)block)[i].FirstCluster); if( i==ENTRIES_PER_SECTOR) { VFATReadSectors(DeviceExt->StorageDevice,StartingSector+1,1,block); i=0; } memcpy(&Fcb->entry,&((FATDirEntry *)block)[i], sizeof(FATDirEntry)); ExFreePool(block); return(STATUS_SUCCESS); } } } /* It seems that directory sectors cannot be fragmented and therefore, they only have a first cluster, but the one's after it are marked with 0xffff. This theory is still not 100% certain, so the following lines are commented and not removed */ StartingSector++; /* if (Parent == NULL) { StartingSector++; } else { NextCluster = GetNextCluster(DeviceExt,NextCluster); if (NextCluster == 0) { ExFreePool(block); return(STATUS_UNSUCCESSFUL); } StartingSector = ClusterToSector(DeviceExt,NextCluster); } */ } ExFreePool(block); return(STATUS_UNSUCCESSFUL); } NTSTATUS FsdCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject) /* * FUNCTION: Closes a file */ { /* NOP */ } NTSTATUS FsdOpenFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PWSTR FileName) /* * FUNCTION: Opens a file */ { PWSTR current; PWSTR next; PWSTR string = FileName; PFCB ParentFcb = NULL; PFCB Fcb = ExAllocatePool(NonPagedPool,sizeof(FCB)); PFCB Temp; NTSTATUS Status; next = &string[0]; current = next+1; while (next!=NULL) { DPRINT("current %w next %x\n",current,next); *next = '\\'; current = next+1; next = wcschr(next+1,'\\'); if (next!=NULL) { *next=0; } Status = FindFile(DeviceExt,Fcb,ParentFcb,current); if (Status != STATUS_SUCCESS) { return(Status); } Temp = Fcb; if (ParentFcb == NULL) { Fcb = ExAllocatePool(NonPagedPool,sizeof(FCB)); ParentFcb = Temp; } else { Fcb = ParentFcb; ParentFcb = Temp; } } FileObject->FsContext = ParentFcb; DPRINT("ParentFcb->entry.FileSize %d\n",ParentFcb->entry.FileSize); 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 */ { int i; 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); } } void VFATLoadCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster) { 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); } void VFATWriteCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster) { 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; PFCB Fcb; PVOID Temp; ULONG TempLength; DPRINT("FsdReadFile(DeviceExt %x, FileObject %x, Buffer %x, " "Length %d, ReadOffset %d)\n",DeviceExt,FileObject,Buffer, Length,ReadOffset); FirstCluster = ReadOffset / DeviceExt->BytesPerCluster; Fcb = FileObject->FsContext; if (DeviceExt->FatType == FAT32) CurrentCluster = Fcb->entry.FirstCluster+Fcb->entry.FirstClusterHigh*65536; else CurrentCluster = Fcb->entry.FirstCluster; if (ReadOffset >= Fcb->entry.FileSize) { return(STATUS_END_OF_FILE); } if ((ReadOffset + Length) > Fcb->entry.FileSize) { Length = Fcb->entry.FileSize - ReadOffset; } *LengthRead = 0; DPRINT("DeviceExt->BytesPerCluster %x\n",DeviceExt->BytesPerCluster); Temp = ExAllocatePool(NonPagedPool,DeviceExt->BytesPerCluster); for (FileOffset=0; FileOffset < FirstCluster; FileOffset++) { CurrentCluster = GetNextCluster(DeviceExt,CurrentCluster); } CHECKPOINT; if ((ReadOffset % DeviceExt->BytesPerCluster)!=0) { 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) { VFATLoadCluster(DeviceExt, Buffer, CurrentCluster); CurrentCluster = GetNextCluster(DeviceExt, CurrentCluster); if (CurrentCluster == 0) { ExFreePool(Temp); return(STATUS_SUCCESS); } (*LengthRead) = (*LengthRead) + DeviceExt->BytesPerCluster; Buffer = Buffer + DeviceExt->BytesPerCluster; Length = Length - DeviceExt->BytesPerCluster; } CHECKPOINT; if (Length > 0) { (*LengthRead) = (*LengthRead) + Length; VFATLoadCluster(DeviceExt, Temp, 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; PFCB Fcb; PVOID Temp; ULONG TempLength; /* Locate the first cluster of the file */ FirstCluster = WriteOffset / DeviceExt->BytesPerCluster; Fcb = FileObject->FsContext; if (DeviceExt->FatType == FAT32) CurrentCluster = Fcb->entry.FirstCluster+Fcb->entry.FirstClusterHigh*65536; else CurrentCluster = Fcb->entry.FirstCluster; /* Allocate a buffer to hold 1 cluster of data */ Temp = ExAllocatePool(NonPagedPool,DeviceExt->BytesPerCluster); /* Find the cluster according to the offset in the file */ for (FileOffset=0; FileOffset < FirstCluster; 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) { TempLength = min(Length,DeviceExt->BytesPerCluster - (WriteOffset % DeviceExt->BytesPerCluster)); /* Read in the existing cluster data */ VFATLoadCluster(DeviceExt,Temp,CurrentCluster); /* Overwrite the last parts of the data as necessary */ memcpy(Temp + WriteOffset % DeviceExt->BytesPerCluster, Buffer, TempLength); /* Write the cluster back */ VFATWriteCluster(DeviceExt,Temp,CurrentCluster); /* Next write cluster */ CurrentCluster = GetNextWriteCluster(DeviceExt, CurrentCluster); Length = Length - TempLength; Buffer = Buffer + TempLength; } CHECKPOINT; /* Write the buffer in chunks of 1 cluster */ while (Length > DeviceExt->BytesPerCluster) { VFATWriteCluster(DeviceExt, Buffer, CurrentCluster); CurrentCluster = GetNextWriteCluster(DeviceExt, CurrentCluster); if (CurrentCluster == 0) { ExFreePool(Temp); return(STATUS_SUCCESS); } Buffer = Buffer + DeviceExt->BytesPerCluster; Length = Length - DeviceExt->BytesPerCluster; } CHECKPOINT; /* Write the remainder */ if (Length > 0) { memcpy(Temp, Buffer, Length); VFATWriteCluster(DeviceExt, Temp, CurrentCluster); } ExFreePool(Temp); return(STATUS_SUCCESS); } NTSTATUS FsdClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = Stack->FileObject; PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; NTSTATUS Status; 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) { PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = Stack->FileObject; NTSTATUS Status; PDEVICE_EXTENSION DeviceExt; DPRINT("VFAT FsdCreate...\n"); DeviceExt = DeviceObject->DeviceExtension; Status = FsdOpenFile(DeviceExt,FileObject,FileObject->FileName.Buffer); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(Status); } NTSTATUS FsdWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp) { 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.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) { ULONG Length; PVOID Buffer; ULONG Offset; PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); PFILE_OBJECT FileObject = Stack->FileObject; PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension; NTSTATUS Status; ULONG LengthRead; DPRINT("FsdRead(DeviceObject %x, Irp %x)\n",DeviceObject,Irp); Length = Stack->Parameters.Read.Length; Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress); Offset = Stack->Parameters.Read.ByteOffset.LowPart; Status = FsdReadFile(DeviceExt,FileObject,Buffer,Length,Offset, &LengthRead); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = LengthRead; IoCompleteRequest(Irp,IO_NO_INCREMENT); return(Status); } NTSTATUS FsdMount(PDEVICE_OBJECT DeviceToMount) { PDEVICE_OBJECT DeviceObject; PDEVICE_EXTENSION DeviceExt; IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_FILE_SYSTEM, 0, FALSE, &DeviceObject); DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO; DeviceExt = (PVOID)DeviceObject->DeviceExtension; FsdMountDevice(DeviceExt,DeviceToMount); DeviceExt->StorageDevice = IoAttachDeviceToDeviceStack(DeviceObject, DeviceToMount); return(STATUS_SUCCESS); } NTSTATUS FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); // PVPB vpb = Stack->Parameters.Mount.Vpb; PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject; NTSTATUS Status; DPRINT("VFAT FSC\n"); if (FsdHasFileSystem(DeviceToMount)) { Status = FsdMount(DeviceToMount); } else { DPRINT("VFAT: Unrecognized Volume\n"); Status = STATUS_UNRECOGNIZED_VOLUME; } DPRINT("VFAT File system successfully mounted\n"); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); return(Status); } NTSTATUS FsdGetStandardInformation(PFCB FCB, PDEVICE_OBJECT DeviceObject, PFILE_STANDARD_INFORMATION StandardInfo) { PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; unsigned long AllocSize; RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION)); /* Make allocsize a rounded up multiple of BytesPerCluster */ AllocSize = 0; while(AllocSizeentry.FileSize) { AllocSize+=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 FsdQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); FILE_INFORMATION_CLASS FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass; PFILE_OBJECT FileObject = NULL; PFCB FCB = NULL; PCCB CCB = NULL; NTSTATUS RC = STATUS_SUCCESS; void *SystemBuffer; FileObject = Stack->FileObject; CCB = (PCCB)(FileObject->FsContext2); FCB = CCB->Buffer; // Should be CCB->FCB??? SystemBuffer = Irp->AssociatedIrp.SystemBuffer; switch(FileInformationClass) { case FileStandardInformation: RC = FsdGetStandardInformation(FCB, DeviceObject, SystemBuffer); break; } return RC; } NTSTATUS DriverEntry(PDRIVER_OBJECT _DriverObject, PUNICODE_STRING RegistryPath) /* * FUNCTION: Called by the system to initalize the driver * ARGUMENTS: * DriverObject = object describing this driver * RegistryPath = path to our configuration entries * RETURNS: Success or failure */ { PDEVICE_OBJECT DeviceObject; NTSTATUS ret; UNICODE_STRING ustr; ANSI_STRING astr; DbgPrint("VFAT 0.0.4\n"); DriverObject = _DriverObject; RtlInitAnsiString(&astr,"\\Device\\VFAT"); RtlAnsiStringToUnicodeString(&ustr,&astr,TRUE); ret = IoCreateDevice(DriverObject,0,&ustr, FILE_DEVICE_FILE_SYSTEM,0,FALSE,&DeviceObject); if (ret!=STATUS_SUCCESS) { return(ret); } DeviceObject->Flags=0; DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsdClose; DriverObject->MajorFunction[IRP_MJ_CREATE] = FsdCreate; DriverObject->MajorFunction[IRP_MJ_READ] = FsdRead; DriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite; DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FsdFileSystemControl; DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = FsdQueryInformation; DriverObject->DriverUnload = NULL; IoRegisterFileSystem(DeviceObject); return(STATUS_SUCCESS); }