mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: IRP_MJ_SET_INFORMATION: FileRenameInformation
This commit is contained in:
		| @@ -550,11 +550,21 @@ NTSTATUS FspFsvolCreateComplete( | ||||
|             FSP_RETURN(); | ||||
|         } | ||||
|  | ||||
|         /* fix FileNode->FileName if we were doing SL_OPEN_TARGET_DIRECTORY */ | ||||
|         if (Request->Req.Create.OpenTargetDirectory) | ||||
|         { | ||||
|             UNICODE_STRING Suffix; | ||||
|  | ||||
|             FspUnicodePathSuffix(&FileNode->FileName, &FileNode->FileName, &Suffix); | ||||
|         } | ||||
|  | ||||
|         /* populate the FileNode/FileDesc fields from the Response */ | ||||
|         FileNode->UserContext = Response->Rsp.Create.Opened.UserContext; | ||||
|         FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber; | ||||
|         FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes, | ||||
|             FILE_ATTRIBUTE_DIRECTORY); | ||||
|         FileNode->IsRootDirectory = FileNode->IsDirectory && | ||||
|             sizeof(WCHAR) == FileNode->FileName.Length && L'\\' == FileNode->FileName.Buffer[0]; | ||||
|         FileDesc->UserContext2 = Response->Rsp.Create.Opened.UserContext2; | ||||
|         FileDesc->DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE); | ||||
|  | ||||
|   | ||||
| @@ -336,6 +336,9 @@ ULONG FspHashMixPointer(PVOID Pointer) | ||||
| } | ||||
|  | ||||
| /* utility */ | ||||
| PVOID FspAllocMustSucceed(SIZE_T Size); | ||||
| PVOID FspAllocateIrpMustSucceed(CCHAR StackSize); | ||||
| VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); | ||||
| NTSTATUS FspCreateGuid(GUID *Guid); | ||||
| NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes); | ||||
|  | ||||
| @@ -601,6 +604,7 @@ typedef struct | ||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage; | ||||
|     /* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource */ | ||||
|     UNICODE_STRING FileName; | ||||
|     PWSTR ExternalFileName; | ||||
|     /* locked under Header.Resource */ | ||||
|     UINT64 InfoExpirationTime; | ||||
|     UINT32 FileAttributes; | ||||
| @@ -616,6 +620,7 @@ typedef struct | ||||
|     UINT64 UserContext; | ||||
|     UINT64 IndexNumber; | ||||
|     BOOLEAN IsDirectory; | ||||
|     BOOLEAN IsRootDirectory; | ||||
|     WCHAR FileNameBuf[]; | ||||
| } FSP_FILE_NODE; | ||||
| typedef struct | ||||
| @@ -639,6 +644,7 @@ VOID FspFileNodeDereference(FSP_FILE_NODE *FileNode) | ||||
|     if (0 == RefCount) | ||||
|         FspFileNodeDelete(FileNode); | ||||
| } | ||||
| VOID FspFileNodeSetExternalFileName(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); | ||||
| VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags); | ||||
| BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags); | ||||
| VOID FspFileNodeAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags); | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
| NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, | ||||
|     ULONG ExtraSize, FSP_FILE_NODE **PFileNode); | ||||
| VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode); | ||||
| VOID FspFileNodeSetExternalFileName(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); | ||||
| VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags); | ||||
| BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags); | ||||
| VOID FspFileNodeAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags); | ||||
| @@ -32,6 +33,7 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); | ||||
| #ifdef ALLOC_PRAGMA | ||||
| #pragma alloc_text(PAGE, FspFileNodeCreate) | ||||
| #pragma alloc_text(PAGE, FspFileNodeDelete) | ||||
| #pragma alloc_text(PAGE, FspFileNodeSetExternalFileName) | ||||
| #pragma alloc_text(PAGE, FspFileNodeAcquireSharedF) | ||||
| #pragma alloc_text(PAGE, FspFileNodeTryAcquireSharedF) | ||||
| #pragma alloc_text(PAGE, FspFileNodeAcquireExclusiveF) | ||||
| @@ -100,6 +102,9 @@ VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode) | ||||
|  | ||||
|     FspDeviceDereference(FileNode->FsvolDeviceObject); | ||||
|  | ||||
|     if (0 != FileNode->ExternalFileName) | ||||
|         FspFree(FileNode->ExternalFileName); | ||||
|  | ||||
|     ExDeleteResourceLite(&FileNode->NonPaged->PagingIoResource); | ||||
|     ExDeleteResourceLite(&FileNode->NonPaged->Resource); | ||||
|     FspFree(FileNode->NonPaged); | ||||
| @@ -107,6 +112,17 @@ VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode) | ||||
|     FspFree(FileNode); | ||||
| } | ||||
|  | ||||
| VOID FspFileNodeSetExternalFileName(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     if (0 != FileNode->ExternalFileName) | ||||
|         FspFree(FileNode->ExternalFileName); | ||||
|  | ||||
|     FileNode->FileName = *NewFileName; | ||||
|     FileNode->ExternalFileName = NewFileName->Buffer; | ||||
| } | ||||
|  | ||||
| VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject, | ||||
| static NTSTATUS FspFsvolQueryInformation( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete; | ||||
| static FSP_IOP_REQUEST_FINI FspFsvolQueryInformationRequestFini; | ||||
| static NTSTATUS FspFsvolSetAllocationInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| @@ -44,13 +45,14 @@ static NTSTATUS FspFsvolSetEndOfFileInformation(PFILE_OBJECT FileObject, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| static NTSTATUS FspFsvolSetPositionInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length); | ||||
| static NTSTATUS FspFsvolSetRenameInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| static NTSTATUS FspFsvolSetRenameInformation( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| NTSTATUS FspFsvolSetRenameInformationSuccess( | ||||
|     PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| static NTSTATUS FspFsvolSetInformation( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete; | ||||
| static FSP_IOP_REQUEST_FINI FspFsvolInformationRequestFini; | ||||
| static FSP_IOP_REQUEST_FINI FspFsvolSetInformationRequestFini; | ||||
| FSP_DRIVER_DISPATCH FspQueryInformation; | ||||
| FSP_DRIVER_DISPATCH FspSetInformation; | ||||
|  | ||||
| @@ -65,25 +67,32 @@ FSP_DRIVER_DISPATCH FspSetInformation; | ||||
| #pragma alloc_text(PAGE, FspFsvolQueryStandardInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolQueryInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolQueryInformationComplete) | ||||
| #pragma alloc_text(PAGE, FspFsvolQueryInformationRequestFini) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetAllocationInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetBasicInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetDispositionInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetEndOfFileInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetPositionInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetRenameInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetRenameInformationSuccess) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetInformationComplete) | ||||
| #pragma alloc_text(PAGE, FspFsvolInformationRequestFini) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetInformationRequestFini) | ||||
| #pragma alloc_text(PAGE, FspQueryInformation) | ||||
| #pragma alloc_text(PAGE, FspSetInformation) | ||||
| #endif | ||||
|  | ||||
| enum | ||||
| { | ||||
|     /* QueryInformation */ | ||||
|     RequestFileNode                     = 0, | ||||
|     RequestInfoChangeNumber             = 1, | ||||
|     RequestAllInformationResult         = 2, | ||||
|     RequestAllInformationBuffer         = 3, | ||||
|  | ||||
|     /* SetInformation */ | ||||
|     //RequestFileNode                   = 0, | ||||
|     RequestDeviceObject                 = 1, | ||||
| }; | ||||
|  | ||||
| static NTSTATUS FspFsvolQueryAllInformation(PFILE_OBJECT FileObject, | ||||
| @@ -439,7 +448,7 @@ static NTSTATUS FspFsvolQueryInformation( | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request; | ||||
|  | ||||
|     Result = FspIopCreateRequestEx(Irp, FileNameRequired ? &FileNode->FileName : 0, 0, | ||||
|         FspFsvolInformationRequestFini, &Request); | ||||
|         FspFsvolQueryInformationRequestFini, &Request); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         FspFileNodeRelease(FileNode, Full); | ||||
| @@ -540,6 +549,16 @@ NTSTATUS FspFsvolQueryInformationComplete( | ||||
|         IrpSp->FileObject); | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolQueryInformationRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FILE_NODE *FileNode = Context[RequestFileNode]; | ||||
|  | ||||
|     if (0 != FileNode) | ||||
|         FspFileNodeReleaseOwner(FileNode, Full, Request); | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolSetAllocationInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| @@ -631,6 +650,12 @@ static NTSTATUS FspFsvolSetDispositionInformation(PFILE_OBJECT FileObject, | ||||
|     { | ||||
|         if (sizeof(FILE_DISPOSITION_INFORMATION) > Length) | ||||
|             return STATUS_INVALID_PARAMETER; | ||||
|  | ||||
|         FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||
|  | ||||
|         if (FileNode->IsRootDirectory) | ||||
|             /* cannot delete root directory */ | ||||
|             return STATUS_CANNOT_DELETE; | ||||
|     } | ||||
|     else if (0 == Response) | ||||
|     { | ||||
| @@ -714,13 +739,175 @@ static NTSTATUS FspFsvolSetPositionInformation(PFILE_OBJECT FileObject, | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolSetRenameInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| static NTSTATUS FspFsvolSetRenameInformation( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     return STATUS_INVALID_DEVICE_REQUEST; | ||||
|     NTSTATUS Result; | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
|     PFILE_OBJECT TargetFileObject = IrpSp->Parameters.SetFile.FileObject; | ||||
|     PFILE_RENAME_INFORMATION Info = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer; | ||||
|     ULONG Length = IrpSp->Parameters.SetFile.Length; | ||||
|     BOOLEAN ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists; | ||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||
|     FSP_FILE_DESC *FileDesc = FileObject->FsContext2; | ||||
|     FSP_FILE_NODE *TargetFileNode = 0 != TargetFileObject ? | ||||
|         TargetFileObject->FsContext : 0; | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request; | ||||
|     UNICODE_STRING NewFileName; | ||||
|  | ||||
|     ASSERT(FileNode == FileDesc->FileNode); | ||||
|  | ||||
|     if (sizeof(FILE_RENAME_INFORMATION) > Length) | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|     if (sizeof(WCHAR) > Info->FileNameLength) | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|     if (FileNode->IsRootDirectory) | ||||
|         /* cannot rename root directory */ | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|  | ||||
|     if (0 != TargetFileNode) | ||||
|     { | ||||
|         if (!FspFileNodeIsValid(TargetFileNode)) | ||||
|             return STATUS_INVALID_PARAMETER; | ||||
|  | ||||
|         ASSERT(TargetFileNode->IsDirectory); | ||||
|     } | ||||
|  | ||||
|     FspFsvolDeviceFileRenameAcquireExclusive(FsvolDeviceObject); | ||||
|     FspFileNodeAcquireExclusive(FileNode, Full); | ||||
|  | ||||
|     if (L'\\' == Info->FileName[0]) | ||||
|     { | ||||
|         Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, | ||||
|             Info->FileNameLength + sizeof(WCHAR), | ||||
|             FspFsvolSetInformationRequestFini, &Request); | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|             goto unlock_exit; | ||||
|  | ||||
|         Request->Req.SetInformation.Info.Rename.NewFileName.Size = | ||||
|             (UINT16)(Info->FileNameLength + sizeof(WCHAR)); | ||||
|  | ||||
|         RtlCopyMemory(Request->Buffer + Request->FileName.Size, | ||||
|             Info->FileName, Info->FileNameLength); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         UNICODE_STRING Remain, Suffix; | ||||
|  | ||||
|         FspUnicodePathSuffix(&FileNode->FileName, &Remain, &Suffix); | ||||
|  | ||||
|         Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, | ||||
|             Remain.Length + sizeof(WCHAR) + Info->FileNameLength + sizeof(WCHAR), | ||||
|             FspFsvolSetInformationRequestFini, &Request); | ||||
|         if (!NT_SUCCESS(Result)) | ||||
|             goto unlock_exit; | ||||
|  | ||||
|         Request->Req.SetInformation.Info.Rename.NewFileName.Size = | ||||
|             (UINT16)(Remain.Length + sizeof(WCHAR) + Info->FileNameLength + sizeof(WCHAR)); | ||||
|  | ||||
|         RtlCopyMemory(Request->Buffer + Request->FileName.Size, | ||||
|             Remain.Buffer, Remain.Length); | ||||
|         *(PWSTR)(Request->Buffer + Request->FileName.Size + Remain.Length) = L'\\'; | ||||
|         RtlCopyMemory(Request->Buffer + Request->FileName.Size + Remain.Length + sizeof(WCHAR), | ||||
|             Info->FileName, Info->FileNameLength); | ||||
|     } | ||||
|  | ||||
|     *(PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Size) = L'\0'; | ||||
|  | ||||
|     Request->Kind = FspFsctlTransactSetInformationKind; | ||||
|     Request->Req.SetInformation.UserContext = FileNode->UserContext; | ||||
|     Request->Req.SetInformation.UserContext2 = FileDesc->UserContext2; | ||||
|     Request->Req.SetInformation.FileInformationClass = FileRenameInformation; | ||||
|     Request->Req.SetInformation.Info.Rename.NewFileName.Offset = Request->FileName.Size; | ||||
|     Request->Req.SetInformation.Info.Rename.ReplaceIfExists = ReplaceIfExists; | ||||
|  | ||||
|     FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request); | ||||
|     FspFileNodeSetOwner(FileNode, Full, Request); | ||||
|     FspIopRequestContext(Request, RequestFileNode) = FileNode; | ||||
|     FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject; | ||||
|  | ||||
|     /* | ||||
|      * Special rules for renaming open files: | ||||
|      * -   A file cannot be renamed if it has any open handles, | ||||
|      *     unless it is only open because of a batch opportunistic lock (oplock) | ||||
|      *     and the batch oplock can be broken immediately. | ||||
|      * -   A file cannot be renamed if a file with the same name exists | ||||
|      *     and has open handles (except in the batch-oplock case described earlier). | ||||
|      * -   A directory cannot be renamed if it or any of its subdirectories contains a file | ||||
|      *     that has open handles (except in the batch-oplock case described earlier). | ||||
|      */ | ||||
|  | ||||
|     NewFileName.Length = NewFileName.MaximumLength = | ||||
|         Request->Req.SetInformation.Info.Rename.NewFileName.Size - sizeof(WCHAR); | ||||
|     NewFileName.Buffer = (PVOID)(Request->Buffer + Request->FileName.Size); | ||||
|  | ||||
|     Result = STATUS_SUCCESS; | ||||
|     FspFsvolDeviceLockContextTable(FsvolDeviceObject); | ||||
|     if (FileNode->IsDirectory) | ||||
|     { | ||||
|         if (1 < FileNode->OpenCount || | ||||
|             0 != FspFsvolDeviceLookupChildContextByName(FsvolDeviceObject, &FileNode->FileName) || | ||||
|             0 != FspFsvolDeviceLookupContextByName(FsvolDeviceObject, &NewFileName) || | ||||
|             0 != FspFsvolDeviceLookupChildContextByName(FsvolDeviceObject, &NewFileName)) | ||||
|             Result = STATUS_ACCESS_DENIED; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         if (1 < FileNode->OpenCount || | ||||
|             0 != FspFsvolDeviceLookupContextByName(FsvolDeviceObject, &NewFileName) || | ||||
|             0 != FspFsvolDeviceLookupChildContextByName(FsvolDeviceObject, &NewFileName)) | ||||
|             Result = STATUS_ACCESS_DENIED; | ||||
|     } | ||||
|     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return Result; | ||||
|  | ||||
|     return FSP_STATUS_IOQ_POST; | ||||
|  | ||||
| unlock_exit: | ||||
|     FspFileNodeRelease(FileNode, Full); | ||||
|     FspFsvolDeviceFileRenameRelease(FsvolDeviceObject); | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspFsvolSetRenameInformationSuccess( | ||||
|     PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject; | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); | ||||
|     UNICODE_STRING NewFileName; | ||||
|     BOOLEAN Deleted, Inserted; | ||||
|  | ||||
|     NewFileName.Length = NewFileName.MaximumLength = | ||||
|         Request->Req.SetInformation.Info.Rename.NewFileName.Size - sizeof(WCHAR); | ||||
|     NewFileName.Buffer = FspAllocMustSucceed(NewFileName.Length); | ||||
|     RtlCopyMemory(NewFileName.Buffer, Request->Buffer + Request->FileName.Size, NewFileName.Length); | ||||
|  | ||||
|     FspFsvolDeviceLockContextTable(FsvolDeviceObject); | ||||
|     FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName, &Deleted); | ||||
|     ASSERT(Deleted); | ||||
|     FspFileNodeSetExternalFileName(FileNode, &NewFileName); | ||||
|     FspFsvolDeviceInsertContextByName(FsvolDeviceObject, &FileNode->FileName, FileNode, | ||||
|         &FileNode->ContextByNameElementStorage, &Inserted); | ||||
|     ASSERT(Inserted); | ||||
|     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); | ||||
|  | ||||
|     FspIopRequestContext(Request, RequestFileNode) = 0; | ||||
|     FspIopRequestContext(Request, RequestDeviceObject) = 0; | ||||
|     FspFileNodeReleaseOwner(FileNode, Full, Request); | ||||
|     FspFsvolDeviceFileRenameRelease(FsvolDeviceObject); | ||||
|  | ||||
|     Irp->IoStatus.Information = 0; | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolSetInformation( | ||||
| @@ -732,8 +919,13 @@ static NTSTATUS FspFsvolSetInformation( | ||||
|     if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext)) | ||||
|         return STATUS_INVALID_DEVICE_REQUEST; | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass; | ||||
|  | ||||
|     /* special case FileRenameInformation */ | ||||
|     if (FileRenameInformation == FileInformationClass) | ||||
|         return FspFsvolSetRenameInformation(FsvolDeviceObject, Irp, IrpSp); | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
|     PVOID Buffer = Irp->AssociatedIrp.SystemBuffer; | ||||
|     ULONG Length = IrpSp->Parameters.SetFile.Length; | ||||
| @@ -759,9 +951,6 @@ static NTSTATUS FspFsvolSetInformation( | ||||
|     case FilePositionInformation: | ||||
|         Result = FspFsvolSetPositionInformation(FileObject, Buffer, Length); | ||||
|         return Result; | ||||
|     case FileRenameInformation: | ||||
|         Result = FspFsvolSetRenameInformation(FileObject, Buffer, Length, 0, 0); | ||||
|         break; | ||||
|     case FileValidDataLengthInformation: | ||||
|         Result = STATUS_INVALID_PARAMETER;  /* no ValidDataLength support */ | ||||
|         return Result; | ||||
| @@ -782,7 +971,7 @@ static NTSTATUS FspFsvolSetInformation( | ||||
|     ASSERT(FileNode == FileDesc->FileNode); | ||||
|  | ||||
|     Result = FspIopCreateRequestEx(Irp, FileNameRequired ? &FileNode->FileName : 0, 0, | ||||
|         FspFsvolInformationRequestFini, &Request); | ||||
|         FspFsvolSetInformationRequestFini, &Request); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return Result; | ||||
|  | ||||
| @@ -810,9 +999,6 @@ static NTSTATUS FspFsvolSetInformation( | ||||
|         Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length, | ||||
|             IrpSp->Parameters.SetFile.AdvanceOnly, Request, 0); | ||||
|         break; | ||||
|     case FileRenameInformation: | ||||
|         Result = FspFsvolSetRenameInformation(FileObject, Buffer, Length, Request, 0); | ||||
|         break; | ||||
|     default: | ||||
|         ASSERT(0); | ||||
|         Result = STATUS_INVALID_PARAMETER; | ||||
| @@ -838,6 +1024,14 @@ NTSTATUS FspFsvolSetInformationComplete( | ||||
|     } | ||||
|  | ||||
|     FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass; | ||||
|  | ||||
|     /* special case FileRenameInformation */ | ||||
|     if (FileRenameInformation == FileInformationClass) | ||||
|     { | ||||
|         Result = FspFsvolSetRenameInformationSuccess(Irp, Response); | ||||
|         FSP_RETURN(); | ||||
|     } | ||||
|  | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||
|     PVOID Buffer = Irp->AssociatedIrp.SystemBuffer; | ||||
| @@ -859,9 +1053,6 @@ NTSTATUS FspFsvolSetInformationComplete( | ||||
|         Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length, | ||||
|             IrpSp->Parameters.SetFile.AdvanceOnly, Request, Response); | ||||
|         break; | ||||
|     case FileRenameInformation: | ||||
|         Result = FspFsvolSetRenameInformation(FileObject, Buffer, Length, Request, Response); | ||||
|         break; | ||||
|     default: | ||||
|         ASSERT(0); | ||||
|         Result = STATUS_INVALID_PARAMETER; | ||||
| @@ -878,14 +1069,18 @@ NTSTATUS FspFsvolSetInformationComplete( | ||||
|         IrpSp->FileObject); | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolInformationRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| static VOID FspFsvolSetInformationRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FILE_NODE *FileNode = Context[RequestFileNode]; | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = Context[RequestDeviceObject]; | ||||
|  | ||||
|     if (0 != FileNode) | ||||
|         FspFileNodeReleaseOwner(FileNode, Full, Request); | ||||
|  | ||||
|     if (0 != FsvolDeviceObject) | ||||
|         FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, Request); | ||||
| } | ||||
|  | ||||
| NTSTATUS FspQueryInformation( | ||||
|   | ||||
| @@ -39,48 +39,6 @@ NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response | ||||
| #pragma alloc_text(PAGE, FspIopDispatchComplete) | ||||
| #endif | ||||
|  | ||||
| static const LONG Delays[] = | ||||
| { | ||||
|     -100, | ||||
|     -200, | ||||
|     -300, | ||||
|     -400, | ||||
|     -500, | ||||
|     -1000, | ||||
| }; | ||||
|  | ||||
| static PVOID FspAllocMustSucceed(SIZE_T Size) | ||||
| { | ||||
|     PVOID Result; | ||||
|     LARGE_INTEGER Delay; | ||||
|  | ||||
|     for (ULONG i = 0, n = sizeof(Delays) / sizeof(Delays[0]);; i++) | ||||
|     { | ||||
|         Result = FspAlloc(Size); | ||||
|         if (0 != Result) | ||||
|             return Result; | ||||
|  | ||||
|         Delay.QuadPart = n > i ? Delays[i] : Delays[n - 1]; | ||||
|         KeDelayExecutionThread(KernelMode, FALSE, &Delay); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static PVOID FspAllocateIrpMustSucceed(CCHAR StackSize) | ||||
| { | ||||
|     PIRP Result; | ||||
|     LARGE_INTEGER Delay; | ||||
|  | ||||
|     for (ULONG i = 0, n = sizeof(Delays) / sizeof(Delays[0]);; i++) | ||||
|     { | ||||
|         Result = IoAllocateIrp(StackSize, FALSE); | ||||
|         if (0 != Result) | ||||
|             return Result; | ||||
|  | ||||
|         Delay.QuadPart = n > i ? Delays[i] : Delays[n - 1]; | ||||
|         KeDelayExecutionThread(KernelMode, FALSE, &Delay); | ||||
|     } | ||||
| } | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|     FSP_IOP_REQUEST_FINI *RequestFini; | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
|  | ||||
| #include <sys/driver.h> | ||||
|  | ||||
| VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix); | ||||
| NTSTATUS FspCreateGuid(GUID *Guid); | ||||
| VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem, | ||||
|     PWORKER_THREAD_ROUTINE Routine, PVOID Context); | ||||
| @@ -17,6 +18,7 @@ VOID FspQueueDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem, LARGE_INTEG | ||||
| static KDEFERRED_ROUTINE FspQueueDelayedWorkItemDPC; | ||||
|  | ||||
| #ifdef ALLOC_PRAGMA | ||||
| #pragma alloc_text(PAGE, FspUnicodePathSuffix) | ||||
| #pragma alloc_text(PAGE, FspCreateGuid) | ||||
| #pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem) | ||||
| #pragma alloc_text(PAGE, FspExecuteSynchronousWorkItem) | ||||
| @@ -25,6 +27,78 @@ static KDEFERRED_ROUTINE FspQueueDelayedWorkItemDPC; | ||||
| #pragma alloc_text(PAGE, FspQueueDelayedWorkItem) | ||||
| #endif | ||||
|  | ||||
| static const LONG Delays[] = | ||||
| { | ||||
|     -100, | ||||
|     -200, | ||||
|     -300, | ||||
|     -400, | ||||
|     -500, | ||||
|     -1000, | ||||
| }; | ||||
|  | ||||
| PVOID FspAllocMustSucceed(SIZE_T Size) | ||||
| { | ||||
|     PVOID Result; | ||||
|     LARGE_INTEGER Delay; | ||||
|  | ||||
|     for (ULONG i = 0, n = sizeof(Delays) / sizeof(Delays[0]);; i++) | ||||
|     { | ||||
|         Result = FspAlloc(Size); | ||||
|         if (0 != Result) | ||||
|             return Result; | ||||
|  | ||||
|         Delay.QuadPart = n > i ? Delays[i] : Delays[n - 1]; | ||||
|         KeDelayExecutionThread(KernelMode, FALSE, &Delay); | ||||
|     } | ||||
| } | ||||
|  | ||||
| PVOID FspAllocateIrpMustSucceed(CCHAR StackSize) | ||||
| { | ||||
|     PIRP Result; | ||||
|     LARGE_INTEGER Delay; | ||||
|  | ||||
|     for (ULONG i = 0, n = sizeof(Delays) / sizeof(Delays[0]);; i++) | ||||
|     { | ||||
|         Result = IoAllocateIrp(StackSize, FALSE); | ||||
|         if (0 != Result) | ||||
|             return Result; | ||||
|  | ||||
|         Delay.QuadPart = n > i ? Delays[i] : Delays[n - 1]; | ||||
|         KeDelayExecutionThread(KernelMode, FALSE, &Delay); | ||||
|     } | ||||
| } | ||||
|  | ||||
| VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     PWSTR PathBgn, PathEnd, PathPtr, RemainEnd, SuffixBgn; | ||||
|  | ||||
|     PathBgn = Path->Buffer; | ||||
|     PathEnd = (PWSTR)((PUINT8)PathBgn + Path->Length); | ||||
|     PathPtr = PathBgn; | ||||
|  | ||||
|     RemainEnd = PathEnd; | ||||
|     SuffixBgn = PathEnd; | ||||
|  | ||||
|     while (PathEnd > PathPtr) | ||||
|         if (L'\\' == *PathPtr) | ||||
|         { | ||||
|             RemainEnd = PathPtr++; | ||||
|             for (; L'\\' == *PathPtr; PathPtr++) | ||||
|                 ; | ||||
|             SuffixBgn = PathPtr; | ||||
|         } | ||||
|         else | ||||
|             PathPtr++; | ||||
|  | ||||
|     Remain->Length = Remain->MaximumLength = (USHORT)((PUINT8)RemainEnd - (PUINT8)PathBgn); | ||||
|     Remain->Buffer = PathBgn; | ||||
|     Suffix->Length = Suffix->MaximumLength = (USHORT)((PUINT8)PathEnd - (PUINT8)SuffixBgn); | ||||
|     Suffix->Buffer = SuffixBgn; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspCreateGuid(GUID *Guid) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user