1dda28197Spatrick //===-- HostInfoWindows.cpp -----------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "lldb/Host/windows/windows.h"
10061da546Spatrick
11061da546Spatrick #include <objbase.h>
12061da546Spatrick
13061da546Spatrick #include <mutex>
14*f6aab3d8Srobert #include <optional>
15061da546Spatrick
16061da546Spatrick #include "lldb/Host/windows/HostInfoWindows.h"
17061da546Spatrick #include "lldb/Host/windows/PosixApi.h"
18061da546Spatrick #include "lldb/Utility/UserIDResolver.h"
19061da546Spatrick #include "llvm/ADT/SmallString.h"
20061da546Spatrick #include "llvm/Support/ConvertUTF.h"
21061da546Spatrick #include "llvm/Support/FileSystem.h"
22061da546Spatrick #include "llvm/Support/ManagedStatic.h"
23061da546Spatrick #include "llvm/Support/Path.h"
24061da546Spatrick #include "llvm/Support/Threading.h"
25061da546Spatrick #include "llvm/Support/raw_ostream.h"
26061da546Spatrick
27061da546Spatrick using namespace lldb_private;
28061da546Spatrick
29061da546Spatrick namespace {
30061da546Spatrick class WindowsUserIDResolver : public UserIDResolver {
31061da546Spatrick protected:
DoGetUserName(id_t uid)32*f6aab3d8Srobert std::optional<std::string> DoGetUserName(id_t uid) override {
33*f6aab3d8Srobert return std::nullopt;
34061da546Spatrick }
DoGetGroupName(id_t gid)35*f6aab3d8Srobert std::optional<std::string> DoGetGroupName(id_t gid) override {
36*f6aab3d8Srobert return std::nullopt;
37061da546Spatrick }
38061da546Spatrick };
39061da546Spatrick } // namespace
40061da546Spatrick
41061da546Spatrick FileSpec HostInfoWindows::m_program_filespec;
42061da546Spatrick
Initialize(SharedLibraryDirectoryHelper * helper)43be691f3bSpatrick void HostInfoWindows::Initialize(SharedLibraryDirectoryHelper *helper) {
44061da546Spatrick ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
45be691f3bSpatrick HostInfoBase::Initialize(helper);
46061da546Spatrick }
47061da546Spatrick
Terminate()48061da546Spatrick void HostInfoWindows::Terminate() {
49061da546Spatrick HostInfoBase::Terminate();
50061da546Spatrick ::CoUninitialize();
51061da546Spatrick }
52061da546Spatrick
GetPageSize()53061da546Spatrick size_t HostInfoWindows::GetPageSize() {
54061da546Spatrick SYSTEM_INFO systemInfo;
55061da546Spatrick GetNativeSystemInfo(&systemInfo);
56061da546Spatrick return systemInfo.dwPageSize;
57061da546Spatrick }
58061da546Spatrick
GetOSVersion()59061da546Spatrick llvm::VersionTuple HostInfoWindows::GetOSVersion() {
60061da546Spatrick OSVERSIONINFOEX info;
61061da546Spatrick
62061da546Spatrick ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
63061da546Spatrick info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
64061da546Spatrick #pragma warning(push)
65061da546Spatrick #pragma warning(disable : 4996)
66061da546Spatrick // Starting with Microsoft SDK for Windows 8.1, this function is deprecated
67061da546Spatrick // in favor of the new Windows Version Helper APIs. Since we don't specify a
68061da546Spatrick // minimum SDK version, it's easier to simply disable the warning rather than
69061da546Spatrick // try to support both APIs.
70061da546Spatrick if (GetVersionEx((LPOSVERSIONINFO)&info) == 0)
71061da546Spatrick return llvm::VersionTuple();
72061da546Spatrick #pragma warning(pop)
73061da546Spatrick
74061da546Spatrick return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion,
75061da546Spatrick info.wServicePackMajor);
76061da546Spatrick }
77061da546Spatrick
GetOSBuildString()78*f6aab3d8Srobert std::optional<std::string> HostInfoWindows::GetOSBuildString() {
79061da546Spatrick llvm::VersionTuple version = GetOSVersion();
80061da546Spatrick if (version.empty())
81*f6aab3d8Srobert return std::nullopt;
82061da546Spatrick
83*f6aab3d8Srobert return "Windows NT " + version.getAsString();
84061da546Spatrick }
85061da546Spatrick
GetOSKernelDescription()86*f6aab3d8Srobert std::optional<std::string> HostInfoWindows::GetOSKernelDescription() {
87*f6aab3d8Srobert return GetOSBuildString();
88061da546Spatrick }
89061da546Spatrick
GetHostname(std::string & s)90061da546Spatrick bool HostInfoWindows::GetHostname(std::string &s) {
91061da546Spatrick wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1];
92061da546Spatrick DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
93061da546Spatrick if (!::GetComputerNameW(buffer, &dwSize))
94061da546Spatrick return false;
95061da546Spatrick
96061da546Spatrick // The conversion requires an empty string.
97061da546Spatrick s.clear();
98061da546Spatrick return llvm::convertWideToUTF8(buffer, s);
99061da546Spatrick }
100061da546Spatrick
GetProgramFileSpec()101061da546Spatrick FileSpec HostInfoWindows::GetProgramFileSpec() {
102061da546Spatrick static llvm::once_flag g_once_flag;
103061da546Spatrick llvm::call_once(g_once_flag, []() {
104061da546Spatrick std::vector<wchar_t> buffer(PATH_MAX);
105061da546Spatrick ::GetModuleFileNameW(NULL, buffer.data(), buffer.size());
106061da546Spatrick std::string path;
107061da546Spatrick llvm::convertWideToUTF8(buffer.data(), path);
108061da546Spatrick m_program_filespec.SetFile(path, FileSpec::Style::native);
109061da546Spatrick });
110061da546Spatrick return m_program_filespec;
111061da546Spatrick }
112061da546Spatrick
GetDefaultShell()113061da546Spatrick FileSpec HostInfoWindows::GetDefaultShell() {
114061da546Spatrick // Try to retrieve ComSpec from the environment. On the rare occasion
115061da546Spatrick // that it fails, try a well-known path for ComSpec instead.
116061da546Spatrick
117061da546Spatrick std::string shell;
118061da546Spatrick if (GetEnvironmentVar("ComSpec", shell))
119061da546Spatrick return FileSpec(shell);
120061da546Spatrick
121061da546Spatrick return FileSpec("C:\\Windows\\system32\\cmd.exe");
122061da546Spatrick }
123061da546Spatrick
GetEnvironmentVar(const std::string & var_name,std::string & var)124061da546Spatrick bool HostInfoWindows::GetEnvironmentVar(const std::string &var_name,
125061da546Spatrick std::string &var) {
126061da546Spatrick std::wstring wvar_name;
127061da546Spatrick if (!llvm::ConvertUTF8toWide(var_name, wvar_name))
128061da546Spatrick return false;
129061da546Spatrick
130061da546Spatrick if (const wchar_t *wvar = _wgetenv(wvar_name.c_str()))
131061da546Spatrick return llvm::convertWideToUTF8(wvar, var);
132061da546Spatrick return false;
133061da546Spatrick }
134061da546Spatrick
135061da546Spatrick static llvm::ManagedStatic<WindowsUserIDResolver> g_user_id_resolver;
136061da546Spatrick
GetUserIDResolver()137061da546Spatrick UserIDResolver &HostInfoWindows::GetUserIDResolver() {
138061da546Spatrick return *g_user_id_resolver;
139061da546Spatrick }
140