[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:
Aleksey Bragin 2009-10-17 13:18:29 +00:00
parent fdaf0acd73
commit b9e1012f27
6 changed files with 318 additions and 20 deletions

View file

@ -11,16 +11,6 @@
#define NDEBUG
#include "fastfat.h"
NTSYSAPI
NTSTATUS
NTAPI
RtlUpcaseUnicodeStringToCountedOemString(
IN OUT POEM_STRING DestinationString,
IN PCUNICODE_STRING SourceString,
IN BOOLEAN AllocateDestinationString
);
/* FUNCTIONS *****************************************************************/
IO_STATUS_BLOCK

View file

@ -35,6 +35,15 @@
ExReleaseResourceLite(&(FatGlobalData.Resource)); \
}
NTSYSAPI
NTSTATUS
NTAPI
RtlUpcaseUnicodeStringToCountedOemString(
IN OUT POEM_STRING DestinationString,
IN PCUNICODE_STRING SourceString,
IN BOOLEAN AllocateDestinationString
);
/* ------------------------------------------------------ shutdown.c */
@ -211,6 +220,14 @@ FatReadBlocks(FF_T_UINT8 *pBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Count,
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
@ -221,6 +238,10 @@ FatFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
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

View file

@ -133,9 +133,10 @@ typedef struct _FAT_METHODS {
PFAT_SETFAT_VALUE_RUN_ROUTINE SetValueRun;
} FAT_METHODS, *PFAT_METHODS;
#define VCB_STATE_FLAG_LOCKED 0x01
#define VCB_STATE_FLAG_DIRTY 0x02
#define VCB_STATE_MOUNTED_DIRTY 0x04
#define VCB_STATE_FLAG_LOCKED 0x01
#define VCB_STATE_FLAG_DIRTY 0x02
#define VCB_STATE_MOUNTED_DIRTY 0x04
#define VCB_STATE_CREATE_IN_PROGRESS 0x08
typedef enum _VCB_CONDITION
{
@ -249,6 +250,8 @@ typedef enum _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
typedef struct _FCB
{
@ -264,7 +267,6 @@ typedef struct _FCB
ERESOURCE Resource; // nonpaged!
ERESOURCE PagingIoResource; // nonpaged!
FILE_LOCK Lock;
/* First cluster in the fat allocation chain */
ULONG FirstClusterOfFile;
/* A list of all FCBs of that DCB */
@ -305,6 +307,13 @@ typedef struct _FCB
PKEVENT OutstandingAsyncEvent;
union
{
struct
{
/* File and Op locks */
FILE_LOCK Lock;
OPLOCK Oplock;
} Fcb;
struct
{
/* A list of all FCBs/DCBs opened under this DCB */

View file

@ -191,9 +191,243 @@ FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
OUT PBOOLEAN OplockPostIrp)
{
IO_STATUS_BLOCK Iosb = {{0}};
ACCESS_MASK AddedAccess = 0;
BOOLEAN Hidden;
BOOLEAN System;
PCCB Ccb = NULL;
NTSTATUS Status;
Iosb.Status = STATUS_NOT_IMPLEMENTED;
UNIMPLEMENTED;
/* 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;
}
/* 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;
}
@ -213,11 +447,16 @@ FatGetFcbUnicodeName(IN PFAT_IRP_CONTEXT IrpContext,
OEM_STRING LongNameOem;
NTSTATUS Status;
/* We support only files now, not directories */
if (Fcb->Header.NodeTypeCode != FAT_NTC_FCB)
/* Make sure this FCB has a FullFAT handle associated with it */
if (Fcb->FatHandle == NULL &&
FatNodeType(Fcb) == FAT_NTC_DCB)
{
UNIMPLEMENTED;
ASSERT(FALSE);
/* Open the dir with FullFAT */
Fcb->FatHandle = FF_OpenW(Fcb->Vcb->Ioman, &Fcb->FullFileName, FF_MODE_DIR, NULL);
if (!Fcb->FatHandle)
{
ASSERT(FALSE);
}
}
/* Get the dir entry */

View file

@ -77,4 +77,27 @@ FatReadBlocks(FF_T_UINT8 *DestBuffer, FF_T_UINT32 SectorAddress, FF_T_UINT32 Cou
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 */

View file

@ -21,4 +21,20 @@ FatLockControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
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 */