sys: IRP_MJ_SET_INFORMATION: FileRenameInformation

This commit is contained in:
Bill Zissimopoulos 2016-02-09 11:26:03 -08:00
parent 38839ddd82
commit 6c94eb3398
6 changed files with 323 additions and 64 deletions

View File

@ -550,11 +550,21 @@ NTSTATUS FspFsvolCreateComplete(
FSP_RETURN(); 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 */ /* populate the FileNode/FileDesc fields from the Response */
FileNode->UserContext = Response->Rsp.Create.Opened.UserContext; FileNode->UserContext = Response->Rsp.Create.Opened.UserContext;
FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber; FileNode->IndexNumber = Response->Rsp.Create.Opened.FileInfo.IndexNumber;
FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes, FileNode->IsDirectory = BooleanFlagOn(Response->Rsp.Create.Opened.FileInfo.FileAttributes,
FILE_ATTRIBUTE_DIRECTORY); 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->UserContext2 = Response->Rsp.Create.Opened.UserContext2;
FileDesc->DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE); FileDesc->DeleteOnClose = BooleanFlagOn(IrpSp->Parameters.Create.Options, FILE_DELETE_ON_CLOSE);

View File

@ -336,6 +336,9 @@ ULONG FspHashMixPointer(PVOID Pointer)
} }
/* utility */ /* 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 FspCreateGuid(GUID *Guid);
NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes); NTSTATUS FspCcSetFileSizes(PFILE_OBJECT FileObject, PCC_FILE_SIZES FileSizes);
@ -601,6 +604,7 @@ typedef struct
FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage; FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage;
/* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource */ /* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource */
UNICODE_STRING FileName; UNICODE_STRING FileName;
PWSTR ExternalFileName;
/* locked under Header.Resource */ /* locked under Header.Resource */
UINT64 InfoExpirationTime; UINT64 InfoExpirationTime;
UINT32 FileAttributes; UINT32 FileAttributes;
@ -616,6 +620,7 @@ typedef struct
UINT64 UserContext; UINT64 UserContext;
UINT64 IndexNumber; UINT64 IndexNumber;
BOOLEAN IsDirectory; BOOLEAN IsDirectory;
BOOLEAN IsRootDirectory;
WCHAR FileNameBuf[]; WCHAR FileNameBuf[];
} FSP_FILE_NODE; } FSP_FILE_NODE;
typedef struct typedef struct
@ -639,6 +644,7 @@ VOID FspFileNodeDereference(FSP_FILE_NODE *FileNode)
if (0 == RefCount) if (0 == RefCount)
FspFileNodeDelete(FileNode); FspFileNodeDelete(FileNode);
} }
VOID FspFileNodeSetExternalFileName(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags); VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags);
BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags); BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags);
VOID FspFileNodeAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags); VOID FspFileNodeAcquireExclusiveF(FSP_FILE_NODE *FileNode, ULONG Flags);

View File

@ -9,6 +9,7 @@
NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject, NTSTATUS FspFileNodeCreate(PDEVICE_OBJECT DeviceObject,
ULONG ExtraSize, FSP_FILE_NODE **PFileNode); ULONG ExtraSize, FSP_FILE_NODE **PFileNode);
VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode); VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode);
VOID FspFileNodeSetExternalFileName(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName);
VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags); VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags);
BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags); BOOLEAN FspFileNodeTryAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags);
VOID FspFileNodeAcquireExclusiveF(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 #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspFileNodeCreate) #pragma alloc_text(PAGE, FspFileNodeCreate)
#pragma alloc_text(PAGE, FspFileNodeDelete) #pragma alloc_text(PAGE, FspFileNodeDelete)
#pragma alloc_text(PAGE, FspFileNodeSetExternalFileName)
#pragma alloc_text(PAGE, FspFileNodeAcquireSharedF) #pragma alloc_text(PAGE, FspFileNodeAcquireSharedF)
#pragma alloc_text(PAGE, FspFileNodeTryAcquireSharedF) #pragma alloc_text(PAGE, FspFileNodeTryAcquireSharedF)
#pragma alloc_text(PAGE, FspFileNodeAcquireExclusiveF) #pragma alloc_text(PAGE, FspFileNodeAcquireExclusiveF)
@ -100,6 +102,9 @@ VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode)
FspDeviceDereference(FileNode->FsvolDeviceObject); FspDeviceDereference(FileNode->FsvolDeviceObject);
if (0 != FileNode->ExternalFileName)
FspFree(FileNode->ExternalFileName);
ExDeleteResourceLite(&FileNode->NonPaged->PagingIoResource); ExDeleteResourceLite(&FileNode->NonPaged->PagingIoResource);
ExDeleteResourceLite(&FileNode->NonPaged->Resource); ExDeleteResourceLite(&FileNode->NonPaged->Resource);
FspFree(FileNode->NonPaged); FspFree(FileNode->NonPaged);
@ -107,6 +112,17 @@ VOID FspFileNodeDelete(FSP_FILE_NODE *FileNode)
FspFree(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) VOID FspFileNodeAcquireSharedF(FSP_FILE_NODE *FileNode, ULONG Flags)
{ {
PAGED_CODE(); PAGED_CODE();

View File

@ -30,6 +30,7 @@ static NTSTATUS FspFsvolQueryStandardInformation(PFILE_OBJECT FileObject,
static NTSTATUS FspFsvolQueryInformation( static NTSTATUS FspFsvolQueryInformation(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete; FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete;
static FSP_IOP_REQUEST_FINI FspFsvolQueryInformationRequestFini;
static NTSTATUS FspFsvolSetAllocationInformation(PFILE_OBJECT FileObject, static NTSTATUS FspFsvolSetAllocationInformation(PFILE_OBJECT FileObject,
PVOID Buffer, ULONG Length, PVOID Buffer, ULONG Length,
FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response); 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); FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response);
static NTSTATUS FspFsvolSetPositionInformation(PFILE_OBJECT FileObject, static NTSTATUS FspFsvolSetPositionInformation(PFILE_OBJECT FileObject,
PVOID Buffer, ULONG Length); PVOID Buffer, ULONG Length);
static NTSTATUS FspFsvolSetRenameInformation(PFILE_OBJECT FileObject, static NTSTATUS FspFsvolSetRenameInformation(
PVOID Buffer, ULONG Length, PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response); NTSTATUS FspFsvolSetRenameInformationSuccess(
PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response);
static NTSTATUS FspFsvolSetInformation( static NTSTATUS FspFsvolSetInformation(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete; FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete;
static FSP_IOP_REQUEST_FINI FspFsvolInformationRequestFini; static FSP_IOP_REQUEST_FINI FspFsvolSetInformationRequestFini;
FSP_DRIVER_DISPATCH FspQueryInformation; FSP_DRIVER_DISPATCH FspQueryInformation;
FSP_DRIVER_DISPATCH FspSetInformation; FSP_DRIVER_DISPATCH FspSetInformation;
@ -65,25 +67,32 @@ FSP_DRIVER_DISPATCH FspSetInformation;
#pragma alloc_text(PAGE, FspFsvolQueryStandardInformation) #pragma alloc_text(PAGE, FspFsvolQueryStandardInformation)
#pragma alloc_text(PAGE, FspFsvolQueryInformation) #pragma alloc_text(PAGE, FspFsvolQueryInformation)
#pragma alloc_text(PAGE, FspFsvolQueryInformationComplete) #pragma alloc_text(PAGE, FspFsvolQueryInformationComplete)
#pragma alloc_text(PAGE, FspFsvolQueryInformationRequestFini)
#pragma alloc_text(PAGE, FspFsvolSetAllocationInformation) #pragma alloc_text(PAGE, FspFsvolSetAllocationInformation)
#pragma alloc_text(PAGE, FspFsvolSetBasicInformation) #pragma alloc_text(PAGE, FspFsvolSetBasicInformation)
#pragma alloc_text(PAGE, FspFsvolSetDispositionInformation) #pragma alloc_text(PAGE, FspFsvolSetDispositionInformation)
#pragma alloc_text(PAGE, FspFsvolSetEndOfFileInformation) #pragma alloc_text(PAGE, FspFsvolSetEndOfFileInformation)
#pragma alloc_text(PAGE, FspFsvolSetPositionInformation) #pragma alloc_text(PAGE, FspFsvolSetPositionInformation)
#pragma alloc_text(PAGE, FspFsvolSetRenameInformation) #pragma alloc_text(PAGE, FspFsvolSetRenameInformation)
#pragma alloc_text(PAGE, FspFsvolSetRenameInformationSuccess)
#pragma alloc_text(PAGE, FspFsvolSetInformation) #pragma alloc_text(PAGE, FspFsvolSetInformation)
#pragma alloc_text(PAGE, FspFsvolSetInformationComplete) #pragma alloc_text(PAGE, FspFsvolSetInformationComplete)
#pragma alloc_text(PAGE, FspFsvolInformationRequestFini) #pragma alloc_text(PAGE, FspFsvolSetInformationRequestFini)
#pragma alloc_text(PAGE, FspQueryInformation) #pragma alloc_text(PAGE, FspQueryInformation)
#pragma alloc_text(PAGE, FspSetInformation) #pragma alloc_text(PAGE, FspSetInformation)
#endif #endif
enum enum
{ {
/* QueryInformation */
RequestFileNode = 0, RequestFileNode = 0,
RequestInfoChangeNumber = 1, RequestInfoChangeNumber = 1,
RequestAllInformationResult = 2, RequestAllInformationResult = 2,
RequestAllInformationBuffer = 3, RequestAllInformationBuffer = 3,
/* SetInformation */
//RequestFileNode = 0,
RequestDeviceObject = 1,
}; };
static NTSTATUS FspFsvolQueryAllInformation(PFILE_OBJECT FileObject, static NTSTATUS FspFsvolQueryAllInformation(PFILE_OBJECT FileObject,
@ -439,7 +448,7 @@ static NTSTATUS FspFsvolQueryInformation(
FSP_FSCTL_TRANSACT_REQ *Request; FSP_FSCTL_TRANSACT_REQ *Request;
Result = FspIopCreateRequestEx(Irp, FileNameRequired ? &FileNode->FileName : 0, 0, Result = FspIopCreateRequestEx(Irp, FileNameRequired ? &FileNode->FileName : 0, 0,
FspFsvolInformationRequestFini, &Request); FspFsvolQueryInformationRequestFini, &Request);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
{ {
FspFileNodeRelease(FileNode, Full); FspFileNodeRelease(FileNode, Full);
@ -540,6 +549,16 @@ NTSTATUS FspFsvolQueryInformationComplete(
IrpSp->FileObject); 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, static NTSTATUS FspFsvolSetAllocationInformation(PFILE_OBJECT FileObject,
PVOID Buffer, ULONG Length, PVOID Buffer, ULONG Length,
FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response) 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) if (sizeof(FILE_DISPOSITION_INFORMATION) > Length)
return STATUS_INVALID_PARAMETER; 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) else if (0 == Response)
{ {
@ -714,13 +739,175 @@ static NTSTATUS FspFsvolSetPositionInformation(PFILE_OBJECT FileObject,
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
static NTSTATUS FspFsvolSetRenameInformation(PFILE_OBJECT FileObject, static NTSTATUS FspFsvolSetRenameInformation(
PVOID Buffer, ULONG Length, PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response)
{ {
PAGED_CODE(); 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( static NTSTATUS FspFsvolSetInformation(
@ -732,8 +919,13 @@ static NTSTATUS FspFsvolSetInformation(
if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext)) if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext))
return STATUS_INVALID_DEVICE_REQUEST; return STATUS_INVALID_DEVICE_REQUEST;
NTSTATUS Result;
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass; 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; PFILE_OBJECT FileObject = IrpSp->FileObject;
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer; PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
ULONG Length = IrpSp->Parameters.SetFile.Length; ULONG Length = IrpSp->Parameters.SetFile.Length;
@ -759,9 +951,6 @@ static NTSTATUS FspFsvolSetInformation(
case FilePositionInformation: case FilePositionInformation:
Result = FspFsvolSetPositionInformation(FileObject, Buffer, Length); Result = FspFsvolSetPositionInformation(FileObject, Buffer, Length);
return Result; return Result;
case FileRenameInformation:
Result = FspFsvolSetRenameInformation(FileObject, Buffer, Length, 0, 0);
break;
case FileValidDataLengthInformation: case FileValidDataLengthInformation:
Result = STATUS_INVALID_PARAMETER; /* no ValidDataLength support */ Result = STATUS_INVALID_PARAMETER; /* no ValidDataLength support */
return Result; return Result;
@ -782,7 +971,7 @@ static NTSTATUS FspFsvolSetInformation(
ASSERT(FileNode == FileDesc->FileNode); ASSERT(FileNode == FileDesc->FileNode);
Result = FspIopCreateRequestEx(Irp, FileNameRequired ? &FileNode->FileName : 0, 0, Result = FspIopCreateRequestEx(Irp, FileNameRequired ? &FileNode->FileName : 0, 0,
FspFsvolInformationRequestFini, &Request); FspFsvolSetInformationRequestFini, &Request);
if (!NT_SUCCESS(Result)) if (!NT_SUCCESS(Result))
return Result; return Result;
@ -810,9 +999,6 @@ static NTSTATUS FspFsvolSetInformation(
Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length, Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length,
IrpSp->Parameters.SetFile.AdvanceOnly, Request, 0); IrpSp->Parameters.SetFile.AdvanceOnly, Request, 0);
break; break;
case FileRenameInformation:
Result = FspFsvolSetRenameInformation(FileObject, Buffer, Length, Request, 0);
break;
default: default:
ASSERT(0); ASSERT(0);
Result = STATUS_INVALID_PARAMETER; Result = STATUS_INVALID_PARAMETER;
@ -838,6 +1024,14 @@ NTSTATUS FspFsvolSetInformationComplete(
} }
FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass; 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; PFILE_OBJECT FileObject = IrpSp->FileObject;
FSP_FILE_NODE *FileNode = FileObject->FsContext; FSP_FILE_NODE *FileNode = FileObject->FsContext;
PVOID Buffer = Irp->AssociatedIrp.SystemBuffer; PVOID Buffer = Irp->AssociatedIrp.SystemBuffer;
@ -859,9 +1053,6 @@ NTSTATUS FspFsvolSetInformationComplete(
Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length, Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length,
IrpSp->Parameters.SetFile.AdvanceOnly, Request, Response); IrpSp->Parameters.SetFile.AdvanceOnly, Request, Response);
break; break;
case FileRenameInformation:
Result = FspFsvolSetRenameInformation(FileObject, Buffer, Length, Request, Response);
break;
default: default:
ASSERT(0); ASSERT(0);
Result = STATUS_INVALID_PARAMETER; Result = STATUS_INVALID_PARAMETER;
@ -878,14 +1069,18 @@ NTSTATUS FspFsvolSetInformationComplete(
IrpSp->FileObject); 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(); PAGED_CODE();
FSP_FILE_NODE *FileNode = Context[RequestFileNode]; FSP_FILE_NODE *FileNode = Context[RequestFileNode];
PDEVICE_OBJECT FsvolDeviceObject = Context[RequestDeviceObject];
if (0 != FileNode) if (0 != FileNode)
FspFileNodeReleaseOwner(FileNode, Full, Request); FspFileNodeReleaseOwner(FileNode, Full, Request);
if (0 != FsvolDeviceObject)
FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, Request);
} }
NTSTATUS FspQueryInformation( NTSTATUS FspQueryInformation(

View File

@ -39,48 +39,6 @@ NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response
#pragma alloc_text(PAGE, FspIopDispatchComplete) #pragma alloc_text(PAGE, FspIopDispatchComplete)
#endif #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 typedef struct
{ {
FSP_IOP_REQUEST_FINI *RequestFini; FSP_IOP_REQUEST_FINI *RequestFini;

View File

@ -6,6 +6,7 @@
#include <sys/driver.h> #include <sys/driver.h>
VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE_STRING Suffix);
NTSTATUS FspCreateGuid(GUID *Guid); NTSTATUS FspCreateGuid(GUID *Guid);
VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem, VOID FspInitializeSynchronousWorkItem(FSP_SYNCHRONOUS_WORK_ITEM *SynchronousWorkItem,
PWORKER_THREAD_ROUTINE Routine, PVOID Context); PWORKER_THREAD_ROUTINE Routine, PVOID Context);
@ -17,6 +18,7 @@ VOID FspQueueDelayedWorkItem(FSP_DELAYED_WORK_ITEM *DelayedWorkItem, LARGE_INTEG
static KDEFERRED_ROUTINE FspQueueDelayedWorkItemDPC; static KDEFERRED_ROUTINE FspQueueDelayedWorkItemDPC;
#ifdef ALLOC_PRAGMA #ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FspUnicodePathSuffix)
#pragma alloc_text(PAGE, FspCreateGuid) #pragma alloc_text(PAGE, FspCreateGuid)
#pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem) #pragma alloc_text(PAGE, FspInitializeSynchronousWorkItem)
#pragma alloc_text(PAGE, FspExecuteSynchronousWorkItem) #pragma alloc_text(PAGE, FspExecuteSynchronousWorkItem)
@ -25,6 +27,78 @@ static KDEFERRED_ROUTINE FspQueueDelayedWorkItemDPC;
#pragma alloc_text(PAGE, FspQueueDelayedWorkItem) #pragma alloc_text(PAGE, FspQueueDelayedWorkItem)
#endif #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) NTSTATUS FspCreateGuid(GUID *Guid)
{ {
PAGED_CODE(); PAGED_CODE();