剛開始,遇到的問題是權限不足,
後來才知道開檔案的時候要多加DELETE的權限.
之後就遇到無法Create目錄的Handle.
查MSND才知道要用FILE_FLAG_BACKUP_SEMANTICS去Create目錄的HANDLE.
才再試著改寫成, 不要直接使用CreateFile這個API,
改使用ntdll的NtCreateFile.
於是就有了以下的source codes了.
而使用方式是 XRenameFile(L"\\??\\C:\\old.txt", L"\\??\\C:\\new.txt");
大致上在64bits Win10 user mode下測試是workable的.
BOOLEAN XRenameFile(PWCHAR OldName, PWCHAR NewName)
{
NTSTATUS ntStatus;
OBJECT_ATTRIBUTES objectAttributes;
HANDLE fileHandle;
IO_STATUS_BLOCK ioStatus;
PCHAR renameInformationBuffer;
ULONG newNameLength;
PFILE_RENAME_INFORMATION renameInformation;
UNICODE_STRING OldNameUS;
if (OldName == NULL || NewName == NULL) {
return FALSE;
}
OldNameUS.Buffer = OldName;
OldNameUS.Length = wcslen(OldName) * 2;
OldNameUS.MaximumLength = OldNameUS.Length + 2;
newNameLength = wcslen(NewName) * 2;
renameInformationBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, (sizeof(FILE_RENAME_INFORMATION) + newNameLength));
if (renameInformationBuffer==NULL) {
return FALSE;
}
#if 1
InitializeObjectAttributes(&objectAttributes,
&OldNameUS,
0,
NULL,
NULL);
ntStatus = NtCreateFile(&fileHandle,
(DELETE | SYNCHRONIZE),
&objectAttributes,
&ioStatus,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if (!NT_SUCCESS(ntStatus)) {
RtlFreeHeap(RtlGetProcessHeap(), 0, renameInformationBuffer);
return FALSE;
}
#else
fileHandle = CreateFile(OldName,
( DELETE | SYNCHRONIZE),
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (INVALID_HANDLE_VALUE == fileHandle) {
return FALSE;
}
#endif
renameInformation = (PFILE_RENAME_INFORMATION)renameInformationBuffer;
renameInformation->ReplaceIfExists = 1;
renameInformation->RootDirectory = 0;
renameInformation->FileNameLength = newNameLength;
wcscpy(renameInformation->FileName, NewName);
ntStatus = NtSetInformationFile(fileHandle, &ioStatus, renameInformation,
sizeof(FILE_RENAME_INFORMATION) + newNameLength,
FileRenameInformation);
NtClose(fileHandle);
RtlFreeHeap(RtlGetProcessHeap(), 0, renameInformationBuffer);
return NT_SUCCESS(ntStatus);
}