diff options
Diffstat (limited to 'toolsrc/src/vcpkg_System.cpp')
| -rw-r--r-- | toolsrc/src/vcpkg_System.cpp | 181 |
1 files changed, 142 insertions, 39 deletions
diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 71b4087d2..472f8450f 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -1,39 +1,116 @@ +#include "pch.h" #include "vcpkg_System.h" -#include <iostream> -#include <Windows.h> -#include <regex> +#include "vcpkg_Checks.h" -namespace fs = std::tr2::sys; - -namespace vcpkg {namespace System +namespace vcpkg::System { fs::path get_exe_path_of_current_process() { - wchar_t buf[_MAX_PATH ]; + wchar_t buf[_MAX_PATH]; int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); } + int cmd_execute_clean(const wchar_t* cmd_line) + { + static const std::wstring system_root = *get_environmental_variable(L"SystemRoot"); + static const std::wstring system_32 = system_root + LR"(\system32)"; + static const std::wstring new_PATH = Strings::wformat(LR"(Path=%s;%s;%s\WindowsPowerShell\v1.0\)", system_32, system_root, system_32); + + std::vector<std::wstring> env_wstrings = + { + L"ALLUSERSPROFILE", + L"APPDATA", + L"CommonProgramFiles", + L"CommonProgramFiles(x86)", + L"CommonProgramW6432", + L"COMPUTERNAME", + L"ComSpec", + L"HOMEDRIVE", + L"HOMEPATH", + L"LOCALAPPDATA", + L"LOGONSERVER", + L"NUMBER_OF_PROCESSORS", + L"OS", + L"PATHEXT", + L"PROCESSOR_ARCHITECTURE", + L"PROCESSOR_IDENTIFIER", + L"PROCESSOR_LEVEL", + L"PROCESSOR_REVISION", + L"ProgramData", + L"ProgramFiles", + L"ProgramFiles(x86)", + L"ProgramW6432", + L"PROMPT", + L"PSModulePath", + L"PUBLIC", + L"SystemDrive", + L"SystemRoot", + L"TEMP", + L"TMP", + L"USERDNSDOMAIN", + L"USERDOMAIN", + L"USERDOMAIN_ROAMINGPROFILE", + L"USERNAME", + L"USERPROFILE", + L"windir", + // Enables proxy information to be passed to Curl, the underlying download library in cmake.exe + L"HTTP_PROXY", + L"HTTPS_PROXY", + }; + + // Flush stdout before launching external process + _flushall(); + + std::vector<const wchar_t*> env_cstr; + env_cstr.reserve(env_wstrings.size() + 2); + + for (auto&& env_wstring : env_wstrings) + { + auto v = System::get_environmental_variable(env_wstring.c_str()); + if (v == nullptr || v->empty()) + continue; + + env_wstring.push_back(L'='); + env_wstring.append(*v); + env_cstr.push_back(env_wstring.c_str()); + } + + env_cstr.push_back(new_PATH.c_str()); + env_cstr.push_back(nullptr); + + // Basically we are wrapping it in quotes + const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); + auto exit_code = _wspawnlpe(_P_WAIT, L"cmd.exe", L"cmd.exe", L"/c", actual_cmd_line.c_str(), nullptr, env_cstr.data()); + return static_cast<int>(exit_code); + } + int cmd_execute(const wchar_t* cmd_line) { + // Flush stdout before launching external process + _flushall(); + // Basically we are wrapping it in quotes - const std::wstring& actual_cmd_line = Strings::format(LR"###("%s")###", cmd_line); + const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); int exit_code = _wsystem(actual_cmd_line.c_str()); return exit_code; } exit_code_and_output cmd_execute_and_capture_output(const wchar_t* cmd_line) { - const std::wstring& actual_cmd_line = Strings::format(LR"###("%s")###", cmd_line); + // Flush stdout before launching external process + fflush(stdout); + + const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); std::string output; char buf[1024]; auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); if (pipe == nullptr) { - return {1, output}; + return { 1, output }; } while (fgets(buf, 1024, pipe)) { @@ -41,24 +118,35 @@ namespace vcpkg {namespace System } if (!feof(pipe)) { - return {1, output}; + return { 1, output }; } auto ec = _pclose(pipe); - return {ec, output}; + return { ec, output }; + } + + std::wstring create_powershell_script_cmd(const fs::path& script_path) + { + return create_powershell_script_cmd(script_path, L""); + } + + std::wstring create_powershell_script_cmd(const fs::path& script_path, const std::wstring& args) + { + // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned + return Strings::wformat(LR"(powershell -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.native(), args); } void print(const char* message) { - std::cout << message; + fputs(message, stdout); } void println(const char* message) { print(message); - std::cout << "\n"; + putchar('\n'); } - void print(color c, const char* message) + void print(const color c, const char* message) { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); @@ -66,46 +154,61 @@ namespace vcpkg {namespace System GetConsoleScreenBufferInfo(hConsole, &consoleScreenBufferInfo); auto original_color = consoleScreenBufferInfo.wAttributes; - SetConsoleTextAttribute(hConsole, static_cast<int>(c) | (original_color & 0xF0)); - std::cout << message; + SetConsoleTextAttribute(hConsole, static_cast<WORD>(c) | (original_color & 0xF0)); + print(message); SetConsoleTextAttribute(hConsole, original_color); } - void println(color c, const char* message) + void println(const color c, const char* message) { print(c, message); - std::cout << "\n"; + putchar('\n'); } - std::wstring wdupenv_str(const wchar_t* varname) noexcept + optional<std::wstring> get_environmental_variable(const wchar_t* varname) noexcept { - std::wstring ret; - wchar_t* buffer; - _wdupenv_s(&buffer, nullptr, varname); - if (buffer != nullptr) - { - ret = buffer; - free(buffer); - } + auto sz = GetEnvironmentVariableW(varname, nullptr, 0); + if (sz == 0) + return nullptr; + + auto ret = std::make_unique<std::wstring>(sz, L'\0'); + Checks::check_exit(MAXDWORD >= ret->size()); + auto sz2 = GetEnvironmentVariableW(varname, ret->data(), static_cast<DWORD>(ret->size())); + Checks::check_exit(sz2 + 1 == sz); + ret->pop_back(); return ret; } - void Stopwatch::start() + void set_environmental_variable(const wchar_t* varname, const wchar_t* varvalue) noexcept { - static_assert(sizeof(start_time) == sizeof(LARGE_INTEGER), ""); - - QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&start_time)); + _wputenv_s(varname, varvalue); } - void Stopwatch::stop() + static bool is_string_keytype(DWORD hkey_type) { - QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&end_time)); - QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&freq)); + return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ; } - double Stopwatch::microseconds() const + optional<std::wstring> get_registry_string(HKEY base, const wchar_t* subKey, const wchar_t* valuename) { - return (reinterpret_cast<const LARGE_INTEGER*>(&end_time)->QuadPart - - reinterpret_cast<const LARGE_INTEGER*>(&start_time)->QuadPart) * 1000000.0 / reinterpret_cast<const LARGE_INTEGER*>(&freq)->QuadPart; + HKEY k = nullptr; + LSTATUS ec = RegOpenKeyExW(base, subKey, NULL, KEY_READ, &k); + if (ec != ERROR_SUCCESS) + return nullptr; + + DWORD dwBufferSize = 0; + DWORD dwType = 0; + auto rc = RegQueryValueExW(k, valuename, nullptr, &dwType, nullptr, &dwBufferSize); + if (rc != ERROR_SUCCESS || !is_string_keytype(dwType) || dwBufferSize == 0 || dwBufferSize % sizeof(wchar_t) != 0) + return nullptr; + std::wstring ret; + ret.resize(dwBufferSize / sizeof(wchar_t)); + + rc = RegQueryValueExW(k, valuename, nullptr, &dwType, reinterpret_cast<LPBYTE>(ret.data()), &dwBufferSize); + if (rc != ERROR_SUCCESS || !is_string_keytype(dwType) || dwBufferSize != sizeof(wchar_t) * ret.size()) + return nullptr; + + ret.pop_back(); // remove extra trailing null byte + return std::make_unique<std::wstring>(std::move(ret)); } -}} +} |
