mirror of
https://github.com/reactos/reactos.git
synced 2025-06-26 12:40:03 +00:00
[fastfat_new]
- Implement FatiOpenExistingFcb. - Make FatGetFcbUnicodeName supporting DCBs. - Implement FF_OpenW wrapper around FullFAT to support opening files/dirs using a unicode name. svn path=/trunk/; revision=43528
This commit is contained in:
parent
fdaf0acd73
commit
b9e1012f27
6 changed files with 318 additions and 20 deletions
|
@ -11,16 +11,6 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include "fastfat.h"
|
#include "fastfat.h"
|
||||||
|
|
||||||
NTSYSAPI
|
|
||||||
NTSTATUS
|
|
||||||
NTAPI
|
|
||||||
RtlUpcaseUnicodeStringToCountedOemString(
|
|
||||||
IN OUT POEM_STRING DestinationString,
|
|
||||||
IN PCUNICODE_STRING SourceString,
|
|
||||||
IN BOOLEAN AllocateDestinationString
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
IO_STATUS_BLOCK
|
IO_STATUS_BLOCK
|
||||||
|
|
|
@ -35,6 +35,15 @@
|
||||||
ExReleaseResourceLite(&(FatGlobalData.Resource)); \
|
ExReleaseResourceLite(&(FatGlobalData.Resource)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSYSAPI
|
||||||
|
NTSTATUS
|
||||||
|
NTAPI
|
||||||
|
RtlUpcaseUnicodeStringToCountedOemString(
|
||||||
|
IN OUT POEM_STRING DestinationString,
|
||||||
|
IN PCUNICODE_STRING SourceString,
|
||||||
|
IN BOOLEAN AllocateDestinationString
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------ shutdown.c */
|
/* ------------------------------------------------------ shutdown.c */
|
||||||
|
|
||||||
|
@ -211,6 +220,14 @@ FatReadBlocks(FF_T_UINT8 *pBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Count,
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
FatLockControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
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 */
|
/* --------------------------------------------------------- fsctl.c */
|
||||||
|
|
||||||
NTSTATUS NTAPI
|
NTSTATUS NTAPI
|
||||||
|
@ -221,6 +238,10 @@ FatFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||||
NTSTATUS NTAPI FatQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
NTSTATUS NTAPI FatQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp);
|
||||||
NTSTATUS NTAPI FatSetInformation(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 */
|
/* --------------------------------------------------------- iface.c */
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
|
|
@ -136,6 +136,7 @@ typedef struct _FAT_METHODS {
|
||||||
#define VCB_STATE_FLAG_LOCKED 0x01
|
#define VCB_STATE_FLAG_LOCKED 0x01
|
||||||
#define VCB_STATE_FLAG_DIRTY 0x02
|
#define VCB_STATE_FLAG_DIRTY 0x02
|
||||||
#define VCB_STATE_MOUNTED_DIRTY 0x04
|
#define VCB_STATE_MOUNTED_DIRTY 0x04
|
||||||
|
#define VCB_STATE_CREATE_IN_PROGRESS 0x08
|
||||||
|
|
||||||
typedef enum _VCB_CONDITION
|
typedef enum _VCB_CONDITION
|
||||||
{
|
{
|
||||||
|
@ -249,6 +250,8 @@ typedef enum _FCB_CONDITION
|
||||||
|
|
||||||
#define FCB_STATE_HAS_NAMES 0x01
|
#define FCB_STATE_HAS_NAMES 0x01
|
||||||
#define FCB_STATE_HAS_UNICODE_NAME 0x02
|
#define FCB_STATE_HAS_UNICODE_NAME 0x02
|
||||||
|
#define FCB_STATE_PAGEFILE 0x04
|
||||||
|
#define FCB_STATE_DELAY_CLOSE 0x08
|
||||||
|
|
||||||
typedef struct _FCB
|
typedef struct _FCB
|
||||||
{
|
{
|
||||||
|
@ -264,7 +267,6 @@ typedef struct _FCB
|
||||||
ERESOURCE Resource; // nonpaged!
|
ERESOURCE Resource; // nonpaged!
|
||||||
ERESOURCE PagingIoResource; // nonpaged!
|
ERESOURCE PagingIoResource; // nonpaged!
|
||||||
|
|
||||||
FILE_LOCK Lock;
|
|
||||||
/* First cluster in the fat allocation chain */
|
/* First cluster in the fat allocation chain */
|
||||||
ULONG FirstClusterOfFile;
|
ULONG FirstClusterOfFile;
|
||||||
/* A list of all FCBs of that DCB */
|
/* A list of all FCBs of that DCB */
|
||||||
|
@ -305,6 +307,13 @@ typedef struct _FCB
|
||||||
PKEVENT OutstandingAsyncEvent;
|
PKEVENT OutstandingAsyncEvent;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
/* File and Op locks */
|
||||||
|
FILE_LOCK Lock;
|
||||||
|
OPLOCK Oplock;
|
||||||
|
} Fcb;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
/* A list of all FCBs/DCBs opened under this DCB */
|
/* A list of all FCBs/DCBs opened under this DCB */
|
||||||
|
|
|
@ -191,9 +191,243 @@ FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
OUT PBOOLEAN OplockPostIrp)
|
OUT PBOOLEAN OplockPostIrp)
|
||||||
{
|
{
|
||||||
IO_STATUS_BLOCK Iosb = {{0}};
|
IO_STATUS_BLOCK Iosb = {{0}};
|
||||||
|
ACCESS_MASK AddedAccess = 0;
|
||||||
|
BOOLEAN Hidden;
|
||||||
|
BOOLEAN System;
|
||||||
|
PCCB Ccb = NULL;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
Iosb.Status = STATUS_NOT_IMPLEMENTED;
|
/* Acquire exclusive FCB lock */
|
||||||
|
(VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);
|
||||||
|
|
||||||
|
*OplockPostIrp = FALSE;
|
||||||
|
|
||||||
|
/* Check if there is a batch oplock */
|
||||||
|
if (FsRtlCurrentBatchOplock(&Fcb->Fcb.Oplock))
|
||||||
|
{
|
||||||
|
/* Return with a special information field */
|
||||||
|
Iosb.Information = FILE_OPBATCH_BREAK_UNDERWAY;
|
||||||
|
|
||||||
|
/* Check the oplock */
|
||||||
|
Iosb.Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
|
||||||
|
IrpContext->Irp,
|
||||||
|
IrpContext,
|
||||||
|
FatOplockComplete,
|
||||||
|
FatPrePostIrp);
|
||||||
|
|
||||||
|
if (Iosb.Status != STATUS_SUCCESS &&
|
||||||
|
Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)
|
||||||
|
{
|
||||||
|
/* The Irp needs to be queued */
|
||||||
|
*OplockPostIrp = TRUE;
|
||||||
|
|
||||||
|
/* Release the FCB and return */
|
||||||
|
FatReleaseFcb(IrpContext, Fcb);
|
||||||
|
return Iosb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate parameters and modify access */
|
||||||
|
if (CreateDisposition == FILE_CREATE)
|
||||||
|
{
|
||||||
|
Iosb.Status = STATUS_OBJECT_NAME_COLLISION;
|
||||||
|
|
||||||
|
/* Release the FCB and return */
|
||||||
|
FatReleaseFcb(IrpContext, Fcb);
|
||||||
|
return Iosb;
|
||||||
|
}
|
||||||
|
else if (CreateDisposition == FILE_SUPERSEDE)
|
||||||
|
{
|
||||||
|
SetFlag(AddedAccess, DELETE & ~(*DesiredAccess));
|
||||||
|
*DesiredAccess |= DELETE;
|
||||||
|
}
|
||||||
|
else if ((CreateDisposition == FILE_OVERWRITE) ||
|
||||||
|
(CreateDisposition == FILE_OVERWRITE_IF))
|
||||||
|
{
|
||||||
|
SetFlag(AddedAccess,
|
||||||
|
(FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
|
||||||
|
& ~(*DesiredAccess) );
|
||||||
|
|
||||||
|
*DesiredAccess |= FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Check desired access
|
||||||
|
|
||||||
|
// TODO: Check if this file is readonly and DeleteOnClose is set
|
||||||
|
|
||||||
|
/* Validate disposition information */
|
||||||
|
if ((CreateDisposition == FILE_SUPERSEDE) ||
|
||||||
|
(CreateDisposition == FILE_OVERWRITE) ||
|
||||||
|
(CreateDisposition == FILE_OVERWRITE_IF))
|
||||||
|
{
|
||||||
|
// TODO: Get this attributes from the dirent
|
||||||
|
Hidden = FALSE;
|
||||||
|
System = FALSE;
|
||||||
|
|
||||||
|
if ((Hidden && !FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) ||
|
||||||
|
(System && !FlagOn(FileAttributes, FILE_ATTRIBUTE_SYSTEM)))
|
||||||
|
{
|
||||||
|
DPRINT1("Hidden/system attributes don't match\n");
|
||||||
|
|
||||||
|
Iosb.Status = STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
|
/* Release the FCB and return */
|
||||||
|
FatReleaseFcb(IrpContext, Fcb);
|
||||||
|
return Iosb;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Check for write protected volume
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check share access */
|
||||||
|
Iosb.Status = IoCheckShareAccess(*DesiredAccess,
|
||||||
|
ShareAccess,
|
||||||
|
FileObject,
|
||||||
|
&Fcb->ShareAccess,
|
||||||
|
FALSE);
|
||||||
|
if (!NT_SUCCESS(Iosb.Status))
|
||||||
|
{
|
||||||
|
/* Release the FCB and return */
|
||||||
|
FatReleaseFcb(IrpContext, Fcb);
|
||||||
|
return Iosb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the oplock status after checking for share access */
|
||||||
|
Iosb.Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
|
||||||
|
IrpContext->Irp,
|
||||||
|
IrpContext,
|
||||||
|
FatOplockComplete,
|
||||||
|
FatPrePostIrp );
|
||||||
|
|
||||||
|
if (Iosb.Status != STATUS_SUCCESS &&
|
||||||
|
Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)
|
||||||
|
{
|
||||||
|
/* The Irp needs to be queued */
|
||||||
|
*OplockPostIrp = TRUE;
|
||||||
|
|
||||||
|
/* Release the FCB and return */
|
||||||
|
FatReleaseFcb(IrpContext, Fcb);
|
||||||
|
return Iosb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set Fast I/O flag */
|
||||||
|
Fcb->Header.IsFastIoPossible = FALSE; //FatiIsFastIoPossible(Fcb);
|
||||||
|
|
||||||
|
/* Make sure image is not mapped */
|
||||||
|
if (DeleteOnClose || FlagOn(*DesiredAccess, FILE_WRITE_DATA))
|
||||||
|
{
|
||||||
|
/* Try to flush the image section */
|
||||||
|
if (!MmFlushImageSection(&Fcb->SectionObjectPointers, MmFlushForWrite))
|
||||||
|
{
|
||||||
|
/* Yes, image section exists, set correct status code */
|
||||||
|
if (DeleteOnClose)
|
||||||
|
Iosb.Status = STATUS_CANNOT_DELETE;
|
||||||
|
else
|
||||||
|
Iosb.Status = STATUS_SHARING_VIOLATION;
|
||||||
|
|
||||||
|
/* Release the FCB and return */
|
||||||
|
FatReleaseFcb(IrpContext, Fcb);
|
||||||
|
return Iosb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Flush the cache if it's non-cached non-pagefile access */
|
||||||
|
if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING) &&
|
||||||
|
Fcb->SectionObjectPointers.DataSectionObject &&
|
||||||
|
!FlagOn(Fcb->State, FCB_STATE_PAGEFILE))
|
||||||
|
{
|
||||||
|
/* Set the flag that create is in progress */
|
||||||
|
SetFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS);
|
||||||
|
|
||||||
|
/* Flush the cache */
|
||||||
|
CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);
|
||||||
|
|
||||||
|
/* Acquire and release Paging I/O resource before purging the cache section
|
||||||
|
to let lazy writer finish */
|
||||||
|
ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
|
||||||
|
ExReleaseResourceLite( Fcb->Header.PagingIoResource );
|
||||||
|
|
||||||
|
/* Delete the cache section */
|
||||||
|
CcPurgeCacheSection(&Fcb->SectionObjectPointers, NULL, 0, FALSE);
|
||||||
|
|
||||||
|
/* Clear the flag */
|
||||||
|
ClearFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check create disposition flags and branch accordingly */
|
||||||
|
if (CreateDisposition == FILE_OPEN ||
|
||||||
|
CreateDisposition == FILE_OPEN_IF)
|
||||||
|
{
|
||||||
|
DPRINT("Opening a file\n");
|
||||||
|
|
||||||
|
/* Check if we need to bother with EA */
|
||||||
|
if (NoEaKnowledge && FALSE /* FatIsFat32(Vcb)*/)
|
||||||
|
{
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set up file object */
|
||||||
|
Ccb = FatCreateCcb(IrpContext);
|
||||||
|
FatSetFileObject(FileObject,
|
||||||
|
UserFileOpen,
|
||||||
|
Fcb,
|
||||||
|
Ccb);
|
||||||
|
|
||||||
|
FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
|
||||||
|
|
||||||
|
/* The file is opened */
|
||||||
|
Iosb.Information = FILE_OPENED;
|
||||||
|
goto SuccComplete;
|
||||||
|
}
|
||||||
|
else if ((CreateDisposition == FILE_SUPERSEDE) ||
|
||||||
|
(CreateDisposition == FILE_OVERWRITE) ||
|
||||||
|
(CreateDisposition == FILE_OVERWRITE_IF))
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We can't get here */
|
||||||
|
KeBugCheckEx(0x23, CreateDisposition, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SuccComplete:
|
||||||
|
/* If all is fine */
|
||||||
|
if (Iosb.Status != STATUS_PENDING &&
|
||||||
|
NT_SUCCESS(Iosb.Status))
|
||||||
|
{
|
||||||
|
/* Update access if needed */
|
||||||
|
if (AddedAccess)
|
||||||
|
{
|
||||||
|
/* Remove added access flags from desired access */
|
||||||
|
ClearFlag(*DesiredAccess, AddedAccess);
|
||||||
|
|
||||||
|
/* Check share access */
|
||||||
|
Status = IoCheckShareAccess(*DesiredAccess,
|
||||||
|
ShareAccess,
|
||||||
|
FileObject,
|
||||||
|
&Fcb->ShareAccess,
|
||||||
|
TRUE);
|
||||||
|
|
||||||
|
/* Make sure it's success */
|
||||||
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Update the share access */
|
||||||
|
IoUpdateShareAccess(FileObject, &Fcb->ShareAccess);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the delay close */
|
||||||
|
ClearFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
|
||||||
|
|
||||||
|
/* Increase global volume counter */
|
||||||
|
Vcb->OpenFileCount++;
|
||||||
|
|
||||||
|
// TODO: Handle DeleteOnClose and OpenedAsDos by storing those flags in CCB
|
||||||
|
}
|
||||||
|
|
||||||
return Iosb;
|
return Iosb;
|
||||||
}
|
}
|
||||||
|
@ -213,12 +447,17 @@ FatGetFcbUnicodeName(IN PFAT_IRP_CONTEXT IrpContext,
|
||||||
OEM_STRING LongNameOem;
|
OEM_STRING LongNameOem;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
/* We support only files now, not directories */
|
/* Make sure this FCB has a FullFAT handle associated with it */
|
||||||
if (Fcb->Header.NodeTypeCode != FAT_NTC_FCB)
|
if (Fcb->FatHandle == NULL &&
|
||||||
|
FatNodeType(Fcb) == FAT_NTC_DCB)
|
||||||
|
{
|
||||||
|
/* Open the dir with FullFAT */
|
||||||
|
Fcb->FatHandle = FF_OpenW(Fcb->Vcb->Ioman, &Fcb->FullFileName, FF_MODE_DIR, NULL);
|
||||||
|
if (!Fcb->FatHandle)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED;
|
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the dir entry */
|
/* Get the dir entry */
|
||||||
Err = FF_GetEntry(Fcb->Vcb->Ioman,
|
Err = FF_GetEntry(Fcb->Vcb->Ioman,
|
||||||
|
|
|
@ -77,4 +77,27 @@ FatReadBlocks(FF_T_UINT8 *DestBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Cou
|
||||||
return Count;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -21,4 +21,20 @@ FatLockControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
return STATUS_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
FatOplockComplete(IN PVOID Context,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
FatPrePostIrp(IN PVOID Context,
|
||||||
|
IN PIRP Irp)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue