diff --git a/src/sys/create.c b/src/sys/create.c index 82fb8677..85e2aaf7 100644 --- a/src/sys/create.c +++ b/src/sys/create.c @@ -649,7 +649,8 @@ NTSTATUS FspFsvolCreateComplete( /* did the user-mode file system sent us a failure code? */ if (!NT_SUCCESS(Response->IoStatus.Status)) { - Irp->IoStatus.Information = 0; + Irp->IoStatus.Information = STATUS_SHARING_VIOLATION == Response->IoStatus.Status ? + Response->IoStatus.Information : 0; Result = Response->IoStatus.Status; FSP_RETURN(); } @@ -842,8 +843,10 @@ NTSTATUS FspFsvolCreateComplete( { if (STATUS_SHARING_VIOLATION == Result) { + ASSERT(0 != OpenedFileNode); + FspIopSetIrpResponse(Irp, Response); - FspIopRequestContext(Request, FspIopRequestExtraContext) = FileNode; + FspIopRequestContext(Request, FspIopRequestExtraContext) = OpenedFileNode; Result = FspFsvolCreateSharingViolationOplock( FsvolDeviceObject, Irp, IrpSp, FALSE); @@ -1240,13 +1243,13 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock( FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); FSP_FSCTL_TRANSACT_RSP *Response; - FSP_FILE_NODE *FileNode = FspIopRequestContext(Request, FspIopRequestExtraContext); + FSP_FILE_NODE *ExtraFileNode = FspIopRequestContext(Request, FspIopRequestExtraContext); BOOLEAN OpbatchBreakUnderway = FALSE; NTSTATUS Result; BOOLEAN Success; Success = DEBUGTEST(90) && - FspFileNodeTryAcquireSharedF(FileNode, FspFileNodeAcquireMain, CanWait); + FspFileNodeTryAcquireSharedF(ExtraFileNode, FspFileNodeAcquireMain, CanWait); if (!Success) return FspWqRepostIrpWorkItem(Irp, FspFsvolCreateSharingViolationOplock, FspFsvolCreateRequestFini); @@ -1257,11 +1260,11 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock( * If there is no batch or CACHE_HANDLE_LEVEL oplock we are done; * else retry in a worker thread to break the oplocks. */ - Success = !FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(FileNode)) && + Success = !FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode)) && (FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) || - !FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(FileNode))); + !FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode))); - FspFileNodeRelease(FileNode, Main); + FspFileNodeRelease(ExtraFileNode, Main); if (!Success) return FspWqRepostIrpWorkItem(Irp, @@ -1274,7 +1277,7 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock( { #if 0 /* ???: is this needed in this case? */ - Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(FileNode), Irp, + Result = FspCheckOplockEx(FspFileNodeAddrOfOplock(ExtraFileNode), Irp, OPLOCK_FLAG_OPLOCK_KEY_CHECK_ONLY, 0, 0, 0); if (!NT_SUCCESS(Result)) { @@ -1283,10 +1286,10 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock( } #endif - if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(FileNode))) + if (FsRtlCurrentBatchOplock(FspFileNodeAddrOfOplock(ExtraFileNode))) { /* wait for batch oplock break to complete */ - Result = FspCheckOplock(FspFileNodeAddrOfOplock(FileNode), Irp, + Result = FspCheckOplock(FspFileNodeAddrOfOplock(ExtraFileNode), Irp, 0, 0, 0); if (STATUS_SUCCESS == Result) OpbatchBreakUnderway = TRUE; @@ -1295,24 +1298,24 @@ static NTSTATUS FspFsvolCreateSharingViolationOplock( Result = STATUS_SHARING_VIOLATION; if (!FlagOn(IrpSp->Parameters.Create.Options, FILE_COMPLETE_IF_OPLOCKED) && - FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(FileNode))) + FsRtlCurrentOplockH(FspFileNodeAddrOfOplock(ExtraFileNode))) { /* wait for CACHE_HANDLE_LEVEL oplock break to complete */ - Result = FspOplockBreakH(FspFileNodeAddrOfOplock(FileNode), Irp, + Result = FspOplockBreakH(FspFileNodeAddrOfOplock(ExtraFileNode), Irp, 0, 0, 0, 0); } #if 0 exit: #endif - FspFileNodeRelease(FileNode, Main); + FspFileNodeRelease(ExtraFileNode, Main); Response = FspIopIrpResponse(Irp); if (NT_SUCCESS(Result)) { - FspFileNodeClose(FileNode, 0, TRUE); - FspFileNodeDereference(FileNode); + FspFileNodeClose(ExtraFileNode, 0, TRUE); + FspFileNodeDereference(ExtraFileNode); FspIopRequestContext(Request, FspIopRequestExtraContext) = 0; } else diff --git a/src/sys/driver.h b/src/sys/driver.h index fecb61be..b4656c22 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -1114,7 +1114,7 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, BOOLEAN HandleCleanup); /* TRUE to decrement handle count */ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge); -BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, +BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp, FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName); VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); diff --git a/src/sys/file.c b/src/sys/file.c index 1345bd0e..963fce61 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -41,7 +41,7 @@ VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, BOOLEAN HandleCleanup); /* TRUE to decrement handle count */ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, UINT64 FlushOffset64, ULONG FlushLength, BOOLEAN FlushAndPurge); -BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, +BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp, FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName); VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); @@ -493,6 +493,7 @@ NTSTATUS FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, FlagOn(GrantedAccess, FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE)) { + OpenedFileNode = FileNode->MainFileNode; Result = STATUS_SHARING_VIOLATION; goto exit; } @@ -833,7 +834,7 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, return IoStatus.Status; } -BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, +BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp, FSP_FILE_NODE *FileNode, PUNICODE_STRING FileName) { PAGED_CODE(); @@ -860,6 +861,8 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, DescendantFileNodes = DescendantFileNodeArray; DescendantFileNodeCount = 0; + FspFsvolDeviceLockContextTable(FsvolDeviceObject); + /* if we are checking the existing file name, do a quick check here */ if (CheckingOldName) { @@ -873,8 +876,6 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, /* Note: when CheckingOldName==TRUE, the old FileNode is not included in enumerations below */ } - FspFsvolDeviceLockContextTable(FsvolDeviceObject); - /* count descendant file nodes and try to gather them in a local array if possible */ memset(&RestartKey, 0, sizeof RestartKey); for (;;) @@ -895,6 +896,12 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, DescendantFileNodeCount++; } + if (0 == DescendantFileNodeCount) + { + ASSERT(Success); + goto unlock_exit; + } + /* if the local array is out of space, gather descendant file nodes in the pool */ if (ARRAYSIZE(DescendantFileNodeArray) < DescendantFileNodeCount) { @@ -956,7 +963,7 @@ BOOLEAN FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~1); if (HasOpenHandles) - FspCheckOplock(FspFileNodeAddrOfOplock(DescendantFileNode), Irp, 0, 0, 0); + FspCheckOplock(FspFileNodeAddrOfOplock(DescendantFileNode), OplockIrp, 0, 0, 0); } FspFsvolDeviceLockContextTable(FsvolDeviceObject); diff --git a/src/sys/fileinfo.c b/src/sys/fileinfo.c index 33a17c7e..32ce5475 100644 --- a/src/sys/fileinfo.c +++ b/src/sys/fileinfo.c @@ -1280,7 +1280,7 @@ retry: * that has open handles (except in the batch-oplock case described earlier). */ Result = STATUS_SUCCESS; - if (!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, FileNode, &FileNode->FileName) && + if (!FspFileNodeRenameCheck(FsvolDeviceObject, Irp, FileNode, &FileNode->FileName) || !FspFileNodeRenameCheck(FsvolDeviceObject, Irp, 0, &NewFileName)) Result = STATUS_ACCESS_DENIED; if (!NT_SUCCESS(Result)) diff --git a/src/sys/iop.c b/src/sys/iop.c index 742be42c..ac5028f1 100644 --- a/src/sys/iop.c +++ b/src/sys/iop.c @@ -164,6 +164,7 @@ NTSTATUS FspIopCreateRequestWorkItem(FSP_FSCTL_TRANSACT_REQ *Request) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(RequestWorkItem, sizeof *RequestWorkItem); + RequestHeader->WorkItem = RequestWorkItem; } return STATUS_SUCCESS; diff --git a/src/sys/wq.c b/src/sys/wq.c index 5073d1f0..b5ab7166 100644 --- a/src/sys/wq.c +++ b/src/sys/wq.c @@ -93,6 +93,9 @@ NTSTATUS FspWqCreateAndPostIrpWorkItem(PIRP Irp, ExInitializeWorkItem(&RequestWorkItem->WorkQueueItem, FspWqWorkRoutine, Irp); } + ASSERT(RequestFini == ((FSP_FSCTL_TRANSACT_REQ_HEADER *) + ((PUINT8)Request - sizeof(FSP_FSCTL_TRANSACT_REQ_HEADER)))->RequestFini); + if (!CreateAndPost) return STATUS_SUCCESS; @@ -117,6 +120,7 @@ VOID FspWqPostIrpWorkItem(PIRP Irp) case IRP_MJ_WRITE: case IRP_MJ_DIRECTORY_CONTROL: case IRP_MJ_LOCK_CONTROL: + break; default: ASSERT(0); break;