mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 00:43:00 -05:00
sys: IRP_MJ_SET_INFORMATION: FileRenameInformation
This commit is contained in:
parent
ed483c99d9
commit
cc19ddcd92
@ -81,7 +81,7 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
|||||||
NTSTATUS (*Rename)(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS (*Rename)(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
PVOID FileNode,
|
PVOID FileNode,
|
||||||
PWSTR ExistingFileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists);
|
PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists);
|
||||||
} FSP_FILE_SYSTEM_INTERFACE;
|
} FSP_FILE_SYSTEM_INTERFACE;
|
||||||
typedef struct _FSP_FILE_SYSTEM
|
typedef struct _FSP_FILE_SYSTEM
|
||||||
{
|
{
|
||||||
|
@ -795,7 +795,10 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
|||||||
FSP_FILE_NODE *TargetFileNode = 0 != TargetFileObject ?
|
FSP_FILE_NODE *TargetFileNode = 0 != TargetFileObject ?
|
||||||
TargetFileObject->FsContext : 0;
|
TargetFileObject->FsContext : 0;
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||||
|
UNICODE_STRING Remain, Suffix;
|
||||||
UNICODE_STRING NewFileName;
|
UNICODE_STRING NewFileName;
|
||||||
|
PUINT8 NewFileNameBuffer;
|
||||||
|
BOOLEAN AppendBackslash;
|
||||||
|
|
||||||
ASSERT(FileNode == FileDesc->FileNode);
|
ASSERT(FileNode == FileDesc->FileNode);
|
||||||
|
|
||||||
@ -818,49 +821,41 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
|||||||
FspFsvolDeviceFileRenameAcquireExclusive(FsvolDeviceObject);
|
FspFsvolDeviceFileRenameAcquireExclusive(FsvolDeviceObject);
|
||||||
FspFileNodeAcquireExclusive(FileNode, Full);
|
FspFileNodeAcquireExclusive(FileNode, Full);
|
||||||
|
|
||||||
if (L'\\' == Info->FileName[0])
|
if (0 != TargetFileNode)
|
||||||
{
|
Remain = TargetFileNode->FileName;
|
||||||
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
|
else
|
||||||
{
|
|
||||||
UNICODE_STRING Remain, Suffix;
|
|
||||||
|
|
||||||
FspUnicodePathSuffix(&FileNode->FileName, &Remain, &Suffix);
|
FspUnicodePathSuffix(&FileNode->FileName, &Remain, &Suffix);
|
||||||
|
|
||||||
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName,
|
Suffix.Length = Suffix.MaximumLength = (USHORT)Info->FileNameLength;
|
||||||
Remain.Length + sizeof(WCHAR) + Info->FileNameLength + sizeof(WCHAR),
|
Suffix.Buffer = Info->FileName;
|
||||||
FspFsvolSetInformationRequestFini, &Request);
|
if (L'\\' == Suffix.Buffer[0])
|
||||||
if (!NT_SUCCESS(Result))
|
FspUnicodePathSuffix(&Suffix, &NewFileName, &Suffix);
|
||||||
goto unlock_exit;
|
|
||||||
|
|
||||||
Request->Req.SetInformation.Info.Rename.NewFileName.Size =
|
AppendBackslash = sizeof(WCHAR) < Remain.Length;
|
||||||
(UINT16)(Remain.Length + sizeof(WCHAR) + Info->FileNameLength + sizeof(WCHAR));
|
NewFileName.Length = NewFileName.MaximumLength =
|
||||||
|
Remain.Length + AppendBackslash * sizeof(WCHAR) + Suffix.Length;
|
||||||
|
|
||||||
RtlCopyMemory(Request->Buffer + Request->FileName.Size,
|
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName,
|
||||||
Remain.Buffer, Remain.Length);
|
NewFileName.Length + sizeof(WCHAR),
|
||||||
*(PWSTR)(Request->Buffer + Request->FileName.Size + Remain.Length) = L'\\';
|
FspFsvolSetInformationRequestFini, &Request);
|
||||||
RtlCopyMemory(Request->Buffer + Request->FileName.Size + Remain.Length + sizeof(WCHAR),
|
if (!NT_SUCCESS(Result))
|
||||||
Info->FileName, Info->FileNameLength);
|
goto unlock_exit;
|
||||||
}
|
|
||||||
|
|
||||||
*(PWSTR)(Request->Buffer + Request->Req.SetInformation.Info.Rename.NewFileName.Size) = L'\0';
|
NewFileNameBuffer = Request->Buffer + Request->FileName.Size;
|
||||||
|
NewFileName.Buffer = (PVOID)NewFileNameBuffer;
|
||||||
|
|
||||||
|
RtlCopyMemory(NewFileNameBuffer, Remain.Buffer, Remain.Length);
|
||||||
|
*(PWSTR)(NewFileNameBuffer + Remain.Length) = L'\\';
|
||||||
|
RtlCopyMemory(NewFileNameBuffer + Remain.Length + AppendBackslash * sizeof(WCHAR),
|
||||||
|
Suffix.Buffer, Suffix.Length);
|
||||||
|
*(PWSTR)(NewFileNameBuffer + NewFileName.Length) = L'\0';
|
||||||
|
|
||||||
Request->Kind = FspFsctlTransactSetInformationKind;
|
Request->Kind = FspFsctlTransactSetInformationKind;
|
||||||
Request->Req.SetInformation.UserContext = FileNode->UserContext;
|
Request->Req.SetInformation.UserContext = FileNode->UserContext;
|
||||||
Request->Req.SetInformation.UserContext2 = FileDesc->UserContext2;
|
Request->Req.SetInformation.UserContext2 = FileDesc->UserContext2;
|
||||||
Request->Req.SetInformation.FileInformationClass = FileRenameInformation;
|
Request->Req.SetInformation.FileInformationClass = FileRenameInformation;
|
||||||
Request->Req.SetInformation.Info.Rename.NewFileName.Offset = Request->FileName.Size;
|
Request->Req.SetInformation.Info.Rename.NewFileName.Offset = Request->FileName.Size;
|
||||||
|
Request->Req.SetInformation.Info.Rename.NewFileName.Size = NewFileName.Length + sizeof(WCHAR);
|
||||||
Request->Req.SetInformation.Info.Rename.ReplaceIfExists = ReplaceIfExists;
|
Request->Req.SetInformation.Info.Rename.ReplaceIfExists = ReplaceIfExists;
|
||||||
|
|
||||||
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request);
|
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request);
|
||||||
@ -879,10 +874,6 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
|||||||
* that has open handles (except in the batch-oplock case described earlier).
|
* 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;
|
Result = STATUS_SUCCESS;
|
||||||
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
FspFsvolDeviceLockContextTable(FsvolDeviceObject);
|
||||||
if (FileNode->IsDirectory)
|
if (FileNode->IsDirectory)
|
||||||
|
@ -95,6 +95,8 @@ VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE
|
|||||||
|
|
||||||
Remain->Length = Remain->MaximumLength = (USHORT)((PUINT8)RemainEnd - (PUINT8)PathBgn);
|
Remain->Length = Remain->MaximumLength = (USHORT)((PUINT8)RemainEnd - (PUINT8)PathBgn);
|
||||||
Remain->Buffer = PathBgn;
|
Remain->Buffer = PathBgn;
|
||||||
|
if (0 == Remain->Length && PathBgn < PathEnd && L'\\' == *PathBgn)
|
||||||
|
Remain->Length = Remain->MaximumLength = sizeof(WCHAR);
|
||||||
Suffix->Length = Suffix->MaximumLength = (USHORT)((PUINT8)PathEnd - (PUINT8)SuffixBgn);
|
Suffix->Length = Suffix->MaximumLength = (USHORT)((PUINT8)PathEnd - (PUINT8)SuffixBgn);
|
||||||
Suffix->Buffer = SuffixBgn;
|
Suffix->Buffer = SuffixBgn;
|
||||||
}
|
}
|
||||||
|
@ -502,10 +502,45 @@ NTSTATUS CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
||||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||||
PVOID FileNode,
|
PVOID FileNode0,
|
||||||
PWSTR ExistingFileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists)
|
PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists)
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_DEVICE_REQUEST;
|
MEMFS *Memfs = (MEMFS *)FileSystem->UserContext;
|
||||||
|
MEMFS_FILE_NODE *FileNode = (MEMFS_FILE_NODE *)FileNode0;
|
||||||
|
MEMFS_FILE_NODE *NewFileNode;
|
||||||
|
BOOLEAN Inserted;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
assert(0 == FileName || 0 == wcscmp(FileNode->FileName, FileName));
|
||||||
|
|
||||||
|
if (MAX_PATH <= wcslen(NewFileName))
|
||||||
|
return STATUS_OBJECT_NAME_INVALID;
|
||||||
|
|
||||||
|
NewFileNode = MemfsFileNodeMapGet(Memfs->FileNodeMap, NewFileName);
|
||||||
|
if (0 != NewFileNode)
|
||||||
|
{
|
||||||
|
if (NewFileNode->FileInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||||
|
return STATUS_ACCESS_DENIED;
|
||||||
|
|
||||||
|
if (ReplaceIfExists)
|
||||||
|
return STATUS_OBJECT_NAME_COLLISION;
|
||||||
|
|
||||||
|
NewFileNode->RefCount++;
|
||||||
|
MemfsFileNodeMapRemove(Memfs->FileNodeMap, NewFileNode);
|
||||||
|
if (0 == --NewFileNode->RefCount)
|
||||||
|
MemfsFileNodeDelete(NewFileNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemfsFileNodeMapRemove(Memfs->FileNodeMap, FileNode);
|
||||||
|
wcscpy_s(FileNode->FileName, sizeof FileNode->FileName / sizeof(WCHAR), NewFileName);
|
||||||
|
Result = MemfsFileNodeMapInsert(Memfs->FileNodeMap, FileNode, &Inserted);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspDebugLog(__FUNCTION__ ": cannot insert into FileNodeMap; aborting\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user