[vcpkg] Refactor RAII registry key manipulation
MODIFY
include/vcpkg_System.h
include/vcpkg_System.h
#pragma once
+#include <Windows.h>
#include "vcpkg_Strings.h"
#include "filesystem_fs.h"
#include "vcpkg_optional.h"
namespace vcpkg::System
{
+ optional<std::wstring> get_registry_string(HKEY base, const wchar_t* subkey, const wchar_t* valuename);
+
fs::path get_exe_path_of_current_process();
struct exit_code_and_output

MODIFY
src/metrics.cpp
src/metrics.cpp
@@ -227,37 +227,11 @@ true
std::wstring GetSQMUser()
{
- LONG err;
-
- struct RAII_HKEY
- {
- HKEY hkey = nullptr;
-
- ~RAII_HKEY()
- {
- if (hkey != nullptr)
- RegCloseKey(hkey);
- }
- } HKCU_SQMClient;
-
- err = RegOpenKeyExW(HKEY_CURRENT_USER, LR"(Software\Microsoft\SQMClient)", NULL, KEY_READ, &HKCU_SQMClient.hkey);
- if (err != ERROR_SUCCESS)
- {
- return L"{}";
- }
-
- std::array<wchar_t, 128> buffer;
- DWORD lType = 0;
- DWORD dwBufferSize = static_cast<DWORD>(buffer.size() * sizeof(wchar_t));
- err = RegQueryValueExW(HKCU_SQMClient.hkey, L"UserId", nullptr, &lType, reinterpret_cast<LPBYTE>(buffer.data()), &dwBufferSize);
- if (err == ERROR_SUCCESS && lType == REG_SZ && dwBufferSize >= sizeof(wchar_t))
- {
- size_t sz = dwBufferSize / sizeof(wchar_t);
- if (buffer[sz - 1] == '\0')
- --sz;
- return std::wstring(buffer.begin(), buffer.begin() + sz);
- }
+ auto hkcu_sqmclient = System::get_registry_string(HKEY_CURRENT_USER, LR"(Software\Microsoft\SQMClient)", L"UserId");
+ if (hkcu_sqmclient)
+ return std::move(*hkcu_sqmclient);
+ else
return L"{}";
}

MODIFY
src/vcpkg_System.cpp
src/vcpkg_System.cpp
@@ -107,4 +107,32 @@ namespace vcpkg::System
{
_wputenv_s(varname, varvalue);
}
+
+ static bool is_string_keytype(DWORD hkey_type)
+ {
+ return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ;
+ }
+
+ optional<std::wstring> get_registry_string(HKEY base, const wchar_t* subKey, const wchar_t* valuename)
+ {
+ 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));
+ }
}

[vcpkg] Refactor RAII registry key manipulation