Skip to content

Support: use Windows 10 RS1+ API if possible to make moves more atomic #102240

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions llvm/include/llvm/Support/Windows/WindowsSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,17 @@
#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H
#define LLVM_SUPPORT_WINDOWSSUPPORT_H

#if defined(__MINGW32__)
// mingw-w64 tends to define it as 0x0502 in its headers.
#undef _WIN32_WINNT
#undef NTDDI_VERSION
// Expose APIs from Windows 10 RS1. We only require Windows 7 at runtime, so
// make sure that we only use such features optionally, with fallbacks where
// relevant.
#define _WIN32_WINNT 0x0a00
#define NTDDI_VERSION 0x0a000002 // expose APIs from WIN10_RS1
#endif

// Require at least Windows 7 API.
#define _WIN32_WINNT 0x0601
#define WIN32_LEAN_AND_MEAN
#ifndef NOMINMAX
#define NOMINMAX
Expand Down
42 changes: 33 additions & 9 deletions llvm/lib/Support/Windows/Path.inc
Original file line number Diff line number Diff line change
Expand Up @@ -466,21 +466,45 @@ static std::error_code rename_internal(HANDLE FromHandle, const Twine &To,
(ToWide.size() * sizeof(wchar_t)));
FILE_RENAME_INFO &RenameInfo =
*reinterpret_cast<FILE_RENAME_INFO *>(RenameInfoBuf.data());
RenameInfo.ReplaceIfExists = ReplaceIfExists;
RenameInfo.RootDirectory = 0;
RenameInfo.FileNameLength = ToWide.size() * sizeof(wchar_t);
std::copy(ToWide.begin(), ToWide.end(), &RenameInfo.FileName[0]);

SetLastError(ERROR_SUCCESS);
if (!SetFileInformationByHandle(FromHandle, FileRenameInfo, &RenameInfo,
RenameInfoBuf.size())) {
unsigned Error = GetLastError();
if (Error == ERROR_SUCCESS)
Error = ERROR_CALL_NOT_IMPLEMENTED; // Wine doesn't always set error code.
return mapWindowsError(Error);
static const struct {
DWORD dwFlags;
FILE_INFO_BY_HANDLE_CLASS Class;
} kRenameStyles[] = {
{ static_cast<DWORD>(FILE_RENAME_FLAG_POSIX_SEMANTICS | (ReplaceIfExists ? FILE_RENAME_FLAG_REPLACE_IF_EXISTS : 0)), FileRenameInfoEx },
{ 0, FileRenameInfo },
};

DWORD dwError;
for (const auto &style : kRenameStyles) {
if (style.dwFlags)
RenameInfo.Flags = style.dwFlags;
else
RenameInfo.ReplaceIfExists = ReplaceIfExists;

SetLastError(ERROR_SUCCESS);
if (SetFileInformationByHandle(FromHandle, style.Class, &RenameInfo,
RenameInfoBuf.size()))
return std::error_code();

dwError = GetLastError();

// Wine doesn't always set error code.
if (dwError == ERROR_SUCCESS)
dwError = ERROR_CALL_NOT_IMPLEMENTED;

// Retry with a different style if we do not support this style.
if (dwError == ERROR_INVALID_PARAMETER ||
dwError == ERROR_CALL_NOT_IMPLEMENTED)
continue;

return mapWindowsError(dwError);
}

return std::error_code();
return mapWindowsError(dwError);
}

static std::error_code rename_handle(HANDLE FromHandle, const Twine &To) {
Expand Down
Loading