carb/extras/WindowsPath.h
File members: carb/extras/WindowsPath.h
// Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
//
// NVIDIA CORPORATION and its licensors retain all intellectual property
// and proprietary rights in and to this software, related documentation
// and any modifications thereto. Any use, reproduction, disclosure or
// distribution of this software and related documentation without an express
// license agreement from NVIDIA CORPORATION is strictly prohibited.
//
#pragma once
#include "../Defines.h"
#if CARB_PLATFORM_WINDOWS || defined(DOXYGEN_BUILD)
# include "../CarbWindows.h"
# include "../Error.h"
# include "Unicode.h"
# include <algorithm>
# include <string>
namespace carb
{
namespace extras
{
std::wstring convertCarboniteToWindowsPath(const std::string& path);
std::string convertWindowsToCarbonitePath(const std::wstring& pathW);
std::wstring fixWindowsPathPrefix(const std::wstring& pathW);
std::wstring getWindowsCanonicalPath(const std::wstring& pathW);
std::wstring getWindowsFullPath(const std::wstring& pathW);
void adjustWindowsDllSearchPaths();
//
// Implementations
//
inline std::wstring convertCarboniteToWindowsPath(const std::string& path)
{
std::wstring pathW = convertUtf8ToWide(path);
if (pathW == kUnicodeToWideFailure)
{
ErrorApi::instance().setError(kResultFail);
return L"";
}
std::replace(pathW.begin(), pathW.end(), L'/', L'\\');
return fixWindowsPathPrefix(pathW);
}
inline std::string convertWindowsToCarbonitePath(const std::wstring& pathW)
{
bool hasPrefix = (pathW.compare(0, 4, L"\\\\?\\") == 0);
std::string path = convertWideToUtf8(pathW.c_str() + (hasPrefix ? 4 : 0));
if (path == kUnicodeToUtf8Failure)
{
ErrorApi::instance().setError(kResultFail);
return "";
}
std::replace(path.begin(), path.end(), '\\', '/');
return path;
}
inline std::wstring fixWindowsPathPrefix(const std::wstring& pathW)
{
bool hasPrefix = (pathW.compare(0, 4, L"\\\\?\\") == 0);
if (pathW.size() >= CARBWIN_MAX_PATH && !hasPrefix)
{
return L"\\\\?\\" + pathW;
}
if (pathW.size() < CARBWIN_MAX_PATH && hasPrefix)
{
return pathW.substr(4, pathW.size() - 4);
}
return pathW;
}
inline std::wstring getWindowsCanonicalPath(const std::wstring& pathW)
{
wchar_t* canonical = nullptr;
auto hr = PathAllocCanonicalize(pathW.c_str(), CARBWIN_PATHCCH_ALLOW_LONG_PATHS, &canonical);
if (CARBWIN_SUCCEEDED(hr))
{
std::wstring result = canonical;
LocalFree(canonical);
return result;
}
ErrorApi::instance().setError(
omni::core::kResultFail, omni::string{ omni::formatted, "PathAllocCanonicalize failed with HRESULT 0x%08x", hr });
return pathW;
}
inline std::wstring getWindowsFullPath(const std::wstring& pathW)
{
// Retrieve the size
DWORD size = GetFullPathNameW(pathW.c_str(), 0, nullptr, nullptr);
if (size != 0)
{
std::wstring fullPathName(size - 1, '\0');
size = GetFullPathNameW(pathW.c_str(), size, &fullPathName[0], nullptr);
if (size)
{
// Assert if the Win32 API lied to us. Note that sometimes it does use less than asked for.
CARB_ASSERT(size <= fullPathName.size());
fullPathName.resize(size);
return fullPathName;
}
}
ErrorApi::setFromWinApiErrorCode();
return pathW;
}
inline void adjustWindowsDllSearchPaths()
{
// MSDN:
// https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-setdefaultdlldirectories
// LOAD_LIBRARY_SEARCH_DEFAULT_DIRS
// This value is a combination of LOAD_LIBRARY_SEARCH_APPLICATION_DIR, LOAD_LIBRARY_SEARCH_SYSTEM32, and
// LOAD_LIBRARY_SEARCH_USER_DIRS.
SetDefaultDllDirectories(CARBWIN_LOAD_LIBRARY_SEARCH_DEFAULT_DIRS);
}
} // namespace extras
} // namespace carb
#endif