mirror of
https://github.com/reactos/reactos.git
synced 2025-06-01 23:48:12 +00:00
[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:
parent
e9bc2c9b4c
commit
26dd1bcf1f
40 changed files with 0 additions and 16323 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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 */
|
|
@ -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
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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>
|
|
@ -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 */
|
|
@ -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 */
|
||||
|
||||
|
|
@ -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)
|
|
@ -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
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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 */
|
|
@ -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 */
|
1
reactos/sdk/lib/3rdparty/CMakeLists.txt
vendored
1
reactos/sdk/lib/3rdparty/CMakeLists.txt
vendored
|
@ -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)
|
||||
|
|
24
reactos/sdk/lib/3rdparty/fullfat/CMakeLists.txt
vendored
24
reactos/sdk/lib/3rdparty/fullfat/CMakeLists.txt
vendored
|
@ -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()
|
85
reactos/sdk/lib/3rdparty/fullfat/ff_blk.c
vendored
85
reactos/sdk/lib/3rdparty/fullfat/ff_blk.c
vendored
|
@ -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;
|
||||
}
|
||||
|
255
reactos/sdk/lib/3rdparty/fullfat/ff_crc.c
vendored
255
reactos/sdk/lib/3rdparty/fullfat/ff_crc.c
vendored
|
@ -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;
|
||||
}
|
2627
reactos/sdk/lib/3rdparty/fullfat/ff_dir.c
vendored
2627
reactos/sdk/lib/3rdparty/fullfat/ff_dir.c
vendored
File diff suppressed because it is too large
Load diff
111
reactos/sdk/lib/3rdparty/fullfat/ff_error.c
vendored
111
reactos/sdk/lib/3rdparty/fullfat/ff_error.c
vendored
|
@ -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
|
844
reactos/sdk/lib/3rdparty/fullfat/ff_fat.c
vendored
844
reactos/sdk/lib/3rdparty/fullfat/ff_fat.c
vendored
|
@ -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
|
1767
reactos/sdk/lib/3rdparty/fullfat/ff_file.c
vendored
1767
reactos/sdk/lib/3rdparty/fullfat/ff_file.c
vendored
File diff suppressed because it is too large
Load diff
132
reactos/sdk/lib/3rdparty/fullfat/ff_format.c
vendored
132
reactos/sdk/lib/3rdparty/fullfat/ff_format.c
vendored
|
@ -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;
|
||||
|
||||
|
||||
}
|
119
reactos/sdk/lib/3rdparty/fullfat/ff_hash.c
vendored
119
reactos/sdk/lib/3rdparty/fullfat/ff_hash.c
vendored
|
@ -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
|
1100
reactos/sdk/lib/3rdparty/fullfat/ff_ioman.c
vendored
1100
reactos/sdk/lib/3rdparty/fullfat/ff_ioman.c
vendored
File diff suppressed because it is too large
Load diff
102
reactos/sdk/lib/3rdparty/fullfat/ff_memory.c
vendored
102
reactos/sdk/lib/3rdparty/fullfat/ff_memory.c
vendored
|
@ -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
|
175
reactos/sdk/lib/3rdparty/fullfat/ff_safety.c
vendored
175
reactos/sdk/lib/3rdparty/fullfat/ff_safety.c
vendored
|
@ -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.
|
||||
*
|
||||
*
|
||||
*
|
||||
**/
|
||||
|
||||
|
456
reactos/sdk/lib/3rdparty/fullfat/ff_string.c
vendored
456
reactos/sdk/lib/3rdparty/fullfat/ff_string.c
vendored
|
@ -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
|
72
reactos/sdk/lib/3rdparty/fullfat/ff_time.c
vendored
72
reactos/sdk/lib/3rdparty/fullfat/ff_time.c
vendored
|
@ -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
|
294
reactos/sdk/lib/3rdparty/fullfat/ff_unicode.c
vendored
294
reactos/sdk/lib/3rdparty/fullfat/ff_unicode.c
vendored
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue