[FASTFAT_NEW] [FULLFAT] Remove the FullFAT-based "fastfat_new" driver and the third-party FullFAT library itself.

Our driver has not seen any development since 2010 and the current fastfat driver has long surpassed it.
Even more important, FullFAT is licensed under a modified version of GPLv3 that forbids commercial usage. Shipping it as a ReactOS dependency would render the OS unusable for commercial scenarios.
If anybody wants to resurrect the driver, you can always get it from the repository history.

svn path=/trunk/; revision=75986
This commit is contained in:
Colin Finck 2017-09-29 10:21:33 +00:00
parent e9bc2c9b4c
commit 26dd1bcf1f
40 changed files with 0 additions and 16323 deletions

View file

@ -3,7 +3,6 @@ add_subdirectory(btrfs)
add_subdirectory(cdfs)
add_subdirectory(ext2)
add_subdirectory(fastfat)
#add_subdirectory(fastfat_new)
add_subdirectory(ffs)
add_subdirectory(fs_rec)
add_subdirectory(msfs)

View file

@ -1,31 +0,0 @@
include_directories(
.
${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/fullfat)
list(APPEND SOURCE
cleanup.c
close.c
create.c
device.c
dir.c
ea.c
fastfat.c
fastio.c
fat.c
fcb.c
finfo.c
flush.c
fsctl.c
fullfat.c
lock.c
rw.c
shutdown.c
volume.c
fastfat.h)
add_library(fastfat_new SHARED ${SOURCE} fastfat.rc)
set_module_type(fastfat_new kernelmodedriver)
target_link_libraries(fastfat_new ${PSEH_LIB} fullfat)
add_importlibs(fastfat_new ntoskrnl hal)
add_pch(fastfat_new fastfat.h SOURCE)

View file

@ -1,443 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/cleanup.c
* PURPOSE: Cleanup routines
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
/* Last handle to a file object is closed */
NTSTATUS
NTAPI
FatiCleanup(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
TYPE_OF_OPEN TypeOfOpen;
PSHARE_ACCESS ShareAccess;
BOOLEAN SendUnlockNotification = FALSE;
PLARGE_INTEGER TruncateSize = NULL;
//LARGE_INTEGER LocalTruncateSize;
BOOLEAN AcquiredVcb = FALSE, AcquiredFcb = FALSE;
NTSTATUS Status;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DPRINT("FatiCleanup\n");
DPRINT("\tIrp = %p\n", Irp);
DPRINT("\t->FileObject = %p\n", IrpSp->FileObject);
FileObject = IrpSp->FileObject;
TypeOfOpen = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
if (TypeOfOpen == UnopenedFileObject)
{
DPRINT1("Unopened File Object\n");
FatCompleteRequest(IrpContext, Irp, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
if (FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ))
{
/* Just flush the file */
if (FlagOn(Vcb->State, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
FlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED) &&
(TypeOfOpen == UserFileOpen))
{
//Status = FatFlushFile(IrpContext, Fcb, Flush);
//if (!NT_SUCCESS(Status)) FatNormalizeAndRaiseStatus(IrpContext, Status);
UNIMPLEMENTED;
}
FatCompleteRequest(IrpContext, Irp, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
if (TypeOfOpen == UserFileOpen ||
TypeOfOpen == UserDirectoryOpen)
{
ASSERT(Fcb != NULL);
(VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);
AcquiredFcb = TRUE;
/* Set FCB flags according to DELETE_ON_CLOSE */
if (FlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE))
{
ASSERT(FatNodeType(Fcb) != FAT_NTC_ROOT_DCB);
SetFlag(Fcb->State, FCB_STATE_DELETE_ON_CLOSE);
/* Issue a notification */
if (TypeOfOpen == UserDirectoryOpen)
{
FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
&Vcb->NotifyList,
FileObject->FsContext,
NULL,
FALSE,
FALSE,
0,
NULL,
NULL,
NULL);
}
}
/* If file should be deleted, acquire locks */
if ((Fcb->UncleanCount == 1) &&
FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
(Fcb->Condition != FcbBad) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
{
FatReleaseFcb(IrpContext, Fcb);
AcquiredFcb = FALSE;
(VOID)FatAcquireExclusiveVcb(IrpContext, Vcb);
AcquiredVcb = TRUE;
(VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);
AcquiredFcb = TRUE;
}
}
/* Acquire VCB lock if it was a volume open */
if (TypeOfOpen == UserVolumeOpen)
{
(VOID)FatAcquireExclusiveVcb(IrpContext, Vcb);
AcquiredVcb = TRUE;
}
/* Cleanup all notifications */
if (TypeOfOpen == UserDirectoryOpen)
{
FsRtlNotifyCleanup(Vcb->NotifySync,
&Vcb->NotifyList,
Ccb);
}
if (Fcb)
{
//TODO: FatVerifyFcb
}
switch (TypeOfOpen)
{
case DirectoryFile:
case VirtualVolumeFile:
DPRINT1("Cleanup VirtualVolumeFile/DirectoryFile\n");
ShareAccess = NULL;
break;
case UserVolumeOpen:
DPRINT("Cleanup UserVolumeOpen\n");
if (FlagOn(Ccb->Flags, CCB_COMPLETE_DISMOUNT))
{
FatCheckForDismount( IrpContext, Vcb, TRUE );
} else if (FileObject->WriteAccess &&
FlagOn(FileObject->Flags, FO_FILE_MODIFIED))
{
UNIMPLEMENTED;
}
/* Release the volume and send notification */
if (FlagOn(Vcb->State, VCB_STATE_FLAG_LOCKED) &&
(Vcb->FileObjectWithVcbLocked == FileObject))
{
UNIMPLEMENTED;
SendUnlockNotification = TRUE;
}
ShareAccess = &Vcb->ShareAccess;
break;
case EaFile:
DPRINT1("Cleanup EaFileObject\n");
ShareAccess = NULL;
break;
case UserDirectoryOpen:
DPRINT("Cleanup UserDirectoryOpen\n");
ShareAccess = &Fcb->ShareAccess;
/* Should it be a delayed close? */
if ((Fcb->UncleanCount == 1) &&
(Fcb->OpenCount == 1) &&
(Fcb->Dcb.DirectoryFileOpenCount == 0) &&
!FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
Fcb->Condition == FcbGood)
{
/* Yes, a delayed one */
SetFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
}
if (VcbGood == Vcb->Condition)
{
//FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
//TODO: Actually update dirent
}
if ((Fcb->UncleanCount == 1) &&
(FatNodeType(Fcb) == FAT_NTC_DCB) &&
(FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE)) &&
(Fcb->Condition != FcbBad) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
{
UNIMPLEMENTED;
}
/* Decrement unclean counter */
ASSERT(Fcb->UncleanCount != 0);
Fcb->UncleanCount--;
break;
case UserFileOpen:
DPRINT("Cleanup UserFileOpen\n");
ShareAccess = &Fcb->ShareAccess;
/* Should it be a delayed close? */
if ((FileObject->SectionObjectPointer->DataSectionObject == NULL) &&
(FileObject->SectionObjectPointer->ImageSectionObject == NULL) &&
(Fcb->UncleanCount == 1) &&
(Fcb->OpenCount == 1) &&
!FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
Fcb->Condition == FcbGood)
{
/* Yes, a delayed one */
//SetFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
DPRINT1("Setting a delay on close for some reason for FCB %p, FF handle %p, file name '%wZ'\n", Fcb, Fcb->FatHandle, &Fcb->FullFileName);
}
/* Unlock all file locks */
FsRtlFastUnlockAll(&Fcb->Fcb.Lock,
FileObject,
IoGetRequestorProcess(Irp),
NULL);
if (Vcb->Condition == VcbGood)
{
if (Fcb->Condition != FcbBad)
{
//FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
// TODO: Update on-disk structures
}
if (Fcb->UncleanCount == 1 &&
Fcb->Condition != FcbBad)
{
//DELETE_CONTEXT DeleteContext;
/* Should this file be deleted on close? */
if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
{
UNIMPLEMENTED;
}
else
{
if (!FlagOn(Fcb->State, FCB_STATE_PAGEFILE) &&
(Fcb->Header.ValidDataLength.LowPart < Fcb->Header.FileSize.LowPart))
{
#if 0
ULONG ValidDataLength;
ValidDataLength = Fcb->Header.ValidDataLength.LowPart;
if (ValidDataLength < Fcb->ValidDataToDisk) {
ValidDataLength = Fcb->ValidDataToDisk;
}
if (ValidDataLength < Fcb->Header.FileSize.LowPart)
{
FatZeroData( IrpContext,
Vcb,
FileObject,
ValidDataLength,
Fcb->Header.FileSize.LowPart -
ValidDataLength );
Fcb->ValidDataToDisk =
Fcb->Header.ValidDataLength.LowPart =
Fcb->Header.FileSize.LowPart;
if (CcIsFileCached(FileObject))
{
CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
}
}
#endif
DPRINT1("Zeroing out data is not implemented\n");
}
}
/* Should the file be truncated on close? */
if (FlagOn(Fcb->State, FCB_STATE_TRUNCATE_ON_CLOSE))
{
if (Vcb->Condition == VcbGood)
{
// TODO: Actually truncate the file allocation
UNIMPLEMENTED;
}
/* Remove truncation flag */
Fcb->State &= ~FCB_STATE_TRUNCATE_ON_CLOSE;
}
/* Check again if it should be deleted */
if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
Fcb->Header.AllocationSize.LowPart == 0)
{
FatNotifyReportChange(IrpContext,
Vcb,
Fcb,
FILE_NOTIFY_CHANGE_FILE_NAME,
FILE_ACTION_REMOVED);
}
/* Remove the entry from the splay table if the file was deleted */
if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE))
{
FatRemoveNames(IrpContext, Fcb);
}
}
}
ASSERT(Fcb->UncleanCount != 0);
Fcb->UncleanCount--;
if (!FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
{
ASSERT(Fcb->NonCachedUncleanCount != 0);
Fcb->NonCachedUncleanCount--;
}
if (FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
(Fcb->NonCachedUncleanCount != 0) &&
(Fcb->NonCachedUncleanCount == Fcb->UncleanCount) &&
(Fcb->SectionObjectPointers.DataSectionObject != NULL))
{
CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
/* Acquire and release PagingIo to get in sync with lazy writer */
ExAcquireResourceExclusiveLite(Fcb->Header.PagingIoResource, TRUE);
ExReleaseResourceLite(Fcb->Header.PagingIoResource);
CcPurgeCacheSection(&Fcb->SectionObjectPointers,
NULL,
0,
FALSE);
}
if (Fcb->Condition == FcbBad)
{
//TruncateSize = &FatLargeZero;
UNIMPLEMENTED;
}
/* Cleanup the cache map */
CcUninitializeCacheMap(FileObject, TruncateSize, NULL);
break;
default:
KeBugCheckEx(FAT_FILE_SYSTEM, __LINE__, (ULONG_PTR)TypeOfOpen, 0, 0);
}
/* Cleanup the share access */
if (ShareAccess)
{
DPRINT("Cleaning up the share access\n");
IoRemoveShareAccess(FileObject, ShareAccess);
}
if (TypeOfOpen == UserFileOpen)
{
/* Update oplocks */
FsRtlCheckOplock(&Fcb->Fcb.Oplock,
Irp,
IrpContext,
NULL,
NULL);
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible(Fcb);
}
/* Set the FO_CLEANUP_COMPLETE flag */
SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
Status = STATUS_SUCCESS;
// TODO: Unpin repinned BCBs
//FatUnpinRepinnedBcbs(IrpContext);
/* Flush the volume if necessary */
if (FlagOn(Vcb->State, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
{
UNIMPLEMENTED;
}
/* Cleanup */
if (AcquiredFcb) FatReleaseFcb(IrpContext, Fcb);
if (AcquiredVcb) FatReleaseVcb(IrpContext, Vcb);
/* Send volume notification */
if (SendUnlockNotification)
FsRtlNotifyVolumeEvent(FileObject, FSRTL_VOLUME_UNLOCK);
return Status;
}
NTSTATUS
NTAPI
FatCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PFAT_IRP_CONTEXT IrpContext;
NTSTATUS Status;
DPRINT("FatCleanup(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
/* FatCleanup works only with a volume device object */
if (DeviceObject == FatGlobalData.DiskDeviceObject)
{
/* Complete the request and return success */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
return STATUS_SUCCESS;
}
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, TRUE);
/* Call internal function */
Status = FatiCleanup(IrpContext, Irp);
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}
/* EOF */

View file

@ -1,651 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/close.c
* PURPOSE: Closing routines
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
VOID NTAPI
FatQueueClose(IN PCLOSE_CONTEXT CloseContext,
IN BOOLEAN DelayClose);
PCLOSE_CONTEXT NTAPI
FatRemoveClose(PVCB Vcb OPTIONAL,
PVCB LastVcbHint OPTIONAL);
const ULONG FatMaxDelayedCloseCount = 16;
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
FatiCommonClose(IN PVCB Vcb,
IN PFCB Fcb,
IN PCCB Ccb,
IN TYPE_OF_OPEN TypeOfOpen,
IN BOOLEAN Wait,
OUT PBOOLEAN VcbDeleted)
{
NTSTATUS Status;
PFCB ParentDcb;
BOOLEAN RecursiveClose, VcbDeletedLv = FALSE;
FAT_IRP_CONTEXT IrpContext;
if (VcbDeleted) *VcbDeleted = FALSE;
if (TypeOfOpen == UnopenedFileObject)
{
DPRINT1("Closing unopened file object\n");
Status = STATUS_SUCCESS;
return Status;
}
RtlZeroMemory(&IrpContext, sizeof(FAT_IRP_CONTEXT));
IrpContext.NodeTypeCode = FAT_NTC_IRP_CONTEXT;
IrpContext.NodeByteSize = sizeof(IrpContext);
IrpContext.MajorFunction = IRP_MJ_CLOSE;
if (Wait) SetFlag(IrpContext.Flags, IRPCONTEXT_CANWAIT);
if (!ExAcquireResourceExclusiveLite(&Vcb->Resource, Wait)) return STATUS_PENDING;
if (Vcb->State & VCB_STATE_FLAG_CLOSE_IN_PROGRESS)
{
RecursiveClose = TRUE;
}
else
{
SetFlag(Vcb->State, VCB_STATE_FLAG_CLOSE_IN_PROGRESS);
RecursiveClose = FALSE;
Vcb->OpenFileCount++;
}
/* Update on-disk structures */
switch (TypeOfOpen)
{
case VirtualVolumeFile:
DPRINT1("Close VirtualVolumeFile\n");
InterlockedDecrement((PLONG)&(Vcb->InternalOpenCount));
InterlockedDecrement((PLONG)&(Vcb->ResidualOpenCount));
Status = STATUS_SUCCESS;
goto close_done;
break;
case UserVolumeOpen:
DPRINT1("Close UserVolumeOpen\n");
Vcb->DirectAccessOpenCount--;
Vcb->OpenFileCount--;
if (FlagOn(Ccb->Flags, CCB_READ_ONLY)) Vcb->ReadOnlyCount--;
FatDeleteCcb(&IrpContext, Ccb);
Status = STATUS_SUCCESS;
goto close_done;
break;
case EaFile:
UNIMPLEMENTED;
break;
case DirectoryFile:
DPRINT1("Close DirectoryFile\n");
InterlockedDecrement((PLONG)&(Fcb->Dcb.DirectoryFileOpenCount));
InterlockedDecrement((PLONG)&(Vcb->InternalOpenCount));
if (FatNodeType(Fcb) == FAT_NTC_ROOT_DCB)
{
InterlockedDecrement((PLONG)&(Vcb->ResidualOpenCount));
}
if (RecursiveClose)
{
Status = STATUS_SUCCESS;
goto close_done;
}
else
{
break;
}
case UserDirectoryOpen:
case UserFileOpen:
DPRINT("Close UserFileOpen/UserDirectoryOpen\n");
if ((FatNodeType(Fcb) == FAT_NTC_DCB) &&
IsListEmpty(&Fcb->Dcb.ParentDcbList) &&
(Fcb->OpenCount == 1) &&
(Fcb->Dcb.DirectoryFile != NULL))
{
PFILE_OBJECT DirectoryFileObject = Fcb->Dcb.DirectoryFile;
DPRINT1("Uninitialize the stream file object\n");
CcUninitializeCacheMap(DirectoryFileObject, NULL, NULL);
Fcb->Dcb.DirectoryFile = NULL;
ObDereferenceObject(DirectoryFileObject);
}
Fcb->OpenCount--;
Vcb->OpenFileCount--;
if (FlagOn(Ccb->Flags, CCB_READ_ONLY)) Vcb->ReadOnlyCount --;
FatDeleteCcb(&IrpContext, Ccb);
break;
default:
KeBugCheckEx(FAT_FILE_SYSTEM, __LINE__, (ULONG_PTR)TypeOfOpen, 0, 0);
}
/* Update in-memory structures */
if (((FatNodeType(Fcb) == FAT_NTC_FCB) &&
(Fcb->OpenCount == 0))
||
((FatNodeType(Fcb) == FAT_NTC_DCB) &&
(IsListEmpty(&Fcb->Dcb.ParentDcbList)) &&
(Fcb->OpenCount == 0) &&
(Fcb->Dcb.DirectoryFileOpenCount == 0)))
{
ParentDcb = Fcb->ParentFcb;
SetFlag(Vcb->State, VCB_STATE_FLAG_DELETED_FCB);
FatDeleteFcb(&IrpContext, Fcb);
while ((FatNodeType(ParentDcb) == FAT_NTC_DCB) &&
IsListEmpty(&ParentDcb->Dcb.ParentDcbList) &&
(ParentDcb->OpenCount == 0) &&
(ParentDcb->Dcb.DirectoryFile != NULL))
{
PFILE_OBJECT DirectoryFileObject;
DirectoryFileObject = ParentDcb->Dcb.DirectoryFile;
DPRINT1("Uninitialize parent Stream Cache Map\n");
CcUninitializeCacheMap(DirectoryFileObject, NULL, NULL);
ParentDcb->Dcb.DirectoryFile = NULL;
ObDereferenceObject(DirectoryFileObject);
if (ParentDcb->Dcb.DirectoryFileOpenCount == 0)
{
PFCB CurrentDcb;
CurrentDcb = ParentDcb;
ParentDcb = CurrentDcb->ParentFcb;
SetFlag(Vcb->State, VCB_STATE_FLAG_DELETED_FCB);
FatDeleteFcb(&IrpContext, CurrentDcb);
}
else
{
break;
}
}
}
Status = STATUS_SUCCESS;
close_done:
/* Closing is done, check if VCB could be closed too */
if (!RecursiveClose)
{
/* One open left - yes, VCB can go away */
if (Vcb->OpenFileCount == 1 &&
!FlagOn(Vcb->State, VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS)
&& VcbDeleted)
{
FatReleaseVcb(&IrpContext, Vcb );
SetFlag(IrpContext.Flags, IRPCONTEXT_CANWAIT);
FatAcquireExclusiveGlobal(&IrpContext);
FatAcquireExclusiveVcb(&IrpContext, Vcb);
Vcb->OpenFileCount--;
VcbDeletedLv = FatCheckForDismount(&IrpContext, Vcb, FALSE);
FatReleaseGlobal(&IrpContext);
if (VcbDeleted) *VcbDeleted = VcbDeletedLv;
}
else
{
/* Remove extra referenec */
Vcb->OpenFileCount --;
}
/* Clear recursion flag if necessary */
if (!VcbDeletedLv)
{
ClearFlag(Vcb->State, VCB_STATE_FLAG_CLOSE_IN_PROGRESS);
}
}
/* Release VCB if it wasn't deleted */
if (!VcbDeletedLv)
FatReleaseVcb(&IrpContext, Vcb);
return Status;
}
NTSTATUS
NTAPI
FatiClose(IN PFAT_IRP_CONTEXT IrpContext,
IN PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
BOOLEAN TopLevel, Wait, VcbDeleted = FALSE, DelayedClose = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
PCLOSE_CONTEXT CloseContext = NULL;
TopLevel = FatIsTopLevelIrp(Irp);
/* Get current IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Decode incoming file object */
TypeOfOpen = FatDecodeFileObject(IrpSp->FileObject, &Vcb, &Fcb, &Ccb);
/* Set CCB read only flag */
if (Ccb && IsFileObjectReadOnly(IrpSp->FileObject))
SetFlag(Ccb->Flags, CCB_READ_ONLY);
/* It's possible to wait only if we are top level or not a system process */
Wait = TopLevel && (PsGetCurrentProcess() != FatGlobalData.SystemProcess);
/* Determine if it's a delayed close, by flags first */
if ((TypeOfOpen == UserFileOpen || TypeOfOpen == UserDirectoryOpen) &&
(Fcb->State & FCB_STATE_DELAY_CLOSE) &&
!FatGlobalData.ShutdownStarted)
{
DelayedClose = TRUE;
}
/* If close is not delayed, try to perform the close operation */
if (!DelayedClose)
Status = FatiCommonClose(Vcb, Fcb, Ccb, TypeOfOpen, Wait, &VcbDeleted);
/* We have to delay close if either it's defined by a flag or it was not possible
to perform it synchronously */
if (DelayedClose || Status == STATUS_PENDING)
{
DPRINT1("Queuing a pending close, Vcb %p, Fcb %p, Ccb %p\n", Vcb, Fcb, Ccb);
/* Check if a close context should be allocated */
if (TypeOfOpen == VirtualVolumeFile)
{
ASSERT(Vcb->CloseContext != NULL);
CloseContext = Vcb->CloseContext;
Vcb->CloseContext = NULL;
CloseContext->Free = TRUE;
}
else if (TypeOfOpen == DirectoryFile ||
TypeOfOpen == EaFile)
{
UNIMPLEMENTED;
//CloseContext = FatAllocateCloseContext(Vcb);
//ASSERT(CloseContext != NULL);
CloseContext->Free = TRUE;
}
else
{
//TODO: FatDeallocateCcbStrings( Ccb );
/* Set CloseContext to a buffer inside Ccb */
CloseContext = &Ccb->CloseContext;
CloseContext->Free = FALSE;
SetFlag(Ccb->Flags, CCB_CLOSE_CONTEXT);
}
/* Save all info in the close context */
CloseContext->Vcb = Vcb;
CloseContext->Fcb = Fcb;
CloseContext->TypeOfOpen = TypeOfOpen;
/* Queue the close */
FatQueueClose(CloseContext, (BOOLEAN)(Fcb && FlagOn(Fcb->State, FCB_STATE_DELAY_CLOSE)));
}
else
{
/* Close finished right away */
if (TypeOfOpen == VirtualVolumeFile ||
TypeOfOpen == DirectoryFile ||
TypeOfOpen == EaFile)
{
if (TypeOfOpen == VirtualVolumeFile)
{
/* Free close context for the not deleted VCB */
if (!VcbDeleted)
{
CloseContext = Vcb->CloseContext;
Vcb->CloseContext = NULL;
ASSERT(CloseContext != NULL);
}
}
else
{
//CloseContext = FatAllocateCloseContext(Vcb);
DPRINT1("TODO: Allocate close context!\n");
ASSERT(CloseContext != NULL);
}
/* Free close context */
if (CloseContext) ExFreePool(CloseContext);
}
}
/* Complete the request */
FatCompleteRequest(NULL, Irp, Status);
/* Reset the top level IRP if necessary */
if (TopLevel) IoSetTopLevelIrp(NULL);
return Status;
}
NTSTATUS
NTAPI
FatClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PFAT_IRP_CONTEXT IrpContext;
NTSTATUS Status;
DPRINT("FatClose(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
/* FatClose works only with a volume device object */
if (DeviceObject == FatGlobalData.DiskDeviceObject)
{
/* Complete the request and return success */
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
return STATUS_SUCCESS;
}
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, TRUE);
/* Call internal function */
Status = FatiClose(IrpContext, Irp);
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}
VOID
NTAPI
FatPendingClose(IN PVCB Vcb OPTIONAL)
{
PCLOSE_CONTEXT CloseContext;
PVCB CurrentVcb = NULL;
PVCB LastVcb = NULL;
BOOLEAN FreeContext;
ULONG Loops = 0;
/* Do the top-level IRP trick */
if (!Vcb) IoSetTopLevelIrp((PIRP)FSRTL_FSP_TOP_LEVEL_IRP);
while ((CloseContext = FatRemoveClose(Vcb, LastVcb)))
{
if (!Vcb)
{
if (!FatGlobalData.ShutdownStarted)
{
if (CloseContext->Vcb != CurrentVcb)
{
Loops = 0;
/* Release previous VCB */
if (CurrentVcb)
ExReleaseResourceLite(&CurrentVcb->Resource);
/* Lock the new VCB */
CurrentVcb = CloseContext->Vcb;
(VOID)ExAcquireResourceExclusiveLite(&CurrentVcb->Resource, TRUE);
}
else
{
/* Try to lock */
if (++Loops >= 20)
{
if (ExGetSharedWaiterCount(&CurrentVcb->Resource) +
ExGetExclusiveWaiterCount(&CurrentVcb->Resource))
{
ExReleaseResourceLite(&CurrentVcb->Resource);
(VOID)ExAcquireResourceExclusiveLite(&CurrentVcb->Resource, TRUE);
}
Loops = 0;
}
}
/* Check open count */
if (CurrentVcb->OpenFileCount <= 1)
{
ExReleaseResourceLite(&CurrentVcb->Resource);
CurrentVcb = NULL;
}
}
else if (CurrentVcb)
{
ExReleaseResourceLite(&CurrentVcb->Resource);
CurrentVcb = NULL;
}
}
LastVcb = CurrentVcb;
/* Remember if we should free the context */
FreeContext = CloseContext->Free;
FatiCommonClose(CloseContext->Vcb,
CloseContext->Fcb,
(FreeContext ? NULL : CONTAINING_RECORD(CloseContext, CCB, CloseContext)),
CloseContext->TypeOfOpen,
TRUE,
NULL);
/* Free context if necessary */
if (FreeContext) ExFreePool(CloseContext);
}
/* Release VCB if necessary */
if (CurrentVcb) ExReleaseResourceLite(&CurrentVcb->Resource);
/* Reset top level IRP */
if (!Vcb) IoSetTopLevelIrp( NULL );
}
VOID
NTAPI
FatCloseWorker(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
FsRtlEnterFileSystem();
FatPendingClose((PVCB)Context);
FsRtlExitFileSystem();
}
VOID
NTAPI
FatQueueClose(IN PCLOSE_CONTEXT CloseContext,
IN BOOLEAN DelayClose)
{
BOOLEAN RunWorker = FALSE;
/* Acquire the close lists mutex */
ExAcquireFastMutexUnsafe(&FatCloseQueueMutex);
/* Add it to the desired list */
if (DelayClose)
{
InsertTailList(&FatGlobalData.DelayedCloseList,
&CloseContext->GlobalLinks);
InsertTailList(&CloseContext->Vcb->DelayedCloseList,
&CloseContext->VcbLinks);
FatGlobalData.DelayedCloseCount++;
if (FatGlobalData.DelayedCloseCount > FatMaxDelayedCloseCount &&
!FatGlobalData.AsyncCloseActive)
{
FatGlobalData.AsyncCloseActive = TRUE;
RunWorker = TRUE;
}
}
else
{
InsertTailList(&FatGlobalData.AsyncCloseList,
&CloseContext->GlobalLinks);
InsertTailList(&CloseContext->Vcb->AsyncCloseList,
&CloseContext->VcbLinks);
FatGlobalData.AsyncCloseCount++;
if (!FatGlobalData.AsyncCloseActive)
{
FatGlobalData.AsyncCloseActive = TRUE;
RunWorker = TRUE;
}
}
/* Release the close lists mutex */
ExReleaseFastMutexUnsafe(&FatCloseQueueMutex);
if (RunWorker)
IoQueueWorkItem(FatGlobalData.FatCloseItem, FatCloseWorker, CriticalWorkQueue, NULL);
}
PCLOSE_CONTEXT
NTAPI
FatRemoveClose(PVCB Vcb OPTIONAL,
PVCB LastVcbHint OPTIONAL)
{
PLIST_ENTRY Entry;
PCLOSE_CONTEXT CloseContext;
BOOLEAN IsWorker = FALSE;
/* Acquire the close lists mutex */
ExAcquireFastMutexUnsafe(&FatCloseQueueMutex);
if (!Vcb) IsWorker = TRUE;
if (Vcb == NULL && LastVcbHint != NULL)
{
// TODO: A very special case of overflowing the queue
UNIMPLEMENTED;
}
/* Usual processing from a worker thread */
if (!Vcb)
{
TryToCloseAgain:
/* Is there anything in the async close list */
if (!IsListEmpty(&FatGlobalData.AsyncCloseList))
{
Entry = RemoveHeadList(&FatGlobalData.AsyncCloseList);
FatGlobalData.AsyncCloseCount--;
CloseContext = CONTAINING_RECORD(Entry,
CLOSE_CONTEXT,
GlobalLinks);
RemoveEntryList(&CloseContext->VcbLinks);
} else if (!IsListEmpty(&FatGlobalData.DelayedCloseList) &&
(FatGlobalData.DelayedCloseCount > FatMaxDelayedCloseCount/2 ||
FatGlobalData.ShutdownStarted))
{
/* In case of a shutdown or when delayed queue is filled at half - perform closing */
Entry = RemoveHeadList(&FatGlobalData.DelayedCloseList);
FatGlobalData.DelayedCloseCount--;
CloseContext = CONTAINING_RECORD(Entry,
CLOSE_CONTEXT,
GlobalLinks);
RemoveEntryList(&CloseContext->VcbLinks);
}
else
{
/* Nothing to close */
CloseContext = NULL;
if (IsWorker) FatGlobalData.AsyncCloseActive = FALSE;
}
}
else
{
if (!IsListEmpty(&Vcb->AsyncCloseList))
{
/* Is there anything in the async close list */
Entry = RemoveHeadList(&Vcb->AsyncCloseList);
FatGlobalData.AsyncCloseCount--;
CloseContext = CONTAINING_RECORD(Entry,
CLOSE_CONTEXT,
VcbLinks);
RemoveEntryList(&CloseContext->GlobalLinks);
}
else if (!IsListEmpty(&Vcb->DelayedCloseList))
{
/* Process delayed close list */
Entry = RemoveHeadList(&Vcb->DelayedCloseList);
FatGlobalData.DelayedCloseCount--;
CloseContext = CONTAINING_RECORD(Entry,
CLOSE_CONTEXT,
VcbLinks);
RemoveEntryList(&CloseContext->GlobalLinks);
}
else if (LastVcbHint)
{
/* Try again */
goto TryToCloseAgain;
}
else
{
/* Nothing to close */
CloseContext = NULL;
}
}
/* Release the close lists mutex */
ExReleaseFastMutexUnsafe(&FatCloseQueueMutex);
return CloseContext;
}
/* EOF */

File diff suppressed because it is too large Load diff

View file

@ -1,76 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/device.c
* PURPOSE: Device control
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
FatDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT1("FatDeviceControl()\n");
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
FatPerformDevIoCtrl(PDEVICE_OBJECT DeviceObject,
ULONG ControlCode,
PVOID InputBuffer,
ULONG InputBufferSize,
PVOID OutputBuffer,
ULONG OutputBufferSize,
BOOLEAN Override)
{
PIRP Irp;
KEVENT Event;
NTSTATUS Status;
PIO_STACK_LOCATION Stack;
IO_STATUS_BLOCK IoStatus;
/* Initialize the event for waiting */
KeInitializeEvent(&Event, NotificationEvent, FALSE);
/* Build the device I/O control request */
Irp = IoBuildDeviceIoControlRequest(ControlCode,
DeviceObject,
InputBuffer,
InputBufferSize,
OutputBuffer,
OutputBufferSize,
FALSE,
&Event,
&IoStatus);
/* Fail if IRP hasn't been allocated */
if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
/* Set verify override flag if requested */
if (Override)
{
Stack = IoGetNextIrpStackLocation(Irp);
Stack->Flags |= SL_OVERRIDE_VERIFY_VOLUME;
}
/* Call the driver */
Status = IoCallDriver(DeviceObject, Irp);
/* Wait if needed */
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
return Status;
}
/* EOF */

View file

@ -1,280 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/dir.c
* PURPOSE: Directory Control
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
FatDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT1("FatDirectoryControl()\n");
return STATUS_NOT_IMPLEMENTED;
}
VOID
NTAPI
FatCreateRootDcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb)
{
PFCB Dcb;
/* Make sure it's not already created */
ASSERT(!Vcb->RootDcb);
/* Allocate the DCB */
Dcb = FsRtlAllocatePoolWithTag(NonPagedPool,
sizeof(FCB),
TAG_FCB);
/* Zero it */
RtlZeroMemory(Dcb, sizeof(FCB));
/* Assign it to the VCB */
Vcb->RootDcb = Dcb;
/* Set its header */
Dcb->Header.NodeTypeCode = FAT_NTC_ROOT_DCB;
Dcb->Header.NodeByteSize = sizeof(FCB);
/* FCB is in a good condition */
Dcb->Condition = FcbGood;
/* Initialize FCB's resource */
Dcb->Header.Resource = &Dcb->Resource;
ExInitializeResourceLite(&Dcb->Resource);
/* Initialize Paging Io resource*/
Dcb->Header.PagingIoResource = &Dcb->PagingIoResource;
ExInitializeResourceLite(&Dcb->PagingIoResource);
/* Initialize a list of parent DCBs*/
InitializeListHead(&Dcb->ParentDcbLinks);
/* Set VCB */
Dcb->Vcb = Vcb;
/* Initialize parent's DCB list */
InitializeListHead(&Dcb->Dcb.ParentDcbList);
/* Initialize the full file name */
Dcb->FullFileName.Buffer = L"\\";
Dcb->FullFileName.Length = 1 * sizeof(WCHAR);
Dcb->FullFileName.MaximumLength = 2 * sizeof(WCHAR);
Dcb->ShortName.Name.Ansi.Buffer = "\\";
Dcb->ShortName.Name.Ansi.Length = 1;
Dcb->ShortName.Name.Ansi.MaximumLength = 2 * sizeof(CHAR);
/* Fill dirent attribute byte copy */
Dcb->DirentFatFlags = FILE_ATTRIBUTE_DIRECTORY;
/* Initialize advanced FCB header fields */
ExInitializeFastMutex(&Dcb->HeaderMutex);
FsRtlSetupAdvancedHeader(&Dcb->Header, &Dcb->HeaderMutex);
/* Set up first cluster field depending on FAT type */
if (TRUE/*FatIsFat32(Vcb)*/)
{
/* First cluster is really the first cluster of this volume */
Dcb->FirstClusterOfFile = Vcb->Bpb.RootDirFirstCluster;
/* Calculate size of FAT32 root dir */
Dcb->Header.AllocationSize.LowPart = 0xFFFFFFFF;
//FatLookupFileAllocationSize(IrpContext, Dcb);
DPRINT1("Calculation of a size of a root dir is missing!\n");
Dcb->Header.FileSize.QuadPart = Dcb->Header.AllocationSize.QuadPart;
}
else
{
#if 0
/* Add MCB entry */
FatAddMcbEntry(Vcb,
&Dcb->Mcb,
0,
FatRootDirectoryLbo(&Vcb->Bpb),
FatRootDirectorySize(&Vcb->Bpb));
/* Set a real size of the root directory */
Dcb->Header.FileSize.QuadPart = FatRootDirectorySize(&Vcb->Bpb);
Dcb->Header.AllocationSize.QuadPart = Dcb->Header.FileSize.QuadPart;
#endif
UNIMPLEMENTED;
}
}
PFCB
NTAPI
FatCreateDcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFCB ParentDcb,
IN FF_FILE *FileHandle)
{
PFCB Fcb;
/* Allocate it and zero it */
Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(FCB), TAG_FCB);
RtlZeroMemory(Fcb, sizeof(FCB));
/* Set node types */
Fcb->Header.NodeTypeCode = FAT_NTC_DCB;
Fcb->Header.NodeByteSize = sizeof(FCB);
Fcb->Condition = FcbGood;
/* Initialize resources */
Fcb->Header.Resource = &Fcb->Resource;
ExInitializeResourceLite(Fcb->Header.Resource);
Fcb->Header.PagingIoResource = &Fcb->PagingIoResource;
ExInitializeResourceLite(Fcb->Header.PagingIoResource);
/* Initialize mutexes */
Fcb->Header.FastMutex = &Fcb->HeaderMutex;
ExInitializeFastMutex(&Fcb->HeaderMutex);
FsRtlSetupAdvancedHeader(&Fcb->Header, &Fcb->HeaderMutex);
/* Insert into parent's DCB list */
InsertHeadList(&ParentDcb->Dcb.ParentDcbList, &Fcb->ParentDcbLinks);
/* Set backlinks */
Fcb->ParentFcb = ParentDcb;
Fcb->Vcb = Vcb;
/* Initialize parent dcb list */
InitializeListHead(&Fcb->Dcb.ParentDcbList);
/* Set FullFAT handle */
Fcb->FatHandle = FileHandle;
/* Set names */
if (FileHandle)
{
FatSetFcbNames(IrpContext, Fcb);
/* Ensure the full name is set */
FatSetFullFileNameInFcb(IrpContext, Fcb);
}
return Fcb;
}
IO_STATUS_BLOCK
NTAPI
FatiOpenExistingDcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
IN PVCB Vcb,
IN PFCB Dcb,
IN PACCESS_MASK DesiredAccess,
IN USHORT ShareAccess,
IN ULONG CreateDisposition,
IN BOOLEAN NoEaKnowledge,
IN BOOLEAN DeleteOnClose)
{
IO_STATUS_BLOCK Iosb = {{0}};
PCCB Ccb;
/* Exclusively lock this FCB */
FatAcquireExclusiveFcb(IrpContext, Dcb);
/* Check if it's a delete-on-close of a root DCB */
if (FatNodeType(Dcb) == FAT_NTC_ROOT_DCB && DeleteOnClose)
{
Iosb.Status = STATUS_CANNOT_DELETE;
/* Release the lock and return */
FatReleaseFcb(IrpContext, Dcb);
return Iosb;
}
/*if (NoEaKnowledge && NodeType(Dcb) != FAT_NTC_ROOT_DCB &&
!FatIsFat32(Vcb))
{
UNIMPLEMENTED;
}*/
/* Check the create disposition and desired access */
if ((CreateDisposition != FILE_OPEN) &&
(CreateDisposition != FILE_OPEN_IF))
{
Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
/* Release the lock and return */
FatReleaseFcb(IrpContext, Dcb);
return Iosb;
}
#if 0
if (!FatCheckFileAccess(IrpContext,
Dcb->DirentFatFlags,
DesiredAccess))
{
Iosb.Status = STATUS_ACCESS_DENIED;
try_return( Iosb );
}
#endif
/* If it's already opened - check share access */
if (Dcb->OpenCount > 0)
{
Iosb.Status = IoCheckShareAccess(*DesiredAccess,
ShareAccess,
FileObject,
&Dcb->ShareAccess,
TRUE);
if (!NT_SUCCESS(Iosb.Status))
{
/* Release the lock and return */
FatReleaseFcb(IrpContext, Dcb);
return Iosb;
}
}
else
{
IoSetShareAccess(*DesiredAccess,
ShareAccess,
FileObject,
&Dcb->ShareAccess);
}
/* Set the file object */
Ccb = FatCreateCcb();
FatSetFileObject(FileObject,
UserDirectoryOpen,
Dcb,
Ccb);
/* Increase counters */
Dcb->UncleanCount++;
Dcb->OpenCount++;
Vcb->OpenFileCount++;
if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
/* Set delete on close */
if (DeleteOnClose)
SetFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE);
/* Clear delay close flag */
ClearFlag(Dcb->State, FCB_STATE_DELAY_CLOSE);
/* That's it */
Iosb.Status = STATUS_SUCCESS;
Iosb.Information = FILE_OPENED;
/* Release the lock */
FatReleaseFcb(IrpContext, Dcb);
return Iosb;
}
/* EOF */

View file

@ -1,22 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/ea.c
* PURPOSE: Extended Attributes support
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS *****************************************************************/
NTSTATUS
VfatSetExtendedAttributes(PFILE_OBJECT FileObject,
PVOID Ea,
ULONG EaLength)
{
return STATUS_EAS_NOT_SUPPORTED;
}

View file

@ -1,562 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/fastfat.c
* PURPOSE: Initialization routines
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* GLOBALS ******************************************************************/
FAT_GLOBAL_DATA FatGlobalData;
FAST_MUTEX FatCloseQueueMutex;
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Fat");
NTSTATUS Status;
/* Create a device object */
Status = IoCreateDevice(DriverObject,
0,
&DeviceName,
FILE_DEVICE_DISK_FILE_SYSTEM,
0,
FALSE,
&DeviceObject);
if (!NT_SUCCESS(Status)) return Status;
/* Zero global storage */
RtlZeroMemory(&FatGlobalData, sizeof(FAT_GLOBAL_DATA));
FatGlobalData.DriverObject = DriverObject;
FatGlobalData.DiskDeviceObject = DeviceObject;
FatGlobalData.SystemProcess = PsGetCurrentProcess();
/* Fill major function handlers */
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FatClose;
DriverObject->MajorFunction[IRP_MJ_CREATE] = FatCreate;
DriverObject->MajorFunction[IRP_MJ_READ] = FatRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = FatWrite;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = FatFileSystemControl;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = FatQueryInformation;
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = FatSetInformation;
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FatDirectoryControl;
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = FatQueryVolumeInfo;
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = FatSetVolumeInfo;
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = FatShutdown;
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = FatLockControl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FatDeviceControl;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FatCleanup;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = FatFlushBuffers;
//DriverObject->MajorFunction[IRP_MJ_QUERY_EA]
//DriverObject->MajorFunction[IRP_MJ_SET_EA]
//DriverObject->MajorFunction[IRP_MJ_PNP]
DriverObject->DriverUnload = NULL;
/* Initialize cache manager callbacks */
FatGlobalData.CacheMgrCallbacks.AcquireForLazyWrite = FatAcquireForLazyWrite;
FatGlobalData.CacheMgrCallbacks.ReleaseFromLazyWrite = FatReleaseFromLazyWrite;
FatGlobalData.CacheMgrCallbacks.AcquireForReadAhead = FatAcquireForReadAhead;
FatGlobalData.CacheMgrCallbacks.ReleaseFromReadAhead = FatReleaseFromReadAhead;
FatGlobalData.CacheMgrNoopCallbacks.AcquireForLazyWrite = FatNoopAcquire;
FatGlobalData.CacheMgrNoopCallbacks.ReleaseFromLazyWrite = FatNoopRelease;
FatGlobalData.CacheMgrNoopCallbacks.AcquireForReadAhead = FatNoopAcquire;
FatGlobalData.CacheMgrNoopCallbacks.ReleaseFromReadAhead = FatNoopRelease;
/* Initialize Fast I/O dispatchers */
FatInitFastIoRoutines(&FatGlobalData.FastIoDispatch);
DriverObject->FastIoDispatch = &FatGlobalData.FastIoDispatch;
/* Initialize lookaside lists */
ExInitializeNPagedLookasideList(&FatGlobalData.NonPagedFcbList,
NULL,
NULL,
0,
sizeof(FCB),
TAG_FCB,
0);
ExInitializeNPagedLookasideList(&FatGlobalData.ResourceList,
NULL,
NULL,
0,
sizeof(ERESOURCE),
TAG_CCB,
0);
ExInitializeNPagedLookasideList(&FatGlobalData.IrpContextList,
NULL,
NULL,
0,
sizeof(FAT_IRP_CONTEXT),
TAG_IRP,
0);
/* Initialize synchronization resource for the global data */
ExInitializeResourceLite(&FatGlobalData.Resource);
/* Initialize queued close stuff */
InitializeListHead(&FatGlobalData.AsyncCloseList);
InitializeListHead(&FatGlobalData.DelayedCloseList);
FatGlobalData.FatCloseItem = IoAllocateWorkItem(DeviceObject);
ExInitializeFastMutex(&FatCloseQueueMutex);
/* Initialize global VCB list */
InitializeListHead(&FatGlobalData.VcbListHead);
/* Register and reference our filesystem */
IoRegisterFileSystem(DeviceObject);
ObReferenceObject(DeviceObject);
return STATUS_SUCCESS;
}
PFAT_IRP_CONTEXT
NTAPI
FatBuildIrpContext(PIRP Irp,
BOOLEAN CanWait)
{
PIO_STACK_LOCATION IrpSp;
PFAT_IRP_CONTEXT IrpContext;
PVOLUME_DEVICE_OBJECT VolumeObject;
/* Get current IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Allocate memory for the Irp context */
IrpContext = ExAllocateFromNPagedLookasideList(&FatGlobalData.IrpContextList);
/* Zero init memory */
RtlZeroMemory(IrpContext, sizeof(FAT_IRP_CONTEXT));
/* Save IRP, MJ and MN */
IrpContext->Irp = Irp;
IrpContext->Stack = IrpSp;
IrpContext->MajorFunction = IrpSp->MajorFunction;
IrpContext->MinorFunction = IrpSp->MinorFunction;
/* Set DeviceObject */
if (IrpSp->FileObject)
{
IrpContext->DeviceObject = IrpSp->FileObject->DeviceObject;
/* Save VCB pointer */
VolumeObject = (PVOLUME_DEVICE_OBJECT)IrpSp->DeviceObject;
IrpContext->Vcb = &VolumeObject->Vcb;
/* TODO: Handle write-through */
}
else if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL)
{
/* Handle FSCTRL case */
IrpContext->DeviceObject = IrpSp->Parameters.MountVolume.Vpb->RealDevice;
}
/* Set Wait flag */
if (CanWait) IrpContext->Flags |= IRPCONTEXT_CANWAIT;
/* Return prepared context */
return IrpContext;
}
VOID
NTAPI
FatDestroyIrpContext(PFAT_IRP_CONTEXT IrpContext)
{
PAGED_CODE();
/* Make sure it has no pinned stuff */
ASSERT(IrpContext->PinCount == 0);
/* If there is a FatIo context associated with it - free it */
if (IrpContext->FatIoContext)
{
if (!(IrpContext->Flags & IRPCONTEXT_STACK_IO_CONTEXT))
{
/* If a zero mdl was allocated - free it */
if (IrpContext->FatIoContext->ZeroMdl)
IoFreeMdl(IrpContext->FatIoContext->ZeroMdl);
/* Free memory of FatIo context */
ExFreePool(IrpContext->FatIoContext);
}
}
/* Free memory */
ExFreeToNPagedLookasideList(&FatGlobalData.IrpContextList, IrpContext);
}
VOID
NTAPI
FatCompleteRequest(PFAT_IRP_CONTEXT IrpContext OPTIONAL,
PIRP Irp OPTIONAL,
NTSTATUS Status)
{
PAGED_CODE();
if (IrpContext)
{
/* TODO: Unpin repinned BCBs */
//ASSERT(IrpContext->Repinned.Bcb[0] == NULL);
//FatUnpinRepinnedBcbs( IrpContext );
/* Destroy IRP context */
FatDestroyIrpContext(IrpContext);
}
/* Complete the IRP */
if (Irp)
{
/* Cleanup IoStatus.Information in case of error input operation */
if (NT_ERROR(Status) && (Irp->Flags & IRP_INPUT_OPERATION))
{
Irp->IoStatus.Information = 0;
}
/* Save status and complete this IRP */
Irp->IoStatus.Status = Status;
IoCompleteRequest( Irp, IO_DISK_INCREMENT );
}
}
VOID
NTAPI
FatDequeueRequest(IN PVOID Context)
{
PFAT_IRP_CONTEXT IrpContext;
IrpContext = (PFAT_IRP_CONTEXT) Context;
/* Enter critical region. */
FsRtlEnterFileSystem();
/* Handle top level IRP Correctly. */
if (!FlagOn(IrpContext->Flags, IRPCONTEXT_TOPLEVEL))
IoSetTopLevelIrp((PIRP) FSRTL_FSP_TOP_LEVEL_IRP);
/* Enable Synchronous IO. */
SetFlag(IrpContext->Flags, IRPCONTEXT_CANWAIT);
/* Invoke the handler routine. */
IrpContext->QueuedOperationHandler(IrpContext);
/* Restore top level IRP. */
IoSetTopLevelIrp(NULL);
/* Leave critical region. */
FsRtlExitFileSystem();
}
VOID
NTAPI
FatQueueRequest(IN PFAT_IRP_CONTEXT IrpContext,
IN PFAT_OPERATION_HANDLER OperationHandler)
{
/* Save the worker routine. */
IrpContext->QueuedOperationHandler = OperationHandler;
/* Indicate if top level IRP was set. */
if (IoGetTopLevelIrp() == IrpContext->Irp)
SetFlag(IrpContext->Flags, IRPCONTEXT_TOPLEVEL);
/* Initialize work item. */
ExInitializeWorkItem(&IrpContext->WorkQueueItem,
FatDequeueRequest,
IrpContext);
ExQueueWorkItem(&IrpContext->WorkQueueItem,
DelayedWorkQueue);
}
TYPE_OF_OPEN
NTAPI
FatDecodeFileObject(IN PFILE_OBJECT FileObject,
OUT PVCB *Vcb,
OUT PFCB *FcbOrDcb,
OUT PCCB *Ccb)
{
TYPE_OF_OPEN TypeOfOpen = UnopenedFileObject;
PVOID FsContext = FileObject->FsContext;
PVOID FsContext2 = FileObject->FsContext2;
/* If FsContext is NULL, then everything is NULL */
if (!FsContext)
{
*Ccb = NULL;
*FcbOrDcb = NULL;
*Vcb = NULL;
return TypeOfOpen;
}
/* CCB is always stored in FsContext2 */
*Ccb = FsContext2;
/* Switch according to the NodeType */
switch (FatNodeType(FsContext))
{
/* Volume */
case FAT_NTC_VCB:
*FcbOrDcb = NULL;
*Vcb = FsContext;
TypeOfOpen = ( *Ccb == NULL ? VirtualVolumeFile : UserVolumeOpen );
break;
/* Root or normal directory*/
case FAT_NTC_ROOT_DCB:
case FAT_NTC_DCB:
*FcbOrDcb = FsContext;
*Vcb = (*FcbOrDcb)->Vcb;
TypeOfOpen = (*Ccb == NULL ? DirectoryFile : UserDirectoryOpen);
DPRINT("Referencing a directory: %wZ\n", &(*FcbOrDcb)->FullFileName);
break;
/* File */
case FAT_NTC_FCB:
*FcbOrDcb = FsContext;
*Vcb = (*FcbOrDcb)->Vcb;
TypeOfOpen = (*Ccb == NULL ? EaFile : UserFileOpen);
DPRINT("Referencing a file: %wZ\n", &(*FcbOrDcb)->FullFileName);
break;
default:
DPRINT1("Unknown node type %x\n", FatNodeType(FsContext));
ASSERT(FALSE);
}
return TypeOfOpen;
}
VOID
NTAPI
FatSetFileObject(PFILE_OBJECT FileObject,
TYPE_OF_OPEN TypeOfOpen,
PVOID Fcb,
PCCB Ccb)
{
if (Fcb)
{
/* Check Fcb's type */
if (FatNodeType(Fcb) == FAT_NTC_VCB)
{
FileObject->Vpb = ((PVCB)Fcb)->Vpb;
}
else
{
FileObject->Vpb = ((PFCB)Fcb)->Vcb->Vpb;
}
}
/* Set FsContext */
if (FileObject)
{
FileObject->FsContext = Fcb;
FileObject->FsContext2 = Ccb;
}
}
BOOLEAN
NTAPI
FatAcquireExclusiveVcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb)
{
/* Acquire VCB's resource if possible */
if (ExAcquireResourceExclusiveLite(&Vcb->Resource,
BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
{
return TRUE;
}
else
{
return FALSE;
}
}
BOOLEAN
NTAPI
FatAcquireSharedVcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb)
{
/* Acquire VCB's resource if possible */
if (ExAcquireResourceSharedLite(&Vcb->Resource,
BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
{
return TRUE;
}
else
{
return FALSE;
}
}
VOID
NTAPI
FatReleaseVcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb)
{
/* Release VCB's resource */
ExReleaseResourceLite(&Vcb->Resource);
}
BOOLEAN
NTAPI
FatAcquireExclusiveFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb)
{
RetryLockingE:
/* Try to acquire the exclusive lock*/
if (ExAcquireResourceExclusiveLite(Fcb->Header.Resource,
BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
{
/* Wait same way MS's FASTFAT wait, i.e.
checking that there are outstanding async writes,
or someone is waiting on it*/
if (Fcb->OutstandingAsyncWrites &&
((IrpContext->MajorFunction != IRP_MJ_WRITE) ||
!FlagOn(IrpContext->Irp->Flags, IRP_NOCACHE) ||
ExGetSharedWaiterCount(Fcb->Header.Resource) ||
ExGetExclusiveWaiterCount(Fcb->Header.Resource)))
{
KeWaitForSingleObject(Fcb->OutstandingAsyncEvent,
Executive,
KernelMode,
FALSE,
NULL);
/* Release the lock */
FatReleaseFcb(IrpContext, Fcb);
/* Retry */
goto RetryLockingE;
}
/* Return success */
return TRUE;
}
/* Return failure */
return FALSE;
}
BOOLEAN
NTAPI
FatAcquireSharedFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb)
{
RetryLockingS:
/* Try to acquire the shared lock*/
if (ExAcquireResourceSharedLite(Fcb->Header.Resource,
BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
{
/* Wait same way MS's FASTFAT wait, i.e.
checking that there are outstanding async writes,
or someone is waiting on it*/
if (Fcb->OutstandingAsyncWrites &&
((IrpContext->MajorFunction != IRP_MJ_WRITE) ||
!FlagOn(IrpContext->Irp->Flags, IRP_NOCACHE) ||
ExGetSharedWaiterCount(Fcb->Header.Resource) ||
ExGetExclusiveWaiterCount(Fcb->Header.Resource)))
{
KeWaitForSingleObject(Fcb->OutstandingAsyncEvent,
Executive,
KernelMode,
FALSE,
NULL);
/* Release the lock */
FatReleaseFcb(IrpContext, Fcb);
/* Retry */
goto RetryLockingS;
}
/* Return success */
return TRUE;
}
/* Return failure */
return FALSE;
}
VOID
NTAPI
FatReleaseFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb)
{
/* Release FCB's resource */
ExReleaseResourceLite(Fcb->Header.Resource);
}
PVOID
FASTCALL
FatMapUserBuffer(PIRP Irp)
{
if (!Irp->MdlAddress)
return Irp->UserBuffer;
else
return MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
}
BOOLEAN
NTAPI
FatIsTopLevelIrp(IN PIRP Irp)
{
if (!IoGetTopLevelIrp())
{
IoSetTopLevelIrp(Irp);
return TRUE;
}
return FALSE;
}
VOID
NTAPI
FatNotifyReportChange(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFCB Fcb,
IN ULONG Filter,
IN ULONG Action)
{
if (Fcb->FullFileName.Buffer == NULL)
FatSetFullFileNameInFcb(IrpContext, Fcb);
ASSERT(Fcb->FullFileName.Length != 0 );
ASSERT(Fcb->FileNameLength != 0 );
ASSERT(Fcb->FullFileName.Length > Fcb->FileNameLength );
ASSERT(Fcb->FullFileName.Buffer[(Fcb->FullFileName.Length - Fcb->FileNameLength)/sizeof(WCHAR) - 1] == L'\\' );
FsRtlNotifyFullReportChange(Vcb->NotifySync,
&Vcb->NotifyList,
(PSTRING)&Fcb->FullFileName,
(USHORT)(Fcb->FullFileName.Length -
Fcb->FileNameLength),
NULL,
NULL,
Filter,
Action,
NULL);
}
/* EOF */

View file

@ -1,408 +0,0 @@
#include <ntifs.h>
#include <bugcodes.h>
#include <ntdddisk.h>
#include <debug.h>
#include <pseh/pseh2.h>
#include "fullfat.h"
#include <fat.h>
#include <fatstruc.h>
#define Add2Ptr(P,I,T) ((T)((PUCHAR)(P) + (I)))
#define PtrOffset(B,O) ((ULONG)((ULONG_PTR)(O) - (ULONG_PTR)(B)))
#define TAG_CCB 'BCCV'
#define TAG_FCB 'BCFV'
#define TAG_IRP 'PRIV'
#define TAG_VFAT 'TAFV'
#define TAG_FSD_CLOSE_CONTEXT 'CLCV'
/* Global resource acquire/release */
#define FatAcquireExclusiveGlobal(IrpContext) \
( \
ExAcquireResourceExclusiveLite(&FatGlobalData.Resource, \
(IrpContext)->Flags & IRPCONTEXT_CANWAIT) \
)
#define FatAcquireSharedGlobal(IrpContext) \
( \
ExAcquireResourceSharedLite(&FatGlobalData.Resource, \
(IrpContext)->Flags & IRPCONTEXT_CANWAIT) \
)
#define FatReleaseGlobal(IrpContext) \
{ \
ExReleaseResourceLite(&(FatGlobalData.Resource)); \
}
#define FatIsFastIoPossible(FCB) ((BOOLEAN) \
(((FCB)->Condition != FcbGood || !FsRtlOplockIsFastIoPossible(&(FCB)->Fcb.Oplock)) ? \
FastIoIsNotPossible \
: \
(!FsRtlAreThereCurrentFileLocks(&(FCB)->Fcb.Lock) && \
((FCB)->OutstandingAsyncWrites == 0) && \
!FlagOn((FCB)->Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED) ? \
FastIoIsPossible \
: \
FastIoIsQuestionable \
) \
) \
)
#define IsFileObjectReadOnly(FO) (!((FO)->WriteAccess | (FO)->DeleteAccess))
#define IsFileDeleted(FCB) (FlagOn((FCB)->State, FCB_STATE_DELETE_ON_CLOSE) && ((FCB)->UncleanCount == 0))
BOOLEAN
FORCEINLINE
FatIsIoRangeValid(IN LARGE_INTEGER Start, IN ULONG Length)
{
/* Check if it's more than 32bits, or if the length causes 32bit overflow.
FAT-specific! */
return !(Start.HighPart || Start.LowPart + Length < Start.LowPart);
}
NTSYSAPI
NTSTATUS
NTAPI
RtlUpcaseUnicodeStringToCountedOemString(
IN OUT POEM_STRING DestinationString,
IN PCUNICODE_STRING SourceString,
IN BOOLEAN AllocateDestinationString
);
/* ------------------------------------------------------ shutdown.c */
DRIVER_DISPATCH FatShutdown;
NTSTATUS NTAPI
FatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp);
/* -------------------------------------------------------- volume.c */
NTSTATUS NTAPI
FatQueryVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS NTAPI
FatSetVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp);
VOID NTAPI
FatReadStreamFile(PVCB Vcb,
ULONGLONG ByteOffset,
ULONG ByteSize,
PBCB *Bcb,
PVOID *Buffer);
BOOLEAN
NTAPI
FatCheckForDismount(IN PFAT_IRP_CONTEXT IrpContext,
PVCB Vcb,
IN BOOLEAN Force);
/* ----------------------------------------------------------- dir.c */
NTSTATUS NTAPI
FatDirectoryControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
VOID NTAPI
FatCreateRootDcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb);
PFCB NTAPI
FatCreateDcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFCB ParentDcb,
IN FF_FILE *FileHandle);
IO_STATUS_BLOCK NTAPI
FatiOpenExistingDcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
IN PVCB Vcb,
IN PFCB Dcb,
IN PACCESS_MASK DesiredAccess,
IN USHORT ShareAccess,
IN ULONG CreateDisposition,
IN BOOLEAN NoEaKnowledge,
IN BOOLEAN DeleteOnClose);
/* -------------------------------------------------------- create.c */
IO_STATUS_BLOCK
NTAPI
FatiOverwriteFile(PFAT_IRP_CONTEXT IrpContext,
PFILE_OBJECT FileObject,
PFCB Fcb,
ULONG AllocationSize,
PFILE_FULL_EA_INFORMATION EaBuffer,
ULONG EaLength,
UCHAR FileAttributes,
ULONG CreateDisposition,
BOOLEAN NoEaKnowledge);
NTSTATUS NTAPI
FatCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
/* --------------------------------------------------------- close.c */
NTSTATUS NTAPI
FatClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
/* ------------------------------------------------------- cleanup.c */
NTSTATUS NTAPI
FatCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp);
/* --------------------------------------------------------- fastio.c */
VOID
FatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch);
BOOLEAN NTAPI
FatAcquireForLazyWrite(IN PVOID Context,
IN BOOLEAN Wait);
VOID NTAPI
FatReleaseFromLazyWrite(IN PVOID Context);
BOOLEAN NTAPI
FatAcquireForReadAhead(IN PVOID Context,
IN BOOLEAN Wait);
VOID NTAPI
FatReleaseFromReadAhead(IN PVOID Context);
BOOLEAN NTAPI
FatNoopAcquire(IN PVOID Context,
IN BOOLEAN Wait);
VOID NTAPI
FatNoopRelease(IN PVOID Context);
/* --------------------------------------------------------- fastfat.c */
extern FAST_MUTEX FatCloseQueueMutex;
PFAT_IRP_CONTEXT NTAPI
FatBuildIrpContext(PIRP Irp, BOOLEAN CanWait);
VOID NTAPI
FatDestroyIrpContext(PFAT_IRP_CONTEXT IrpContext);
VOID
NTAPI
FatQueueRequest(IN PFAT_IRP_CONTEXT IrpContext,
IN PFAT_OPERATION_HANDLER OperationHandler);
VOID NTAPI
FatCompleteRequest(PFAT_IRP_CONTEXT IrpContext OPTIONAL,
PIRP Irp OPTIONAL,
NTSTATUS Status);
BOOLEAN NTAPI
FatAcquireExclusiveVcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb);
BOOLEAN NTAPI
FatAcquireSharedVcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb);
VOID NTAPI
FatReleaseVcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb);
BOOLEAN NTAPI
FatAcquireExclusiveFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb);
BOOLEAN NTAPI
FatAcquireSharedFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb);
VOID NTAPI
FatReleaseFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb);
TYPE_OF_OPEN
NTAPI
FatDecodeFileObject(IN PFILE_OBJECT FileObject,
OUT PVCB *Vcb,
OUT PFCB *FcbOrDcb,
OUT PCCB *Ccb);
VOID NTAPI
FatSetFileObject(PFILE_OBJECT FileObject,
TYPE_OF_OPEN TypeOfOpen,
PVOID Fcb,
PCCB Ccb);
PVOID FASTCALL
FatMapUserBuffer(PIRP Irp);
BOOLEAN NTAPI
FatIsTopLevelIrp(IN PIRP Irp);
VOID NTAPI
FatNotifyReportChange(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFCB Fcb,
IN ULONG Filter,
IN ULONG Action);
/* --------------------------------------------------------- fullfat.c */
FF_T_SINT32
FatWriteBlocks(FF_T_UINT8 *pBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Count, void *pParam);
FF_T_SINT32
FatReadBlocks(FF_T_UINT8 *pBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Count, void *pParam);
VOID NTAPI
FatQueryFileTimes(OUT PLARGE_INTEGER FileTimes,
IN PDIR_ENTRY Dirent);
/* --------------------------------------------------------- lock.c */
NTSTATUS NTAPI
FatLockControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
VOID NTAPI
FatOplockComplete(IN PVOID Context,
IN PIRP Irp);
VOID NTAPI
FatPrePostIrp(IN PVOID Context,
IN PIRP Irp);
/* --------------------------------------------------------- fsctl.c */
NTSTATUS NTAPI
FatFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
/* --------------------------------------------------------- finfo.c */
NTSTATUS NTAPI FatQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS NTAPI FatSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
/* --------------------------------------------------------- fullfat.c */
FF_FILE *FF_OpenW(FF_IOMAN *pIoman, PUNICODE_STRING pathW, FF_T_UINT8 Mode, FF_ERROR *pError);
/* --------------------------------------------------------- iface.c */
NTSTATUS
NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
/* ----------------------------------------------------------- fat.c */
NTSTATUS NTAPI
FatInitializeVcb(
IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDEVICE_OBJECT TargetDeviceObject,
IN PVPB Vpb);
VOID NTAPI
FatUninitializeVcb(
IN PVCB Vcb);
/* ------------------------------------------------------ device.c */
NTSTATUS NTAPI
FatDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS
FatPerformDevIoCtrl(PDEVICE_OBJECT DeviceObject,
ULONG ControlCode,
PVOID InputBuffer,
ULONG InputBufferSize,
PVOID OutputBuffer,
ULONG OutputBufferSize,
BOOLEAN Override);
/* ----------------------------------------------------------- fcb.c */
PFCB NTAPI
FatCreateFcb(
IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFCB ParentDcb,
IN FF_FILE *FileHandle);
VOID NTAPI
FatDeleteFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb);
IO_STATUS_BLOCK NTAPI
FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFILE_OBJECT FileObject,
IN PVCB Vcb,
IN PFCB Fcb,
IN PACCESS_MASK DesiredAccess,
IN USHORT ShareAccess,
IN ULONG AllocationSize,
IN PFILE_FULL_EA_INFORMATION EaBuffer,
IN ULONG EaLength,
IN UCHAR FileAttributes,
IN ULONG CreateDisposition,
IN BOOLEAN NoEaKnowledge,
IN BOOLEAN DeleteOnClose,
IN BOOLEAN OpenedAsDos,
OUT PBOOLEAN OplockPostIrp);
PFCB NTAPI
FatFindFcb(PFAT_IRP_CONTEXT IrpContext,
PRTL_SPLAY_LINKS *RootNode,
PSTRING AnsiName,
PBOOLEAN IsDosName);
VOID NTAPI
FatInsertName(IN PFAT_IRP_CONTEXT IrpContext,
IN PRTL_SPLAY_LINKS *RootNode,
IN PFCB_NAME_LINK Name);
VOID NTAPI
FatRemoveNames(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb);
PCCB NTAPI
FatCreateCcb(VOID);
VOID NTAPI
FatDeleteCcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PCCB Ccb);
VOID NTAPI
FatSetFullNameInFcb(PFCB Fcb,
PUNICODE_STRING Name);
VOID NTAPI
FatSetFullFileNameInFcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb);
VOID NTAPI
FatSetFcbNames(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb);
VOID NTAPI
Fati8dot3ToString(IN PCHAR FileName,
IN BOOLEAN DownCase,
OUT POEM_STRING OutString);
/* ------------------------------------------------------------ rw.c */
NTSTATUS NTAPI
FatRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS NTAPI
FatWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp);
/* ------------------------------------------------------------- flush.c */
NTSTATUS NTAPI
FatFlushBuffers(PDEVICE_OBJECT DeviceObject, PIRP Irp);
/* EOF */

View file

@ -1,5 +0,0 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "VFAT IFS Driver"
#define REACTOS_STR_INTERNAL_NAME "vfatfs"
#define REACTOS_STR_ORIGINAL_FILENAME "vfatfs.sys"
#include <reactos/version.rc>

View file

@ -1,288 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/fastio.c
* PURPOSE: Fast IO routines
* PROGRAMMERS: Herve Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
BOOLEAN
NTAPI
FatFastIoCheckIfPossible(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
IN BOOLEAN CheckForReadOperation,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
/* Prevent all Fast I/O requests */
DPRINT("FatFastIoCheckIfPossible(): returning FALSE.\n");
return FALSE;
}
BOOLEAN
NTAPI
FatFastIoRead(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatFastIoRead()\n");
return FALSE;
}
BOOLEAN
NTAPI
FatFastIoWrite(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN ULONG LockKey,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatFastIoWrite()\n");
return FALSE;
}
BOOLEAN
NTAPI
FatFastIoQueryBasicInfo(IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
OUT PFILE_BASIC_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatFastIoQueryBasicInfo()\n");
return FALSE;
}
BOOLEAN
NTAPI
FatFastIoQueryStandardInfo(IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
OUT PFILE_STANDARD_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatFastIoQueryStandardInfo\n");
return FALSE;
}
BOOLEAN
NTAPI
FatFastIoLock(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length,
PEPROCESS ProcessId,
ULONG Key,
BOOLEAN FailImmediately,
BOOLEAN ExclusiveLock,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatFastIoLock\n");
return FALSE;
}
BOOLEAN
NTAPI
FatFastIoUnlockSingle(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PLARGE_INTEGER Length,
PEPROCESS ProcessId,
ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatFastIoUnlockSingle\n");
return FALSE;
}
BOOLEAN
NTAPI
FatFastIoUnlockAll(IN PFILE_OBJECT FileObject,
PEPROCESS ProcessId,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatFastIoUnlockAll\n");
return FALSE;
}
BOOLEAN
NTAPI
FatFastIoUnlockAllByKey(IN PFILE_OBJECT FileObject,
PVOID ProcessId,
ULONG Key,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatFastIoUnlockAllByKey\n");
return FALSE;
}
BOOLEAN
NTAPI
FatFastIoQueryNetworkOpenInfo(IN PFILE_OBJECT FileObject,
IN BOOLEAN Wait,
OUT PFILE_NETWORK_OPEN_INFORMATION Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatFastIoQueryNetworkOpenInfo\n");
return FALSE;
}
BOOLEAN
NTAPI
FatMdlRead(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG LockKey,
OUT PMDL* MdlChain,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatMdlRead\n");
return FALSE;
}
BOOLEAN
NTAPI
FatMdlReadComplete(IN PFILE_OBJECT FileObject,
IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatMdlReadComplete\n");
return FALSE;
}
BOOLEAN
NTAPI
FatPrepareMdlWrite(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG LockKey,
OUT PMDL* MdlChain,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatPrepareMdlWrite\n");
return FALSE;
}
BOOLEAN
NTAPI
FatMdlWriteComplete(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatMdlWriteComplete\n");
return FALSE;
}
NTSTATUS
NTAPI
FatAcquireForCcFlush(IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatAcquireForCcFlush\n");
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
FatReleaseForCcFlush(IN PFILE_OBJECT FileObject,
IN PDEVICE_OBJECT DeviceObject)
{
DPRINT("FatReleaseForCcFlush\n");
return STATUS_SUCCESS;
}
BOOLEAN
NTAPI
FatAcquireForLazyWrite(IN PVOID Context,
IN BOOLEAN Wait)
{
DPRINT("FatAcquireForLazyWrite()\n");
return FALSE;
}
VOID
NTAPI
FatReleaseFromLazyWrite(IN PVOID Context)
{
DPRINT("FatReleaseFromLazyWrite()\n");
}
BOOLEAN
NTAPI
FatAcquireForReadAhead(IN PVOID Context,
IN BOOLEAN Wait)
{
DPRINT("FatAcquireForReadAhead()\n");
return FALSE;
}
VOID
NTAPI
FatReleaseFromReadAhead(IN PVOID Context)
{
DPRINT("FatReleaseFromReadAhead()\n");
}
BOOLEAN
NTAPI
FatNoopAcquire(IN PVOID Context,
IN BOOLEAN Wait)
{
return TRUE;
}
VOID
NTAPI
FatNoopRelease(IN PVOID Context)
{
}
VOID
FatInitFastIoRoutines(PFAST_IO_DISPATCH FastIoDispatch)
{
/* Set Fast I/O dispatcher callbacks */
FastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
FastIoDispatch->FastIoCheckIfPossible = FatFastIoCheckIfPossible;
FastIoDispatch->FastIoRead = FatFastIoRead;
FastIoDispatch->FastIoWrite = FatFastIoWrite;
FastIoDispatch->FastIoQueryBasicInfo = FatFastIoQueryBasicInfo;
FastIoDispatch->FastIoQueryStandardInfo = FatFastIoQueryStandardInfo;
FastIoDispatch->FastIoLock = FatFastIoLock;
FastIoDispatch->FastIoUnlockSingle = FatFastIoUnlockSingle;
FastIoDispatch->FastIoUnlockAll = FatFastIoUnlockAll;
FastIoDispatch->FastIoUnlockAllByKey = FatFastIoUnlockAllByKey;
FastIoDispatch->FastIoQueryNetworkOpenInfo = FatFastIoQueryNetworkOpenInfo;
FastIoDispatch->MdlRead = FatMdlRead;
FastIoDispatch->MdlReadComplete = FatMdlReadComplete;
FastIoDispatch->PrepareMdlWrite = FatPrepareMdlWrite;
FastIoDispatch->MdlWriteComplete = FatMdlWriteComplete;
FastIoDispatch->AcquireForCcFlush = FatAcquireForCcFlush;
FastIoDispatch->ReleaseForCcFlush = FatReleaseForCcFlush;
}
/* EOF */

View file

@ -1,266 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/fat.c
* PURPOSE: FAT support routines
* PROGRAMMERS: Aleksey Bragin <aleksey@reactos.org>
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* PROTOTYPES ***************************************************************/
BOOLEAN
NTAPI
FatValidBpb(IN PBIOS_PARAMETER_BLOCK Bpb);
/* VARIABLES ****************************************************************/
BOOLEAN
NTAPI
FatValidBpb(IN PBIOS_PARAMETER_BLOCK Bpb)
{
return (FatValidBytesPerSector(Bpb->BytesPerSector)
&& FatValidSectorsPerCluster(Bpb->SectorsPerCluster)
&& Bpb->ReservedSectors > 0
&& Bpb->Fats > 0
&& (Bpb->Sectors > 0 || Bpb->LargeSectors > 0)
&& (Bpb->SectorsPerFat > 0
|| (Bpb->LargeSectorsPerFat > 0 && Bpb->FsVersion == 0))
&& (Bpb->Media == 0xf0
|| Bpb->Media == 0xf8
|| Bpb->Media == 0xf9
|| Bpb->Media == 0xfb
|| Bpb->Media == 0xfc
|| Bpb->Media == 0xfd
|| Bpb->Media == 0xfe
|| Bpb->Media == 0xff)
&& (Bpb->SectorsPerFat == 0 || Bpb->RootEntries > 0)
&& (Bpb->SectorsPerFat > 0 || !Bpb->MirrorDisabled));
}
/**
* Determines the index of the set bit.
*
* @param Number
* Number having a single bit set.
*
* @return
* Index of the set bit.
*/
FORCEINLINE
ULONG
FatPowerOfTwo(
ULONG Number)
{
ULONG Temp;
Temp = Number
- ((Number >> 1) & 033333333333)
- ((Number >> 2) & 011111111111);
return (((Temp + (Temp >> 3)) & 030707070707) % 63);
}
VOID
NTAPI
FatiInitializeVcb(PVCB Vcb)
{
ULONG ClustersCapacity;
/* Various characteristics needed for navigation in FAT */
if ((Vcb->Sectors = Vcb->Bpb.Sectors) == 0)
Vcb->Sectors = Vcb->Bpb.LargeSectors;
if ((Vcb->SectorsPerFat = Vcb->Bpb.SectorsPerFat) == 0)
Vcb->SectorsPerFat = Vcb->Bpb.LargeSectorsPerFat;
Vcb->RootDirent = Vcb->Bpb.ReservedSectors + Vcb->Bpb.Fats * Vcb->SectorsPerFat;
Vcb->RootDirentSectors = BytesToSectors(Vcb,
Vcb->Bpb.RootEntries * sizeof(DIR_ENTRY));
Vcb->DataArea = Vcb->RootDirent + Vcb->RootDirentSectors;
Vcb->Clusters = (Vcb->Sectors - Vcb->Bpb.ReservedSectors
- Vcb->Bpb.Fats * Vcb->SectorsPerFat
- Vcb->RootDirentSectors) / Vcb->Bpb.SectorsPerCluster;
if (Vcb->BytesPerClusterLog < 4087)
{
Vcb->IndexDepth = 0x0c;
//Vcb->Methods = Fat12Methods;
}
else
{
Vcb->IndexDepth = 0x10;
//Vcb->Methods = Fat16Methods;
}
/* Large Sectors are used for FAT32 */
if (Vcb->Bpb.Sectors == 0) {
Vcb->IndexDepth = 0x20;
//Vcb->Methods = Fat32Methods;
}
ClustersCapacity = (SectorsToBytes(Vcb, Vcb->Sectors) * 0x8 / Vcb->IndexDepth) - 1;
if (Vcb->Clusters > ClustersCapacity)
Vcb->Clusters = ClustersCapacity;
Vcb->BytesPerCluster = SectorsToBytes(Vcb, Vcb->Bpb.SectorsPerCluster);
Vcb->BytesPerClusterLog = FatPowerOfTwo(Vcb->BytesPerCluster);
Vcb->BeyondLastClusterInFat = ((LONGLONG) Vcb->Clusters) * Vcb->IndexDepth / 0x8;
/* Update real volume size with the real value. */
Vcb->Header.FileSize.QuadPart =
Vcb->Header.AllocationSize.QuadPart = SectorsToBytes(Vcb, Vcb->Sectors);
}
NTSTATUS
NTAPI
FatInitializeVcb(IN PFAT_IRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PDEVICE_OBJECT TargetDeviceObject,
IN PVPB Vpb)
{
NTSTATUS Status;
PBCB Bcb;
PVOID Buffer;
LARGE_INTEGER Offset;
RtlZeroMemory(Vcb, sizeof(*Vcb));
/* Initialize list head, so that it will
* not fail in cleanup.
*/
InitializeListHead(&Vcb->VcbLinks);
/* Setup FCB Header */
Vcb->Header.NodeTypeCode = FAT_NTC_VCB;
Vcb->Header.NodeByteSize = sizeof(*Vcb);
/* Setup Vcb fields */
Vcb->TargetDeviceObject = TargetDeviceObject;
ObReferenceObject(TargetDeviceObject);
Vcb->Vpb = Vpb;
/* Setup FCB Header */
ExInitializeFastMutex(&Vcb->HeaderMutex);
FsRtlSetupAdvancedHeader(&Vcb->Header, &Vcb->HeaderMutex);
/* Create Volume File Object */
Vcb->StreamFileObject = IoCreateStreamFileObject(NULL,
Vcb->TargetDeviceObject);
/* We have to setup all FCB fields needed for CC */
Vcb->StreamFileObject->FsContext = Vcb;
Vcb->StreamFileObject->SectionObjectPointer = &Vcb->SectionObjectPointers;
/* At least full boot sector should be available */
//Vcb->Header.FileSize.QuadPart = sizeof(PACKED_BOOT_SECTOR);
//Vcb->Header.AllocationSize.QuadPart = sizeof(PACKED_BOOT_SECTOR);
Vcb->Header.ValidDataLength.HighPart = MAXLONG;
Vcb->Header.ValidDataLength.LowPart = MAXULONG;
Vcb->Header.AllocationSize.QuadPart = Int32x32To64(5*1024, 1024*1024); //HACK: 5 Gb
Vcb->Header.FileSize.QuadPart = Vcb->Header.AllocationSize.QuadPart;
/* Set VCB to a good condition */
Vcb->Condition = VcbGood;
/* Initialize VCB's resource */
ExInitializeResourceLite(&Vcb->Resource);
/* Initialize close queue lists */
InitializeListHead(&Vcb->AsyncCloseList);
InitializeListHead(&Vcb->DelayedCloseList);
/* Initialize CC */
CcInitializeCacheMap(Vcb->StreamFileObject,
(PCC_FILE_SIZES)&Vcb->Header.AllocationSize,
FALSE,
&FatGlobalData.CacheMgrNoopCallbacks,
Vcb);
/* Read boot sector */
Offset.QuadPart = 0;
Bcb = NULL;
/* Note: Volume Read path does not require
* any of the parameters set further
* in this routine.
*/
if (CcMapData(Vcb->StreamFileObject,
&Offset,
sizeof(PACKED_BOOT_SECTOR),
TRUE,
&Bcb,
&Buffer))
{
PPACKED_BOOT_SECTOR BootSector = (PPACKED_BOOT_SECTOR) Buffer;
FatUnpackBios(&Vcb->Bpb, &BootSector->PackedBpb);
if (!(FatBootSectorJumpValid(BootSector->Jump) &&
FatValidBpb(&Vcb->Bpb)))
{
Status = STATUS_UNRECOGNIZED_VOLUME;
}
CopyUchar4(&Vcb->Vpb->SerialNumber, BootSector->Id);
CcUnpinData(Bcb);
}
else
{
Status = STATUS_UNRECOGNIZED_VOLUME;
goto FatInitializeVcbCleanup;
}
/* Increase internal / residual open counter */
InterlockedIncrement((PLONG)&(Vcb->InternalOpenCount));
InterlockedIncrement((PLONG)&(Vcb->ResidualOpenCount));
/* Set up notifications */
FsRtlNotifyInitializeSync(&Vcb->NotifySync);
InitializeListHead(&Vcb->NotifyList);
/* Call helper function */
FatiInitializeVcb(Vcb);
/* Add this Vcb to global Vcb list */
(VOID)FatAcquireExclusiveGlobal(IrpContext);
InsertTailList(&FatGlobalData.VcbListHead, &Vcb->VcbLinks);
FatReleaseGlobal(IrpContext);
return STATUS_SUCCESS;
FatInitializeVcbCleanup:
/* Unwind the routine actions */
FatUninitializeVcb(Vcb);
return Status;
}
VOID
NTAPI
FatUninitializeVcb(IN PVCB Vcb)
{
LARGE_INTEGER ZeroSize;
ZeroSize.QuadPart = 0LL;
/* Close volume file */
if (Vcb->StreamFileObject != NULL)
{
/* Uninitialize CC. */
CcUninitializeCacheMap(Vcb->StreamFileObject, &ZeroSize, NULL);
ObDereferenceObject(Vcb->StreamFileObject);
Vcb->StreamFileObject = NULL;
}
/* Free ContextClose if it's not freed up already */
if (Vcb->CloseContext) ExFreePool(Vcb->CloseContext);
/* Free notifications stuff */
FsRtlNotifyUninitializeSync(&Vcb->NotifySync);
/* Unlink from global Vcb list. */
RemoveEntryList(&Vcb->VcbLinks);
/* Release Target Device */
ObDereferenceObject(Vcb->TargetDeviceObject);
Vcb->TargetDeviceObject = NULL;
}
/* EOF */

View file

@ -1,289 +0,0 @@
#pragma once
//
// Might be a good idea to have this as a shared
// header with FS Recognizer.
//
//
// Conversion types and macros taken from internal ntifs headers
//
typedef union _UCHAR1
{
UCHAR Uchar[1];
UCHAR ForceAlignment;
} UCHAR1, *PUCHAR1;
typedef union _UCHAR2
{
UCHAR Uchar[2];
USHORT ForceAlignment;
} UCHAR2, *PUCHAR2;
typedef union _UCHAR4
{
UCHAR Uchar[4];
ULONG ForceAlignment;
} UCHAR4, *PUCHAR4;
#define CopyUchar1(Dst,Src) { \
*((UCHAR1 *)(Dst)) = *((UNALIGNED UCHAR1 *)(Src)); \
}
#define CopyUchar2(Dst,Src) { \
*((UCHAR2 *)(Dst)) = *((UNALIGNED UCHAR2 *)(Src)); \
}
#define CopyUchar4(Dst,Src) { \
*((UCHAR4 *)(Dst)) = *((UNALIGNED UCHAR4 *)(Src)); \
}
#define FatUnpackBios(Bios,Pbios) { \
CopyUchar2(&(Bios)->BytesPerSector, &(Pbios)->BytesPerSector[0] ); \
CopyUchar1(&(Bios)->SectorsPerCluster, &(Pbios)->SectorsPerCluster[0]); \
CopyUchar2(&(Bios)->ReservedSectors, &(Pbios)->ReservedSectors[0] ); \
CopyUchar1(&(Bios)->Fats, &(Pbios)->Fats[0] ); \
CopyUchar2(&(Bios)->RootEntries, &(Pbios)->RootEntries[0] ); \
CopyUchar2(&(Bios)->Sectors, &(Pbios)->Sectors[0] ); \
CopyUchar1(&(Bios)->Media, &(Pbios)->Media[0] ); \
CopyUchar2(&(Bios)->SectorsPerFat, &(Pbios)->SectorsPerFat[0] ); \
CopyUchar2(&(Bios)->SectorsPerTrack, &(Pbios)->SectorsPerTrack[0] ); \
CopyUchar2(&(Bios)->Heads, &(Pbios)->Heads[0] ); \
CopyUchar4(&(Bios)->HiddenSectors, &(Pbios)->HiddenSectors[0] ); \
CopyUchar4(&(Bios)->LargeSectors, &(Pbios)->LargeSectors[0] ); \
CopyUchar4(&(Bios)->LargeSectors, &(Pbios)->LargeSectors[0] ); \
CopyUchar4(&(Bios)->LargeSectorsPerFat,&((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->LargeSectorsPerFat[0] ); \
CopyUchar2(&(Bios)->ExtendedFlags, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->ExtendedFlags[0] ); \
CopyUchar2(&(Bios)->FsVersion, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->FsVersion[0] ); \
CopyUchar4(&(Bios)->RootDirFirstCluster, \
&((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->RootDirFirstCluster[0] ); \
CopyUchar2(&(Bios)->FsInfoSector, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->FsInfoSector[0] ); \
CopyUchar2(&(Bios)->BackupBootSector, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)Pbios)->BackupBootSector[0] ); \
}
//
// Packed versions of the BPB and Boot Sector
//
typedef struct _PACKED_BIOS_PARAMETER_BLOCK
{
UCHAR BytesPerSector[2];
UCHAR SectorsPerCluster[1];
UCHAR ReservedSectors[2];
UCHAR Fats[1];
UCHAR RootEntries[2];
UCHAR Sectors[2];
UCHAR Media[1];
UCHAR SectorsPerFat[2];
UCHAR SectorsPerTrack[2];
UCHAR Heads[2];
UCHAR HiddenSectors[4];
UCHAR LargeSectors[4];
} PACKED_BIOS_PARAMETER_BLOCK, *PPACKED_BIOS_PARAMETER_BLOCK;
// sizeof = 0x019
typedef struct _PACKED_BIOS_PARAMETER_BLOCK_EX
{
PACKED_BIOS_PARAMETER_BLOCK Block;
UCHAR LargeSectorsPerFat[4];
UCHAR ExtendedFlags[2];
UCHAR FsVersion[2];
UCHAR RootDirFirstCluster[4];
UCHAR FsInfoSector[2];
UCHAR BackupBootSector[2];
UCHAR Reserved[12];
} PACKED_BIOS_PARAMETER_BLOCK_EX, *PPACKED_BIOS_PARAMETER_BLOCK_EX;
// sizeof = 0x035 53
//
// Unpacked version of the BPB
//
typedef struct BIOS_PARAMETER_BLOCK
{
USHORT BytesPerSector;
UCHAR SectorsPerCluster;
USHORT ReservedSectors;
UCHAR Fats;
USHORT RootEntries;
USHORT Sectors;
UCHAR Media;
USHORT SectorsPerFat;
USHORT SectorsPerTrack;
USHORT Heads;
ULONG HiddenSectors;
ULONG LargeSectors;
ULONG LargeSectorsPerFat;
union
{
USHORT ExtendedFlags;
struct
{
ULONG ActiveFat:4;
ULONG Reserved0:3;
ULONG MirrorDisabled:1;
ULONG Reserved1:8;
};
};
USHORT FsVersion;
ULONG RootDirFirstCluster;
USHORT FsInfoSector;
USHORT BackupBootSector;
} BIOS_PARAMETER_BLOCK, *PBIOS_PARAMETER_BLOCK;
#define FatValidBytesPerSector(xBytes) \
(!((xBytes) & ((xBytes)-1)) && (xBytes)>=0x80 && (xBytes)<=0x1000)
#define FatValidSectorsPerCluster(xSectors) \
(!((xSectors) & ((xSectors)-1)) && (xSectors)>0 && (xSectors)<=0x80)
typedef struct _PACKED_BOOT_SECTOR
{
UCHAR Jump[3];
UCHAR Oem[8];
PACKED_BIOS_PARAMETER_BLOCK PackedBpb;
UCHAR PhysicalDriveNumber;
UCHAR CurrentHead;
UCHAR Signature;
UCHAR Id[4];
UCHAR VolumeLabel[11];
UCHAR SystemId[8];
} PACKED_BOOT_SECTOR, *PPACKED_BOOT_SECTOR;
// sizeof = 0x03E
typedef struct _PACKED_BOOT_SECTOR_EX
{
UCHAR Jump[3];
UCHAR Oem[8];
PACKED_BIOS_PARAMETER_BLOCK_EX PackedBpb;
UCHAR PhysicalDriveNumber;
UCHAR CurrentHead;
UCHAR Signature;
UCHAR Id[4];
UCHAR VolumeLabel[11];
UCHAR SystemId[8];
} PACKED_BOOT_SECTOR_EX, *PPACKED_BOOT_SECTOR_EX;
// sizeof = 0x060
#define FatBootSectorJumpValid(xMagic) \
((xMagic)[0] == 0xe9 || (xMagic)[0] == 0xeb || (xMagic)[0] == 0x49)
typedef struct _FSINFO_SECTOR
{
ULONG SectorBeginSignature;
UCHAR Reserved[480];
ULONG FsInfoSignature;
ULONG FreeClusterCount;
ULONG NextFreeCluster;
UCHAR Reserved0[12];
ULONG SectorEndSignature;
} FSINFO_SECTOR, *PFSINFO_SECTOR;
// sizeof = 0x200
#define FSINFO_SECTOR_BEGIN_SIGNATURE 0x41615252
#define FSINFO_SECTOR_END_SIGNATURE 0xaa550000
#define FSINFO_SIGNATURE 0x61417272
//
// Cluster Markers:
//
#define FAT_CLUSTER_AVAILABLE 0x00000000
#define FAT_CLUSTER_RESERVED 0x0ffffff0
#define FAT_CLUSTER_BAD 0x0ffffff7
#define FAT_CLUSTER_LAST 0x0fffffff
//
// Directory Structure:
//
typedef struct _FAT_TIME
{
union {
struct {
USHORT DoubleSeconds : 5;
USHORT Minute : 6;
USHORT Hour : 5;
};
USHORT Value;
};
} FAT_TIME, *PFAT_TIME;
//
//
//
typedef struct _FAT_DATE {
union {
struct {
USHORT Day : 5;
USHORT Month : 4;
/* Relative to 1980 */
USHORT Year : 7;
};
USHORT Value;
};
} FAT_DATE, *PFAT_DATE;
//
//
//
typedef struct _FAT_DATETIME {
union {
struct {
FAT_TIME Time;
FAT_DATE Date;
};
ULONG Value;
};
} FAT_DATETIME, *PFAT_DATETIME;
//
//
//
typedef struct _DIR_ENTRY
{
UCHAR FileName[11];
UCHAR Attributes;
UCHAR Case;
UCHAR CreationTimeTenMs;
FAT_DATETIME CreationDateTime;
FAT_DATE LastAccessDate;
union {
USHORT ExtendedAttributes;
USHORT FirstClusterOfFileHi;
};
FAT_DATETIME LastWriteDateTime;
USHORT FirstCluster;
ULONG FileSize;
} DIR_ENTRY, *PDIR_ENTRY;
// sizeof = 0x020
typedef struct _LONG_FILE_NAME_ENTRY {
UCHAR SeqNum;
UCHAR NameA[10];
UCHAR Attributes;
UCHAR Type;
UCHAR Checksum;
USHORT NameB[6];
USHORT Reserved;
USHORT NameC[2];
} LONG_FILE_NAME_ENTRY, *PLONG_FILE_NAME_ENTRY;
// sizeof = 0x020
#define FAT_LFN_NAME_LENGTH \
(RTL_FIELD_SIZE(LONG_FILE_NAME_ENTRY, NameA) \
+ RTL_FIELD_SIZE(LONG_FILE_NAME_ENTRY, NameB) \
+ RTL_FIELD_SIZE(LONG_FILE_NAME_ENTRY, NameC))
#define FAT_FN_DIR_ENTRY_LAST 0x40
#define FAT_FN_MAX_DIR_ENTIES 0x14
#define FAT_BYTES_PER_DIRENT 0x20
#define FAT_BYTES_PER_DIRENT_LOG 0x05
#define FAT_DIRENT_NEVER_USED 0x00
#define FAT_DIRENT_REALLY_0E5 0x05
#define FAT_DIRENT_DIRECTORY_ALIAS 0x2e
#define FAT_DIRENT_DELETED 0xe5
#define FAT_CASE_LOWER_BASE 0x08
#define FAT_CASE_LOWER_EXT 0x10
#define FAT_DIRENT_ATTR_READ_ONLY 0x01
#define FAT_DIRENT_ATTR_HIDDEN 0x02
#define FAT_DIRENT_ATTR_SYSTEM 0x04
#define FAT_DIRENT_ATTR_VOLUME_ID 0x08
#define FAT_DIRENT_ATTR_DIRECTORY 0x10
#define FAT_DIRENT_ATTR_ARCHIVE 0x20
#define FAT_DIRENT_ATTR_DEVICE 0x40
#define FAT_DIRENT_ATTR_LFN (FAT_DIRENT_ATTR_READ_ONLY | \
FAT_DIRENT_ATTR_HIDDEN | \
FAT_DIRENT_ATTR_SYSTEM | \
FAT_DIRENT_ATTR_VOLUME_ID)

View file

@ -1,453 +0,0 @@
#pragma once
typedef struct _FAT_SCAN_CONTEXT *PFAT_SCAN_CONTEXT;
typedef struct _FAT_IO_CONTEXT *PFAT_IO_CONTEXT;
typedef struct _FAT_IRP_CONTEXT *PFAT_IRP_CONTEXT;
typedef PVOID PBCB;
typedef NTSTATUS (*PFAT_OPERATION_HANDLER) (PFAT_IRP_CONTEXT);
/* Node type stuff */
typedef CSHORT FAT_NODE_TYPE;
typedef FAT_NODE_TYPE *PFAT_NODE_TYPE;
#define FatNodeType(Ptr) (*((PFAT_NODE_TYPE)(Ptr)))
/* Node type codes */
#define FAT_NTC_VCB (CSHORT) '00VF'
#define FAT_NTC_FCB (CSHORT) 'CF'
#define FAT_NTC_DCB (CSHORT) 'DF'
#define FAT_NTC_ROOT_DCB (CSHORT) 'RFD'
#define FAT_NTC_CCB (CSHORT) 'BCC'
#define FAT_NTC_IRP_CONTEXT (CSHORT) 'PRI'
typedef struct _FAT_GLOBAL_DATA
{
ERESOURCE Resource;
PEPROCESS SystemProcess;
PDRIVER_OBJECT DriverObject;
PDEVICE_OBJECT DiskDeviceObject;
LIST_ENTRY VcbListHead;
NPAGED_LOOKASIDE_LIST NonPagedFcbList;
NPAGED_LOOKASIDE_LIST ResourceList;
NPAGED_LOOKASIDE_LIST IrpContextList;
FAST_IO_DISPATCH FastIoDispatch;
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks;
CACHE_MANAGER_CALLBACKS CacheMgrNoopCallbacks;
BOOLEAN Win31FileSystem;
BOOLEAN ShutdownStarted;
/* Jan 1, 1980 System Time */
LARGE_INTEGER DefaultFileTime;
/* Queued close */
ULONG AsyncCloseCount;
ULONG DelayedCloseCount;
LIST_ENTRY AsyncCloseList;
LIST_ENTRY DelayedCloseList;
PIO_WORKITEM FatCloseItem;
/* Various flags */
BOOLEAN AsyncCloseActive;
/* FullFAT integration */
FF_IOMAN *Ioman;
FF_ERROR FF_Error;
} FAT_GLOBAL_DATA;
typedef struct _FAT_PAGE_CONTEXT
{
PFILE_OBJECT FileObject;
LARGE_INTEGER EndOfData;
LARGE_INTEGER Offset;
LARGE_INTEGER EndOfPage;
SIZE_T ValidLength;
PVOID Buffer;
PBCB Bcb;
BOOLEAN CanWait;
} FAT_PAGE_CONTEXT, *PFAT_PAGE_CONTEXT;
#define FatPinSetupContext(xContext, xFcb, CanWait) \
{ \
(xContext)->FileObject = (xFcb)->StreamFileObject; \
(xContext)->EndOfData = (xFcb)->Header.FileSize; \
(xContext)->Offset.QuadPart = -1LL; \
(xContext)->Bcb = NULL; \
(xContext)->CanWait = CanWait; \
}
#define FatPinCleanupContext(xContext) \
if ((xContext)->Bcb != NULL) { \
CcUnpinData((xContext)->Bcb); \
(xContext)->Bcb = NULL; \
} \
#define FatPinEndOfPage(xContext, xType) \
Add2Ptr((xContext)->Buffer, (xContext)->ValidLength, xType)
#define FatPinIsLastPage(xContext) \
((xContext)->ValidLength != PAGE_SIZE)
#define IRPCONTEXT_CANWAIT 0x0001
#define IRPCONTEXT_PENDINGRETURNED 0x0002
#define IRPCONTEXT_STACK_IO_CONTEXT 0x0004
#define IRPCONTEXT_WRITETHROUGH 0x0008
#define IRPCONTEXT_TOPLEVEL 0x0010
typedef struct _FAT_IRP_CONTEXT
{
/* Type and size of this record (must be FAT_NTC_IRP_CONTEXT) */
FAT_NODE_TYPE NodeTypeCode;
CSHORT NodeByteSize;
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
UCHAR MajorFunction;
UCHAR MinorFunction;
PFILE_OBJECT FileObject;
ULONG Flags;
struct _VCB *Vcb;
ULONG PinCount;
FAT_PAGE_CONTEXT Page;
struct _FAT_IO_CONTEXT *FatIoContext;
WORK_QUEUE_ITEM WorkQueueItem;
PFAT_OPERATION_HANDLER QueuedOperationHandler;
PIO_STACK_LOCATION Stack;
KEVENT Event;
} FAT_IRP_CONTEXT;
typedef struct _FAT_IO_CONTEXT
{
PMDL ZeroMdl;
PIRP Irp;
LONG RunCount;
SIZE_T Length;
LONGLONG Offset;
PFILE_OBJECT FileObject;
union
{
struct
{
PERESOURCE Resource;
PERESOURCE PagingIoResource;
ERESOURCE_THREAD ResourceThreadId;
} Async;
KEVENT SyncEvent;
} Wait;
PIRP AssociatedIrp[0];
} FAT_IO_CONTEXT;
typedef ULONG (*PFAT_SCANFAT_FOR_CONTINOUS_RUN_ROUTINE) (PFAT_PAGE_CONTEXT, PULONG, BOOLEAN);
typedef ULONG (*PFAT_SETFAT_CONTINOUS_RUN_ROUTINE) (PFAT_PAGE_CONTEXT, ULONG, ULONG, BOOLEAN);
typedef ULONG (*PFAT_SCANFAT_FOR_VALUE_RUN_ROUTINE) (PFAT_PAGE_CONTEXT, PULONG, ULONG, BOOLEAN);
typedef ULONG (*PFAT_SETFAT_VALUE_RUN_ROUTINE) (PFAT_PAGE_CONTEXT, ULONG, ULONG, ULONG, BOOLEAN);
typedef struct _FAT_METHODS {
PFAT_SCANFAT_FOR_CONTINOUS_RUN_ROUTINE ScanContinousRun;
PFAT_SETFAT_CONTINOUS_RUN_ROUTINE SetContinousRun;
PFAT_SCANFAT_FOR_VALUE_RUN_ROUTINE ScanValueRun;
PFAT_SETFAT_VALUE_RUN_ROUTINE SetValueRun;
} FAT_METHODS, *PFAT_METHODS;
#define VCB_STATE_FLAG_LOCKED 0x001
#define VCB_STATE_FLAG_DIRTY 0x002
#define VCB_STATE_MOUNTED_DIRTY 0x004
#define VCB_STATE_CREATE_IN_PROGRESS 0x008
#define VCB_STATE_FLAG_CLOSE_IN_PROGRESS 0x010
#define VCB_STATE_FLAG_DELETED_FCB 0x020
#define VCB_STATE_FLAG_DISMOUNT_IN_PROGRESS 0x040
#define VCB_STATE_FLAG_DEFERRED_FLUSH 0x080
#define VCB_STATE_FLAG_WRITE_PROTECTED 0x100
typedef enum _VCB_CONDITION
{
VcbGood,
VcbNotMounted,
VcbBad
} VCB_CONDITION;
/* Volume Control Block */
typedef struct _VCB
{
FSRTL_ADVANCED_FCB_HEADER Header;
FAST_MUTEX HeaderMutex;
SECTION_OBJECT_POINTERS SectionObjectPointers;
PFILE_OBJECT StreamFileObject;
PDEVICE_OBJECT TargetDeviceObject;
LIST_ENTRY VcbLinks;
PVPB Vpb;
ULONG State;
VCB_CONDITION Condition;
ERESOURCE Resource;
struct _CLOSE_CONTEXT *CloseContext;
LIST_ENTRY AsyncCloseList;
LIST_ENTRY DelayedCloseList;
/* Direct volume access */
SHARE_ACCESS ShareAccess;
PFILE_OBJECT FileObjectWithVcbLocked;
/* Notifications support */
PNOTIFY_SYNC NotifySync;
LIST_ENTRY NotifyList;
/* Volume Characteristics: */
ULONG SerialNumber;
BIOS_PARAMETER_BLOCK Bpb;
ULONG BytesPerClusterLog;
ULONG BytesPerCluster;
ULONG SectorsPerFat;
ULONG DataArea;
ULONG Sectors;
ULONG Clusters;
ULONG IndexDepth;
ULONG RootDirent;
ULONG RootDirentSectors;
LONGLONG BeyondLastClusterInFat;
FAT_METHODS Methods;
/* Root Directory Control block */
struct _FCB *RootDcb;
/* Counters */
ULONG DirectOpenCount;
ULONG OpenFileCount;
ULONG ReadOnlyCount;
ULONG InternalOpenCount;
ULONG ResidualOpenCount;
ULONG DirectAccessOpenCount;
ULONG MediaChangeCount;
/* FullFAT integration */
FF_IOMAN *Ioman;
} VCB, *PVCB;
#define VcbToVolumeDeviceObject(xVcb) \
CONTAINING_RECORD((xVcb), VOLUME_DEVICE_OBJECT, Vcb))
#define VcbToDeviceObject(xVcb) \
&(VcbToVolumeDeviceObject(xVcb)->DeviceObject)
#define SectorsToBytes(xVcb, xSectrors) \
((xVcb)->Bpb.BytesPerSector * (xSectrors))
#define BytesToSectors(xVcb, xBytes) \
((xBytes + (xVcb)->Bpb.BytesPerSector - 1) / (xVcb)->Bpb.BytesPerSector)
#define SectorsToClusters(xVcb, xSectors) \
((xSectors + (xVcb)->Bpb.SectorsPerCluster - 1) / (xVcb)->Bpb.SectorsPerCluster)
#define VCB_FAT_BITMAP_SIZE 0x10000
#define VcbFatBitmapIndex(xCluster) ((xCluster)/VCB_FAT_BITMAP_SIZE)
/* Volume Device Object */
typedef struct _VOLUME_DEVICE_OBJECT
{
DEVICE_OBJECT DeviceObject;
union {
FSRTL_COMMON_FCB_HEADER VolumeHeader;
VCB Vcb; /* Must be the last entry! */
};
} VOLUME_DEVICE_OBJECT, *PVOLUME_DEVICE_OBJECT;
typedef enum _TYPE_OF_OPEN
{
UnopenedFileObject,
UserFileOpen,
UserDirectoryOpen,
UserVolumeOpen,
VirtualVolumeFile,
DirectoryFile,
EaFile
} TYPE_OF_OPEN;
//
// Short name always exists in FAT
//
enum _FCB_NAME_TYPE {
FcbShortName = 0x0,
FcbLongName
} FCB_NAME_TYPE;
typedef struct _FCB_NAME_LINK {
struct _FCB *Fcb;
RTL_SPLAY_LINKS Links;
union
{
OEM_STRING Ansi;
UNICODE_STRING String;
} Name;
BOOLEAN IsDosName;
} FCB_NAME_LINK, *PFCB_NAME_LINK;
typedef enum _FCB_CONDITION
{
FcbGood,
FcbBad,
FcbNeedsToBeVerified
} FCB_CONDITION;
#define FCB_STATE_HAS_NAMES 0x01
#define FCB_STATE_HAS_UNICODE_NAME 0x02
#define FCB_STATE_PAGEFILE 0x04
#define FCB_STATE_DELAY_CLOSE 0x08
#define FCB_STATE_TRUNCATE_ON_CLOSE 0x10
#define FCB_STATE_DELETE_ON_CLOSE 0x20
typedef struct _FCB
{
FSRTL_ADVANCED_FCB_HEADER Header;
/*
* Later we might want to move the next four fields
* into a separate structureif we decide to split
* FCB into paged and non paged parts
* (as it is done in MS implementation
*/
FAST_MUTEX HeaderMutex; // nonpaged!
SECTION_OBJECT_POINTERS SectionObjectPointers;
ERESOURCE Resource; // nonpaged!
ERESOURCE PagingIoResource; // nonpaged!
/* First cluster in the fat allocation chain */
ULONG FirstClusterOfFile;
/* A list of all FCBs of that DCB */
LIST_ENTRY ParentDcbLinks;
/* Reference to the Parent Dcb*/
struct _FCB *ParentFcb;
/* Pointer to a Vcb */
PVCB Vcb;
/* Fcb state */
ULONG State;
/* Fcb condition */
FCB_CONDITION Condition;
/* Share access */
SHARE_ACCESS ShareAccess;
ULONG FirstCluster;
/* Links into FCB Tree */
FCB_NAME_LINK ShortName;
FCB_NAME_LINK LongName;
/* Buffer for the short name */
CHAR ShortNameBuffer[0xc];
/* Full file name */
UNICODE_STRING FullFileName;
/* Long name with exact case */
UNICODE_STRING ExactCaseLongName;
/* Hint for the filename length */
ULONG FileNameLength;
/* A copy of fat attribute byte */
UCHAR DirentFatFlags;
/* File basic info */
FILE_BASIC_INFORMATION BasicInfo;
/* FullFAT file handle */
FF_FILE *FatHandle;
/* The file has outstanding async writes */
ULONG OutstandingAsyncWrites;
/* The outstanding async writes sync event */
PKEVENT OutstandingAsyncEvent;
/* Counters */
ULONG OpenCount;
ULONG UncleanCount;
ULONG NonCachedUncleanCount;
union
{
struct
{
/* File and Op locks */
FILE_LOCK Lock;
OPLOCK Oplock;
} Fcb;
struct
{
LIST_ENTRY ParentDcbList; /* A list of all FCBs/DCBs opened under this DCB */
ULONG DirectoryFileOpenCount; /* Sector-based access to the dir */
PFILE_OBJECT DirectoryFile;
/* Directory data stream (just handy to have it). */
//PFILE_OBJECT StreamFileObject;
/* Names */
PRTL_SPLAY_LINKS SplayLinksAnsi;
PRTL_SPLAY_LINKS SplayLinksUnicode;
} Dcb;
};
} FCB, *PFCB;
typedef struct _FAT_ENUM_DIRENT_CONTEXT *PFAT_ENUM_DIRENT_CONTEXT;
typedef struct _FAT_ENUM_DIR_CONTEXT *PFAT_ENUM_DIR_CONTEXT;
typedef ULONG (*PFAT_COPY_DIRENT_ROUTINE) (PFAT_ENUM_DIR_CONTEXT, PDIR_ENTRY, PVOID);
typedef struct _FAT_ENUM_DIRENT_CONTEXT
{
FAT_PAGE_CONTEXT Page;
/* Copy dirent to dirinfo */
PFAT_COPY_DIRENT_ROUTINE CopyDirent;
LONGLONG BytesPerClusterMask;
/* Info buffer characteristics */
PVOID Buffer;
SIZE_T Offset;
SIZE_T Length;
/* Criteria */
PUNICODE_STRING FileName;
UCHAR CcbFlags;
/* Lfn buffer/length offsets */
ULONG LengthOffset;
ULONG NameOffset;
} FAT_ENUM_DIRENT_CONTEXT;
typedef struct _FAT_FIND_DIRENT_CONTEXT
{
FAT_PAGE_CONTEXT Page;
UNICODE_STRING ShortName;
WCHAR ShortNameBuffer[0x18];
/* Criteria */
PUNICODE_STRING FileName;
BOOLEAN Valid8dot3Name;
} FAT_FIND_DIRENT_CONTEXT, *PFAT_FIND_DIRENT_CONTEXT;
typedef struct _CLOSE_CONTEXT
{
LIST_ENTRY GlobalLinks;
LIST_ENTRY VcbLinks;
PVCB Vcb;
PFCB Fcb;
TYPE_OF_OPEN TypeOfOpen;
BOOLEAN Free;
} CLOSE_CONTEXT, *PCLOSE_CONTEXT;
typedef struct _CCB
{
CSHORT NodeTypeCode;
CSHORT NodeByteSize;
LARGE_INTEGER CurrentByteOffset;
ULONG Entry;
UNICODE_STRING SearchPattern;
UCHAR Flags;
CLOSE_CONTEXT CloseContext;
} CCB, *PCCB;
typedef enum _FILE_TIME_INDEX
{
FileCreationTime = 0,
FileLastAccessTime,
FileLastWriteTime,
FileChangeTime
} FILE_TIME_INDEX;
#define CCB_SEARCH_RETURN_SINGLE_ENTRY 0x01
#define CCB_SEARCH_PATTERN_LEGAL_8DOT3 0x02
#define CCB_SEARCH_PATTERN_HAS_WILD_CARD 0x04
#define CCB_DASD_IO 0x08
#define CCB_READ_ONLY 0x10
#define CCB_DELETE_ON_CLOSE 0x20
#define CCB_COMPLETE_DISMOUNT 0x40
#define CCB_CLOSE_CONTEXT 0x80
extern FAT_GLOBAL_DATA FatGlobalData;

File diff suppressed because it is too large Load diff

View file

@ -1,673 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/finfo.c
* PURPOSE: File Information support routines
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
VOID
NTAPI
FatiQueryBasicInformation(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PFILE_OBJECT FileObject,
IN OUT PFILE_BASIC_INFORMATION Buffer,
IN OUT PLONG Length)
{
/* Zero the buffer */
RtlZeroMemory(Buffer, sizeof(FILE_BASIC_INFORMATION));
/* Deduct the written length */
*Length -= sizeof(FILE_BASIC_INFORMATION);
/* Check if it's a dir or a file */
if (FatNodeType(Fcb) == FAT_NTC_FCB)
{
// FIXME: Read dirent and get times from there
Buffer->LastAccessTime.QuadPart = 0;
Buffer->CreationTime.QuadPart = 0;
Buffer->LastWriteTime.QuadPart = 0;
}
else
{
// FIXME: May not be really correct
Buffer->FileAttributes = 0;
DPRINT1("Basic info of a directory '%wZ' is requested!\n", &Fcb->FullFileName);
}
/* If attribute is 0, set normal */
if (Buffer->FileAttributes == 0)
Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
}
VOID
NTAPI
FatiQueryStandardInformation(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PFILE_OBJECT FileObject,
IN OUT PFILE_STANDARD_INFORMATION Buffer,
IN OUT PLONG Length)
{
/* Zero the buffer */
RtlZeroMemory(Buffer, sizeof(FILE_STANDARD_INFORMATION));
/* Deduct the written length */
*Length -= sizeof(FILE_STANDARD_INFORMATION);
Buffer->NumberOfLinks = 1;
Buffer->DeletePending = FALSE; // FIXME
/* Check if it's a dir or a file */
if (FatNodeType(Fcb) == FAT_NTC_FCB)
{
Buffer->Directory = FALSE;
Buffer->EndOfFile.LowPart = Fcb->FatHandle->Filesize;
Buffer->AllocationSize = Buffer->EndOfFile;
DPRINT("Filesize %d, chain length %d\n", Fcb->FatHandle->Filesize, Fcb->FatHandle->iChainLength);
}
else
{
Buffer->Directory = TRUE;
}
}
VOID
NTAPI
FatiQueryInternalInformation(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PFILE_OBJECT FileObject,
IN OUT PFILE_INTERNAL_INFORMATION Buffer,
IN OUT PLONG Length)
{
UNIMPLEMENTED;
}
VOID
NTAPI
FatiQueryNameInformation(IN PFAT_IRP_CONTEXT IrpContext,
IN PFCB Fcb,
IN PFILE_OBJECT FileObject,
IN OUT PFILE_NAME_INFORMATION Buffer,
IN OUT PLONG Length)
{
ULONG ByteSize;
ULONG Trim = 0;
BOOLEAN Overflow = FALSE;
/* Deduct the minimum written length */
*Length -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
/* Build full name if needed */
if (!Fcb->FullFileName.Buffer)
{
FatSetFullFileNameInFcb(IrpContext, Fcb);
}
DPRINT("FullFileName %wZ\n", &Fcb->FullFileName);
if (*Length < Fcb->FullFileName.Length - Trim)
{
/* Buffer can't fit all data */
ByteSize = *Length;
Overflow = TRUE;
}
else
{
/* Deduct the amount of bytes we are going to write */
ByteSize = Fcb->FullFileName.Length - Trim;
*Length -= ByteSize;
}
/* Copy the name */
RtlCopyMemory(Buffer->FileName,
Fcb->FullFileName.Buffer,
ByteSize);
/* Set the length */
Buffer->FileNameLength = Fcb->FullFileName.Length - Trim;
/* Is this a shortname query? */
if (Trim)
{
/* Yes, not supported atm */
ASSERT(FALSE);
}
/* Indicate overflow by passing -1 as the length */
if (Overflow) *Length = -1;
}
NTSTATUS
NTAPI
FatiQueryInformation(IN PFAT_IRP_CONTEXT IrpContext,
IN PIRP Irp)
{
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION IrpSp;
FILE_INFORMATION_CLASS InfoClass;
TYPE_OF_OPEN FileType;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
LONG Length;
PVOID Buffer;
BOOLEAN VcbLocked = FALSE, FcbLocked = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
/* Get IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Get the file object */
FileObject = IrpSp->FileObject;
/* Copy variables to something with shorter names */
InfoClass = IrpSp->Parameters.QueryFile.FileInformationClass;
Length = IrpSp->Parameters.QueryFile.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer;
DPRINT("FatiQueryInformation\n", 0);
DPRINT("\tIrp = %08lx\n", Irp);
DPRINT("\tLength = %08lx\n", Length);
DPRINT("\tFileInformationClass = %08lx\n", InfoClass);
DPRINT("\tBuffer = %08lx\n", Buffer);
FileType = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
DPRINT("Vcb %p, Fcb %p, Ccb %p, open type %d\n", Vcb, Fcb, Ccb, FileType);
/* Acquire VCB lock */
if (InfoClass == FileNameInformation ||
InfoClass == FileAllInformation)
{
if (!FatAcquireExclusiveVcb(IrpContext, Vcb))
{
ASSERT(FALSE);
}
/* Remember we locked the VCB */
VcbLocked = TRUE;
}
/* Acquire FCB lock */
// FIXME: If not paging file
if (!FatAcquireSharedFcb(IrpContext, Fcb))
{
ASSERT(FALSE);
}
FcbLocked = TRUE;
switch (InfoClass)
{
case FileBasicInformation:
FatiQueryBasicInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
break;
case FileStandardInformation:
FatiQueryStandardInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
break;
case FileInternalInformation:
FatiQueryInternalInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
break;
case FileNameInformation:
FatiQueryNameInformation(IrpContext, Fcb, FileObject, Buffer, &Length);
break;
default:
DPRINT1("Unimplemented information class %d requested\n", InfoClass);
Status = STATUS_INVALID_PARAMETER;
}
/* Check for buffer overflow */
if (Length < 0)
{
Status = STATUS_BUFFER_OVERFLOW;
Length = 0;
}
/* Set IoStatus.Information to amount of filled bytes */
Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - Length;
/* Release FCB locks */
if (FcbLocked) FatReleaseFcb(IrpContext, Fcb);
if (VcbLocked) FatReleaseVcb(IrpContext, Vcb);
/* Complete request and return status */
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
NTSTATUS
NTAPI
FatQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
BOOLEAN TopLevel, CanWait;
PFAT_IRP_CONTEXT IrpContext;
CanWait = TRUE;
TopLevel = FALSE;
Status = STATUS_INVALID_DEVICE_REQUEST;
/* Get CanWait flag */
if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
CanWait = IoIsOperationSynchronous(Irp);
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
/* Set Top Level IRP if not set */
TopLevel = FatIsTopLevelIrp(Irp);
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, CanWait);
/* Perform the actual read */
Status = FatiQueryInformation(IrpContext, Irp);
/* Restore top level Irp */
if (TopLevel) IoSetTopLevelIrp(NULL);
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}
NTSTATUS
NTAPI
FatSetEndOfFileInfo(IN PFAT_IRP_CONTEXT IrpContext,
IN PIRP Irp,
IN PFILE_OBJECT FileObject,
IN PVCB Vcb,
IN PFCB Fcb)
{
PFILE_END_OF_FILE_INFORMATION Buffer;
ULONG NewFileSize;
ULONG InitialFileSize;
ULONG InitialValidDataLength;
//ULONG InitialValidDataToDisk;
BOOLEAN CacheMapInitialized = FALSE;
BOOLEAN ResourceAcquired = FALSE;
NTSTATUS Status;
Buffer = Irp->AssociatedIrp.SystemBuffer;
if (FatNodeType(Fcb) != FAT_NTC_FCB)
{
/* Trying to change size of a dir */
Status = STATUS_INVALID_DEVICE_REQUEST;
return Status;
}
/* Validate new size */
if (!FatIsIoRangeValid(Buffer->EndOfFile, 0))
{
Status = STATUS_DISK_FULL;
return Status;
}
NewFileSize = Buffer->EndOfFile.LowPart;
/* Lookup allocation size if needed */
if (Fcb->Header.AllocationSize.QuadPart == (LONGLONG)-1)
UNIMPLEMENTED;//FatLookupFileAllocationSize(IrpContext, Fcb);
/* Cache the file if there is a data section */
if (FileObject->SectionObjectPointer->DataSectionObject &&
(FileObject->SectionObjectPointer->SharedCacheMap == NULL) &&
!FlagOn(Irp->Flags, IRP_PAGING_IO))
{
if (FlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE))
{
/* This is a really weird condition */
UNIMPLEMENTED;
//Raise(STATUS_FILE_CLOSED);
}
/* Initialize the cache map */
CcInitializeCacheMap(FileObject,
(PCC_FILE_SIZES)&Fcb->Header.AllocationSize,
FALSE,
&FatGlobalData.CacheMgrCallbacks,
Fcb);
CacheMapInitialized = TRUE;
}
/* Lazy write case */
if (IoGetCurrentIrpStackLocation(Irp)->Parameters.SetFile.AdvanceOnly)
{
if (!IsFileDeleted(Fcb) &&
(Fcb->Condition == FcbGood))
{
/* Clamp the new file size */
if (NewFileSize >= Fcb->Header.FileSize.LowPart)
NewFileSize = Fcb->Header.FileSize.LowPart;
ASSERT(NewFileSize <= Fcb->Header.AllocationSize.LowPart);
/* Never reduce the file size here! */
// TODO: Actually change file size
DPRINT1("Actually changing file size is missing\n");
/* Notify about file size change */
FatNotifyReportChange(IrpContext,
Vcb,
Fcb,
FILE_NOTIFY_CHANGE_SIZE,
FILE_ACTION_MODIFIED);
}
else
{
DPRINT1("Cannot set size on deleted file\n");
}
Status = STATUS_SUCCESS;
return Status;
}
if ( NewFileSize > Fcb->Header.AllocationSize.LowPart )
{
// TODO: Increase file size
DPRINT1("Actually changing file size is missing\n");
}
if (Fcb->Header.FileSize.LowPart != NewFileSize)
{
if (NewFileSize < Fcb->Header.FileSize.LowPart)
{
if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer,
&Buffer->EndOfFile))
{
Status = STATUS_USER_MAPPED_FILE;
/* Free up resources if necessary */
if (CacheMapInitialized)
CcUninitializeCacheMap(FileObject, NULL, NULL);
return Status;
}
ResourceAcquired = ExAcquireResourceExclusiveLite(Fcb->Header.PagingIoResource, TRUE);
}
/* Set new file sizes */
InitialFileSize = Fcb->Header.FileSize.LowPart;
InitialValidDataLength = Fcb->Header.ValidDataLength.LowPart;
//InitialValidDataToDisk = Fcb->ValidDataToDisk;
Fcb->Header.FileSize.LowPart = NewFileSize;
/* Adjust valid data length if new size is less than that */
if (Fcb->Header.ValidDataLength.LowPart > NewFileSize)
Fcb->Header.ValidDataLength.LowPart = NewFileSize;
//if (Fcb->ValidDataToDisk > NewFileSize)
// Fcb->ValidDataToDisk = NewFileSize;
DPRINT1("New file size is 0x%08lx\n", NewFileSize);
/* Update cache mapping */
CcSetFileSizes(FileObject,
(PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
/* Notify about size change */
FatNotifyReportChange(IrpContext,
Vcb,
Fcb,
FILE_NOTIFY_CHANGE_SIZE,
FILE_ACTION_MODIFIED);
/* Set truncate on close flag */
SetFlag(Fcb->State, FCB_STATE_TRUNCATE_ON_CLOSE);
}
/* Set modified flag */
FileObject->Flags |= FO_FILE_MODIFIED;
/* Free up resources if necessary */
if (CacheMapInitialized)
CcUninitializeCacheMap(FileObject, NULL, NULL);
if (ResourceAcquired)
ExReleaseResourceLite(Fcb->Header.PagingIoResource);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
FatiSetInformation(IN PFAT_IRP_CONTEXT IrpContext,
IN PIRP Irp)
{
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION IrpSp;
FILE_INFORMATION_CLASS InfoClass;
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
LONG Length;
PVOID Buffer;
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN VcbAcquired = FALSE, FcbAcquired = FALSE;
/* Get IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Get the file object */
FileObject = IrpSp->FileObject;
/* Copy variables to something with shorter names */
InfoClass = IrpSp->Parameters.SetFile.FileInformationClass;
Length = IrpSp->Parameters.SetFile.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer;
DPRINT("FatiSetInformation\n", 0);
DPRINT("\tIrp = %08lx\n", Irp);
DPRINT("\tLength = %08lx\n", Length);
DPRINT("\tFileInformationClass = %08lx\n", InfoClass);
DPRINT("\tFileObject = %08lx\n", IrpSp->Parameters.SetFile.FileObject);
DPRINT("\tBuffer = %08lx\n", Buffer);
TypeOfOpen = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
DPRINT("Vcb %p, Fcb %p, Ccb %p, open type %d\n", Vcb, Fcb, Ccb, TypeOfOpen);
switch (TypeOfOpen)
{
case UserVolumeOpen:
Status = STATUS_INVALID_PARAMETER;
/* Complete request and return status */
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
case UserFileOpen:
/* Check oplocks */
if (!FlagOn(Fcb->State, FCB_STATE_PAGEFILE) &&
((InfoClass == FileEndOfFileInformation) ||
(InfoClass == FileAllocationInformation)))
{
Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
Irp,
IrpContext,
NULL,
NULL);
if (Status != STATUS_SUCCESS)
{
/* Complete request and return status */
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
/* Update Fast IO flag */
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible(Fcb);
}
break;
case UserDirectoryOpen:
break;
default:
Status = STATUS_INVALID_PARAMETER;
/* Complete request and return status */
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
/* If it's a root DCB - fail */
if (FatNodeType(Fcb) == FAT_NTC_ROOT_DCB)
{
if (InfoClass == FileDispositionInformation)
Status = STATUS_CANNOT_DELETE;
else
Status = STATUS_INVALID_PARAMETER;
/* Complete request and return status */
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
/* Acquire the volume lock if needed */
if (InfoClass == FileDispositionInformation ||
InfoClass == FileRenameInformation)
{
if (!FatAcquireExclusiveVcb(IrpContext, Vcb))
{
UNIMPLEMENTED;
}
VcbAcquired = TRUE;
}
/* Acquire FCB lock */
if (!FlagOn(Fcb->State, FCB_STATE_PAGEFILE))
{
if (!FatAcquireExclusiveFcb(IrpContext, Fcb))
{
UNIMPLEMENTED;
}
FcbAcquired = TRUE;
}
// TODO: VerifyFcb
switch (InfoClass)
{
case FileBasicInformation:
//Status = FatSetBasicInfo(IrpContext, Irp, Fcb, Ccb);
DPRINT1("FileBasicInformation\n");
break;
case FileDispositionInformation:
if (FlagOn(Vcb->State, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
!FlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))
{
UNIMPLEMENTED;
}
else
{
//Status = FatSetDispositionInfo(IrpContext, Irp, FileObject, Fcb);
DPRINT1("FileDispositionInformation\n");
}
break;
case FileRenameInformation:
if (!FlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))
{
UNIMPLEMENTED;
}
else
{
//Status = FatSetRenameInfo(IrpContext, Irp, Vcb, Fcb, Ccb);
DPRINT1("FileRenameInformation\n");
/* NOTE: Request must not be completed here!
That's why Irp/IrpContext are set to NULL */
if (Status == STATUS_PENDING)
{
Irp = NULL;
IrpContext = NULL;
}
}
break;
case FilePositionInformation:
//Status = FatSetPositionInfo(IrpContext, Irp, FileObject);
DPRINT1("FilePositionInformation\n");
break;
case FileLinkInformation:
Status = STATUS_INVALID_DEVICE_REQUEST;
break;
case FileAllocationInformation:
//Status = FatSetAllocationInfo(IrpContext, Irp, Fcb, FileObject);
DPRINT1("FileAllocationInformation\n");
break;
case FileEndOfFileInformation:
Status = FatSetEndOfFileInfo(IrpContext, Irp, FileObject, Vcb, Fcb);
break;
default:
Status = STATUS_INVALID_PARAMETER;
}
/* Release locks */
if (FcbAcquired) FatReleaseFcb(IrpContext, Fcb);
if (VcbAcquired) FatReleaseVcb(IrpContext, Vcb);
/* Complete request and return status */
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
NTSTATUS
NTAPI
FatSetInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
BOOLEAN TopLevel, CanWait;
PFAT_IRP_CONTEXT IrpContext;
CanWait = TRUE;
TopLevel = FALSE;
Status = STATUS_INVALID_DEVICE_REQUEST;
/* Get CanWait flag */
if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
CanWait = IoIsOperationSynchronous(Irp);
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
/* Set Top Level IRP if not set */
TopLevel = FatIsTopLevelIrp(Irp);
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, CanWait);
/* Perform the actual read */
Status = FatiSetInformation(IrpContext, Irp);
/* Restore top level Irp */
if (TopLevel) IoSetTopLevelIrp(NULL);
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}
/* EOF */

View file

@ -1,25 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/flush.c
* PURPOSE: Flushing routines
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
FatFlushBuffers(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT1("FatFlushBuffers()\n");
return STATUS_NOT_IMPLEMENTED;
}
/* EOF */

View file

@ -1,514 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/fsctl.c
* PURPOSE: Filesystem control
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
FatOplockRequest(IN PFAT_IRP_CONTEXT IrpContext,
IN PIRP Irp)
{
NTSTATUS Status;
DPRINT1("Oplock request!\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
NTSTATUS
NTAPI
FatMarkVolumeDirty(IN PFAT_IRP_CONTEXT IrpContext,
IN PIRP Irp)
{
NTSTATUS Status;
DPRINT1("Marking volume as dirty\n");
Status = STATUS_SUCCESS;
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
NTSTATUS
NTAPI
FatUserFsCtrl(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
ULONG Code;
/* Get current IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Code = IrpSp->Parameters.FileSystemControl.FsControlCode;
/* Set the wait flag */
if (Irp->RequestorMode != KernelMode &&
(Code & 3) == METHOD_NEITHER)
{
SetFlag(IrpContext->Flags, IRPCONTEXT_CANWAIT);
}
/* Branch according to the code */
switch (Code)
{
case FSCTL_REQUEST_OPLOCK_LEVEL_1:
case FSCTL_REQUEST_OPLOCK_LEVEL_2:
case FSCTL_REQUEST_BATCH_OPLOCK:
case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
case FSCTL_OPLOCK_BREAK_NOTIFY:
case FSCTL_OPLOCK_BREAK_ACK_NO_2:
case FSCTL_REQUEST_FILTER_OPLOCK :
Status = FatOplockRequest(IrpContext, Irp);
break;
case FSCTL_LOCK_VOLUME:
//Status = FatLockVolume( IrpContext, Irp );
DPRINT1("FSCTL_LOCK_VOLUME\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_UNLOCK_VOLUME:
//Status = FatUnlockVolume( IrpContext, Irp );
DPRINT1("FSCTL_UNLOCK_VOLUME\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_DISMOUNT_VOLUME:
//Status = FatDismountVolume( IrpContext, Irp );
DPRINT1("FSCTL_DISMOUNT_VOLUME\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_MARK_VOLUME_DIRTY:
Status = FatMarkVolumeDirty(IrpContext, Irp);
break;
case FSCTL_IS_VOLUME_DIRTY:
//Status = FatIsVolumeDirty( IrpContext, Irp );
DPRINT1("FSCTL_IS_VOLUME_DIRTY\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_IS_VOLUME_MOUNTED:
//Status = FatIsVolumeMounted( IrpContext, Irp );
DPRINT1("FSCTL_IS_VOLUME_MOUNTED\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_IS_PATHNAME_VALID:
//Status = FatIsPathnameValid( IrpContext, Irp );
DPRINT1("FSCTL_IS_PATHNAME_VALID\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_QUERY_RETRIEVAL_POINTERS:
//Status = FatQueryRetrievalPointers( IrpContext, Irp );
DPRINT1("FSCTL_QUERY_RETRIEVAL_POINTERS\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_QUERY_FAT_BPB:
//Status = FatQueryBpb( IrpContext, Irp );
DPRINT1("FSCTL_QUERY_FAT_BPB\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_FILESYSTEM_GET_STATISTICS:
//Status = FatGetStatistics( IrpContext, Irp );
DPRINT1("FSCTL_FILESYSTEM_GET_STATISTICS\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_GET_VOLUME_BITMAP:
//Status = FatGetVolumeBitmap( IrpContext, Irp );
DPRINT1("FSCTL_GET_VOLUME_BITMAP\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_GET_RETRIEVAL_POINTERS:
//Status = FatGetRetrievalPointers( IrpContext, Irp );
DPRINT1("FSCTL_GET_RETRIEVAL_POINTERS\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_MOVE_FILE:
//Status = FatMoveFile( IrpContext, Irp );
DPRINT1("FSCTL_MOVE_FILE\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
case FSCTL_ALLOW_EXTENDED_DASD_IO:
//Status = FatAllowExtendedDasdIo( IrpContext, Irp );
DPRINT1("FSCTL_ALLOW_EXTENDED_DASD_IO\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
break;
default:
DPRINT("FatUserFsCtrl(), unhandled fs control code 0x%x\n", Code);
Status = STATUS_INVALID_DEVICE_REQUEST;
FatCompleteRequest(IrpContext, Irp, Status);
}
//(((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method))
// 9c040
// 1 1 0 0 0
// 6 4 8 4 0
// 10011100000001000000
// DT = 1001 = 9
// Access = 11 = 3
// Function = 10000 = 16
// Method = 0
return Status;
}
NTSTATUS
NTAPI
FatVerifyVolume(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
{
DPRINT1("FatVerifyVolume()\n");
FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST);
return STATUS_INVALID_DEVICE_REQUEST;
}
VOID
NTAPI
FatiCleanVcbs(PFAT_IRP_CONTEXT IrpContext)
{
/* Make sure this IRP is waitable */
ASSERT(IrpContext->Flags & IRPCONTEXT_CANWAIT);
/* Acquire global resource */
ExAcquireResourceExclusiveLite(&FatGlobalData.Resource, TRUE);
/* TODO: Go through all VCBs and delete unmounted ones */
/* Release global resource */
ExReleaseResourceLite(&FatGlobalData.Resource);
}
VOID
NTAPI
FatiUnpackBpb(PBIOS_PARAMETER_BLOCK Bpb, PPACKED_BIOS_PARAMETER_BLOCK PackedBpb)
{
CopyUchar2(&Bpb->BytesPerSector, &PackedBpb->BytesPerSector[0]);
CopyUchar1(&Bpb->SectorsPerCluster, &PackedBpb->SectorsPerCluster[0]);
CopyUchar2(&Bpb->ReservedSectors, &PackedBpb->ReservedSectors[0]);
CopyUchar1(&Bpb->Fats, &PackedBpb->Fats[0]);
CopyUchar2(&Bpb->RootEntries, &PackedBpb->RootEntries[0]);
CopyUchar2(&Bpb->Sectors, &PackedBpb->Sectors[0]);
CopyUchar1(&Bpb->Media, &PackedBpb->Media[0]);
CopyUchar2(&Bpb->SectorsPerFat, &PackedBpb->SectorsPerFat[0]);
CopyUchar2(&Bpb->SectorsPerTrack, &PackedBpb->SectorsPerTrack[0]);
CopyUchar2(&Bpb->Heads, &PackedBpb->Heads[0]);
CopyUchar4(&Bpb->HiddenSectors, &PackedBpb->HiddenSectors[0]);
CopyUchar4(&Bpb->LargeSectors, &PackedBpb->LargeSectors[0]);
CopyUchar4(&Bpb->LargeSectorsPerFat, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)PackedBpb)->LargeSectorsPerFat[0]);
CopyUchar2(&Bpb->ExtendedFlags, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)PackedBpb)->ExtendedFlags[0]);
CopyUchar2(&Bpb->FsVersion, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)PackedBpb)->FsVersion[0]);
CopyUchar4(&Bpb->RootDirFirstCluster,&((PPACKED_BIOS_PARAMETER_BLOCK_EX)PackedBpb)->RootDirFirstCluster[0]);
CopyUchar2(&Bpb->FsInfoSector, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)PackedBpb)->FsInfoSector[0]);
CopyUchar2(&Bpb->BackupBootSector, &((PPACKED_BIOS_PARAMETER_BLOCK_EX)PackedBpb)->BackupBootSector[0]);
}
BOOLEAN
NTAPI
FatiBpbFat32(PPACKED_BIOS_PARAMETER_BLOCK PackedBpb)
{
return (*(USHORT *)(&PackedBpb->SectorsPerFat) == 0);
}
NTSTATUS
NTAPI
FatMountVolume(PFAT_IRP_CONTEXT IrpContext,
PDEVICE_OBJECT TargetDeviceObject,
PVPB Vpb,
PDEVICE_OBJECT FsDeviceObject)
{
NTSTATUS Status;
DISK_GEOMETRY DiskGeometry;
ULONG MediaChangeCount = 0;
PVOLUME_DEVICE_OBJECT VolumeDevice;
VCB *Vcb;
FF_ERROR Error;
PBCB BootBcb;
PPACKED_BOOT_SECTOR BootSector;
DPRINT1("FatMountVolume()\n");
/* Make sure this IRP is waitable */
ASSERT(IrpContext->Flags & IRPCONTEXT_CANWAIT);
/* Request media changes count, mostly useful for removable devices */
Status = FatPerformDevIoCtrl(TargetDeviceObject,
IOCTL_STORAGE_CHECK_VERIFY,
NULL,
0,
&MediaChangeCount,
sizeof(ULONG),
TRUE);
if (!NT_SUCCESS(Status)) return Status;
/* TODO: Check if data-track present in case of a CD drive */
/* TODO: IOCTL_DISK_GET_PARTITION_INFO_EX */
/* Remove unmounted VCBs */
FatiCleanVcbs(IrpContext);
/* Acquire the global exclusive lock */
FatAcquireExclusiveGlobal(IrpContext);
/* Create a new volume device object */
Status = IoCreateDevice(FatGlobalData.DriverObject,
sizeof(VOLUME_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
NULL,
FILE_DEVICE_DISK_FILE_SYSTEM,
0,
FALSE,
(PDEVICE_OBJECT *)&VolumeDevice);
if (!NT_SUCCESS(Status))
{
/* Release the global lock */
FatReleaseGlobal(IrpContext);
return Status;
}
/* Match alignment requirements */
if (TargetDeviceObject->AlignmentRequirement > VolumeDevice->DeviceObject.AlignmentRequirement)
{
VolumeDevice->DeviceObject.AlignmentRequirement = TargetDeviceObject->AlignmentRequirement;
}
/* Init stack size */
VolumeDevice->DeviceObject.StackSize = TargetDeviceObject->StackSize + 1;
/* Get sector size */
Status = FatPerformDevIoCtrl(TargetDeviceObject,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL,
0,
&DiskGeometry,
sizeof(DISK_GEOMETRY),
TRUE);
if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
VolumeDevice->DeviceObject.SectorSize = (USHORT) DiskGeometry.BytesPerSector;
/* Signal we're done with initializing */
VolumeDevice->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
/* Save device object in a VPB */
Vpb->DeviceObject = (PDEVICE_OBJECT)VolumeDevice;
/* Initialize VCB for this volume */
Status = FatInitializeVcb(IrpContext, &VolumeDevice->Vcb, TargetDeviceObject, Vpb);
if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
Vcb = &VolumeDevice->Vcb;
/* Initialize FullFAT library */
Vcb->Ioman = FF_CreateIOMAN(NULL,
8192,
VolumeDevice->DeviceObject.SectorSize,
&Error);
ASSERT(Vcb->Ioman);
/* Register block device read/write functions */
Error = FF_RegisterBlkDevice(Vcb->Ioman,
VolumeDevice->DeviceObject.SectorSize,
(FF_WRITE_BLOCKS)FatWriteBlocks,
(FF_READ_BLOCKS)FatReadBlocks,
Vcb);
if (Error)
{
DPRINT1("Registering block device with FullFAT failed with error %d\n", Error);
FF_DestroyIOMAN(Vcb->Ioman);
goto FatMountVolumeCleanup;
}
/* Mount the volume using FullFAT */
if(FF_MountPartition(Vcb->Ioman, 0))
{
DPRINT1("Partition mounting failed\n");
FF_DestroyIOMAN(Vcb->Ioman);
goto FatMountVolumeCleanup;
}
/* Read the boot sector */
FatReadStreamFile(Vcb, 0, sizeof(PACKED_BOOT_SECTOR), &BootBcb, (PVOID)&BootSector);
/* Check if it's successful */
if (!BootBcb)
{
Status = STATUS_UNRECOGNIZED_VOLUME;
goto FatMountVolumeCleanup;
}
/* Unpack data */
FatiUnpackBpb(&Vcb->Bpb, &BootSector->PackedBpb);
/* Verify if sector size matches */
if (DiskGeometry.BytesPerSector != Vcb->Bpb.BytesPerSector)
{
DPRINT1("Disk geometry BPS %d and bios BPS %d don't match!\n",
DiskGeometry.BytesPerSector, Vcb->Bpb.BytesPerSector);
/* Fail */
Status = STATUS_UNRECOGNIZED_VOLUME;
goto FatMountVolumeCleanup;
}
/* If Sectors value is set, discard the LargeSectors value */
if (Vcb->Bpb.Sectors) Vcb->Bpb.LargeSectors = 0;
/* Copy serial number */
if (FatiBpbFat32(&BootSector->PackedBpb))
{
CopyUchar4(&Vpb->SerialNumber, ((PPACKED_BOOT_SECTOR_EX)BootSector)->Id);
}
else
{
/* This is FAT12/16 */
CopyUchar4(&Vpb->SerialNumber, BootSector->Id);
}
/* Unpin the BCB */
CcUnpinData(BootBcb);
/* Create root DCB for it */
FatCreateRootDcb(IrpContext, &VolumeDevice->Vcb);
/* Keep trace of media changes */
VolumeDevice->Vcb.MediaChangeCount = MediaChangeCount;
//ObDereferenceObject(TargetDeviceObject);
/* Release the global lock */
FatReleaseGlobal(IrpContext);
/* Notify about volume mount */
//FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.StreamFileObject, FSRTL_VOLUME_MOUNT);
/* Return success */
return STATUS_SUCCESS;
FatMountVolumeCleanup:
/* Unwind the routine actions */
IoDeleteDevice((PDEVICE_OBJECT)VolumeDevice);
/* Release the global lock */
FatReleaseGlobal(IrpContext);
return Status;
}
NTSTATUS
NTAPI
FatiFileSystemControl(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
/* Get current IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Dispatch depending on the minor function */
switch (IrpSp->MinorFunction)
{
case IRP_MN_KERNEL_CALL:
case IRP_MN_USER_FS_REQUEST:
Status = FatUserFsCtrl(IrpContext, Irp);
break;
case IRP_MN_MOUNT_VOLUME:
Status = FatMountVolume(IrpContext,
IrpSp->Parameters.MountVolume.DeviceObject,
IrpSp->Parameters.MountVolume.Vpb,
IrpSp->DeviceObject);
FatCompleteRequest(IrpContext, Irp, Status);
break;
case IRP_MN_VERIFY_VOLUME:
Status = FatVerifyVolume(IrpContext, Irp);
break;
default:
DPRINT1("Unhandled FSCTL minor 0x%x\n", IrpSp->MinorFunction);
FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST);
Status = STATUS_INVALID_DEVICE_REQUEST;
}
return Status;
}
NTSTATUS
NTAPI
FatFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status = STATUS_SUCCESS;
PFAT_IRP_CONTEXT IrpContext;
BOOLEAN CanWait = TRUE;
DPRINT("FatFileSystemControl(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
/* Get CanWait flag */
if (IoGetCurrentIrpStackLocation(Irp)->FileObject)
{
CanWait = IoIsOperationSynchronous(Irp);
}
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, CanWait);
/* Call internal function */
Status = FatiFileSystemControl(IrpContext, Irp);
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}

View file

@ -1,213 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/fullfat.c
* PURPOSE: FullFAT integration routines
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* GLOBALS ******************************************************************/
#define TAG_FULLFAT 'FLUF'
/* FUNCTIONS ****************************************************************/
VOID *
FF_Malloc(FF_T_UINT32 allocSize)
{
return ExAllocatePoolWithTag(PagedPool, allocSize, TAG_FULLFAT);
}
VOID
FF_Free(VOID *pBuffer)
{
ExFreePoolWithTag(pBuffer, TAG_FULLFAT);
}
FF_T_SINT32
FatWriteBlocks(FF_T_UINT8 *pBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Count, void *pParam)
{
DPRINT1("FatWriteBlocks %p %d %d %p\n", pBuffer, SectorAddress, Count, pParam);
return 0;
}
FF_T_SINT32
FatReadBlocks(FF_T_UINT8 *DestBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Count, void *pParam)
{
LARGE_INTEGER Offset;
//PVOID Buffer;
PVCB Vcb = (PVCB)pParam;
//PBCB Bcb;
ULONG SectorSize = 512; // FIXME: hardcoding 512 is bad
IO_STATUS_BLOCK IoSb;
DPRINT("FatReadBlocks %p %d %d %p\n", DestBuffer, SectorAddress, Count, pParam);
/* Calculate the offset */
Offset.QuadPart = Int32x32To64(SectorAddress, SectorSize);
#if 0
if (!CcMapData(Vcb->StreamFileObject,
&Offset,
Count * SectorSize,
TRUE,
&Bcb,
&Buffer))
{
ASSERT(FALSE);
/* Mapping failed */
return 0;
}
/* Copy data to the buffer */
RtlCopyMemory(DestBuffer, Buffer, Count * SectorSize);
/* Unpin unneeded data */
CcUnpinData(Bcb);
#else
CcCopyRead(Vcb->StreamFileObject, &Offset, Count * SectorSize, TRUE, DestBuffer, &IoSb);
#endif
/* Return amount of read data in sectors */
return Count;
}
FF_FILE *FF_OpenW(FF_IOMAN *pIoman, PUNICODE_STRING pathW, FF_T_UINT8 Mode, FF_ERROR *pError)
{
OEM_STRING AnsiName;
CHAR AnsiNameBuf[512];
NTSTATUS Status;
/* Convert the name to ANSI */
AnsiName.Buffer = AnsiNameBuf;
AnsiName.Length = 0;
AnsiName.MaximumLength = sizeof(AnsiNameBuf);
RtlZeroMemory(AnsiNameBuf, sizeof(AnsiNameBuf));
Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiName, pathW, FALSE);
if (!NT_SUCCESS(Status))
{
ASSERT(FALSE);
}
DPRINT1("Opening '%s'\n", AnsiName.Buffer);
/* Call FullFAT's handler */
return FF_Open(pIoman, AnsiName.Buffer, Mode, pError);
}
FORCEINLINE
VOID
FatDateTimeToSystemTime(OUT PLARGE_INTEGER SystemTime,
IN PFAT_DATETIME FatDateTime,
IN UCHAR TenMs OPTIONAL)
{
TIME_FIELDS TimeFields;
/* Setup time fields */
TimeFields.Year = FatDateTime->Date.Year + 1980;
TimeFields.Month = FatDateTime->Date.Month;
TimeFields.Day = FatDateTime->Date.Day;
TimeFields.Hour = FatDateTime->Time.Hour;
TimeFields.Minute = FatDateTime->Time.Minute;
TimeFields.Second = (FatDateTime->Time.DoubleSeconds << 1);
/* Adjust up to 10 milliseconds
* if the parameter was supplied
*/
if (ARGUMENT_PRESENT(TenMs))
{
TimeFields.Second += TenMs / 100;
TimeFields.Milliseconds = (TenMs % 100) * 10;
}
else
{
TimeFields.Milliseconds = 0;
}
/* Fix seconds value that might get beyoud the bound */
if (TimeFields.Second > 59) TimeFields.Second = 0;
/* Perform ceonversion to system time if possible */
if (RtlTimeFieldsToTime(&TimeFields, SystemTime))
{
/* Convert to system time */
ExLocalTimeToSystemTime(SystemTime, SystemTime);
}
else
{
/* Set to default time if conversion failed */
*SystemTime = FatGlobalData.DefaultFileTime;
}
}
// TODO: Make it a helper around FullFAT library
VOID
NTAPI
FatQueryFileTimes(OUT PLARGE_INTEGER FileTimes,
IN PDIR_ENTRY Dirent)
{
/* Convert LastWriteTime */
FatDateTimeToSystemTime(&FileTimes[FileLastWriteTime],
&Dirent->LastWriteDateTime,
0);
/* All other time fileds are valid (according to MS)
* only if Win31 compatability mode is set.
*/
if (FatGlobalData.Win31FileSystem)
{
/* We can avoid calling conversion routine
* if time in dirent is 0 or equals to already
* known time (LastWriteTime).
*/
if (Dirent->CreationDateTime.Value == 0)
{
/* Set it to default time */
FileTimes[FileCreationTime] = FatGlobalData.DefaultFileTime;
}
else if (Dirent->CreationDateTime.Value
== Dirent->LastWriteDateTime.Value)
{
/* Assign the already known time */
FileTimes[FileCreationTime] = FileTimes[FileLastWriteTime];
/* Adjust milliseconds from extra dirent field */
FileTimes[FileCreationTime].QuadPart
+= (ULONG) Dirent->CreationTimeTenMs * 100000;
}
else
{
/* Perform conversion */
FatDateTimeToSystemTime(&FileTimes[FileCreationTime],
&Dirent->CreationDateTime,
Dirent->CreationTimeTenMs);
}
if (Dirent->LastAccessDate.Value == 0)
{
/* Set it to default time */
FileTimes[FileLastAccessTime] = FatGlobalData.DefaultFileTime;
}
else if (Dirent->LastAccessDate.Value
== Dirent->LastWriteDateTime.Date.Value)
{
/* Assign the already known time */
FileTimes[FileLastAccessTime] = FileTimes[FileLastWriteTime];
}
else
{
/* Perform conversion */
FAT_DATETIME LastAccessDateTime;
LastAccessDateTime.Date.Value = Dirent->LastAccessDate.Value;
LastAccessDateTime.Time.Value = 0;
FatDateTimeToSystemTime(&FileTimes[FileLastAccessTime],
&LastAccessDateTime,
0);
}
}
}
/* EOF */

View file

@ -1,126 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/lock.c
* PURPOSE: Lock support routines
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
FatiLockControl(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
NTSTATUS Status;
/* Get IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Determine type of open */
TypeOfOpen = FatDecodeFileObject(IrpSp->FileObject, &Vcb, &Fcb, &Ccb);
/* Only user file open is allowed */
if (TypeOfOpen != UserFileOpen)
{
FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER);
return STATUS_INVALID_PARAMETER;
}
/* Acquire shared FCB lock */
if (!FatAcquireSharedFcb(IrpContext, Fcb))
{
UNIMPLEMENTED;
//Status = FatFsdPostRequest(IrpContext, Irp);
Status = STATUS_NOT_IMPLEMENTED;
return Status;
}
/* Check oplock state */
Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
Irp,
IrpContext,
FatOplockComplete,
NULL);
if (Status != STATUS_SUCCESS)
{
/* Release FCB lock */
FatReleaseFcb(IrpContext, Fcb);
return Status;
}
/* Process the lock */
Status = FsRtlProcessFileLock(&Fcb->Fcb.Lock, Irp, NULL);
/* Update Fast I/O state */
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible(Fcb);
/* Complete the request */
FatCompleteRequest(IrpContext, NULL, 0);
/* Release FCB lock */
FatReleaseFcb(IrpContext, Fcb);
return Status;
}
NTSTATUS
NTAPI
FatLockControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PFAT_IRP_CONTEXT IrpContext;
NTSTATUS Status;
BOOLEAN TopLevel;
DPRINT1("FatLockControl()\n");
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
/* Set Top Level IRP if not set */
TopLevel = FatIsTopLevelIrp(Irp);
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, IoIsOperationSynchronous(Irp));
/* Call internal function */
Status = FatiLockControl(IrpContext, Irp);
/* Reset Top Level IRP */
if (TopLevel) IoSetTopLevelIrp(NULL);
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}
VOID
NTAPI
FatOplockComplete(IN PVOID Context,
IN PIRP Irp)
{
UNIMPLEMENTED;
}
VOID
NTAPI
FatPrePostIrp(IN PVOID Context,
IN PIRP Irp)
{
UNIMPLEMENTED;
}
/* EOF */

View file

@ -1,120 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/rw.c
* PURPOSE: Read/write support
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
FatiRead(PFAT_IRP_CONTEXT IrpContext)
{
ULONG NumberOfBytes;
LARGE_INTEGER ByteOffset;
PFILE_OBJECT FileObject;
TYPE_OF_OPEN OpenType;
PIO_STACK_LOCATION IrpSp = IrpContext->Stack;
PFCB Fcb;
PVCB Vcb;
PCCB Ccb;
PVOID Buffer;
LONG BytesRead;
FileObject = IrpSp->FileObject;
NumberOfBytes = IrpSp->Parameters.Read.Length;
ByteOffset = IrpSp->Parameters.Read.ByteOffset;
if (NumberOfBytes == 0)
{
FatCompleteRequest(IrpContext, IrpContext->Irp, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
OpenType = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
DPRINT("FatiRead() Fcb %p, Name %wZ, Offset %d, Length %d, Handle %p\n",
Fcb, &FileObject->FileName, ByteOffset.LowPart, NumberOfBytes, Fcb->FatHandle);
/* Perform actual read */
if (IrpContext->MinorFunction & IRP_MN_MDL)
{
DPRINT1("MDL read\n");
}
else
{
Buffer = FatMapUserBuffer(IrpContext->Irp);
DPRINT("Normal cached read, buffer %p\n");
/* Set offset */
FF_Seek(Fcb->FatHandle, ByteOffset.LowPart, FF_SEEK_SET);
/* Read */
BytesRead = FF_Read(Fcb->FatHandle, NumberOfBytes, 1, Buffer);
DPRINT("Read %d bytes\n", BytesRead);
/* Indicate we read requested amount of bytes */
IrpContext->Irp->IoStatus.Information = BytesRead;
IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
}
/* Complete the request */
FatCompleteRequest(IrpContext, IrpContext->Irp, STATUS_SUCCESS);
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
FatRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
BOOLEAN TopLevel, CanWait;
PFAT_IRP_CONTEXT IrpContext;
CanWait = TRUE;
TopLevel = FALSE;
Status = STATUS_INVALID_DEVICE_REQUEST;
/* Get CanWait flag */
if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
CanWait = IoIsOperationSynchronous(Irp);
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
if (DeviceObject != FatGlobalData.DiskDeviceObject)
{
/* Set Top Level IRP if not set */
TopLevel = FatIsTopLevelIrp(Irp);
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, CanWait);
/* Perform the actual read */
Status = FatiRead(IrpContext);
/* Restore top level Irp */
if (TopLevel)
IoSetTopLevelIrp(NULL);
}
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}
NTSTATUS
NTAPI
FatWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT1("FatWrite()\n");
return STATUS_NOT_IMPLEMENTED;
}

View file

@ -1,25 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/shutdown.c
* PURPOSE: Shutdown support routines
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
FatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT1("FatShutdown(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
return STATUS_NOT_IMPLEMENTED;
}
/* EOF */

View file

@ -1,271 +0,0 @@
/*
* PROJECT: ReactOS FAT file system driver
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
* FILE: drivers/filesystems/fastfat/volume.c
* PURPOSE: Volume information
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include "fastfat.h"
/* FUNCTIONS ****************************************************************/
NTSTATUS
NTAPI
FatiQueryFsVolumeInfo(PVCB Vcb,
PFILE_FS_VOLUME_INFORMATION Buffer,
PLONG Length)
{
ULONG ByteSize;
NTSTATUS Status = STATUS_SUCCESS;
/* Deduct the minimum written length */
*Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
/* Zero it */
RtlZeroMemory(Buffer, sizeof(FILE_FS_VOLUME_INFORMATION));
DPRINT("Serial number 0x%x, label length %d\n",
Vcb->Vpb->SerialNumber, Vcb->Vpb->VolumeLabelLength);
/* Save serial number */
Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
/* Set max byte size */
ByteSize = Vcb->Vpb->VolumeLabelLength;
/* Check buffer length and reduce byte size if needed */
if (*Length < Vcb->Vpb->VolumeLabelLength)
{
/* Copy only up to what buffer size was provided */
ByteSize = *Length;
Status = STATUS_BUFFER_OVERFLOW;
}
/* Copy volume label */
Buffer->VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
RtlCopyMemory(Buffer->VolumeLabel, Vcb->Vpb->VolumeLabel, ByteSize);
*Length -= ByteSize;
return Status;
}
NTSTATUS
NTAPI
FatiQueryFsSizeInfo(PVCB Vcb,
PFILE_FS_SIZE_INFORMATION Buffer,
PLONG Length)
{
FF_PARTITION *Partition;
NTSTATUS Status = STATUS_SUCCESS;
/* Deduct the minimum written length */
*Length -= sizeof(FILE_FS_SIZE_INFORMATION);
/* Zero it */
RtlZeroMemory(Buffer, sizeof(FILE_FS_SIZE_INFORMATION));
/* Reference FullFAT's partition */
Partition = Vcb->Ioman->pPartition;
/* Set values */
Buffer->AvailableAllocationUnits.LowPart = Partition->FreeClusterCount;
Buffer->TotalAllocationUnits.LowPart = Partition->NumClusters;
Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->NumClusters,
Partition->FreeClusterCount, Vcb->Bpb.SectorsPerCluster, Vcb->Bpb.BytesPerSector);
return Status;
}
NTSTATUS
NTAPI
FatiQueryFsDeviceInfo(PVCB Vcb,
PFILE_FS_DEVICE_INFORMATION Buffer,
PLONG Length)
{
/* Deduct the minimum written length */
*Length -= sizeof(FILE_FS_DEVICE_INFORMATION);
/* Zero it */
RtlZeroMemory(Buffer, sizeof(FILE_FS_DEVICE_INFORMATION));
/* Set values */
Buffer->DeviceType = FILE_DEVICE_DISK;
Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
FatiQueryVolumeInfo(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
{
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION IrpSp;
FILE_INFORMATION_CLASS InfoClass;
TYPE_OF_OPEN FileType;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
LONG Length;
PVOID Buffer;
BOOLEAN VcbLocked = FALSE;
NTSTATUS Status = STATUS_SUCCESS;
/* Get IRP stack location */
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Get the file object */
FileObject = IrpSp->FileObject;
/* Copy variables to something with shorter names */
InfoClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
Length = IrpSp->Parameters.QueryVolume.Length;
Buffer = Irp->AssociatedIrp.SystemBuffer;
DPRINT("FatiQueryVolumeInfo\n", 0);
DPRINT("\tIrp = %08lx\n", Irp);
DPRINT("\tLength = %08lx\n", Length);
DPRINT("\tFsInformationClass = %08lx\n", InfoClass);
DPRINT("\tBuffer = %08lx\n", Buffer);
FileType = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
DPRINT("Vcb %p, Fcb %p, Ccb %p, open type %d\n", Vcb, Fcb, Ccb, FileType);
switch (InfoClass)
{
case FileFsVolumeInformation:
/* Acquired the shared VCB lock */
if (!FatAcquireSharedVcb(IrpContext, Vcb))
{
ASSERT(FALSE);
}
/* Remember we locked it */
VcbLocked = TRUE;
/* Call FsVolumeInfo handler */
Status = FatiQueryFsVolumeInfo(Vcb, Buffer, &Length);
break;
case FileFsSizeInformation:
/* Call FsVolumeInfo handler */
Status = FatiQueryFsSizeInfo(Vcb, Buffer, &Length);
break;
case FileFsDeviceInformation:
Status = FatiQueryFsDeviceInfo(Vcb, Buffer, &Length);
break;
case FileFsAttributeInformation:
UNIMPLEMENTED;
//Status = FatiQueryFsAttributeInfo(IrpContext, Vcb, Buffer, &Length);
break;
case FileFsFullSizeInformation:
UNIMPLEMENTED;
//Status = FatiQueryFsFullSizeInfo(IrpContext, Vcb, Buffer, &Length);
break;
default:
Status = STATUS_INVALID_PARAMETER;
}
/* Set IoStatus.Information to amount of filled bytes */
Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
/* Release VCB lock */
if (VcbLocked) FatReleaseVcb(IrpContext, Vcb);
/* Complete request and return status */
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
NTSTATUS
NTAPI
FatQueryVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
NTSTATUS Status;
BOOLEAN TopLevel, CanWait;
PFAT_IRP_CONTEXT IrpContext;
CanWait = TRUE;
TopLevel = FALSE;
Status = STATUS_INVALID_DEVICE_REQUEST;
/* Get CanWait flag */
if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
CanWait = IoIsOperationSynchronous(Irp);
/* Enter FsRtl critical region */
FsRtlEnterFileSystem();
/* Set Top Level IRP if not set */
TopLevel = FatIsTopLevelIrp(Irp);
/* Build an irp context */
IrpContext = FatBuildIrpContext(Irp, CanWait);
/* Call the request handler */
Status = FatiQueryVolumeInfo(IrpContext, Irp);
/* Restore top level Irp */
if (TopLevel)
IoSetTopLevelIrp(NULL);
/* Leave FsRtl critical region */
FsRtlExitFileSystem();
return Status;
}
NTSTATUS
NTAPI
FatSetVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
DPRINT1("FatSetVolumeInfo()\n");
return STATUS_NOT_IMPLEMENTED;
}
VOID
NTAPI
FatReadStreamFile(PVCB Vcb,
ULONGLONG ByteOffset,
ULONG ByteSize,
PBCB *Bcb,
PVOID *Buffer)
{
LARGE_INTEGER Offset;
Offset.QuadPart = ByteOffset;
if (!CcMapData(Vcb->StreamFileObject,
&Offset,
ByteSize,
TRUE, // FIXME: CanWait
Bcb,
Buffer))
{
ASSERT(FALSE);
}
}
BOOLEAN
NTAPI
FatCheckForDismount(IN PFAT_IRP_CONTEXT IrpContext,
PVCB Vcb,
IN BOOLEAN Force)
{
/* We never allow deletion of a volume for now */
return FALSE;
}
/* EOF */

View file

@ -3,7 +3,6 @@ add_subdirectory(adns)
add_subdirectory(bzip2)
add_subdirectory(cardlib)
add_subdirectory(freetype)
add_subdirectory(fullfat)
add_subdirectory(libmpg123)
add_subdirectory(libsamplerate)
add_subdirectory(libwine)

View file

@ -1,24 +0,0 @@
include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/fullfat)
add_definitions(-D__NTDRIVER__)
list(APPEND SOURCE
ff_blk.c
ff_crc.c
ff_dir.c
ff_error.c
ff_fat.c
ff_file.c
ff_hash.c
ff_ioman.c
ff_memory.c
ff_safety.c
ff_string.c
ff_time.c)
add_library(fullfat ${SOURCE})
add_dependencies(fullfat bugcodes xdk)
if((NOT MSVC) AND (NOT CMAKE_C_COMPILER_ID STREQUAL "Clang"))
add_target_compile_flags(fullfat "-Wno-unused-but-set-variable")
endif()

View file

@ -1,85 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_blk.c
* @author James Walmsley
* @ingroup BLK
*
* @defgroup BLK Block Calculater
* @brief Handle Block Number conversions
*
* Helps calculate block numbers.
**/
#include "ff_blk.h"
/**
* @private
**/
FF_T_UINT32 FF_getClusterChainNumber(FF_IOMAN *pIoman, FF_T_UINT32 nEntry, FF_T_UINT16 nEntrySize) {
FF_PARTITION *pPart = pIoman->pPartition;
FF_T_UINT32 clusterChainNumber = nEntry / (pIoman->BlkSize * (pPart->SectorsPerCluster * pPart->BlkFactor) / nEntrySize);
return clusterChainNumber;
}
FF_T_UINT32 FF_getClusterPosition(FF_IOMAN *pIoman, FF_T_UINT32 nEntry, FF_T_UINT16 nEntrySize) {
return nEntry % ((pIoman->BlkSize * (pIoman->pPartition->SectorsPerCluster * pIoman->pPartition->BlkFactor)) / nEntrySize);
}
/**
* @private
**/
FF_T_UINT32 FF_getMajorBlockNumber(FF_IOMAN *pIoman, FF_T_UINT32 nEntry, FF_T_UINT16 nEntrySize) {
FF_PARTITION *pPart = pIoman->pPartition;
FF_T_UINT32 relClusterEntry = nEntry % (pIoman->BlkSize * (pPart->SectorsPerCluster * pPart->BlkFactor) / nEntrySize);
FF_T_UINT32 majorBlockNumber = relClusterEntry / (pPart->BlkSize / nEntrySize);
return majorBlockNumber;
}
/**
* @private
**/
FF_T_UINT8 FF_getMinorBlockNumber(FF_IOMAN *pIoman, FF_T_UINT32 nEntry, FF_T_UINT16 nEntrySize) {
FF_PARTITION *pPart = pIoman->pPartition;
FF_T_UINT32 relClusterEntry = nEntry % (pIoman->BlkSize * (pPart->SectorsPerCluster * pPart->BlkFactor) / nEntrySize);
FF_T_UINT16 relmajorBlockEntry = (FF_T_UINT16)(relClusterEntry % (pPart->BlkSize / nEntrySize));
FF_T_UINT8 minorBlockNumber = (FF_T_UINT8) (relmajorBlockEntry / (pIoman->BlkSize / nEntrySize));
return minorBlockNumber;
}
/**
* @private
**/
FF_T_UINT32 FF_getMinorBlockEntry(FF_IOMAN *pIoman, FF_T_UINT32 nEntry, FF_T_UINT16 nEntrySize) {
FF_PARTITION *pPart = pIoman->pPartition;
FF_T_UINT32 relClusterEntry = nEntry % (pIoman->BlkSize * (pPart->SectorsPerCluster * pPart->BlkFactor) / nEntrySize);
FF_T_UINT32 relmajorBlockEntry = (FF_T_UINT32)(relClusterEntry % (pPart->BlkSize / nEntrySize));
FF_T_UINT32 minorBlockEntry = (FF_T_UINT32)(relmajorBlockEntry % (pIoman->BlkSize / nEntrySize));
return minorBlockEntry;
}

View file

@ -1,255 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_crc.c
* @author James Walmsley
* @ingroup CRC
*
* @defgroup CRC CRC Checksums for Strings
* @brief Provides fast hashing functions.
*
**/
#include "ff_crc.h"
static const FF_T_UINT32 crc32_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
FF_T_UINT32 FF_GetCRC32(FF_T_UINT8 *pbyData, FF_T_UINT32 stLength) {
register FF_T_UINT32 crc = 0xFFFFFFFF;
while(stLength--) {
crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32_table[(crc^*pbyData++) & 0x000000FF];
}
return (crc ^ 0xFFFFFFFF);
}
static const FF_T_UINT8 crc16_table_low[256] =
{
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x000, 0x0c1, 0x081, 0x040, 0x001, 0x0c0, 0x080, 0x041,
0x001, 0x0c0, 0x080, 0x041, 0x000, 0x0c1, 0x081, 0x040,
};
static const FF_T_UINT8 crc16_table_high[256] =
{
0x000, 0x0c0, 0x0c1, 0x001, 0x0c3, 0x003, 0x002, 0x0c2,
0x0c6, 0x006, 0x007, 0x0c7, 0x005, 0x0c5, 0x0c4, 0x004,
0x0cc, 0x00c, 0x00d, 0x0cd, 0x00f, 0x0cf, 0x0ce, 0x00e,
0x00a, 0x0ca, 0x0cb, 0x00b, 0x0c9, 0x009, 0x008, 0x0c8,
0x0d8, 0x018, 0x019, 0x0d9, 0x01b, 0x0db, 0x0da, 0x01a,
0x01e, 0x0de, 0x0df, 0x01f, 0x0dd, 0x01d, 0x01c, 0x0dc,
0x014, 0x0d4, 0x0d5, 0x015, 0x0d7, 0x017, 0x016, 0x0d6,
0x0d2, 0x012, 0x013, 0x0d3, 0x011, 0x0d1, 0x0d0, 0x010,
0x0f0, 0x030, 0x031, 0x0f1, 0x033, 0x0f3, 0x0f2, 0x032,
0x036, 0x0f6, 0x0f7, 0x037, 0x0f5, 0x035, 0x034, 0x0f4,
0x03c, 0x0fc, 0x0fd, 0x03d, 0x0ff, 0x03f, 0x03e, 0x0fe,
0x0fa, 0x03a, 0x03b, 0x0fb, 0x039, 0x0f9, 0x0f8, 0x038,
0x028, 0x0e8, 0x0e9, 0x029, 0x0eb, 0x02b, 0x02a, 0x0ea,
0x0ee, 0x02e, 0x02f, 0x0ef, 0x02d, 0x0ed, 0x0ec, 0x02c,
0x0e4, 0x024, 0x025, 0x0e5, 0x027, 0x0e7, 0x0e6, 0x026,
0x022, 0x0e2, 0x0e3, 0x023, 0x0e1, 0x021, 0x020, 0x0e0,
0x0a0, 0x060, 0x061, 0x0a1, 0x063, 0x0a3, 0x0a2, 0x062,
0x066, 0x0a6, 0x0a7, 0x067, 0x0a5, 0x065, 0x064, 0x0a4,
0x06c, 0x0ac, 0x0ad, 0x06d, 0x0af, 0x06f, 0x06e, 0x0ae,
0x0aa, 0x06a, 0x06b, 0x0ab, 0x069, 0x0a9, 0x0a8, 0x068,
0x078, 0x0b8, 0x0b9, 0x079, 0x0bb, 0x07b, 0x07a, 0x0ba,
0x0be, 0x07e, 0x07f, 0x0bf, 0x07d, 0x0bd, 0x0bc, 0x07c,
0x0b4, 0x074, 0x075, 0x0b5, 0x077, 0x0b7, 0x0b6, 0x076,
0x072, 0x0b2, 0x0b3, 0x073, 0x0b1, 0x071, 0x070, 0x0b0,
0x050, 0x090, 0x091, 0x051, 0x093, 0x053, 0x052, 0x092,
0x096, 0x056, 0x057, 0x097, 0x055, 0x095, 0x094, 0x054,
0x09c, 0x05c, 0x05d, 0x09d, 0x05f, 0x09f, 0x09e, 0x05e,
0x05a, 0x09a, 0x09b, 0x05b, 0x099, 0x059, 0x058, 0x098,
0x088, 0x048, 0x049, 0x089, 0x04b, 0x08b, 0x08a, 0x04a,
0x04e, 0x08e, 0x08f, 0x04f, 0x08d, 0x04d, 0x04c, 0x08c,
0x044, 0x084, 0x085, 0x045, 0x087, 0x047, 0x046, 0x086,
0x082, 0x042, 0x043, 0x083, 0x041, 0x081, 0x080, 0x040,
};
/*****************************************************************************
* Description: Function to 16 bit CRC check a block of memory
*
* Parameters: pbyData - Pointer to the source data
* stLength - The length to CRC
*
* Return value: The 16 bit CRC value
*
*****************************************************************************/
FF_T_UINT16 FF_GetCRC16(FF_T_UINT8 *pbyData, FF_T_UINT32 stLength) {
FF_T_UINT8 bTableValue;
FF_T_UINT16 wCRC = 0;
while (stLength--) {
bTableValue = (FF_T_UINT8)((wCRC & 0x00FF) ^ *pbyData++);
wCRC = (FF_T_UINT16)(((crc16_table_high[bTableValue]) << 8)
+ (crc16_table_low[bTableValue] ^ ((wCRC >> 8) & 0x00FF)));
}
return wCRC;
}
static const FF_T_UINT8 crc8_table[256] =
{
0, 94, 188, 226, 97, 63, 221, 131,
194, 156, 126, 32, 163, 253, 31, 65,
157, 195, 33, 127, 252, 162, 64, 30,
95, 1, 227, 189, 62, 96, 130, 220,
35, 125, 159, 193, 66, 28, 254, 160,
225, 191, 93, 3, 128, 222, 60, 98,
190, 224, 2, 92, 223, 129, 99, 61,
124, 34, 192, 158, 29, 67, 161, 255,
70, 24, 250, 164, 39, 121, 155, 197,
132, 218, 56, 102, 229, 187, 89, 7,
219, 133, 103, 57, 186, 228, 6, 88,
25, 71, 165, 251, 120, 38, 196, 154,
101, 59, 217, 135, 4, 90, 184, 230,
167, 249, 27, 69, 198, 152, 122, 36,
248, 166, 68, 26, 153, 199, 37, 123,
58, 100, 134, 216, 91, 5, 231, 185,
140, 210, 48, 110, 237, 179, 81, 15,
78, 16, 242, 172, 47, 113, 147, 205,
17, 79, 173, 243, 112, 46, 204, 146,
211, 141, 111, 49, 178, 236, 14, 80,
175, 241, 19, 77, 206, 144, 114, 44,
109, 51, 209, 143, 12, 82, 176, 238,
50, 108, 142, 208, 83, 13, 239, 177,
240, 174, 76, 18, 145, 207, 45, 115,
202, 148, 118, 40, 171, 245, 23, 73,
8, 86, 180, 234, 105, 55, 213, 139,
87, 9, 235, 181, 54, 104, 138, 212,
149, 203, 41, 119, 244, 170, 72, 22,
233, 183, 85, 11, 136, 214, 52, 106,
43, 117, 151, 201, 74, 20, 246, 168,
116, 42, 200, 150, 21, 75, 169, 247,
182, 232, 10, 84, 215, 137, 107, 53
};
/*****************************************************************************
* Description: Function to CRC check a block of memory
*
* Parameters: pbyData - Pointer to the source data
* stLength - The length to CRC
*
* Return value: The 8 bit CRC value
*
*****************************************************************************/
FF_T_UINT8 FF_GetCRC8(FF_T_UINT8 *pbyData, FF_T_UINT32 stLength) {
FF_T_UINT8 byCRC = 0, byData;
while (stLength--) {
byData = *pbyData++;
byCRC = crc8_table[(byCRC ^ byData)];
}
return byCRC;
}

File diff suppressed because it is too large Load diff

View file

@ -1,111 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_error.c
* @author James Walmsley
* @ingroup ERROR
*
* @defgroup ERR Error Message
* @brief Used to return pretty strings for FullFAT error codes.
*
**/
#include "ff_config.h"
#include "ff_types.h"
#include "ff_error.h"
#ifdef FF_DEBUG
const struct _FFERRTAB
{
const FF_T_INT8 * const strErrorString;
const FF_T_SINT32 iErrorCode;
} gcpFullFATErrorTable[] =
{
{"Unknown or Generic Error! - Please contact FullFAT DEV - james@worm.me.uk", -1000},
{"No Error.", FF_ERR_NONE},
{"Null Pointer provided, (probably for IOMAN).", FF_ERR_NULL_POINTER},
{"Not enough memory (malloc() returned NULL).", FF_ERR_NOT_ENOUGH_MEMORY},
{"Device Driver returned a FATAL error!.", FF_ERR_DEVICE_DRIVER_FAILED},
{"The blocksize is not 512 multiple.", FF_ERR_IOMAN_BAD_BLKSIZE},
{"The memory size, is not a multiple of the blocksize. (Atleast 2 Blocks).", FF_ERR_IOMAN_BAD_MEMSIZE},
{"Device is already registered, use FF_UnregisterBlkDevice() first.", FF_ERR_IOMAN_DEV_ALREADY_REGD},
{"No mountable partition was found on the specified device.", FF_ERR_IOMAN_NO_MOUNTABLE_PARTITION},
{"The format of the MBR was unrecognised.", FF_ERR_IOMAN_INVALID_FORMAT},
{"The provided partition number is out-of-range (0 - 3).", FF_ERR_IOMAN_INVALID_PARTITION_NUM},
{"The selected partition / volume doesn't appear to be FAT formatted.", FF_ERR_IOMAN_NOT_FAT_FORMATTED},
{"Cannot register device. (BlkSize not a multiple of 512).", FF_ERR_IOMAN_DEV_INVALID_BLKSIZE},
{"Cannot unregister device, a partition is still mounted.", FF_ERR_IOMAN_PARTITION_MOUNTED},
{"Cannot unmount the partition while there are active FILE handles.", FF_ERR_IOMAN_ACTIVE_HANDLES},
{"The GPT partition header appears to be corrupt, refusing to mount.", FF_ERR_IOMAN_GPT_HEADER_CORRUPT},
{"Cannot open the file, file already in use.", FF_ERR_FILE_ALREADY_OPEN},
{"The specified file could not be found.", FF_ERR_FILE_NOT_FOUND},
{"Cannot open a Directory.", FF_ERR_FILE_OBJECT_IS_A_DIR},
{"Cannot open for writing: File is marked as Read-Only.", FF_ERR_FILE_IS_READ_ONLY},
{"Path not found.", FF_ERR_FILE_INVALID_PATH},
{"A file or folder of the same name already exists.", FF_ERR_DIR_OBJECT_EXISTS},
{"FF_ERR_DIR_DIRECTORY_FULL", FF_ERR_DIR_DIRECTORY_FULL},
{"FF_ERR_DIR_END_OF_DIR", FF_ERR_DIR_END_OF_DIR},
{"The directory is not empty.", FF_ERR_DIR_NOT_EMPTY},
{"Could not extend File or Folder - No Free Space!", FF_ERR_FAT_NO_FREE_CLUSTERS},
{"Could not find the directory specified by the path.", FF_ERR_DIR_INVALID_PATH},
{"The Root Dir is full, and cannot be extended on Fat12 or 16 volumes.", FF_ERR_DIR_CANT_EXTEND_ROOT_DIR},
{"File operation failed - the file was not opened for writing.", FF_ERR_FILE_NOT_OPENED_IN_WRITE_MODE},
{"File operation failed - the file was not opened for reading.", FF_ERR_FILE_NOT_OPENED_IN_READ_MODE},
{"File operation failed - could not extend file.", FF_ERR_FILE_EXTEND_FAILED},
{"Destination file already exists.", FF_ERR_FILE_DESTINATION_EXISTS},
{"Source file was not found.", FF_ERR_FILE_SOURCE_NOT_FOUND},
{"Destination path (dir) was not found.", FF_ERR_FILE_DIR_NOT_FOUND},
{"Failed to create the directory Entry.", FF_ERR_FILE_COULD_NOT_CREATE_DIRENT},
{"Not enough free disk space to complete the disk transaction.", FF_ERR_IOMAN_NOT_ENOUGH_FREE_SPACE},
{"Attempted to Read a sector out of bounds.", FF_ERR_IOMAN_OUT_OF_BOUNDS_READ},
{"Attempted to Write a sector out of bounds.", FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE},
};
/**
* @public
* @brief Returns a pointer to a string relating to a FullFAT error code.
*
* @param iErrorCode The error code.
*
* @return Pointer to a string describing the error.
*
**/
const FF_T_INT8 *FF_GetErrMessage(FF_ERROR iErrorCode) {
FF_T_UINT32 stCount = sizeof (gcpFullFATErrorTable) / sizeof ( struct _FFERRTAB);
while (stCount--){
if (gcpFullFATErrorTable[stCount].iErrorCode == iErrorCode) {
return gcpFullFATErrorTable[stCount].strErrorString;
}
}
return gcpFullFATErrorTable[0].strErrorString;
}
#endif

View file

@ -1,844 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_fat.c
* @author James Walmsley
* @ingroup FAT
*
* @defgroup FAT Fat File-System
* @brief Handles FAT access and traversal.
*
* Provides file-system interfaces for the FAT file-system.
**/
#include "ff_fat.h"
#include "ff_config.h"
#include <string.h>
void FF_lockFAT(FF_IOMAN *pIoman) {
FF_PendSemaphore(pIoman->pSemaphore); // Use Semaphore to protect FAT modifications.
{
while((pIoman->Locks & FF_FAT_LOCK)) {
FF_ReleaseSemaphore(pIoman->pSemaphore);
FF_Yield(); // Keep Releasing and Yielding until we have the Fat protector.
FF_PendSemaphore(pIoman->pSemaphore);
}
pIoman->Locks |= FF_FAT_LOCK;
}
FF_ReleaseSemaphore(pIoman->pSemaphore);
}
void FF_unlockFAT(FF_IOMAN *pIoman) {
FF_PendSemaphore(pIoman->pSemaphore);
{
pIoman->Locks &= ~FF_FAT_LOCK;
}
FF_ReleaseSemaphore(pIoman->pSemaphore);
}
/**
* @private
**/
FF_T_UINT32 FF_getRealLBA(FF_IOMAN *pIoman, FF_T_UINT32 LBA) {
return LBA * pIoman->pPartition->BlkFactor;
}
/**
* @private
**/
FF_T_UINT32 FF_Cluster2LBA(FF_IOMAN *pIoman, FF_T_UINT32 Cluster) {
FF_T_UINT32 lba = 0;
FF_PARTITION *pPart;
if(pIoman) {
pPart = pIoman->pPartition;
if(Cluster > 1) {
lba = ((Cluster - 2) * pPart->SectorsPerCluster) + pPart->FirstDataSector;
} else {
lba = pPart->ClusterBeginLBA;
}
}
return lba;
}
/**
* @private
**/
FF_T_UINT32 FF_LBA2Cluster(FF_IOMAN *pIoman, FF_T_UINT32 Address) {
FF_T_UINT32 cluster = 0;
FF_PARTITION *pPart;
if(pIoman) {
pPart = pIoman->pPartition;
if(pPart->Type == FF_T_FAT32) {
cluster = ((Address - pPart->ClusterBeginLBA) / pPart->SectorsPerCluster) + 2;
} else {
cluster = ((Address - pPart->ClusterBeginLBA) / pPart->SectorsPerCluster);
}
}
return cluster;
}
/**
* @private
**/
FF_T_UINT32 FF_getFatEntry(FF_IOMAN *pIoman, FF_T_UINT32 nCluster, FF_ERROR *pError) {
FF_BUFFER *pBuffer;
FF_T_UINT32 FatOffset;
FF_T_UINT32 FatSector;
FF_T_UINT32 FatSectorEntry;
FF_T_UINT32 FatEntry;
FF_T_UINT8 LBAadjust;
FF_T_UINT16 relClusterEntry;
#ifdef FF_FAT12_SUPPORT
FF_T_UINT8 F12short[2]; // For FAT12 FAT Table Across sector boundary traversal.
#endif
if(pIoman->pPartition->Type == FF_T_FAT32) {
FatOffset = nCluster * 4;
} else if(pIoman->pPartition->Type == FF_T_FAT16) {
FatOffset = nCluster * 2;
}else {
FatOffset = nCluster + (nCluster / 2);
}
FatSector = pIoman->pPartition->FatBeginLBA + (FatOffset / pIoman->pPartition->BlkSize);
FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
LBAadjust = (FF_T_UINT8) (FatSectorEntry / pIoman->BlkSize);
relClusterEntry = (FF_T_UINT32) (FatSectorEntry % pIoman->BlkSize);
FatSector = FF_getRealLBA(pIoman, FatSector);
#ifdef FF_FAT12_SUPPORT
if(pIoman->pPartition->Type == FF_T_FAT12) {
if(relClusterEntry == (FF_T_UINT32)(pIoman->BlkSize - 1)) {
// Fat Entry SPANS a Sector!
// First Buffer get the last Byte in buffer (first byte of our address)!
pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_READ);
{
if(!pBuffer) {
*pError = FF_ERR_DEVICE_DRIVER_FAILED;
return 0;
}
F12short[0] = FF_getChar(pBuffer->pBuffer, (FF_T_UINT16)(pIoman->BlkSize - 1));
}
FF_ReleaseBuffer(pIoman, pBuffer);
// Second Buffer get the first Byte in buffer (second byte of out address)!
pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust + 1, FF_MODE_READ);
{
if(!pBuffer) {
*pError = FF_ERR_DEVICE_DRIVER_FAILED;
return 0;
}
F12short[1] = FF_getChar(pBuffer->pBuffer, 0);
}
FF_ReleaseBuffer(pIoman, pBuffer);
FatEntry = (FF_T_UINT32) FF_getShort((FF_T_UINT8*)&F12short, 0); // Guarantee correct Endianess!
if(nCluster & 0x0001) {
FatEntry = FatEntry >> 4;
}
FatEntry &= 0x0FFF;
return (FF_T_SINT32) FatEntry;
}
}
#endif
pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_READ);
{
if(!pBuffer) {
*pError = FF_ERR_DEVICE_DRIVER_FAILED;
return 0;
}
switch(pIoman->pPartition->Type) {
case FF_T_FAT32:
FatEntry = FF_getLong(pBuffer->pBuffer, relClusterEntry);
FatEntry &= 0x0fffffff; // Clear the top 4 bits.
break;
case FF_T_FAT16:
FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, relClusterEntry);
break;
#ifdef FF_FAT12_SUPPORT
case FF_T_FAT12:
FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, relClusterEntry);
if(nCluster & 0x0001) {
FatEntry = FatEntry >> 4;
}
FatEntry &= 0x0FFF;
break;
#endif
default:
FatEntry = 0;
break;
}
}
FF_ReleaseBuffer(pIoman, pBuffer);
return (FF_T_SINT32) FatEntry;
}
FF_ERROR FF_ClearCluster(FF_IOMAN *pIoman, FF_T_UINT32 nCluster) {
FF_BUFFER *pBuffer;
FF_T_UINT16 i;
FF_T_UINT32 BaseLBA;
BaseLBA = FF_Cluster2LBA(pIoman, nCluster);
BaseLBA = FF_getRealLBA(pIoman, BaseLBA);
for(i = 0; i < pIoman->pPartition->SectorsPerCluster; i++) {
pBuffer = FF_GetBuffer(pIoman, BaseLBA++, FF_MODE_WRITE);
{
if(!pBuffer) {
return FF_ERR_DEVICE_DRIVER_FAILED;
}
memset(pBuffer->pBuffer, 0x00, 512);
}
FF_ReleaseBuffer(pIoman, pBuffer);
}
return FF_ERR_NONE;
}
/**
* @private
* @brief Returns the Cluster address of the Cluster number from the beginning of a chain.
*
* @param pIoman FF_IOMAN Object
* @param Start Cluster address of the first cluster in the chain.
* @param Count Number of Cluster in the chain,
*
*
*
**/
FF_T_UINT32 FF_TraverseFAT(FF_IOMAN *pIoman, FF_T_UINT32 Start, FF_T_UINT32 Count, FF_ERROR *pError) {
FF_T_UINT32 i;
FF_T_UINT32 fatEntry = Start, currentCluster = Start;
*pError = FF_ERR_NONE;
for(i = 0; i < Count; i++) {
fatEntry = FF_getFatEntry(pIoman, currentCluster, pError);
if(*pError) {
return 0;
}
if(FF_isEndOfChain(pIoman, fatEntry)) {
return currentCluster;
} else {
currentCluster = fatEntry;
}
}
return fatEntry;
}
FF_T_UINT32 FF_FindEndOfChain(FF_IOMAN *pIoman, FF_T_UINT32 Start, FF_ERROR *pError) {
FF_T_UINT32 fatEntry = Start, currentCluster = Start;
*pError = FF_ERR_NONE;
while(!FF_isEndOfChain(pIoman, fatEntry)) {
fatEntry = FF_getFatEntry(pIoman, currentCluster, pError);
if(*pError) {
return 0;
}
if(FF_isEndOfChain(pIoman, fatEntry)) {
return currentCluster;
} else {
currentCluster = fatEntry;
}
}
return fatEntry;
}
/**
* @private
* @brief Tests if the fatEntry is an End of Chain Marker.
*
* @param pIoman FF_IOMAN Object
* @param fatEntry The fat entry from the FAT table to be checked.
*
* @return FF_TRUE if it is an end of chain, otherwise FF_FALSE.
*
**/
FF_T_BOOL FF_isEndOfChain(FF_IOMAN *pIoman, FF_T_UINT32 fatEntry) {
FF_T_BOOL result = FF_FALSE;
if(pIoman->pPartition->Type == FF_T_FAT32) {
if((fatEntry & 0x0fffffff) >= 0x0ffffff8) {
result = FF_TRUE;
}
} else if(pIoman->pPartition->Type == FF_T_FAT16) {
if(fatEntry >= 0x0000fff8) {
result = FF_TRUE;
}
} else {
if(fatEntry >= 0x00000ff8) {
result = FF_TRUE;
}
}
if(fatEntry == 0x00000000) {
result = FF_TRUE; //Perhaps trying to read a deleted file!
}
return result;
}
/**
* @private
* @brief Writes a new Entry to the FAT Tables.
*
* @param pIoman IOMAN object.
* @param nCluster Cluster Number to be modified.
* @param Value The Value to store.
**/
FF_ERROR FF_putFatEntry(FF_IOMAN *pIoman, FF_T_UINT32 nCluster, FF_T_UINT32 Value) {
FF_BUFFER *pBuffer;
FF_T_UINT32 FatOffset;
FF_T_UINT32 FatSector;
FF_T_UINT32 FatSectorEntry;
FF_T_UINT32 FatEntry;
FF_T_UINT8 LBAadjust;
FF_T_UINT32 relClusterEntry;
#ifdef FF_FAT12_SUPPORT
FF_T_UINT8 F12short[2]; // For FAT12 FAT Table Across sector boundary traversal.
#endif
if(pIoman->pPartition->Type == FF_T_FAT32) {
FatOffset = nCluster * 4;
} else if(pIoman->pPartition->Type == FF_T_FAT16) {
FatOffset = nCluster * 2;
}else {
FatOffset = nCluster + (nCluster / 2);
}
FatSector = pIoman->pPartition->FatBeginLBA + (FatOffset / pIoman->pPartition->BlkSize);
FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
LBAadjust = (FF_T_UINT8) (FatSectorEntry / pIoman->BlkSize);
relClusterEntry = (FF_T_UINT32)(FatSectorEntry % pIoman->BlkSize);
FatSector = FF_getRealLBA(pIoman, FatSector);
#ifdef FF_FAT12_SUPPORT
if(pIoman->pPartition->Type == FF_T_FAT12) {
if(relClusterEntry == (FF_T_UINT32)(pIoman->BlkSize - 1)) {
// Fat Entry SPANS a Sector!
// First Buffer get the last Byte in buffer (first byte of our address)!
pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_READ);
{
if(!pBuffer) {
return FF_ERR_DEVICE_DRIVER_FAILED;
}
F12short[0] = FF_getChar(pBuffer->pBuffer, (FF_T_UINT16)(pIoman->BlkSize - 1));
}
FF_ReleaseBuffer(pIoman, pBuffer);
// Second Buffer get the first Byte in buffer (second byte of out address)!
pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust + 1, FF_MODE_READ);
{
if(!pBuffer) {
return FF_ERR_DEVICE_DRIVER_FAILED;
}
F12short[1] = FF_getChar(pBuffer->pBuffer, (FF_T_UINT16) 0x0000);
}
FF_ReleaseBuffer(pIoman, pBuffer);
FatEntry = FF_getShort((FF_T_UINT8*)&F12short, (FF_T_UINT16) 0x0000); // Guarantee correct Endianess!
if(nCluster & 0x0001) {
FatEntry &= 0x000F;
Value = (Value << 4);
Value &= 0xFFF0;
} else {
FatEntry &= 0xF000;
Value &= 0x0FFF;
}
FF_putShort((FF_T_UINT8 *)F12short, 0x0000, (FF_T_UINT16) (FatEntry | Value));
pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_WRITE);
{
if(!pBuffer) {
return FF_ERR_DEVICE_DRIVER_FAILED;
}
FF_putChar(pBuffer->pBuffer, (FF_T_UINT16)(pIoman->BlkSize - 1), F12short[0]);
}
FF_ReleaseBuffer(pIoman, pBuffer);
// Second Buffer get the first Byte in buffer (second byte of out address)!
pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust + 1, FF_MODE_READ);
{
if(!pBuffer) {
return FF_ERR_DEVICE_DRIVER_FAILED;
}
FF_putChar(pBuffer->pBuffer, 0x0000, F12short[1]);
}
FF_ReleaseBuffer(pIoman, pBuffer);
return FF_ERR_NONE;
}
}
#endif
pBuffer = FF_GetBuffer(pIoman, FatSector + LBAadjust, FF_MODE_WRITE);
{
if(!pBuffer) {
return FF_ERR_DEVICE_DRIVER_FAILED;
}
if(pIoman->pPartition->Type == FF_T_FAT32) {
Value &= 0x0fffffff; // Clear the top 4 bits.
FF_putLong(pBuffer->pBuffer, relClusterEntry, Value);
} else if(pIoman->pPartition->Type == FF_T_FAT16) {
FF_putShort(pBuffer->pBuffer, relClusterEntry, (FF_T_UINT16) Value);
} else {
FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, relClusterEntry);
if(nCluster & 0x0001) {
FatEntry &= 0x000F;
Value = (Value << 4);
Value &= 0xFFF0;
} else {
FatEntry &= 0xF000;
Value &= 0x0FFF;
}
FF_putShort(pBuffer->pBuffer, relClusterEntry, (FF_T_UINT16) (FatEntry | Value));
}
}
FF_ReleaseBuffer(pIoman, pBuffer);
return FF_ERR_NONE;
}
/**
* @private
* @brief Finds a Free Cluster and returns its number.
*
* @param pIoman IOMAN Object.
*
* @return The number of the cluster found to be free.
* @return 0 on error.
**/
#ifdef FF_FAT12_SUPPORT
static FF_T_UINT32 FF_FindFreeClusterOLD(FF_IOMAN *pIoman, FF_ERROR *pError) {
FF_T_UINT32 nCluster;
FF_T_UINT32 fatEntry;
*pError = FF_ERR_NONE;
for(nCluster = pIoman->pPartition->LastFreeCluster; nCluster < pIoman->pPartition->NumClusters; nCluster++) {
fatEntry = FF_getFatEntry(pIoman, nCluster, pError);
if(*pError) {
return 0;
}
if(fatEntry == 0x00000000) {
pIoman->pPartition->LastFreeCluster = nCluster;
return nCluster;
}
}
return 0;
}
#endif
FF_T_UINT32 FF_FindFreeCluster(FF_IOMAN *pIoman, FF_ERROR *pError) {
FF_BUFFER *pBuffer;
FF_T_UINT32 i, x, nCluster = pIoman->pPartition->LastFreeCluster;
FF_T_UINT32 FatOffset;
FF_T_UINT32 FatSector;
FF_T_UINT32 FatSectorEntry;
FF_T_UINT32 EntriesPerSector;
FF_T_UINT32 FatEntry = 1;
*pError = FF_ERR_NONE;
#ifdef FF_FAT12_SUPPORT
if(pIoman->pPartition->Type == FF_T_FAT12) { // FAT12 tables are too small to optimise, and would make it very complicated!
return FF_FindFreeClusterOLD(pIoman, pError);
}
#endif
if(pIoman->pPartition->Type == FF_T_FAT32) {
EntriesPerSector = pIoman->BlkSize / 4;
FatOffset = nCluster * 4;
} else {
EntriesPerSector = pIoman->BlkSize / 2;
FatOffset = nCluster * 2;
}
// HT addition: don't use non-existing clusters
if (nCluster >= pIoman->pPartition->NumClusters) {
*pError = FF_ERR_FAT_NO_FREE_CLUSTERS;
return 0;
}
FatSector = (FatOffset / pIoman->pPartition->BlkSize);
for(i = FatSector; i < pIoman->pPartition->SectorsPerFAT; i++) {
pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FatBeginLBA + i, FF_MODE_READ);
{
if(!pBuffer) {
*pError = FF_ERR_DEVICE_DRIVER_FAILED;
return 0;
}
for(x = nCluster % EntriesPerSector; x < EntriesPerSector; x++) {
if(pIoman->pPartition->Type == FF_T_FAT32) {
FatOffset = x * 4;
FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
FatEntry = FF_getLong(pBuffer->pBuffer, (FF_T_UINT16)FatSectorEntry);
FatEntry &= 0x0fffffff; // Clear the top 4 bits.
} else {
FatOffset = x * 2;
FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, (FF_T_UINT16)FatSectorEntry);
}
if(FatEntry == 0x00000000) {
FF_ReleaseBuffer(pIoman, pBuffer);
pIoman->pPartition->LastFreeCluster = nCluster;
return nCluster;
}
nCluster++;
}
}
FF_ReleaseBuffer(pIoman, pBuffer);
}
return 0;
}
/**
* @private
* @brief Create's a Cluster Chain
**/
FF_T_UINT32 FF_CreateClusterChain(FF_IOMAN *pIoman, FF_ERROR *pError) {
FF_T_UINT32 iStartCluster;
FF_ERROR Error;
*pError = FF_ERR_NONE;
FF_lockFAT(pIoman);
{
iStartCluster = FF_FindFreeCluster(pIoman, &Error);
if(Error) {
*pError = Error;
FF_unlockFAT(pIoman);
return 0;
}
if(iStartCluster) {
Error = FF_putFatEntry(pIoman, iStartCluster, 0xFFFFFFFF); // Mark the cluster as End-Of-Chain
if(Error) {
*pError = Error;
FF_unlockFAT(pIoman);
return 0;
}
}
}
FF_unlockFAT(pIoman);
if(iStartCluster) {
Error = FF_DecreaseFreeClusters(pIoman, 1);
if(Error) {
*pError = Error;
return 0;
}
}
return iStartCluster;
}
FF_T_UINT32 FF_GetChainLength(FF_IOMAN *pIoman, FF_T_UINT32 pa_nStartCluster, FF_T_UINT32 *piEndOfChain, FF_ERROR *pError) {
FF_T_UINT32 iLength = 0;
*pError = FF_ERR_NONE;
FF_lockFAT(pIoman);
{
while(!FF_isEndOfChain(pIoman, pa_nStartCluster)) {
pa_nStartCluster = FF_getFatEntry(pIoman, pa_nStartCluster, pError);
if(*pError) {
return 0;
}
iLength++;
}
if(piEndOfChain) {
*piEndOfChain = pa_nStartCluster;
}
}
FF_unlockFAT(pIoman);
return iLength;
}
/**
* @private
* @brief Extend a Cluster chain by Count number of Clusters
*
* @param pIoman IOMAN object.
* @param StartCluster Cluster Number that starts the chain.
* @param Count Number of clusters to extend the chain with.
*
**/
/*
FF_T_UINT32 FF_ExtendClusterChain(FF_IOMAN *pIoman, FF_T_UINT32 StartCluster, FF_T_UINT32 Count) {
FF_T_UINT32 currentCluster = StartCluster, nextCluster;
FF_T_UINT32 clusEndOfChain;
FF_T_UINT32 i;
clusEndOfChain = FF_FindEndOfChain(pIoman, StartCluster);
nextCluster = FF_FindFreeCluster(pIoman); // Find Free clusters!
FF_putFatEntry(pIoman, clusEndOfChain, nextCluster);
for(i = 0; i <= Count; i++) {
currentCluster = nextCluster;
if(i == Count) {
FF_putFatEntry(pIoman, currentCluster, 0xFFFFFFFF);
break;
}
nextCluster = FF_FindFreeCluster(pIoman);
FF_putFatEntry(pIoman, currentCluster, ++nextCluster);
}
FF_FlushCache(pIoman);
return currentCluster;
}*/
/**
* @private
* @brief Free's Disk space by freeing unused links on Cluster Chains
*
* @param pIoman, IOMAN object.
* @param StartCluster Cluster Number that starts the chain.
* @param Count Number of Clusters from the end of the chain to unlink.
* @param Count 0 Means Free the entire chain (delete file).
*
* @return 0 On Success.
* @return -1 If the device driver failed to provide access.
*
**/
FF_ERROR FF_UnlinkClusterChain(FF_IOMAN *pIoman, FF_T_UINT32 StartCluster, FF_T_UINT16 Count) {
FF_T_UINT32 fatEntry;
FF_T_UINT32 currentCluster, chainLength = 0;
FF_T_UINT32 iLen = 0;
FF_T_UINT32 lastFree = StartCluster; /* HT addition : reset LastFreeCluster */
FF_ERROR Error;
fatEntry = StartCluster;
if(Count == 0) {
// Free all clusters in the chain!
currentCluster = StartCluster;
fatEntry = currentCluster;
do {
fatEntry = FF_getFatEntry(pIoman, fatEntry, &Error);
if(Error) {
return Error;
}
Error = FF_putFatEntry(pIoman, currentCluster, 0x00000000);
if(Error) {
return Error;
}
if (lastFree > currentCluster) {
lastFree = currentCluster;
}
currentCluster = fatEntry;
iLen ++;
}while(!FF_isEndOfChain(pIoman, fatEntry));
if (pIoman->pPartition->LastFreeCluster > lastFree) {
pIoman->pPartition->LastFreeCluster = lastFree;
}
Error = FF_IncreaseFreeClusters(pIoman, iLen);
if(Error) {
return Error;
}
} else {
// Truncation - This is quite hard, because we can only do it backwards.
do {
fatEntry = FF_getFatEntry(pIoman, fatEntry, &Error);
if(Error) {
return Error;
}
chainLength++;
}while(!FF_isEndOfChain(pIoman, fatEntry));
}
return FF_ERR_NONE;
}
#ifdef FF_FAT12_SUPPORT
FF_T_UINT32 FF_CountFreeClustersOLD(FF_IOMAN *pIoman, FF_ERROR *pError) {
FF_T_UINT32 i;
FF_T_UINT32 TotalClusters = pIoman->pPartition->DataSectors / pIoman->pPartition->SectorsPerCluster;
FF_T_UINT32 FatEntry;
FF_T_UINT32 FreeClusters = 0;
*pError = FF_ERR_NONE;
for(i = 0; i < TotalClusters; i++) {
FatEntry = FF_getFatEntry(pIoman, i, pError);
if(*pError) {
return 0;
}
if(!FatEntry) {
FreeClusters++;
}
}
return FreeClusters;
}
#endif
FF_T_UINT32 FF_CountFreeClusters(FF_IOMAN *pIoman, FF_ERROR *pError) {
FF_BUFFER *pBuffer;
FF_T_UINT32 i, x, nCluster = 0;
FF_T_UINT32 FatOffset;
FF_T_UINT32 FatSector;
FF_T_UINT32 FatSectorEntry;
FF_T_UINT32 EntriesPerSector;
FF_T_UINT32 FatEntry = 1;
FF_T_UINT32 FreeClusters = 0;
*pError = FF_ERR_NONE;
#ifdef FF_FAT12_SUPPORT
if(pIoman->pPartition->Type == FF_T_FAT12) { // FAT12 tables are too small to optimise, and would make it very complicated!
FreeClusters = FF_CountFreeClustersOLD(pIoman, pError);
if(*pError) {
return 0;
}
}
#endif
if(pIoman->pPartition->Type == FF_T_FAT32) {
EntriesPerSector = pIoman->BlkSize / 4;
FatOffset = nCluster * 4;
} else {
EntriesPerSector = pIoman->BlkSize / 2;
FatOffset = nCluster * 2;
}
FatSector = (FatOffset / pIoman->pPartition->BlkSize);
for(i = 0; i < pIoman->pPartition->SectorsPerFAT; i++) {
pBuffer = FF_GetBuffer(pIoman, pIoman->pPartition->FatBeginLBA + i, FF_MODE_READ);
{
if(!pBuffer) {
*pError = FF_ERR_DEVICE_DRIVER_FAILED;
return 0;
}
for(x = nCluster % EntriesPerSector; x < EntriesPerSector; x++) {
if(pIoman->pPartition->Type == FF_T_FAT32) {
FatOffset = x * 4;
FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
FatEntry = FF_getLong(pBuffer->pBuffer, (FF_T_UINT16)FatSectorEntry);
FatEntry &= 0x0fffffff; // Clear the top 4 bits.
} else {
FatOffset = x * 2;
FatSectorEntry = FatOffset % pIoman->pPartition->BlkSize;
FatEntry = (FF_T_UINT32) FF_getShort(pBuffer->pBuffer, FatSectorEntry);
}
if(FatEntry == 0x00000000) {
FreeClusters += 1;
}
nCluster++;
}
}
FF_ReleaseBuffer(pIoman, pBuffer);
}
return FreeClusters <= pIoman->pPartition->NumClusters ? FreeClusters : pIoman->pPartition->NumClusters;
}
#ifdef FF_64_NUM_SUPPORT
FF_T_UINT64 FF_GetFreeSize(FF_IOMAN *pIoman, FF_ERROR *pError) {
FF_T_UINT32 FreeClusters;
FF_T_UINT64 FreeSize;
FF_ERROR Error;
if(pIoman) {
FF_lockFAT(pIoman);
{
if(!pIoman->pPartition->FreeClusterCount) {
pIoman->pPartition->FreeClusterCount = FF_CountFreeClusters(pIoman, &Error);
if(Error) {
if(pError) {
*pError = Error;
}
FF_unlockFAT(pIoman);
return 0;
}
}
FreeClusters = pIoman->pPartition->FreeClusterCount;
}
FF_unlockFAT(pIoman);
FreeSize = (FF_T_UINT64) ((FF_T_UINT64)FreeClusters * (FF_T_UINT64)((FF_T_UINT64)pIoman->pPartition->SectorsPerCluster * (FF_T_UINT64)pIoman->pPartition->BlkSize));
return FreeSize;
}
return 0;
}
#else
FF_T_UINT32 FF_GetFreeSize(FF_IOMAN *pIoman) {
FF_T_UINT32 FreeClusters;
FF_T_UINT32 FreeSize;
if(pIoman) {
FF_lockFAT(pIoman);
{
if(!pIoman->pPartition->FreeClusterCount) {
pIoman->pPartition->FreeClusterCount = FF_CountFreeClusters(pIoman);
}
FreeClusters = pIoman->pPartition->FreeClusterCount;
}
FF_unlockFAT(pIoman);
FreeSize = (FF_T_UINT32) ((FF_T_UINT32)FreeClusters * (FF_T_UINT32)((FF_T_UINT32)pIoman->pPartition->SectorsPerCluster * (FF_T_UINT32)pIoman->pPartition->BlkSize));
return FreeSize;
}
return 0;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,132 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_format.c
* @author James Walmsley
* @ingroup FORMAT
*
* @defgroup FORMAT Independent FAT Formatter
* @brief Provides an interface to format a partition with FAT.
*
*
*
**/
#include "ff_format.h"
#include "ff_types.h"
#include "ff_ioman.h"
#include "ff_fatdef.h"
static FF_T_SINT8 FF_PartitionCount (FF_T_UINT8 *pBuffer)
{
FF_T_SINT8 count = 0;
FF_T_SINT8 part;
// Check PBR or MBR signature
if (FF_getChar(pBuffer, FF_FAT_MBR_SIGNATURE) != 0x55 &&
FF_getChar(pBuffer, FF_FAT_MBR_SIGNATURE) != 0xAA ) {
// No MBR, but is it a PBR ?
if (FF_getChar(pBuffer, 0) == 0xEB && // PBR Byte 0
FF_getChar(pBuffer, 2) == 0x90 && // PBR Byte 2
(FF_getChar(pBuffer, 21) & 0xF0) == 0xF0) {// PBR Byte 21 : Media byte
return 1; // No MBR but PBR exist then only one partition
}
return 0; // No MBR and no PBR then no partition found
}
for (part = 0; part < 4; part++) {
FF_T_UINT8 active = FF_getChar(pBuffer, FF_FAT_PTBL + FF_FAT_PTBL_ACTIVE + (16 * part));
FF_T_UINT8 part_id = FF_getChar(pBuffer, FF_FAT_PTBL + FF_FAT_PTBL_ID + (16 * part));
// The first sector must be a MBR, then check the partition entry in the MBR
if (active != 0x80 && (active != 0 || part_id == 0)) {
break;
}
count++;
}
return count;
}
FF_ERROR FF_FormatPartition(FF_IOMAN *pIoman, FF_T_UINT32 ulPartitionNumber, FF_T_UINT32 ulClusterSize) {
FF_BUFFER *pBuffer;
FF_T_UINT8 ucPartitionType;
FF_T_SINT8 scPartitionCount;
FF_T_UINT32 /*ulPartitionBeginLBA, ulPartitionLength,*/ ulPnum;
FF_ERROR Error = FF_ERR_NONE;
ulClusterSize = 0;
// Get Partition Metrics, and pass on to FF_Format() function
pBuffer = FF_GetBuffer(pIoman, 0, FF_MODE_READ);
{
if(!pBuffer) {
return FF_ERR_DEVICE_DRIVER_FAILED;
}
scPartitionCount = FF_PartitionCount(pBuffer->pBuffer);
ucPartitionType = FF_getChar(pBuffer->pBuffer, FF_FAT_PTBL + FF_FAT_PTBL_ID);
if(ucPartitionType == 0xEE) {
// Handle Extended Partitions
ulPnum = 0;
} else {
if(ulPartitionNumber > (FF_T_UINT32) scPartitionCount) {
FF_ReleaseBuffer(pIoman, pBuffer);
return FF_ERR_IOMAN_INVALID_PARTITION_NUM;
}
ulPnum = ulPartitionNumber;
}
}
FF_ReleaseBuffer(pIoman, pBuffer);
return Error;
}
FF_ERROR FF_Format(FF_IOMAN *pIoman, FF_T_UINT32 ulStartLBA, FF_T_UINT32 ulEndLBA, FF_T_UINT32 ulClusterSize) {
FF_T_UINT32 ulTotalSectors;
FF_T_UINT32 ulTotalClusters;
ulTotalSectors = ulEndLBA - ulStartLBA;
ulTotalClusters = ulTotalSectors / (ulClusterSize / pIoman->BlkSize);
return -1;
}

View file

@ -1,119 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_hash.c
* @author James Walmsley
* @ingroup HASH
*
* @defgroup HASH HASH Table
* @brief Provides a simple HASH lookup table.
*
**/
#include "ff_hash.h"
#include <stdlib.h>
#include <string.h>
#ifdef FF_HASH_CACHE
struct _FF_HASH_TABLE {
FF_T_UINT8 bitTable[FF_HASH_TABLE_SIZE];
};
/**
*
*
**/
FF_HASH_TABLE FF_CreateHashTable() {
FF_HASH_TABLE pHash = (FF_HASH_TABLE) FF_MALLOC(sizeof(struct _FF_HASH_TABLE));
if(pHash) {
FF_ClearHashTable(pHash);
return pHash;
}
return NULL;
}
FF_ERROR FF_ClearHashTable(FF_HASH_TABLE pHash) {
if(pHash) {
memset(pHash->bitTable, 0, FF_HASH_TABLE_SIZE);
return FF_ERR_NONE;
}
return FF_ERR_NULL_POINTER;
}
FF_ERROR FF_SetHash(FF_HASH_TABLE pHash, FF_T_UINT32 nHash) {
FF_T_UINT32 tblIndex = ((nHash / 8) % FF_HASH_TABLE_SIZE);
FF_T_UINT32 tblBit = nHash % 8;
if(pHash) {
pHash->bitTable[tblIndex] |= (0x80 >> tblBit);
return FF_ERR_NONE;
}
return FF_ERR_NULL_POINTER;
}
FF_ERROR FF_ClearHash(FF_HASH_TABLE pHash, FF_T_UINT32 nHash) {
FF_T_UINT32 tblIndex = ((nHash / 8) % FF_HASH_TABLE_SIZE);
FF_T_UINT32 tblBit = nHash % 8;
if(pHash) {
pHash->bitTable[tblIndex] &= ~(0x80 >> tblBit);
return FF_ERR_NONE;
}
return FF_ERR_NULL_POINTER;
}
FF_T_BOOL FF_isHashSet(FF_HASH_TABLE pHash, FF_T_UINT32 nHash) {
FF_T_UINT32 tblIndex = ((nHash / 8) % FF_HASH_TABLE_SIZE);
FF_T_UINT32 tblBit = nHash % 8;
if(pHash) {
if(pHash->bitTable[tblIndex] & (0x80 >> tblBit)) {
return FF_TRUE;
}
}
return FF_FALSE;
}
FF_ERROR FF_DestroyHashTable(FF_HASH_TABLE pHash) {
if(pHash) {
FF_FREE(pHash);
return FF_ERR_NONE;
}
return FF_ERR_NULL_POINTER;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,102 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_memory.c
* @author James Walmsley
* @ingroup MEMORY
*
* @defgroup MEMORY FullFAT Memory Access Routines
* @brief Handles memory access in a portable way.
*
* Provides simple, fast, and portable access to memory routines.
* These are only used to read data from buffers. That are LITTLE ENDIAN
* due to the FAT specification.
*
* These routines may need to be modified to your platform.
*
**/
#include "ff_memory.h"
#include "ff_config.h"
/*
* HT inlined these functions
*
* Not much left for the C-module
*/
#ifndef FF_INLINE_MEMORY_ACCESS
FF_T_UINT8 FF_getChar(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset) {
return (FF_T_UINT8) (pBuffer[aOffset]);
}
FF_T_UINT16 FF_getShort(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset) {
FF_T_UN16 u16;
pBuffer += aOffset;
u16.bytes.u8_1 = pBuffer[1];
u16.bytes.u8_0 = pBuffer[0];
return u16.u16;
}
FF_T_UINT32 FF_getLong(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset) {
FF_T_UN32 u32;
pBuffer += aOffset;
u32.bytes.u8_3 = pBuffer[3];
u32.bytes.u8_2 = pBuffer[2];
u32.bytes.u8_1 = pBuffer[1];
u32.bytes.u8_0 = pBuffer[0];
return u32.u32;
}
void FF_putChar(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT8 Value) {
pBuffer[aOffset] = Value;
}
void FF_putShort(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT16 Value) {
FF_T_UN16 u16;
u16.u16 = Value;
pBuffer += aOffset;
pBuffer[0] = u16.bytes.u8_0;
pBuffer[1] = u16.bytes.u8_1;
}
void FF_putLong(FF_T_UINT8 *pBuffer, FF_T_UINT32 aOffset, FF_T_UINT32 Value) {
FF_T_UN32 u32;
u32.u32 = Value;
pBuffer += aOffset;
pBuffer[0] = u32.bytes.u8_0;
pBuffer[1] = u32.bytes.u8_1;
pBuffer[2] = u32.bytes.u8_2;
pBuffer[3] = u32.bytes.u8_3;
}
#endif

View file

@ -1,175 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_safety.c
* @author James Walmsley
* @ingroup SAFETY
*
* @defgroup SAFETY Process Safety for FullFAT
* @brief Provides semaphores, and thread-safety for FullFAT.
*
* This module aims to be as portable as possible. It is necessary to modify
* the functions FF_CreateSemaphore, FF_PendSemaphore, FF_ReleaseSemaphore,
* and FF_DestroySemaphore, as appropriate for your platform.
*
* If your application has no OS and is therefore single threaded, simply
* have:
*
* FF_CreateSemaphore() return NULL.
*
* FF_PendSemaphore() should do nothing.
*
* FF_ReleaseSemaphore() should do nothing.
*
* FF_DestroySemaphore() should do nothing.
*
**/
#include "ff_safety.h" // Íncludes ff_types.h
#include <ntifs.h>
#define TAG_FULLFAT 'FLUF'
// Call your OS's CreateSemaphore function
//
void *FF_CreateSemaphore(void) {
PKSEMAPHORE ProcessSemaphore;
/* Allocate some memory to store the semaphore */
ProcessSemaphore = ExAllocatePoolWithTag(NonPagedPool,
sizeof(KSEMAPHORE),
TAG_FULLFAT);
if (ProcessSemaphore)
{
/* Initialize it */
KeInitializeSemaphore(ProcessSemaphore,
0,
MAXLONG);
}
return ProcessSemaphore;
}
// Call your OS's PendSemaphore with the provided pSemaphore pointer.
//
// This should block indefinitely until the Semaphore
// becomes available. (No timeout!)
// If your OS doesn't do it for you, you should sleep
// this thread until the Semaphore is available.
void FF_PendSemaphore(void *pSemaphore) {
NTSTATUS Status;
/* Sanity check */
if (pSemaphore)
{
/* Wait for the sempaphore to become signaled */
Status = KeWaitForSingleObject(pSemaphore,
Executive,
KernelMode,
FALSE,
NULL);
if (NT_SUCCESS(Status))
{
if (Status != STATUS_SUCCESS)
{
// log an error?
}
}
else
{
// log an error?
}
}
}
// Call your OS's ReleaseSemaphore with the provided pSemaphore pointer.
//
void FF_ReleaseSemaphore(void *pSemaphore) {
/* Sanity check */
if (pSemaphore)
{
/* Increment the semaphore */
KeReleaseSemaphore(pSemaphore,
0,
1,
FALSE);
}
}
// Call your OS's DestroySemaphore with the provided pSemaphore pointer.
//
void FF_DestroySemaphore(void *pSemaphore) {
/* Sanity check */
if (pSemaphore)
{
/* Free the semaphore memory */
ExFreePoolWithTag(pSemaphore,
TAG_FULLFAT);
}
}
// FIXME: what do we do with this?
void FF_Yield(void) {
// Call your OS's thread Yield function.
// If this doesn't work, then a deadlock will occur
}
// Call your OS's thread sleep function,
// Sleep for TimeMs milliseconds
void FF_Sleep(FF_T_UINT32 TimeMs) {
LARGE_INTEGER Interval;
NTSTATUS Status;
/* Calculate the interval */
Interval.QuadPart = -((LONGLONG)TimeMs * 10000);
/* Do the wait */
Status = KeDelayExecutionThread(KernelMode,
FALSE,
&Interval);
if (!NT_SUCCESS(Status))
{
// log an error?
}
}
/**
* Notes on implementation.
*
*
*
**/

View file

@ -1,456 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_string.c
* @author James Walmsley
* @ingroup STRING
*
* @defgroup STRING FullFAT String Library
* @brief Portable String Library for FullFAT
*
*
**/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "ff_string.h"
#include "ff_error.h"
#ifdef FF_UNICODE_SUPPORT
#include <wchar.h>
#include <wctype.h>
#endif
/*
* These will eventually be moved into a platform independent string
* library. Which will be optional. (To allow the use of system specific versions).
*/
#ifdef FF_UNICODE_SUPPORT
void FF_cstrntowcs(FF_T_WCHAR *wcsDest, const FF_T_INT8 *szpSource, FF_T_UINT32 len) {
while(*szpSource && len--) {
*wcsDest++ = *szpSource++;
}
*wcsDest = '\0';
}
void FF_cstrtowcs(FF_T_WCHAR *wcsDest, const FF_T_INT8 *szpSource) {
while(*szpSource) {
*wcsDest++ = (FF_T_WCHAR) *szpSource++;
}
*wcsDest = '\0';
}
void FF_wcstocstr(FF_T_INT8 *szpDest, const FF_T_WCHAR *wcsSource) {
while(*wcsSource) {
*szpDest++ = (FF_T_INT8) *wcsSource++;
}
*szpDest = '\0';
}
void FF_wcsntocstr(FF_T_INT8 *szpDest, const FF_T_WCHAR *wcsSource, FF_T_UINT32 len) {
while(*wcsSource && len--) {
*szpDest++ = (FF_T_INT8) *wcsSource++;
}
*szpDest = '\0';
}
#endif
/**
* @private
* @brief Converts an ASCII string to lowercase.
**/
#ifndef FF_UNICODE_SUPPORT
/**
* @private
* @brief Converts an ASCII string to uppercase.
**/
void FF_toupper(FF_T_INT8 *string, FF_T_UINT32 strLen) {
FF_T_UINT32 i;
for(i = 0; i < strLen; i++) {
if(string[i] >= 'a' && string[i] <= 'z')
string[i] -= 32;
if(string[i] == '\0')
break;
}
}
void FF_tolower(FF_T_INT8 *string, FF_T_UINT32 strLen) {
FF_T_UINT32 i;
for(i = 0; i < strLen; i++) {
if(string[i] >= 'A' && string[i] <= 'Z')
string[i] += 32;
if(string[i] == '\0')
break;
}
}
#else
void FF_toupper(FF_T_WCHAR *string, FF_T_UINT32 strLen) {
FF_T_UINT32 i;
for(i = 0; i < strLen; i++) {
string[i] = towupper(string[i]);
}
}
void FF_tolower(FF_T_WCHAR *string, FF_T_UINT32 strLen) {
FF_T_UINT32 i;
for(i = 0; i < strLen; i++) {
string[i] = towlower(string[i]);
}
}
#endif
/**
* @private
* @brief Compares 2 strings for the specified length, and returns FF_TRUE is they are identical
* otherwise FF_FALSE is returned.
*
**/
#ifndef FF_UNICODE_SUPPORT
FF_T_BOOL FF_strmatch(const FF_T_INT8 *str1, const FF_T_INT8 *str2, FF_T_UINT16 len) {
register FF_T_UINT16 i;
register FF_T_INT8 char1, char2;
if(!len) {
if(strlen(str1) != strlen(str2)) {
return FF_FALSE;
}
len = (FF_T_UINT16) strlen(str1);
}
for(i = 0; i < len; i++) {
char1 = str1[i];
char2 = str2[i];
if(char1 >= 'A' && char1 <= 'Z') {
char1 += 32;
}
if(char2 >= 'A' && char2 <= 'Z') {
char2 += 32;
}
if(char1 != char2) {
return FF_FALSE;
}
}
return FF_TRUE;
}
#else
FF_T_BOOL FF_strmatch(const FF_T_WCHAR *str1, const FF_T_WCHAR *str2, FF_T_UINT16 len) {
register FF_T_UINT16 i;
register FF_T_WCHAR char1, char2;
if(!len) {
if(wcslen(str1) != wcslen(str2)) {
return FF_FALSE;
}
len = (FF_T_UINT16) wcslen(str1);
}
for(i = 0; i < len; i++) {
char1 = towlower(str1[i]);
char2 = towlower(str2[i]);
if(char1 != char2) {
return FF_FALSE;
}
}
return FF_TRUE;
}
#endif
/**
* @private
* @brief A re-entrant Strtok function. No documentation is provided :P
* Use at your own risk. (This is for FullFAT's use only).
**/
#ifndef FF_UNICODE_SUPPORT
FF_T_INT8 *FF_strtok(const FF_T_INT8 *string, FF_T_INT8 *token, FF_T_UINT16 *tokenNumber, FF_T_BOOL *last, FF_T_UINT16 Length) {
FF_T_UINT16 strLen = Length;
FF_T_UINT16 i,y, tokenStart, tokenEnd = 0;
i = 0;
y = 0;
if(string[i] == '\\' || string[i] == '/') {
i++;
}
tokenStart = i;
while(i < strLen) {
if(string[i] == '\\' || string[i] == '/') {
y++;
if(y == *tokenNumber) {
tokenStart = (FF_T_UINT16)(i + 1);
}
if(y == (*tokenNumber + 1)) {
tokenEnd = i;
break;
}
}
i++;
}
if(!tokenEnd) {
if(*last == FF_TRUE) {
return NULL;
} else {
*last = FF_TRUE;
}
tokenEnd = i;
}
if((tokenEnd - tokenStart) < FF_MAX_FILENAME) {
memcpy(token, (string + tokenStart), (FF_T_UINT32)(tokenEnd - tokenStart));
token[tokenEnd - tokenStart] = '\0';
} else {
memcpy(token, (string + tokenStart), (FF_T_UINT32)(FF_MAX_FILENAME));
token[FF_MAX_FILENAME-1] = '\0';
}
//token[tokenEnd - tokenStart] = '\0';
*tokenNumber += 1;
return token;
}
#else
FF_T_WCHAR *FF_strtok(const FF_T_WCHAR *string, FF_T_WCHAR *token, FF_T_UINT16 *tokenNumber, FF_T_BOOL *last, FF_T_UINT16 Length) {
FF_T_UINT16 strLen = Length;
FF_T_UINT16 i,y, tokenStart, tokenEnd = 0;
i = 0;
y = 0;
if(string[i] == '\\' || string[i] == '/') {
i++;
}
tokenStart = i;
while(i < strLen) {
if(string[i] == '\\' || string[i] == '/') {
y++;
if(y == *tokenNumber) {
tokenStart = (FF_T_UINT16)(i + 1);
}
if(y == (*tokenNumber + 1)) {
tokenEnd = i;
break;
}
}
i++;
}
if(!tokenEnd) {
if(*last == FF_TRUE) {
return NULL;
} else {
*last = FF_TRUE;
}
tokenEnd = i;
}
if((tokenEnd - tokenStart) < FF_MAX_FILENAME) {
memcpy(token, (string + tokenStart), (FF_T_UINT32)(tokenEnd - tokenStart) * sizeof(FF_T_WCHAR));
token[tokenEnd - tokenStart] = '\0';
} else {
memcpy(token, (string + tokenStart), (FF_T_UINT32)(FF_MAX_FILENAME) * sizeof(FF_T_WCHAR));
token[FF_MAX_FILENAME-1] = '\0';
}
//token[tokenEnd - tokenStart] = '\0';
*tokenNumber += 1;
return token;
}
#endif
/*
A Wild-Card Comparator Library function, Provided by Adam Fullerton.
This can be extended or altered to improve or advance wildCard matching
of the FF_FindFirst() and FF_FindNext() API's.
*/
#ifdef FF_FINDAPI_ALLOW_WILDCARDS
/*FF_T_BOOL FF_wildcompare(const FF_T_INT8 *pszWildCard, const FF_T_INT8 *pszString) {
// Check to see if the string contains the wild card
if (!memchr(pszWildCard, '*', strlen(pszWildCard)))
{
// if it does not then do a straight string compare
if (strcmp(pszWildCard, pszString))
{
return FF_FALSE;
}
}
else
{
while ((*pszWildCard)
&& (*pszString))
{
// Test for the wild card
if (*pszWildCard == '*')
{
// Eat more than one
while (*pszWildCard == '*')
{
pszWildCard++;
}
// If there are more chars in the string
if (*pszWildCard)
{
// Search for the next char
pszString = memchr(pszString, (int)*pszWildCard, strlen(pszString));
// if it does not exist then the strings don't match
if (!pszString)
{
return FF_FALSE;
}
}
else
{
if (*pszWildCard)
{
// continue
break;
}
else
{
return FF_TRUE;
}
}
}
else
{
// Fail if they don't match
if (*pszWildCard != *pszString)
{
return FF_FALSE;
}
}
// Bump both pointers
pszWildCard++;
pszString++;
}
// fail if different lengths
if (*pszWildCard != *pszString)
{
return FF_FALSE;
}
}
return FF_TRUE;
}*/
/*
This is a better Wild-card compare function, that works perfectly, and is much more efficient.
This function was contributed by one of our commercial customers.
*/
#ifdef FF_UNICODE_SUPPORT
FF_T_BOOL FF_wildcompare(const FF_T_WCHAR *pszWildCard, const FF_T_WCHAR *pszString) {
register const FF_T_WCHAR *pszWc = NULL;
register const FF_T_WCHAR *pszStr = NULL; // Encourage the string pointers to be placed in memory.
do {
if ( *pszWildCard == '*' ) {
while(*(1 + pszWildCard++) == '*'); // Eat up multiple '*''s
pszWc = (pszWildCard - 1);
pszStr = pszString;
}
if (*pszWildCard == '?' && !*pszString) {
return FF_FALSE; // False when the string is ended, yet a ? charachter is demanded.
}
#ifdef FF_WILDCARD_CASE_INSENSITIVE
if (*pszWildCard != '?' && tolower(*pszWildCard) != tolower(*pszString)) {
#else
if (*pszWildCard != '?' && *pszWildCard != *pszString) {
#endif
if (pszWc == NULL) {
return FF_FALSE;
}
pszWildCard = pszWc;
pszString = pszStr++;
}
} while ( *pszWildCard++ && *pszString++ );
while(*pszWildCard == '*') {
pszWildCard++;
}
if(!*(pszWildCard - 1)) { // WildCard is at the end. (Terminated)
return FF_TRUE; // Therefore this must be a match.
}
return FF_FALSE; // If not, then return FF_FALSE!
}
#else
FF_T_BOOL FF_wildcompare(const FF_T_INT8 *pszWildCard, const FF_T_INT8 *pszString) {
register const FF_T_INT8 *pszWc = NULL;
register const FF_T_INT8 *pszStr = NULL; // Encourage the string pointers to be placed in memory.
do {
if ( *pszWildCard == '*' ) {
while(*(1 + pszWildCard++) == '*'); // Eat up multiple '*''s
pszWc = (pszWildCard - 1);
pszStr = pszString;
}
if (*pszWildCard == '?' && !*pszString) {
return FF_FALSE; // False when the string is ended, yet a ? charachter is demanded.
}
#ifdef FF_WILDCARD_CASE_INSENSITIVE
if (*pszWildCard != '?' && tolower(*pszWildCard) != tolower(*pszString)) {
#else
if (*pszWildCard != '?' && *pszWildCard != *pszString) {
#endif
if (pszWc == NULL) {
return FF_FALSE;
}
pszWildCard = pszWc;
pszString = pszStr++;
}
} while ( *pszWildCard++ && *pszString++ );
while(*pszWildCard == '*') {
pszWildCard++;
}
if(!*(pszWildCard - 1)) { // WildCard is at the end. (Terminated)
return FF_TRUE; // Therefore this must be a match.
}
return FF_FALSE; // If not, then return FF_FALSE!
}
#endif
#endif

View file

@ -1,72 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
#include "ff_time.h"
/**
* @file ff_time.c
* @author James Walmsley
* @ingroup TIME
*
* @defgroup TIME Real-Time Clock Interface
* @brief Allows FullFAT to time-stamp files.
*
* Provides a means for receiving the time on any platform.
**/
#ifdef FF_TIME_SUPPORT
/**
* @public
* @brief Populates an FF_SYSTEMTIME object with the current time from the system.
*
* The developer must modify this function so that it is suitable for their platform.
* The function must return with 0, and if the time is not available all elements of the
* FF_SYSTEMTIME object must be zero'd, as in the examples provided.
*
* @param pTime Pointer to an FF_TIME object.
*
* @return Always returns 0.
**/
FF_T_SINT32 FF_GetSystemTime(FF_SYSTEMTIME *pTime) {
pTime->Hour = 0;
pTime->Minute = 0;
pTime->Second = 0;
pTime->Day = 0;
pTime->Month = 0;
pTime->Year = 0;
return 0;
}
#endif

View file

@ -1,294 +0,0 @@
/*****************************************************************************
* FullFAT - High Performance, Thread-Safe Embedded FAT File-System *
* Copyright (C) 2009 James Walmsley (james@worm.me.uk) *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
* IMPORTANT NOTICE: *
* ================= *
* Alternative Licensing is available directly from the Copyright holder, *
* (James Walmsley). For more information consult LICENSING.TXT to obtain *
* a Commercial license. *
* *
* See RESTRICTIONS.TXT for extra restrictions on the use of FullFAT. *
* *
* Removing the above notice is illegal and will invalidate this license. *
*****************************************************************************
* See http://worm.me.uk/fullfat for more information. *
* Or http://fullfat.googlecode.com/ for latest releases and the wiki. *
*****************************************************************************/
/**
* @file ff_unicode.c
* @author James Walmsley
* @ingroup UNICODE
*
* @defgroup UNICODE FullFAT UNICODE Library
* @brief Portable UNICODE Transformation Library for FullFAT
*
**/
#include "ff_unicode.h"
#include "string.h"
// UTF-8 Routines
/*
UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
*/
FF_T_UINT FF_GetUtf16SequenceLen(FF_T_UINT16 usLeadChar) {
if((usLeadChar & 0xFC00) == 0xD800) {
return 2;
}
return 1;
}
/*
Returns the number of UTF-8 units read.
Will not exceed ulSize UTF-16 units. (ulSize * 2 bytes).
*/
/*
UCS-4 range (hex.) UTF-8 octet sequence (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx -- We don't encode these because we won't receive them. (Invalid UNICODE).
*/
FF_T_SINT32 FF_Utf8ctoUtf16c(FF_T_UINT16 *utf16Dest, const FF_T_UINT8 *utf8Source, FF_T_UINT32 ulSize) {
FF_T_UINT32 ulUtf32char;
FF_T_UINT16 utf16Source = 0;
register FF_T_INT uiSequenceNumber = 0;
while((*utf8Source & (0x80 >> (uiSequenceNumber)))) { // Count number of set bits before a zero.
uiSequenceNumber++;
}
if(!uiSequenceNumber) {
uiSequenceNumber++;
}
if(!ulSize) {
return FF_ERR_UNICODE_DEST_TOO_SMALL;
}
switch(uiSequenceNumber) {
case 1:
utf16Source = (FF_T_UINT16) *utf8Source;
memcpy(utf16Dest,&utf16Source,sizeof(FF_T_UINT16));
//bobtntfullfat *utf16Dest = (FF_T_UINT16) *utf8Source;
break;
case 2:
utf16Source =(FF_T_UINT16) ((*utf8Source & 0x1F) << 6) | ((*(utf8Source + 1) & 0x3F));
memcpy(utf16Dest,&utf16Source,sizeof(FF_T_UINT16));
//bobtntfullfat *utf16Dest = (FF_T_UINT16) ((*utf8Source & 0x1F) << 6) | ((*(utf8Source + 1) & 0x3F));
break;
case 3:
utf16Source =(FF_T_UINT16) ((*utf8Source & 0x0F) << 12) | ((*(utf8Source + 1) & 0x3F) << 6) | ((*(utf8Source + 2) & 0x3F));
memcpy(utf16Dest,&utf16Source,sizeof(FF_T_UINT16));
//bobtntfullfat *utf16Dest = (FF_T_UINT16) ((*utf8Source & 0x0F) << 12) | ((*(utf8Source + 1) & 0x3F) << 6) | ((*(utf8Source + 2) & 0x3F));
break;
case 4:
// Convert to UTF-32 and then into UTF-16
if(ulSize < 2) {
return FF_ERR_UNICODE_DEST_TOO_SMALL;
}
ulUtf32char = (FF_T_UINT16) ((*utf8Source & 0x0F) << 18) | ((*(utf8Source + 1) & 0x3F) << 12) | ((*(utf8Source + 2) & 0x3F) << 6) | ((*(utf8Source + 3) & 0x3F));
utf16Source = (FF_T_UINT16) (((ulUtf32char - 0x10000) & 0xFFC00) >> 10) | 0xD800;
memcpy(utf16Dest,&utf16Source,sizeof(FF_T_UINT16));
utf16Source = (FF_T_UINT16) (((ulUtf32char - 0x10000) & 0x003FF) >> 00) | 0xDC00;
memcpy(utf16Dest+1,&utf16Source,sizeof(FF_T_UINT16));
//bobtntfullfat *(utf16Dest + 0) = (FF_T_UINT16) (((ulUtf32char - 0x10000) & 0xFFC00) >> 10) | 0xD800;
//bobtntfullfat *(utf16Dest + 1) = (FF_T_UINT16) (((ulUtf32char - 0x10000) & 0x003FF) >> 00) | 0xDC00;
break;
default:
break;
}
return uiSequenceNumber;
}
/*
Returns the number of UTF-8 units required to encode the UTF-16 sequence.
Will not exceed ulSize UTF-8 units. (ulSize * 1 bytes).
*/
FF_T_SINT32 FF_Utf16ctoUtf8c(FF_T_UINT8 *utf8Dest, const FF_T_UINT16 *utf16Source, FF_T_UINT32 ulSize) {
FF_T_UINT32 ulUtf32char;
FF_T_UINT16 ulUtf16char;
if(!ulSize) {
return FF_ERR_UNICODE_DEST_TOO_SMALL;
}
memcpy(&ulUtf16char, utf16Source, sizeof(FF_T_UINT16));
if((/*bobtntfullfat *utf16Source*/ulUtf16char & 0xF800) == 0xD800) { // A surrogate sequence was encountered. Must transform to UTF32 first.
ulUtf32char = ((FF_T_UINT32) (ulUtf16char & 0x003FF) << 10) + 0x10000;
//bobtntfullfat ulUtf32char = ((FF_T_UINT32) (*(utf16Source + 0) & 0x003FF) << 10) + 0x10000;
memcpy(&ulUtf16char, utf16Source + 1, sizeof(FF_T_UINT16));
if((/*bobtntfullfat *(utf16Source + 1)*/ulUtf16char & 0xFC00) != 0xDC00) {
return FF_ERR_UNICODE_INVALID_SEQUENCE; // Invalid UTF-16 sequence.
}
ulUtf32char |= ((FF_T_UINT32) (/*bobtntfullfat *(utf16Source + 1)*/ulUtf16char & 0x003FF));
} else {
ulUtf32char = (FF_T_UINT32) /*bobtntfullfat *utf16Source*/ulUtf16char;
}
// Now convert to the UTF-8 sequence.
if(ulUtf32char < 0x00000080) { // Single byte UTF-8 sequence.
*(utf8Dest + 0) = (FF_T_UINT8) ulUtf32char;
return 1;
}
if(ulUtf32char < 0x00000800) { // Double byte UTF-8 sequence.
if(ulSize < 2) {
return FF_ERR_UNICODE_DEST_TOO_SMALL;
}
*(utf8Dest + 0) = (FF_T_UINT8) (0xC0 | ((ulUtf32char >> 6) & 0x1F));
*(utf8Dest + 1) = (FF_T_UINT8) (0x80 | ((ulUtf32char >> 0) & 0x3F));
return 2;
}
if(ulUtf32char < 0x00010000) { // Triple byte UTF-8 sequence.
if(ulSize < 3) {
return FF_ERR_UNICODE_DEST_TOO_SMALL;
}
*(utf8Dest + 0) = (FF_T_UINT8) (0xE0 | ((ulUtf32char >> 12) & 0x0F));
*(utf8Dest + 1) = (FF_T_UINT8) (0x80 | ((ulUtf32char >> 6 ) & 0x3F));
*(utf8Dest + 2) = (FF_T_UINT8) (0x80 | ((ulUtf32char >> 0 ) & 0x3F));
return 3;
}
if(ulUtf32char < 0x00200000) { // Quadruple byte UTF-8 sequence.
if(ulSize < 4) {
return FF_ERR_UNICODE_DEST_TOO_SMALL;
}
*(utf8Dest + 0) = (FF_T_UINT8) (0xF0 | ((ulUtf32char >> 18) & 0x07));
*(utf8Dest + 1) = (FF_T_UINT8) (0x80 | ((ulUtf32char >> 12) & 0x3F));
*(utf8Dest + 2) = (FF_T_UINT8) (0x80 | ((ulUtf32char >> 6 ) & 0x3F));
*(utf8Dest + 3) = (FF_T_UINT8) (0x80 | ((ulUtf32char >> 0 ) & 0x3F));
return 4;
}
return FF_ERR_UNICODE_INVALID_CODE; // Invalid Charachter
}
// UTF-16 Support Functions
// Converts a UTF-32 Charachter into its equivalent UTF-16 sequence.
FF_T_SINT32 FF_Utf32ctoUtf16c(FF_T_UINT16 *utf16Dest, FF_T_UINT32 utf32char, FF_T_UINT32 ulSize) {
// Check that its a valid UTF-32 wide-char!
if(utf32char >= 0xD800 && utf32char <= 0xDFFF) { // This range is not a valid Unicode code point.
return FF_ERR_UNICODE_INVALID_CODE; // Invalid charachter.
}
if(utf32char < 0x10000) {
*utf16Dest = (FF_T_UINT16) utf32char; // Simple conversion! Char comes within UTF-16 space (without surrogates).
return 1;
}
if(ulSize < 2) {
return FF_ERR_UNICODE_DEST_TOO_SMALL; // Not enough UTF-16 units to record this charachter.
}
if(utf32char < 0x00200000) {
// Conversion to a UTF-16 Surrogate pair!
//valueImage = utf32char - 0x10000;
*(utf16Dest + 0) = (FF_T_UINT16) (((utf32char - 0x10000) & 0xFFC00) >> 10) | 0xD800;
*(utf16Dest + 1) = (FF_T_UINT16) (((utf32char - 0x10000) & 0x003FF) >> 00) | 0xDC00;
return 2; // Surrogate pair encoded value.
}
return FF_ERR_UNICODE_INVALID_CODE; // Invalid Charachter
}
// Converts a UTF-16 sequence into its equivalent UTF-32 code point.
FF_T_SINT32 FF_Utf16ctoUtf32c(FF_T_UINT32 *utf32Dest, const FF_T_UINT16 *utf16Source) {
if((*utf16Source & 0xFC00) != 0xD800) { // Not a surrogate sequence.
*utf32Dest = (FF_T_UINT32) *utf16Source;
return 1; // A single UTF-16 item was used to represent the charachter.
}
*utf32Dest = ((FF_T_UINT32) (*(utf16Source + 0) & 0x003FF) << 10) + 0x10000;
if((*(utf16Source + 1) & 0xFC00) != 0xDC00) {
return FF_ERR_UNICODE_INVALID_SEQUENCE; // Invalid UTF-16 sequence.
}
*utf32Dest |= ((FF_T_UINT32) (*(utf16Source + 1) & 0x003FF));
return 2; // 2 utf-16 units make up the Unicode code-point.
}
/*
Returns the total number of UTF-16 items required to represent
the provided UTF-32 string in UTF-16 form.
*/
/*
FF_T_UINT FF_Utf32GetUtf16Len(const FF_T_UINT32 *utf32String) {
FF_T_UINT utf16len = 0;
while(*utf32String) {
if(*utf32String++ <= 0xFFFF) {
utf16len++;
} else {
utf16len += 2;
}
}
return utf16len;
}*/
// String conversions
FF_T_SINT32 FF_Utf32stoUtf8s(FF_T_UINT8 *Utf8String, FF_T_UINT32 *Utf32String) {
int i = 0,y = 0;
FF_T_UINT16 utf16buffer[2];
while(Utf32String[i]) {
// Convert to a UTF16 char.
FF_Utf32ctoUtf16c(utf16buffer, Utf32String[i], 2);
// Now convert the UTF16 to UTF8 sequence.
y += FF_Utf16ctoUtf8c(&Utf8String[y], utf16buffer, 4);
i++;
}
Utf8String[y] = '\0';
return 0;
}