sys: IRP_MJ_CREATE: oplock support

This commit is contained in:
Bill Zissimopoulos 2016-11-10 14:54:41 -08:00
parent 7adbd7a56c
commit fb70eccc9c
5 changed files with 169 additions and 28 deletions

View File

@ -74,7 +74,7 @@ static NTSTATUS FspFsvolClose(
Request->Req.Close.UserContext = FileNode->UserContext; Request->Req.Close.UserContext = FileNode->UserContext;
Request->Req.Close.UserContext2 = FileDesc->UserContext2; Request->Req.Close.UserContext2 = FileDesc->UserContext2;
FspFileNodeClose(FileNode, FileObject, FALSE); FspFileNodeClose(FileNode, FileObject, FALSE, FALSE);
/* delete the FileDesc and deref the FileNode; order is important (FileDesc has FileNode ref) */ /* delete the FileDesc and deref the FileNode; order is important (FileDesc has FileNode ref) */
FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */ FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */

View File

@ -28,6 +28,13 @@ static NTSTATUS FspFsvolCreateNoLock(
BOOLEAN MainFileOpen); BOOLEAN MainFileOpen);
FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; FSP_IOPREP_DISPATCH FspFsvolCreatePrepare;
FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; FSP_IOCMPL_DISPATCH FspFsvolCreateComplete;
static NTSTATUS FspFsvolCreateSharingViolation(
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, FSP_FILE_NODE *FileNode);
static NTSTATUS FspFsvolCreateSharingViolationWork(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
BOOLEAN CanWait);
static VOID FspFsvolCreateSharingViolationOplockComplete(
PVOID Context, PIRP Irp);
static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject, FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject,
BOOLEAN FlushImage); BOOLEAN FlushImage);
@ -45,6 +52,9 @@ FSP_DRIVER_DISPATCH FspCreate;
#pragma alloc_text(PAGE, FspFsvolCreatePrepare) #pragma alloc_text(PAGE, FspFsvolCreatePrepare)
#pragma alloc_text(PAGE, FspFsvolCreateComplete) #pragma alloc_text(PAGE, FspFsvolCreateComplete)
#pragma alloc_text(PAGE, FspFsvolCreateTryOpen) #pragma alloc_text(PAGE, FspFsvolCreateTryOpen)
#pragma alloc_text(PAGE, FspFsvolCreateSharingViolation)
#pragma alloc_text(PAGE, FspFsvolCreateSharingViolationWork)
#pragma alloc_text(PAGE, FspFsvolCreateSharingViolationOplockComplete)
#pragma alloc_text(PAGE, FspFsvolCreatePostClose) #pragma alloc_text(PAGE, FspFsvolCreatePostClose)
#pragma alloc_text(PAGE, FspFsvolCreateRequestFini) #pragma alloc_text(PAGE, FspFsvolCreateRequestFini)
#pragma alloc_text(PAGE, FspFsvolCreateTryOpenRequestFini) #pragma alloc_text(PAGE, FspFsvolCreateTryOpenRequestFini)
@ -813,11 +823,25 @@ NTSTATUS FspFsvolCreateComplete(
FileDesc->DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE); FileDesc->DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE);
/* open the FileNode */ /* open the FileNode */
OpenedFileNode = FspFileNodeOpen(FileNode, FileObject, Result = FspFileNodeOpen(FileNode, FileObject,
Response->Rsp.Create.Opened.GrantedAccess, IrpSp->Parameters.Create.ShareAccess, Response->Rsp.Create.Opened.GrantedAccess, IrpSp->Parameters.Create.ShareAccess,
&Result); &OpenedFileNode);
if (0 == OpenedFileNode) if (!NT_SUCCESS(Result))
{ {
if (STATUS_SHARING_VIOLATION == Result)
{
Result = FspFsvolCreateSharingViolation(Irp, Response, OpenedFileNode);
if (STATUS_PENDING != Result)
{
FspFileNodeClose(OpenedFileNode, FileObject, FALSE, TRUE);
FspFileNodeDereference(OpenedFileNode);
Result = STATUS_SHARING_VIOLATION;
}
Irp->IoStatus.Information = 0;
FSP_RETURN();
}
/* unable to open the FileNode; post a Close request */ /* unable to open the FileNode; post a Close request */
FspFsvolCreatePostClose(FileDesc); FspFsvolCreatePostClose(FileDesc);
@ -955,6 +979,118 @@ NTSTATUS FspFsvolCreateComplete(
IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName); IrpSp->FileObject, IrpSp->FileObject->RelatedFileObject, IrpSp->FileObject->FileName);
} }
static NTSTATUS FspFsvolCreateSharingViolation(
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, FSP_FILE_NODE *FileNode)
{
PAGED_CODE();
NTSTATUS Result;
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
FspIopSetIrpResponse(Irp, Response);
FspIopRequestContext(Request, FspIopRequestExtraContext) = FileNode;
Result = FspWqRepostIrpWorkItem(Irp,
FspFsvolCreateSharingViolationWork, FspFsvolCreateRequestFini);
if (!NT_SUCCESS(Result))
{
FspIopRequestContext(Request, FspIopRequestExtraContext) = 0;
return STATUS_SHARING_VIOLATION;
}
return STATUS_PENDING;
}
static NTSTATUS FspFsvolCreateSharingViolationWork(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
BOOLEAN CanWait)
{
PAGED_CODE();
/*
* Perform oplock checks in the case that we received STATUS_SHARING_VIOLATION.
* The logic below is quite tortured, because it tries to mimic what FastFat
* does in Win7. Here is an explanation.
*
* First notice that this is run in a work thread. So it is assumed that we can
* block here. We cannot block in the completion thread, because it belongs to
* the user mode file system that may have a limited number of threads to service
* file system requests.
*
* Second we want a way to differentiate the case between an oplock break being
* underway and no oplock needed. Unfortunately this only seems possible when a
* completion routine is set in FsRtlCheckOplock and FsRtlOplockBreakH. In this
* case we get STATUS_PENDING when there is an oplock to be broken and
* STATUS_SUCCESS where there is not one.
*
* Third notice that by default we must return STATUS_SHARING_VIOLATION, because
* the share access check failed. The only case that we will completely retry is
* when FspRtlOplockBreakH returns STATUS_PENDING.
*
* So in a nutshell, this routine emulates what happens with FastFat during
* STATUS_SHARING_VIOLATION processing. However FastFat tries to break batch
* oplocks before the share access check. Unfortunately this is hard to do in
* this FSD, so we have to emulate this behavior.
*/
FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp);
FSP_FSCTL_TRANSACT_RSP *Response = FspIopIrpResponse(Irp);
FSP_FILE_NODE *FileNode = FspIopRequestContext(Request, FspIopRequestExtraContext);
BOOLEAN StatusSharingViolation = TRUE, OpbatchBreakUnderway = FALSE;
KEVENT Event;
NTSTATUS Result;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
FspFileNodeAcquireShared(FileNode, Main);
if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(FileNode)))
{
Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp,
&Event, FspFsvolCreateSharingViolationOplockComplete, 0);
if (STATUS_PENDING == Result)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, 0);
if (STATUS_SUCCESS == Irp->IoStatus.Status)
OpbatchBreakUnderway = TRUE;
}
}
KeResetEvent(&Event);
Result = FspOplockBreakH(FspFileNodeAddrOfOplock(FileNode), Irp, 0,
&Event, FspFsvolCreateSharingViolationOplockComplete, 0);
if (STATUS_PENDING == Result)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, 0);
if (STATUS_SUCCESS == Irp->IoStatus.Status)
StatusSharingViolation = FALSE;
}
FspFileNodeRelease(FileNode, Main);
FspFileNodeClose(FileNode, IrpSp->FileObject, FALSE, TRUE);
FspFileNodeDereference(FileNode);
FspIopRequestContext(Request, FspIopRequestExtraContext) = 0;
if (StatusSharingViolation)
{
Response->IoStatus.Status = (UINT32)STATUS_SHARING_VIOLATION;
Response->IoStatus.Information = OpbatchBreakUnderway ? FILE_OPBATCH_BREAK_UNDERWAY : 0;
}
FspIopRetryCompleteIrp(Irp, Response, &Result);
return Result;
}
static VOID FspFsvolCreateSharingViolationOplockComplete(
PVOID Context, PIRP Irp)
{
PAGED_CODE();
KeSetEvent((PKEVENT)Context, FSP_IO_INCREMENT, FALSE);
}
static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response,
FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject, FSP_FILE_NODE *FileNode, FSP_FILE_DESC *FileDesc, PFILE_OBJECT FileObject,
BOOLEAN FlushImage) BOOLEAN FlushImage)
@ -1009,7 +1145,7 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re
if (0 == Request) if (0 == Request)
{ {
FspFsvolCreatePostClose(FileDesc); FspFsvolCreatePostClose(FileDesc);
FspFileNodeClose(FileNode, FileObject, TRUE); FspFileNodeClose(FileNode, FileObject, TRUE, TRUE);
} }
return DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; return DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
@ -1115,7 +1251,7 @@ static VOID FspFsvolCreateTryOpenRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PV
ASSERT(0 != FileObject); ASSERT(0 != FileObject);
FspFsvolCreatePostClose(FileDesc); FspFsvolCreatePostClose(FileDesc);
FspFileNodeClose(FileDesc->FileNode, FileObject, TRUE); FspFileNodeClose(FileDesc->FileNode, FileObject, TRUE, TRUE);
FspFileNodeDereference(FileDesc->FileNode); FspFileNodeDereference(FileDesc->FileNode);
FspFileDescDelete(FileDesc); FspFileDescDelete(FileDesc);
} }
@ -1142,7 +1278,7 @@ static VOID FspFsvolCreateOverwriteRequestFini(FSP_FSCTL_TRANSACT_REQ *Request,
else if (RequestProcessing == State) else if (RequestProcessing == State)
FspFileNodeReleaseOwner(FileDesc->FileNode, Full, Request); FspFileNodeReleaseOwner(FileDesc->FileNode, Full, Request);
FspFileNodeClose(FileDesc->FileNode, FileObject, TRUE); FspFileNodeClose(FileDesc->FileNode, FileObject, TRUE, TRUE);
FspFileNodeDereference(FileDesc->FileNode); FspFileNodeDereference(FileDesc->FileNode);
FspFileDescDelete(FileDesc); FspFileDescDelete(FileDesc);
} }

View File

@ -712,6 +712,10 @@ enum
FspIopCreateRequestNonPagedFlag = 0x02, FspIopCreateRequestNonPagedFlag = 0x02,
FspIopCreateRequestWorkItemFlag = 0x04, FspIopCreateRequestWorkItemFlag = 0x04,
}; };
enum
{
FspIopRequestExtraContext = 4,
};
typedef VOID FSP_IOP_REQUEST_FINI(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]); typedef VOID FSP_IOP_REQUEST_FINI(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]);
typedef NTSTATUS FSP_IOP_REQUEST_WORK( typedef NTSTATUS FSP_IOP_REQUEST_WORK(
PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp, PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp,
@ -724,7 +728,7 @@ typedef struct
typedef struct typedef struct
{ {
FSP_IOP_REQUEST_FINI *RequestFini; FSP_IOP_REQUEST_FINI *RequestFini;
PVOID Context[4]; PVOID Context[4 + 1/*FspIopRequestExtraContext*/];
FSP_FSCTL_TRANSACT_RSP *Response; FSP_FSCTL_TRANSACT_RSP *Response;
FSP_FSCTL_TRANSACT_REQ_WORK_ITEM *WorkItem; FSP_FSCTL_TRANSACT_REQ_WORK_ITEM *WorkItem;
__declspec(align(FSP_FSCTL_TRANSACT_REQ_ALIGNMENT)) UINT8 RequestBuf[]; __declspec(align(FSP_FSCTL_TRANSACT_REQ_ALIGNMENT)) UINT8 RequestBuf[];
@ -1098,13 +1102,13 @@ VOID FspFileNodeReleaseForeign(FSP_FILE_NODE *FileNode)
FileNode = FileNode->MainFileNode; FileNode = FileNode->MainFileNode;
ExReleaseResourceLite(FileNode->Header.Resource); ExReleaseResourceLite(FileNode->Header.Resource);
} }
FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult); UINT32 GrantedAccess, UINT32 ShareAccess, FSP_FILE_NODE **POpenedFileNode);
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
PBOOLEAN PDeletePending); PBOOLEAN PDeletePending);
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
BOOLEAN AlsoCleanup); BOOLEAN RemoveShareAccess, BOOLEAN HandleCleanup);
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge); UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge);
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);

View File

@ -31,13 +31,13 @@ VOID FspFileNodeConvertExclusiveToSharedF(FSP_FILE_NODE *FileNode, ULONG Flags);
VOID FspFileNodeSetOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner); VOID FspFileNodeSetOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner);
VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags); VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags);
VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner); VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner);
FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult); UINT32 GrantedAccess, UINT32 ShareAccess, FSP_FILE_NODE **POpenedFileNode);
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
PBOOLEAN PDeletePending); PBOOLEAN PDeletePending);
VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject);
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
BOOLEAN AlsoCleanup); BOOLEAN RemoveShareAccess, BOOLEAN HandleCleanup);
NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge); UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge);
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
@ -447,8 +447,8 @@ VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner)
FSP_FILE_NODE_CLR_FLAGS(); FSP_FILE_NODE_CLR_FLAGS();
} }
FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult) UINT32 GrantedAccess, UINT32 ShareAccess, FSP_FILE_NODE **POpenedFileNode)
{ {
/* /*
* Attempt to insert our FileNode into the volume device's generic table. * Attempt to insert our FileNode into the volume device's generic table.
@ -596,13 +596,8 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
Result = STATUS_SUCCESS; Result = STATUS_SUCCESS;
exit: exit:
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result) && STATUS_SHARING_VIOLATION != Result)
{
if (0 != PResult)
*PResult = Result;
OpenedFileNode = 0; OpenedFileNode = 0;
}
if (0 != OpenedFileNode) if (0 != OpenedFileNode)
{ {
@ -613,7 +608,9 @@ exit:
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);
return OpenedFileNode; *POpenedFileNode = OpenedFileNode;
return Result;
} }
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
@ -724,7 +721,7 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject
} }
VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
BOOLEAN AlsoCleanup) BOOLEAN RemoveShareAccess, BOOLEAN HandleCleanup)
{ {
/* /*
* Close the FileNode. If the OpenCount becomes zero remove it * Close the FileNode. If the OpenCount becomes zero remove it
@ -740,7 +737,7 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
FspFsvolDeviceLockContextTable(FsvolDeviceObject); FspFsvolDeviceLockContextTable(FsvolDeviceObject);
if (AlsoCleanup) if (RemoveShareAccess)
{ {
/* /*
* Sharing violations between main file and streams were determined * Sharing violations between main file and streams were determined
@ -759,10 +756,11 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
} }
IoRemoveShareAccess(FileObject, &FileNode->ShareAccess); IoRemoveShareAccess(FileObject, &FileNode->ShareAccess);
FileNode->HandleCount--;
} }
if (HandleCleanup)
FileNode->HandleCount--;
if (0 < FileNode->OpenCount && 0 == --FileNode->OpenCount) if (0 < FileNode->OpenCount && 0 == --FileNode->OpenCount)
{ {
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName, FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName,

View File

@ -321,7 +321,10 @@ VOID FspIopCompleteIrpEx(PIRP Irp, NTSTATUS Result, BOOLEAN DeviceDereference)
ClearFlag(Irp->Flags, IRP_INPUT_OPERATION | IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER); ClearFlag(Irp->Flags, IRP_INPUT_OPERATION | IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER);
} }
if (STATUS_SUCCESS != Result && STATUS_REPARSE != Result && STATUS_BUFFER_OVERFLOW != Result) if (STATUS_SUCCESS != Result &&
STATUS_REPARSE != Result &&
STATUS_BUFFER_OVERFLOW != Result &&
STATUS_SHARING_VIOLATION != Result)
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Result; Irp->IoStatus.Status = Result;
IoCompleteRequest(Irp, FSP_IO_INCREMENT); IoCompleteRequest(Irp, FSP_IO_INCREMENT);