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