mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-24 09:23:37 -05:00
sys: IRP_MJ_CREATE refactoring
This commit is contained in:
parent
e885905c77
commit
26e2bf506b
@ -46,7 +46,7 @@ enum
|
||||
{
|
||||
FspFsctlTransactUnknownKind = 0,
|
||||
FspFsctlTransactCreateKind,
|
||||
FspFsctlTransactCreate2Kind,
|
||||
FspFsctlTransactOverwriteKind,
|
||||
FspFsctlTransactCleanupKind,
|
||||
FspFsctlTransactCloseKind,
|
||||
FspFsctlTransactReadKind,
|
||||
@ -124,10 +124,9 @@ typedef struct
|
||||
{
|
||||
UINT64 UserContext;
|
||||
UINT64 UserContext2;
|
||||
UINT32 CloseStatus; /* if non-0 close the file (and do NOT overwrite!) */
|
||||
UINT32 FileAttributes; /* FILE_ATTRIBUTE_{NORMAL,DIRECTORY,etc.} */
|
||||
UINT32 Supersede:1; /* 0: FILE_OVERWRITE operation, 1: FILE_SUPERSEDE operation */
|
||||
} Create2;
|
||||
} Overwrite;
|
||||
struct
|
||||
{
|
||||
UINT64 UserContext;
|
||||
@ -167,7 +166,7 @@ typedef struct
|
||||
struct
|
||||
{
|
||||
UINT64 UserContext; /* open file user context (unique file id) */
|
||||
UINT64 UserContext2; /* kernel file object user context (only low 32 bits valid) */
|
||||
UINT64 UserContext2; /* kernel file object user context (stores as many bits as a pointer) */
|
||||
UINT64 AllocationSize; /* file allocation size */
|
||||
UINT64 FileSize; /* file size */
|
||||
UINT32 GrantedAccess; /* FILE_{READ_DATA,WRITE_DATA,etc.} */
|
||||
@ -180,11 +179,9 @@ typedef struct
|
||||
} Create;
|
||||
struct
|
||||
{
|
||||
UINT64 UserContext; /* open file user context (unique file id) */
|
||||
UINT64 UserContext2; /* kernel file object user context (only low 32 bits valid) */
|
||||
UINT64 AllocationSize; /* file allocation size */
|
||||
UINT64 FileSize; /* file size */
|
||||
} Create2;
|
||||
} Overwrite;
|
||||
} Rsp;
|
||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
|
||||
} FSP_FSCTL_TRANSACT_RSP;
|
||||
|
107
src/sys/create.c
107
src/sys/create.c
@ -15,8 +15,9 @@ static NTSTATUS FspFsvolCreate(
|
||||
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
|
||||
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
|
||||
static VOID FspFsvolCreatePostClose(
|
||||
FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2, NTSTATUS CloseStatus);
|
||||
FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2);
|
||||
static FSP_IOP_REQUEST_FINI FspFsvolCreateRequestFini;
|
||||
static FSP_IOP_REQUEST_FINI FspFsvolCreateOverwriteRequestFini;
|
||||
FSP_DRIVER_DISPATCH FspCreate;
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
@ -27,6 +28,7 @@ FSP_DRIVER_DISPATCH FspCreate;
|
||||
#pragma alloc_text(PAGE, FspFsvolCreateComplete)
|
||||
#pragma alloc_text(PAGE, FspFsvolCreatePostClose)
|
||||
#pragma alloc_text(PAGE, FspFsvolCreateRequestFini)
|
||||
#pragma alloc_text(PAGE, FspFsvolCreateOverwriteRequestFini)
|
||||
#pragma alloc_text(PAGE, FspCreate)
|
||||
#endif
|
||||
|
||||
@ -35,9 +37,13 @@ FSP_DRIVER_DISPATCH FspCreate;
|
||||
|
||||
enum
|
||||
{
|
||||
RequestFsContext = 0,
|
||||
RequestAccessToken,
|
||||
RequestProcess,
|
||||
/* CreateRequest */
|
||||
RequestFsContext = 0,
|
||||
RequestAccessToken = 1,
|
||||
RequestProcess = 2,
|
||||
/* OverwriteRequest */
|
||||
//RequestFsContext = 0,
|
||||
RequestFileObject = 1,
|
||||
};
|
||||
|
||||
static NTSTATUS FspFsctlCreate(
|
||||
@ -302,6 +308,7 @@ NTSTATUS FspFsvolCreatePrepare(
|
||||
HANDLE UserModeAccessToken;
|
||||
PEPROCESS Process;
|
||||
FSP_FILE_CONTEXT *FsContext;
|
||||
PFILE_OBJECT FileObject;
|
||||
|
||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||
{
|
||||
@ -324,9 +331,10 @@ NTSTATUS FspFsvolCreatePrepare(
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (FspFsctlTransactCreate2Kind == Request->Kind)
|
||||
else if (FspFsctlTransactOverwriteKind == Request->Kind)
|
||||
{
|
||||
FsContext = FspIopRequestContext(Request, RequestFsContext);
|
||||
FileObject = FspIopRequestContext(Request, RequestFileObject);
|
||||
|
||||
/* lock the FsContext for Paging IO */
|
||||
Success = FspFileContextPgioLockExclusive(FsContext, FALSE);
|
||||
@ -340,15 +348,19 @@ NTSTATUS FspFsvolCreatePrepare(
|
||||
return Result;
|
||||
}
|
||||
|
||||
FspIopRequestContext(Request, RequestFileObject) = 0;
|
||||
|
||||
/* see what the MM thinks about all this */
|
||||
LARGE_INTEGER Zero = { 0 };
|
||||
Success = MmCanFileBeTruncated(&FsContext->NonPaged->SectionObjectPointers, &Zero);
|
||||
if (!Success)
|
||||
{
|
||||
/* cannot truncate; tell user mode that we are closing the file */
|
||||
FspFileContextPgioUnlock(FsContext);
|
||||
Request->Req.Create2.CloseStatus = (UINT32)STATUS_USER_MAPPED_FILE;
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
FspFileContextClose(FsContext, FileObject);
|
||||
FspFsvolCreatePostClose(FsContext, (UINT_PTR)FileObject->FsContext2);
|
||||
|
||||
return STATUS_USER_MAPPED_FILE;
|
||||
}
|
||||
|
||||
/* purge any caches on this file */
|
||||
@ -458,10 +470,9 @@ VOID FspFsvolCreateComplete(
|
||||
&Result);
|
||||
if (0 == OpenedFsContext)
|
||||
{
|
||||
/* unable to open the FsContext; post a close Create2 request */
|
||||
/* unable to open the FsContext; post a Close request */
|
||||
FspFsvolCreatePostClose(FsContext,
|
||||
Response->Rsp.Create.Opened.UserContext2,
|
||||
Result);
|
||||
Response->Rsp.Create.Opened.UserContext2);
|
||||
|
||||
FSP_RETURN();
|
||||
}
|
||||
@ -497,10 +508,8 @@ VOID FspFsvolCreateComplete(
|
||||
Result = DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
|
||||
|
||||
FspFileContextClose(FsContext, FileObject);
|
||||
|
||||
FspFsvolCreatePostClose(FsContext,
|
||||
Response->Rsp.Create.Opened.UserContext2,
|
||||
Result);
|
||||
Response->Rsp.Create.Opened.UserContext2);
|
||||
|
||||
FSP_RETURN();
|
||||
}
|
||||
@ -523,26 +532,24 @@ VOID FspFsvolCreateComplete(
|
||||
FspIopDeleteRequest(Request);
|
||||
|
||||
/* create the Create2 request; MustSucceed because we must either overwrite or close */
|
||||
FspIopCreateRequestMustSucceed(Irp,
|
||||
FspIopCreateRequestFunnel(Irp,
|
||||
FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FsContext->FileName : 0, 0,
|
||||
FspFsvolCreateOverwriteRequestFini, TRUE,
|
||||
&Request);
|
||||
|
||||
/* associate the FsContext with the Create2 request */
|
||||
FspIopRequestContext(Request, RequestFsContext) = FsContext;
|
||||
|
||||
/* populate the Create2 request */
|
||||
Request->Kind = FspFsctlTransactCreate2Kind;
|
||||
Request->Req.Create2.UserContext = FsContext->UserContext;
|
||||
Request->Req.Create2.UserContext2 = (UINT_PTR)FileObject->FsContext2;
|
||||
Request->Req.Create2.FileAttributes = IrpSp->Parameters.Create.FileAttributes;
|
||||
Request->Req.Create2.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information;
|
||||
Request->Req.Create2.CloseStatus = STATUS_SUCCESS;
|
||||
Request->Kind = FspFsctlTransactOverwriteKind;
|
||||
Request->Req.Overwrite.UserContext = FsContext->UserContext;
|
||||
Request->Req.Overwrite.UserContext2 = (UINT_PTR)FileObject->FsContext2;
|
||||
Request->Req.Overwrite.FileAttributes = IrpSp->Parameters.Create.FileAttributes;
|
||||
Request->Req.Overwrite.Supersede = FILE_SUPERSEDED == Response->IoStatus.Information;
|
||||
|
||||
/*
|
||||
* Note that it is still possible for this request to not be delivered,
|
||||
* if the volume device Ioq is stopped. But such failures are benign
|
||||
* from our perspective, because they mean that the file system is going
|
||||
* away and should correctly tear things down.
|
||||
* if the volume device Ioq is stopped or if the IRP is canceled.
|
||||
*/
|
||||
|
||||
if (FspIoqPostIrpBestEffort(FsvolDeviceExtension->Ioq, Irp, &Result))
|
||||
@ -555,25 +562,18 @@ VOID FspFsvolCreateComplete(
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else if (FspFsctlTransactCreate2Kind == Request->Kind)
|
||||
else if (FspFsctlTransactOverwriteKind == Request->Kind)
|
||||
{
|
||||
/*
|
||||
* A Create2 request will either succeed or else fail and close the corresponding file.
|
||||
* An Overwrite request will either succeed or else fail and close the corresponding file.
|
||||
* There is no need to reach out to user-mode again and ask them to close the file.
|
||||
*/
|
||||
|
||||
/* was this a close request? */
|
||||
if (STATUS_SUCCESS != Request->Req.Create2.CloseStatus)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
Result = STATUS_SUCCESS != Request->Req.Create2.CloseStatus;
|
||||
FSP_RETURN();
|
||||
}
|
||||
|
||||
/* did the user-mode file system sent us a failure code? */
|
||||
if (!NT_SUCCESS(Response->IoStatus.Status))
|
||||
{
|
||||
FspFileContextPgioUnlock(FsContext);
|
||||
|
||||
FspFileContextClose(FsContext, FileObject);
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
@ -588,11 +588,11 @@ VOID FspFsvolCreateComplete(
|
||||
|
||||
FspFileContextPgioUnlock(FsContext);
|
||||
|
||||
/* disassociate the FsContext from the Create2 request */
|
||||
/* disassociate the FsContext from the Overwrite request */
|
||||
FspIopRequestContext(Request, RequestFsContext) = 0;
|
||||
|
||||
/* SUCCESS! */
|
||||
Irp->IoStatus.Information = Request->Req.Create2.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
|
||||
Irp->IoStatus.Information = Request->Req.Overwrite.Supersede ? FILE_SUPERSEDED : FILE_OVERWRITTEN;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
@ -604,12 +604,10 @@ VOID FspFsvolCreateComplete(
|
||||
}
|
||||
|
||||
static VOID FspFsvolCreatePostClose(
|
||||
FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2, NTSTATUS CloseStatus)
|
||||
FSP_FILE_CONTEXT *FsContext, UINT64 UserContext2)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT(STATUS_SUCCESS != CloseStatus);
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = FsContext->FsvolDeviceObject;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
@ -619,11 +617,10 @@ static VOID FspFsvolCreatePostClose(
|
||||
FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FsContext->FileName : 0,
|
||||
0, &Request);
|
||||
|
||||
/* populate the Create2 request */
|
||||
Request->Kind = FspFsctlTransactCreate2Kind;
|
||||
Request->Req.Create2.UserContext = FsContext->UserContext;
|
||||
Request->Req.Create2.UserContext2 = UserContext2;
|
||||
Request->Req.Create2.CloseStatus = CloseStatus;
|
||||
/* populate the Close request */
|
||||
Request->Kind = FspFsctlTransactCloseKind;
|
||||
Request->Req.Close.UserContext = FsContext->UserContext;
|
||||
Request->Req.Close.UserContext2 = UserContext2;
|
||||
|
||||
/*
|
||||
* Post as a BestEffort work request. This allows us to complete our own IRP
|
||||
@ -678,6 +675,28 @@ static VOID FspFsvolCreateRequestFini(PVOID Context[3])
|
||||
}
|
||||
}
|
||||
|
||||
static VOID FspFsvolCreateOverwriteRequestFini(PVOID Context[3])
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if (0 != Context[RequestFsContext])
|
||||
{
|
||||
FSP_FILE_CONTEXT *FsContext = Context[RequestFsContext];
|
||||
PFILE_OBJECT FileObject = Context[RequestFileObject];
|
||||
|
||||
if (0 != FileObject)
|
||||
{
|
||||
FspFsvolCreatePostClose(FsContext, (UINT_PTR)FileObject->FsContext2);
|
||||
FspFileContextClose(FsContext, FileObject);
|
||||
}
|
||||
|
||||
FspFileContextRelease(FsContext);
|
||||
|
||||
Context[RequestFileObject] = 0;
|
||||
Context[RequestFsContext] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS FspCreate(
|
||||
PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
||||
{
|
||||
|
@ -112,7 +112,7 @@ FSP_FILE_CONTEXT *FspFileContextOpen(FSP_FILE_CONTEXT *FsContext, PFILE_OBJECT F
|
||||
* opening a prior FsContext that we found in the table.
|
||||
*
|
||||
* First check and update the share access. If successful then retain the
|
||||
* prior FsContext for our caller.
|
||||
* opened FsContext for our caller.
|
||||
*/
|
||||
ASSERT(OpenedFsContext != FsContext);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user