diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc index c4bd5e2472351..d4e8261ae4feb 100644 --- a/llvm/lib/Support/Windows/Path.inc +++ b/llvm/lib/Support/Windows/Path.inc @@ -25,6 +25,7 @@ // These two headers must be included last, and make sure shlobj is required // after Windows.h to make sure it picks up our definition of _WIN32_WINNT #include "llvm/Support/Windows/WindowsSupport.h" +#include #include #include @@ -1387,14 +1388,33 @@ std::error_code remove_directories(const Twine &path, bool IgnoreErrors) { Path16.push_back(0); Path16.push_back(0); - SHFILEOPSTRUCTW shfos = {}; - shfos.wFunc = FO_DELETE; - shfos.pFrom = Path16.data(); - shfos.fFlags = FOF_NO_UI; - - int result = ::SHFileOperationW(&shfos); - if (result != 0 && !IgnoreErrors) - return mapWindowsError(result); + HRESULT HR; + do { + HR = + CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); + if (FAILED(HR)) + break; + auto Uninitialize = make_scope_exit([] { CoUninitialize(); }); + CComPtr FileOp; + HR = FileOp.CoCreateInstance(CLSID_FileOperation); + if (FAILED(HR)) + break; + HR = FileOp->SetOperationFlags(FOF_NO_UI | FOFX_NOCOPYHOOKS); + if (FAILED(HR)) + break; + PIDLIST_ABSOLUTE PIDL = ILCreateFromPathW(Path16.data()); + auto FreePIDL = make_scope_exit([&PIDL] { ILFree(PIDL); }); + CComPtr ShItem; + HR = SHCreateItemFromIDList(PIDL, IID_PPV_ARGS(&ShItem)); + if (FAILED(HR)) + break; + HR = FileOp->DeleteItem(ShItem, NULL); + if (FAILED(HR)) + break; + HR = FileOp->PerformOperations(); + } while (false); + if (FAILED(HR) && !IgnoreErrors) + return mapWindowsError(HRESULT_CODE(HR)); return std::error_code(); }