FileRenameInfoEx is already handled by NtSetInformationFile, SetFileInformationByHandle need only pass it through correctly.
As of version 5.3, Apple's Metal Developer Tools are dependent on SetFileInformationByHandle to handle FileRenameInfoEx in this fashion.
From: Michael Stopa michael.stopa@tensorworks.com.au
The documentation is extremely sparse but it would appear that SetFileInformationByHandle should handle FileRenameInfoEx in basically the same manner as FileRenameInfo, the only difference between the two being how they store the switch for replacing an existing file. --- dlls/kernelbase/tests/file.c | 51 ++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+)
diff --git a/dlls/kernelbase/tests/file.c b/dlls/kernelbase/tests/file.c index 18dff0a32ab..d95902638de 100644 --- a/dlls/kernelbase/tests/file.c +++ b/dlls/kernelbase/tests/file.c @@ -29,6 +29,7 @@ #include "wine/test.h"
static HRESULT (WINAPI *pQueryIoRingCapabilities)(IORING_CAPABILITIES *); +static BOOL (WINAPI *pSetFileInformationByHandle)(HANDLE, FILE_INFO_BY_HANDLE_CLASS, void *, DWORD);
static void test_ioring_caps(void) { @@ -46,12 +47,62 @@ static void test_ioring_caps(void) todo_wine ok(hr == S_OK, "got %#lx.\n", hr); }
+static void test_SetFileInformationByHandle(void) +{ + HANDLE handle; + static const WCHAR filename1[] = L"test1"; + static const WCHAR filename2[] = L"test2"; + static const WCHAR filename3[] = L"test3"; + BOOL success; + FILE_RENAME_INFO* renameinfo; + size_t renameinfo_sz; + FILE_RENAME_INFO* renameinfoex; + size_t renameinfoex_sz; + + if (!pQueryIoRingCapabilities) + { + win_skip("QueryIoRingCapabilities is not available, skipping tests.\n"); + return; + } + + SetLastError(0xdeadbeef); + handle = CreateFileW(filename1, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_FLAG_DELETE_ON_CLOSE, 0); + ok(handle != INVALID_HANDLE_VALUE, "CreateFileA error: %lu\n", GetLastError()); + + renameinfo_sz = sizeof(FILE_RENAME_INFO) + sizeof(filename2); + renameinfo = malloc(renameinfo_sz); + ok(renameinfo != NULL, "Out of memory\n"); + memset(renameinfo, 0, renameinfo_sz); + SetLastError(0xdeadbeef); + renameinfo->FileNameLength = lstrlenW(filename2); + memcpy(renameinfo->FileName, filename2, sizeof(filename2)); + success = SetFileInformationByHandle(handle, FileRenameInfo, renameinfo, renameinfo_sz); + ok(success, "SetFileInformationByHandle failed to change filename, error: %lu\n", GetLastError()); + + renameinfoex_sz = sizeof(FILE_RENAME_INFO) + sizeof(filename3); + renameinfoex = malloc(renameinfoex_sz); + ok(renameinfoex != NULL, "Out of memory\n"); + memset(renameinfoex, 0, renameinfoex_sz); + SetLastError(0xdeadbeef); + renameinfoex->FileNameLength = lstrlenW(filename3); + memcpy(renameinfoex->FileName, filename3, sizeof(filename3)); + success = SetFileInformationByHandle(handle, FileRenameInfoEx, renameinfoex, renameinfoex_sz); + todo_wine ok(success, "SetFileInformationByHandle failed to change filename, error: %lu\n", GetLastError()); + + free(renameinfo); + free(renameinfoex); + CloseHandle(handle); +} + START_TEST(file) { HMODULE hmod;
hmod = LoadLibraryA("kernelbase.dll"); pQueryIoRingCapabilities = (void *)GetProcAddress(hmod, "QueryIoRingCapabilities"); + pSetFileInformationByHandle = (void *)GetProcAddress(hmod, "SetFileInformationByHandle");
test_ioring_caps(); + test_SetFileInformationByHandle(); }
From: Michael Stopa michael.stopa@tensorworks.com.au
FileRenameInfoEx is already handled by NtSetInformationFile, SetFileInformationByHandle need only pass it through. --- dlls/kernelbase/file.c | 4 +++- dlls/kernelbase/tests/file.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c index 7d8b6844456..042179a8378 100644 --- a/dlls/kernelbase/file.c +++ b/dlls/kernelbase/file.c @@ -3658,6 +3658,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetFileInformationByHandle( HANDLE file, FILE_INFO status = NtSetInformationFile( file, &io, info, size, FileIoPriorityHintInformation ); break; case FileRenameInfo: + case FileRenameInfoEx: { FILE_RENAME_INFORMATION *rename_info; UNICODE_STRING nt_name; @@ -3673,7 +3674,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetFileInformationByHandle( HANDLE file, FILE_INFO memcpy( rename_info, info, sizeof(*rename_info) ); memcpy( rename_info->FileName, nt_name.Buffer, nt_name.Length + sizeof(WCHAR) ); rename_info->FileNameLength = nt_name.Length; - status = NtSetInformationFile( file, &io, rename_info, size, FileRenameInformation ); + status = NtSetInformationFile( file, &io, rename_info, size, + class == FileRenameInfo ? FileRenameInformation : FileRenameInformationEx ); HeapFree( GetProcessHeap(), 0, rename_info ); } RtlFreeUnicodeString( &nt_name ); diff --git a/dlls/kernelbase/tests/file.c b/dlls/kernelbase/tests/file.c index d95902638de..b567b5d40c2 100644 --- a/dlls/kernelbase/tests/file.c +++ b/dlls/kernelbase/tests/file.c @@ -88,7 +88,7 @@ static void test_SetFileInformationByHandle(void) renameinfoex->FileNameLength = lstrlenW(filename3); memcpy(renameinfoex->FileName, filename3, sizeof(filename3)); success = SetFileInformationByHandle(handle, FileRenameInfoEx, renameinfoex, renameinfoex_sz); - todo_wine ok(success, "SetFileInformationByHandle failed to change filename, error: %lu\n", GetLastError()); + ok(success, "SetFileInformationByHandle failed to change filename, error: %lu\n", GetLastError());
free(renameinfo); free(renameinfoex);
Alfred Agrell (@Alcaro) commented about dlls/kernelbase/tests/file.c:
todo_wine ok(hr == S_OK, "got %#lx.\n", hr);
}
+static void test_SetFileInformationByHandle(void) +{
- HANDLE handle;
- static const WCHAR filename1[] = L"test1";
- static const WCHAR filename2[] = L"test2";
- static const WCHAR filename3[] = L"test3";
- BOOL success;
- FILE_RENAME_INFO* renameinfo;
- size_t renameinfo_sz;
- FILE_RENAME_INFO* renameinfoex;
- size_t renameinfoex_sz;
- if (!pQueryIoRingCapabilities)
What does ioring have to do with FileRenameInfoEx? Even if it happens to be introduced on the right Windows version, it still looks weird.
Alfred Agrell (@Alcaro) commented about dlls/kernelbase/tests/file.c:
- }
- SetLastError(0xdeadbeef);
- handle = CreateFileW(filename1, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_FLAG_DELETE_ON_CLOSE, 0);
- ok(handle != INVALID_HANDLE_VALUE, "CreateFileA error: %lu\n", GetLastError());
- renameinfo_sz = sizeof(FILE_RENAME_INFO) + sizeof(filename2);
- renameinfo = malloc(renameinfo_sz);
- ok(renameinfo != NULL, "Out of memory\n");
- memset(renameinfo, 0, renameinfo_sz);
- SetLastError(0xdeadbeef);
- renameinfo->FileNameLength = lstrlenW(filename2);
- memcpy(renameinfo->FileName, filename2, sizeof(filename2));
- success = SetFileInformationByHandle(handle, FileRenameInfo, renameinfo, renameinfo_sz);
- ok(success, "SetFileInformationByHandle failed to change filename, error: %lu\n", GetLastError());
Maybe also check that the file was actually renamed.
Alfred Agrell (@Alcaro) commented about dlls/kernelbase/tests/file.c:
- success = SetFileInformationByHandle(handle, FileRenameInfo, renameinfo, renameinfo_sz);
- ok(success, "SetFileInformationByHandle failed to change filename, error: %lu\n", GetLastError());
- renameinfoex_sz = sizeof(FILE_RENAME_INFO) + sizeof(filename3);
- renameinfoex = malloc(renameinfoex_sz);
- ok(renameinfoex != NULL, "Out of memory\n");
- memset(renameinfoex, 0, renameinfoex_sz);
- SetLastError(0xdeadbeef);
- renameinfoex->FileNameLength = lstrlenW(filename3);
- memcpy(renameinfoex->FileName, filename3, sizeof(filename3));
- success = SetFileInformationByHandle(handle, FileRenameInfoEx, renameinfoex, renameinfoex_sz);
- ok(success, "SetFileInformationByHandle failed to change filename, error: %lu\n", GetLastError());
- free(renameinfo);
- free(renameinfoex);
- CloseHandle(handle);
Should remove the temp file, so it doesn't ERROR_ALREADY_EXISTS the rename if you run the test twice.