sys: IRP_MJ_SET_INFORMATION: FileRenameInformation

This commit is contained in:
Bill Zissimopoulos 2016-02-10 10:48:27 -08:00
parent ed483c99d9
commit cc19ddcd92
4 changed files with 67 additions and 39 deletions

View File

@ -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
{

View File

@ -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)

View File

@ -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;
}

View File

@ -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 =