[FASTFAT_NEW]

- Substantially improve FatiCreate routine, to handle previously unhandled cases, fix wrong code structure in some places, add a stub for further implementation of a new file creation branch.
- Hackskip setting delay-on-close for a file for now (with a debug print reminder!)

svn path=/trunk/; revision=50164
This commit is contained in:
Aleksey Bragin 2010-12-27 16:49:21 +00:00
parent c7c2a79d5b
commit 0858e66dd1
2 changed files with 185 additions and 88 deletions

View file

@ -221,7 +221,8 @@ FatiCleanup(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
Fcb->Condition == FcbGood) Fcb->Condition == FcbGood)
{ {
/* Yes, a delayed one */ /* Yes, a delayed one */
SetFlag(Fcb->State, FCB_STATE_DELAY_CLOSE); //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 */ /* Unlock all file locks */

View file

@ -522,7 +522,7 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
NTSTATUS Status; NTSTATUS Status;
IO_STATUS_BLOCK Iosb; IO_STATUS_BLOCK Iosb;
PIO_STACK_LOCATION IrpSp; PIO_STACK_LOCATION IrpSp;
BOOLEAN EndBackslash = FALSE, OpenedAsDos; BOOLEAN EndBackslash = FALSE, OpenedAsDos, FirstRun = TRUE;
UNICODE_STRING RemainingPart, FirstName, NextName, FileNameUpcased; UNICODE_STRING RemainingPart, FirstName, NextName, FileNameUpcased;
OEM_STRING AnsiFirstName; OEM_STRING AnsiFirstName;
FF_ERROR FfError; FF_ERROR FfError;
@ -592,6 +592,13 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
if (RelatedFO) if (RelatedFO)
FileObject->Vpb = RelatedFO->Vpb; FileObject->Vpb = RelatedFO->Vpb;
/* Reject open by id */
if (Options & FILE_OPEN_BY_FILE_ID)
{
FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER);
return STATUS_INVALID_PARAMETER;
}
/* Prepare file attributes mask */ /* Prepare file attributes mask */
FileAttributes &= (FILE_ATTRIBUTE_READONLY | FileAttributes &= (FILE_ATTRIBUTE_READONLY |
FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_HIDDEN |
@ -652,12 +659,22 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
DPRINT1("This volume is locked\n"); DPRINT1("This volume is locked\n");
Status = STATUS_ACCESS_DENIED; Status = STATUS_ACCESS_DENIED;
/* Set volume dismount status */
if (Vcb->Condition != VcbGood)
Status = STATUS_VOLUME_DISMOUNTED;
/* Cleanup and return */ /* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb); FatReleaseVcb(IrpContext, Vcb);
FatCompleteRequest(IrpContext, Irp, Status);
return Status; return Status;
} }
// TODO: Check if the volume is write protected and disallow DELETE_ON_CLOSE /* Check if the volume is write protected and disallow DELETE_ON_CLOSE */
if (DeleteOnClose & FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
{
ASSERT(FALSE);
return STATUS_NOT_IMPLEMENTED;
}
// TODO: Make sure EAs aren't supported on FAT32 // TODO: Make sure EAs aren't supported on FAT32
@ -716,18 +733,24 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
{ {
DPRINT1("Invalid file object!\n"); DPRINT1("Invalid file object!\n");
Status = STATUS_OBJECT_PATH_NOT_FOUND;
/* Cleanup and return */ /* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb); FatReleaseVcb(IrpContext, Vcb);
return STATUS_OBJECT_PATH_NOT_FOUND; FatCompleteRequest(IrpContext, Irp, Status);
return Status;
} }
/* File path must be relative */ /* File path must be relative */
if (FileName.Length != 0 && if (FileName.Length != 0 &&
FileName.Buffer[0] == L'\\') FileName.Buffer[0] == L'\\')
{ {
Status = STATUS_OBJECT_NAME_INVALID;
/* The name is absolute, fail */ /* The name is absolute, fail */
FatReleaseVcb(IrpContext, Vcb); FatReleaseVcb(IrpContext, Vcb);
return STATUS_OBJECT_NAME_INVALID; FatCompleteRequest(IrpContext, Irp, Status);
return Status;
} }
/* Make sure volume is the same */ /* Make sure volume is the same */
@ -751,18 +774,34 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
if (NonDirectoryFile) if (NonDirectoryFile)
{ {
DPRINT1("Trying to open root dir as a file\n"); DPRINT1("Trying to open root dir as a file\n");
Status = STATUS_FILE_IS_A_DIRECTORY;
/* Cleanup and return */ /* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb); FatReleaseVcb(IrpContext, Vcb);
return STATUS_FILE_IS_A_DIRECTORY; FatCompleteRequest(IrpContext, Irp, Status);
return Status;
}
/* Check for target directory on a root dir */
if (OpenTargetDirectory)
{
Status = STATUS_INVALID_PARAMETER;
/* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb);
FatCompleteRequest(IrpContext, Irp, Status);
return Status;
} }
/* Check delete on close on a root dir */ /* Check delete on close on a root dir */
if (DeleteOnClose) if (DeleteOnClose)
{ {
Status = STATUS_CANNOT_DELETE;
/* Cleanup and return */ /* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb); FatReleaseVcb(IrpContext, Vcb);
return STATUS_CANNOT_DELETE; FatCompleteRequest(IrpContext, Irp, Status);
return Status;
} }
/* Call root directory open routine */ /* Call root directory open routine */
@ -777,6 +816,7 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
/* Cleanup and return */ /* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb); FatReleaseVcb(IrpContext, Vcb);
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
return Iosb.Status; return Iosb.Status;
} }
else else
@ -910,6 +950,27 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
} }
} }
/* Treat page file in a special way */
if (IsPagingFile)
{
UNIMPLEMENTED;
// FIXME: System file too
}
/* Make sure there is no pending delete on a higher-level FCB */
if (Fcb->State & FCB_STATE_DELETE_ON_CLOSE)
{
Iosb.Status = STATUS_DELETE_PENDING;
/* Cleanup and return */
FatReleaseVcb(IrpContext, Vcb);
/* Complete the request */
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
return Iosb.Status;
}
/* We have a valid FCB now */ /* We have a valid FCB now */
if (!RemainingPart.Length) if (!RemainingPart.Length)
{ {
@ -1038,23 +1099,34 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
ParentDcb = Fcb; ParentDcb = Fcb;
while (TRUE) while (TRUE)
{ {
FsRtlDissectName(RemainingPart, &FirstName, &RemainingPart); if (FirstRun)
/* Check for validity */
if ((RemainingPart.Length && RemainingPart.Buffer[0] == L'\\') ||
(NextName.Length > 255 * sizeof(WCHAR)))
{ {
/* The name is invalid */ RemainingPart = NextName;
DPRINT1("Invalid name found\n"); if (AnsiFirstName.Length)
Iosb.Status = STATUS_OBJECT_NAME_INVALID; Status = STATUS_SUCCESS;
ASSERT(FALSE); else
Status = STATUS_UNMAPPABLE_CHARACTER;
} }
else
{
FsRtlDissectName(RemainingPart, &FirstName, &RemainingPart);
/* Convert the name to ANSI */ /* Check for validity */
AnsiFirstName.Buffer = ExAllocatePool(PagedPool, FirstName.Length); if ((RemainingPart.Length && RemainingPart.Buffer[0] == L'\\') ||
AnsiFirstName.Length = 0; (NextName.Length > 255 * sizeof(WCHAR)))
AnsiFirstName.MaximumLength = FirstName.Length; {
Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName, &FirstName, FALSE); /* The name is invalid */
DPRINT1("Invalid name found\n");
Iosb.Status = STATUS_OBJECT_NAME_INVALID;
ASSERT(FALSE);
}
/* Convert the name to ANSI */
AnsiFirstName.Buffer = ExAllocatePool(PagedPool, FirstName.Length);
AnsiFirstName.Length = 0;
AnsiFirstName.MaximumLength = FirstName.Length;
Status = RtlUpcaseUnicodeStringToCountedOemString(&AnsiFirstName, &FirstName, FALSE);
}
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -1087,90 +1159,114 @@ FatiCreate(IN PFAT_IRP_CONTEXT IrpContext,
} }
/* Check, if path is a directory or a file */ /* Check, if path is a directory or a file */
if (FfError == FF_ERR_FILE_OBJECT_IS_A_DIR) if (FfError == FF_ERR_FILE_OBJECT_IS_A_DIR ||
FfError == FF_ERR_NONE)
{ {
if (NonDirectoryFile) if (FfError == FF_ERR_FILE_OBJECT_IS_A_DIR)
{ {
DPRINT1("Can't open dir as a file\n"); if (NonDirectoryFile)
{
DPRINT1("Can't open dir as a file\n");
/* Unlock VCB */
FatReleaseVcb(IrpContext, Vcb);
/* Complete the request */
Iosb.Status = STATUS_FILE_IS_A_DIRECTORY;
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
return Iosb.Status;
}
/* Open this directory */
Iosb = FatiOpenExistingDir(IrpContext,
FileObject,
Vcb,
ParentDcb,
DesiredAccess,
ShareAccess,
AllocationSize,
EaBuffer,
EaLength,
FileAttributes,
CreateDisposition,
DeleteOnClose);
Irp->IoStatus.Information = Iosb.Information;
/* Unlock VCB */ /* Unlock VCB */
FatReleaseVcb(IrpContext, Vcb); FatReleaseVcb(IrpContext, Vcb);
/* Complete the request */ /* Complete the request */
Iosb.Status = STATUS_FILE_IS_A_DIRECTORY;
FatCompleteRequest(IrpContext, Irp, Iosb.Status); FatCompleteRequest(IrpContext, Irp, Iosb.Status);
return Iosb.Status; return Iosb.Status;
} }
else
{
/* This is opening an existing file */
if (OpenDirectory)
{
/* But caller wanted a dir */
Status = STATUS_NOT_A_DIRECTORY;
/* Open this directory */ /* Unlock VCB */
Iosb = FatiOpenExistingDir(IrpContext, FatReleaseVcb(IrpContext, Vcb);
FileObject,
Vcb,
ParentDcb,
DesiredAccess,
ShareAccess,
AllocationSize,
EaBuffer,
EaLength,
FileAttributes,
CreateDisposition,
DeleteOnClose);
Irp->IoStatus.Information = Iosb.Information; /* Complete the request */
FatCompleteRequest(IrpContext, Irp, Status);
/* Unlock VCB */ return Status;
FatReleaseVcb(IrpContext, Vcb); }
/* Complete the request */ /* If end backslash here, then it's definately not permitted,
FatCompleteRequest(IrpContext, Irp, Iosb.Status); since we're opening files here */
if (EndBackslash)
{
/* Unlock VCB */
FatReleaseVcb(IrpContext, Vcb);
return Iosb.Status; /* Complete the request */
Iosb.Status = STATUS_OBJECT_NAME_INVALID;
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
return Iosb.Status;
}
/* Try to open the file */
Iosb = FatiOpenExistingFile(IrpContext,
FileObject,
Vcb,
ParentDcb,
DesiredAccess,
ShareAccess,
AllocationSize,
EaBuffer,
EaLength,
FileAttributes,
CreateDisposition,
FALSE,
DeleteOnClose,
OpenedAsDos);
/* In case of success set cache supported flag */
if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering)
{
SetFlag(FileObject->Flags, FO_CACHE_SUPPORTED);
}
Irp->IoStatus.Information = Iosb.Information;
/* Unlock VCB */
FatReleaseVcb(IrpContext, Vcb);
/* Complete the request */
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
return Iosb.Status;
}
} }
/* If end backslash here, then it's definately not permitted, /* We come here only in the case when a new file is created */
since we're opening files here */ ASSERT(FALSE);
if (EndBackslash)
{
/* Unlock VCB */
FatReleaseVcb(IrpContext, Vcb);
/* Complete the request */
Iosb.Status = STATUS_OBJECT_NAME_INVALID;
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
return Iosb.Status;
}
/* Try to open the file */
Iosb = FatiOpenExistingFile(IrpContext,
FileObject,
Vcb,
ParentDcb,
DesiredAccess,
ShareAccess,
AllocationSize,
EaBuffer,
EaLength,
FileAttributes,
CreateDisposition,
FALSE,
DeleteOnClose,
OpenedAsDos);
/* In case of success set cache supported flag */
if (NT_SUCCESS(Iosb.Status) && !NoIntermediateBuffering)
{
SetFlag(FileObject->Flags, FO_CACHE_SUPPORTED);
}
Irp->IoStatus.Information = Iosb.Information;
/* Unlock VCB */
FatReleaseVcb(IrpContext, Vcb);
/* Complete the request */
FatCompleteRequest(IrpContext, Irp, Iosb.Status);
return Iosb.Status;
} }
NTSTATUS NTSTATUS