sys: IRP_MJ_CREATE refactoring

This commit is contained in:
Bill Zissimopoulos 2016-01-12 14:34:30 -08:00
parent cd28edf6a9
commit 8a77de8908
6 changed files with 65 additions and 38 deletions

View File

@ -131,12 +131,7 @@ typedef struct
{
UINT64 UserContext;
UINT64 UserContext2;
UINT32 ReadAccess:1; /* file was open for read access */
UINT32 WriteAccess:1; /* file was open for write access */
UINT32 DeleteAccess:1; /* file was open for delete access */
UINT32 SharedRead:1; /* file was open for shared read access */
UINT32 SharedWrite:1; /* file was open for shared write access */
UINT32 SharedDelete:1; /* file was open for shared delete access */
UINT32 Delete:1; /* file must be deleted */
} Cleanup;
struct
{

View File

@ -6,6 +6,7 @@
#include <dll/library.h>
#if 0
FSP_API VOID FspShareAccessRemove(FSP_FILE_SYSTEM *FileSystem,
FSP_FSCTL_TRANSACT_REQ *Request, FSP_FILE_NODE *FileNode)
{
@ -65,3 +66,4 @@ FSP_API NTSTATUS FspFileSystemSendCleanupResponse(FSP_FILE_SYSTEM *FileSystem,
Response.IoStatus.Information = 0;
return FspFileSystemSendResponse(FileSystem, &Response);
}
#endif

View File

@ -60,8 +60,9 @@ static NTSTATUS FspFsvolCleanup(
UINT64 UserContext = FsContext->UserContext;
UINT64 UserContext2 = (UINT_PTR)FileObject->FsContext2;
FSP_FSCTL_TRANSACT_REQ *Request;
BOOLEAN DeletePending;
FspFileContextClose(FsContext, FileObject);
FspFileContextClose(FsContext, FileObject, &DeletePending);
/* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */
FspIopCreateRequestMustSucceed(Irp, FileNameRequired ? &FsContext->FileName : 0, 0, &Request);
@ -70,12 +71,7 @@ static NTSTATUS FspFsvolCleanup(
Request->Kind = FspFsctlTransactCleanupKind;
Request->Req.Cleanup.UserContext = UserContext;
Request->Req.Cleanup.UserContext2 = UserContext2;
Request->Req.Cleanup.ReadAccess = !!FileObject->ReadAccess;
Request->Req.Cleanup.WriteAccess = !!FileObject->WriteAccess;
Request->Req.Cleanup.DeleteAccess = !!FileObject->DeleteAccess;
Request->Req.Cleanup.SharedRead = !!FileObject->SharedRead;
Request->Req.Cleanup.SharedWrite = !!FileObject->SharedWrite;
Request->Req.Cleanup.SharedDelete = !!FileObject->SharedDelete;
Request->Req.Cleanup.Delete = DeletePending;
/*
* Note that it is still possible for this request to not be delivered,

View File

@ -359,7 +359,7 @@ NTSTATUS FspFsvolCreatePrepare(
FspFileContextPgioUnlock(FsContext);
FspFsvolCreatePostClose(FsContext, (UINT_PTR)FileObject->FsContext2);
FspFileContextClose(FsContext, FileObject);
FspFileContextClose(FsContext, FileObject, 0);
return STATUS_USER_MAPPED_FILE;
}
@ -468,6 +468,7 @@ VOID FspFsvolCreateComplete(
/* open the FsContext */
OpenedFsContext = FspFileContextOpen(FsContext, FileObject,
Response->Rsp.Create.Opened.GrantedAccess, IrpSp->Parameters.Create.ShareAccess,
DeleteOnClose,
&Result);
if (0 == OpenedFsContext)
{
@ -508,7 +509,7 @@ VOID FspFsvolCreateComplete(
{
FspFsvolCreatePostClose(FsContext,
Response->Rsp.Create.Opened.UserContext2);
FspFileContextClose(FsContext, FileObject);
FspFileContextClose(FsContext, FileObject, 0);
Result = DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
FSP_RETURN();
@ -576,7 +577,7 @@ VOID FspFsvolCreateComplete(
{
FspFileContextPgioUnlock(FsContext);
FspFileContextClose(FsContext, FileObject);
FspFileContextClose(FsContext, FileObject, 0);
Irp->IoStatus.Information = 0;
Result = Response->IoStatus.Status;
@ -686,7 +687,7 @@ static VOID FspFsvolCreateOverwriteRequestFini(PVOID Context[3])
if (0 != FileObject)
{
FspFsvolCreatePostClose(FsContext, (UINT_PTR)FileObject->FsContext2);
FspFileContextClose(FsContext, FileObject);
FspFileContextClose(FsContext, FileObject, 0);
}
FspFileContextRelease(FsContext);

View File

@ -513,10 +513,15 @@ typedef struct
FSP_FILE_CONTEXT_NONPAGED *NonPaged;
/* interlocked access */
LONG RefCount;
/* locked access */
/* locked access (ContextTable lock) */
LONG OpenCount;
SHARE_ACCESS ShareAccess;
/* read-only after creation (and insertion in the GenericTable) */
struct
{
UINT32 DeleteOnClose:1;
UINT32 DeletePending:1;
} Flags;
/* read-only after creation (and insertion in the ContextTable) */
PDEVICE_OBJECT FsvolDeviceObject;
UINT64 UserContext;
FSP_DEVICE_GENERIC_TABLE_ELEMENT ElementStorage;
@ -527,8 +532,9 @@ NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject,
ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext);
VOID FspFileContextDelete(FSP_FILE_CONTEXT *FsContext);
FSP_FILE_CONTEXT *FspFileContextOpen(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT FileObject,
DWORD GrantedAccess, DWORD ShareAccess, NTSTATUS *PResult);
VOID FspFileContextClose(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT FileObject);
DWORD GrantedAccess, DWORD ShareAccess, BOOLEAN DeleteOnClose, NTSTATUS *PResult);
VOID FspFileContextClose(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT FileObject,
PBOOLEAN PDeletePending);
static inline
VOID FspFileContextRetain(FSP_FILE_CONTEXT *FsContext)
{

View File

@ -9,10 +9,16 @@
NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject,
ULONG ExtraSize, FSP_FILE_CONTEXT **PFsContext);
VOID FspFileContextDelete(FSP_FILE_CONTEXT *Context);
FSP_FILE_CONTEXT *FspFileContextOpen(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT FileObject,
DWORD GrantedAccess, DWORD ShareAccess, BOOLEAN DeleteOnClose, NTSTATUS *PResult);
VOID FspFileContextClose(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT FileObject,
PBOOLEAN PDeletePending);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFileContextCreate)
#pragma alloc_text(PAGE, FspFileContextDelete)
#pragma alloc_text(PAGE, FspFileContextOpen)
#pragma alloc_text(PAGE, FspFileContextClose)
#endif
NTSTATUS FspFileContextCreate(PDEVICE_OBJECT DeviceObject,
@ -74,7 +80,7 @@ VOID FspFileContextDelete(FSP_FILE_CONTEXT *FsContext)
}
FSP_FILE_CONTEXT *FspFileContextOpen(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT FileObject,
DWORD GrantedAccess, DWORD ShareAccess, NTSTATUS *PResult)
DWORD GrantedAccess, DWORD ShareAccess, BOOLEAN DeleteOnClose, NTSTATUS *PResult)
{
/*
* Attempt to insert our FsContext into the volume device's generic table.
@ -82,9 +88,12 @@ FSP_FILE_CONTEXT *FspFileContextOpen(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT F
* FsContext instead.
*/
PAGED_CODE();
PDEVICE_OBJECT FsvolDeviceObject = FsContext->FsvolDeviceObject;
FSP_FILE_CONTEXT *OpenedFsContext;
BOOLEAN Inserted;
NTSTATUS Result;
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
@ -102,20 +111,21 @@ FSP_FILE_CONTEXT *FspFileContextOpen(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT F
ASSERT(OpenedFsContext == FsContext);
IoSetShareAccess(GrantedAccess, ShareAccess, FileObject, &FsContext->ShareAccess);
FspFileContextRetain(OpenedFsContext);
OpenedFsContext->OpenCount++;
}
else
{
/*
* The new FsContext was NOT inserted into the Context table. Instead we are
* opening a prior FsContext that we found in the table.
*
* First check and update the share access. If successful then retain the
* opened FsContext for our caller.
*/
ASSERT(OpenedFsContext != FsContext);
if (OpenedFsContext->Flags.DeletePending)
{
Result = STATUS_DELETE_PENDING;
goto exit;
}
/*
* FastFat says to do the following on Vista and above.
*
@ -124,22 +134,20 @@ FSP_FILE_CONTEXT *FspFileContextOpen(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT F
* write sharing - this is neccessary since a section may exist with no handles
* open to the file its based against.
*/
NTSTATUS Result = STATUS_SUCCESS;
if (!FlagOn(ShareAccess, FILE_SHARE_WRITE) &&
FlagOn(GrantedAccess,
FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE) &&
MmDoesFileHaveUserWritableReferences(&FsContext->NonPaged->SectionObjectPointers))
{
Result = STATUS_SHARING_VIOLATION;
goto exit;
}
/* share access check */
if (NT_SUCCESS(Result))
Result = IoCheckShareAccess(GrantedAccess, ShareAccess, FileObject, &FsContext->ShareAccess, TRUE);
if (NT_SUCCESS(Result))
{
FspFileContextRetain(OpenedFsContext);
OpenedFsContext->OpenCount++;
}
else
Result = IoCheckShareAccess(GrantedAccess, ShareAccess, FileObject, &FsContext->ShareAccess, TRUE);
exit:
if (!NT_SUCCESS(Result))
{
if (0 != PResult)
*PResult = Result;
@ -148,23 +156,39 @@ FSP_FILE_CONTEXT *FspFileContextOpen(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT F
}
}
if (0 != OpenedFsContext)
{
FspFileContextRetain(OpenedFsContext);
OpenedFsContext->OpenCount++;
if (DeleteOnClose)
OpenedFsContext->Flags.DeleteOnClose = TRUE;
}
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
return OpenedFsContext;
}
VOID FspFileContextClose(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT FileObject)
VOID FspFileContextClose(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT FileObject,
PBOOLEAN PDeletePending)
{
/*
* Close the FsContext. If the OpenCount becomes zero remove it
* from the Context table.
*/
PAGED_CODE();
PDEVICE_OBJECT FsvolDeviceObject = FsContext->FsvolDeviceObject;
BOOLEAN Deleted = FALSE;
BOOLEAN Deleted = FALSE, DeletePending;
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
if (FsContext->Flags.DeleteOnClose)
FsContext->Flags.DeletePending = TRUE;
DeletePending = 0 != FsContext->Flags.DeletePending;
IoRemoveShareAccess(FileObject, &FsContext->ShareAccess);
if (0 == --FsContext->OpenCount)
FspFsvolDeviceDeleteContext(FsvolDeviceObject, FsContext->UserContext, &Deleted);
@ -173,4 +197,7 @@ VOID FspFileContextClose(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT FileObject)
if (Deleted)
FspFileContextRelease(FsContext);
if (0 != PDeletePending)
*PDeletePending = Deleted && DeletePending;
}