mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-22 16:33:02 -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,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||
PVOID FileNode,
|
||||
PWSTR ExistingFileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists);
|
||||
PWSTR FileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists);
|
||||
} FSP_FILE_SYSTEM_INTERFACE;
|
||||
typedef struct _FSP_FILE_SYSTEM
|
||||
{
|
||||
|
@ -795,7 +795,10 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
||||
FSP_FILE_NODE *TargetFileNode = 0 != TargetFileObject ?
|
||||
TargetFileObject->FsContext : 0;
|
||||
FSP_FSCTL_TRANSACT_REQ *Request;
|
||||
UNICODE_STRING Remain, Suffix;
|
||||
UNICODE_STRING NewFileName;
|
||||
PUINT8 NewFileNameBuffer;
|
||||
BOOLEAN AppendBackslash;
|
||||
|
||||
ASSERT(FileNode == FileDesc->FileNode);
|
||||
|
||||
@ -818,49 +821,41 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
||||
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);
|
||||
}
|
||||
if (0 != TargetFileNode)
|
||||
Remain = TargetFileNode->FileName;
|
||||
else
|
||||
{
|
||||
UNICODE_STRING Remain, Suffix;
|
||||
|
||||
FspUnicodePathSuffix(&FileNode->FileName, &Remain, &Suffix);
|
||||
|
||||
Suffix.Length = Suffix.MaximumLength = (USHORT)Info->FileNameLength;
|
||||
Suffix.Buffer = Info->FileName;
|
||||
if (L'\\' == Suffix.Buffer[0])
|
||||
FspUnicodePathSuffix(&Suffix, &NewFileName, &Suffix);
|
||||
|
||||
AppendBackslash = sizeof(WCHAR) < Remain.Length;
|
||||
NewFileName.Length = NewFileName.MaximumLength =
|
||||
Remain.Length + AppendBackslash * sizeof(WCHAR) + Suffix.Length;
|
||||
|
||||
Result = FspIopCreateRequestEx(Irp, &FileNode->FileName,
|
||||
Remain.Length + sizeof(WCHAR) + Info->FileNameLength + sizeof(WCHAR),
|
||||
NewFileName.Length + 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));
|
||||
NewFileNameBuffer = Request->Buffer + Request->FileName.Size;
|
||||
NewFileName.Buffer = (PVOID)NewFileNameBuffer;
|
||||
|
||||
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';
|
||||
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->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.NewFileName.Size = NewFileName.Length + sizeof(WCHAR);
|
||||
Request->Req.SetInformation.Info.Rename.ReplaceIfExists = ReplaceIfExists;
|
||||
|
||||
FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request);
|
||||
@ -879,10 +874,6 @@ static NTSTATUS FspFsvolSetRenameInformation(
|
||||
* 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)
|
||||
|
@ -95,6 +95,8 @@ VOID FspUnicodePathSuffix(PUNICODE_STRING Path, PUNICODE_STRING Remain, PUNICODE
|
||||
|
||||
Remain->Length = Remain->MaximumLength = (USHORT)((PUINT8)RemainEnd - (PUINT8)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->Buffer = SuffixBgn;
|
||||
}
|
||||
|
@ -502,10 +502,45 @@ NTSTATUS CanDelete(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
||||
NTSTATUS Rename(FSP_FILE_SYSTEM *FileSystem,
|
||||
FSP_FSCTL_TRANSACT_REQ *Request,
|
||||
PVOID FileNode,
|
||||
PWSTR ExistingFileName, PWSTR NewFileName, BOOLEAN ReplaceIfExists)
|
||||
PVOID FileNode0,
|
||||
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 =
|
||||
|
Loading…
x
Reference in New Issue
Block a user