From ccdd7acd0bfa191965d8bd7596fa4ba82d321d54 Mon Sep 17 00:00:00 2001 From: Benjamin Thaut Date: Mon, 27 Aug 2018 14:02:16 +0200 Subject: [PATCH] Avoid rare deadlock inside SHCreateDirectoyExW. Replace call to SHCreateDirectoyExW on the win32 platform with multiple calls to CreateDirectoryW to avoid deadlock within CoUninitialize which is called from SHCreateDirectoyExW. MSDN states that calling CoInitialize during DllMain is prohibited. SHCreateDirectoyExW internally calls CoInitialize, thus calling SHCreateDirectoyExW inside the DllMain is prohibited as well. --- renderdoc/os/win32/win32_stringio.cpp | 31 ++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/renderdoc/os/win32/win32_stringio.cpp b/renderdoc/os/win32/win32_stringio.cpp index 3109e33f4..7c7fe7a0c 100644 --- a/renderdoc/os/win32/win32_stringio.cpp +++ b/renderdoc/os/win32/win32_stringio.cpp @@ -240,7 +240,36 @@ void CreateParentDirectory(const string &filename) if(wfn[i] == L'/') wfn[i] = L'\\'; - SHCreateDirectoryExW(NULL, wfn.c_str(), NULL); + // Remove trailing \\s + size_t trailingSeperatorPos = wfn.find_last_of(L'\\'); + while(trailingSeperatorPos == wfn.length() - 1) + { + wfn.erase(trailingSeperatorPos); + trailingSeperatorPos = wfn.find_last_of(L'\\'); + } + + // Find all directories we need to create + std::vector directoriesToCreate; + while(!wfn.empty()) + { + DWORD fileAttributes = GetFileAttributesW(wfn.c_str()); + if(fileAttributes != INVALID_FILE_ATTRIBUTES) + break; + + directoriesToCreate.push_back(wfn); + + size_t seperatorPos = wfn.find_last_of(L'\\'); + if(seperatorPos == string::npos) + break; + else + wfn = wfn.substr(0, seperatorPos); + } + + // Create the directories in reverse order + for(ptrdiff_t i = directoriesToCreate.size() - 1; i >= 0; i--) + { + CreateDirectoryW(directoriesToCreate[i].c_str(), NULL); + } } string GetReplayAppFilename()