[llvm] Support: unlock Windows API support, switch to Windows 10 RS1+ APIs (PR #102240)

Martin Storsjö via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 14 00:31:23 PDT 2024


================
@@ -466,21 +466,42 @@ 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 },
+  };
+
+  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();
+
+    DWORD 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)
+      return mapWindowsError(dwError);
   }
 
-  return std::error_code();
+  llvm_unreachable();
----------------
mstorsjo wrote:

Hmm, if the second attempt still fails, and if it happens to fail with `ERROR_CALL_NOT_IMPLEMENTED ` (which according to comments could happen on Wine, at least at some point in time), we'll hit the `llvm_unreachable()` here. So should we move the `DWORD dwError` outside of the loop and return `mapWindowsError(dwError)` here too?

https://github.com/llvm/llvm-project/pull/102240


More information about the llvm-commits mailing list