Index: include/llvm/Support/Path.h =================================================================== --- include/llvm/Support/Path.h +++ include/llvm/Support/Path.h @@ -317,6 +317,14 @@ /// @result True if a home directory is set, false otherwise. bool home_directory(SmallVectorImpl &result); +/// @brief Get the home directory of an arbitrary user. +/// +/// @param user The username to look up the home directory for. Must be null +/// terminated. +/// @param result Holds the resulting path name. +/// @result True if a home directory is set, false otherwise. +bool home_directory(StringRef user, SmallVectorImpl &result); + /// @brief Has root name? /// /// root_name != "" Index: lib/Support/Unix/Path.inc =================================================================== --- lib/Support/Unix/Path.inc +++ lib/Support/Unix/Path.inc @@ -678,6 +678,16 @@ return false; } +bool home_directory(StringRef user, SmallVectorImpl &result) { + result.clear(); + struct passwd *user_entry = ::getpwnam(user.data()); + if (user_entry == nullptr) + return false; + + result.append(user_entry->pw_dir); + return true; +} + } // end namespace path } // end namespace sys Index: lib/Support/Windows/Path.inc =================================================================== --- lib/Support/Windows/Path.inc +++ lib/Support/Windows/Path.inc @@ -27,6 +27,7 @@ // after Windows.h to make sure it picks up our definition of _WIN32_WINNT #include "WindowsSupport.h" #include +#include #undef max @@ -867,6 +868,59 @@ return true; } +bool home_directory(StringRef user, SmallVectorImpl &result) { + char sid_buf[SECURITY_MAX_SID_SIZE]; + SID *sid = reinterpret_cast(sid_buf); + DWORD sid_size = SECURITY_MAX_SID_SIZE; + DWORD cch_referenced_domain = 0; + SID_NAME_USE sid_name_use; + bool success = false; + char *string_sid = nullptr; + std::string reg_path; + HKEY hkey = nullptr; + + ::LookupAccountName(nullptr, user.data(), sid, &sid_size, nullptr, + &cch_referenced_domain, &sid_name_use); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + goto finish; + + result.resize(cch_referenced_domain); + if (!::LookupAccountName(nullptr, user.data(), sid, &sid_size, &result[0], + &cch_referenced_domain, &sid_name_use)) + goto finish; + + if (!ConvertSidToStringSid(sid, &string_sid)) + goto finish; + + reg_path.assign( + "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\"); + reg_path.append(string_sid); + if (RegOpenKey(HKEY_LOCAL_MACHINE, reg_path.c_str(), &hkey) != ERROR_SUCCESS) + goto finish; + + DWORD cbData = 0; + DWORD key_type; + if (RegQueryValueEx(hkey, "ProfileImagePath", NULL, &key_type, NULL, + &cbData) != ERROR_SUCCESS) + goto finish; + + result.resize(cbData); + uint8_t *buf_data = reinterpret_cast(result.data()); + if (RegQueryValueEx(hkey, "ProfileImagePath", NULL, &key_type, buf_data, + &cbData) != ERROR_SUCCESS) + goto finish; + + success = true; + +finish: + if (string_sid) + ::LocalFree(string_sid); + if (hkey) + ::RegCloseKey(hkey); + + return success; +} + } // end namespace path namespace windows {