1 | //===-- HostInfoWindows.cpp -----------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "lldb/Host/windows/windows.h" |
10 | |
11 | #include <objbase.h> |
12 | |
13 | #include <mutex> |
14 | #include <optional> |
15 | |
16 | #include "lldb/Host/windows/HostInfoWindows.h" |
17 | #include "lldb/Host/windows/PosixApi.h" |
18 | #include "lldb/Utility/UserIDResolver.h" |
19 | #include "llvm/ADT/SmallString.h" |
20 | #include "llvm/Support/ConvertUTF.h" |
21 | #include "llvm/Support/FileSystem.h" |
22 | #include "llvm/Support/ManagedStatic.h" |
23 | #include "llvm/Support/Path.h" |
24 | #include "llvm/Support/Threading.h" |
25 | #include "llvm/Support/raw_ostream.h" |
26 | |
27 | using namespace lldb_private; |
28 | |
29 | namespace { |
30 | class WindowsUserIDResolver : public UserIDResolver { |
31 | protected: |
32 | std::optional<std::string> DoGetUserName(id_t uid) override { |
33 | return std::nullopt; |
34 | } |
35 | std::optional<std::string> DoGetGroupName(id_t gid) override { |
36 | return std::nullopt; |
37 | } |
38 | }; |
39 | } // namespace |
40 | |
41 | FileSpec HostInfoWindows::m_program_filespec; |
42 | |
43 | void HostInfoWindows::Initialize(SharedLibraryDirectoryHelper *helper) { |
44 | ::CoInitializeEx(nullptr, COINIT_MULTITHREADED); |
45 | HostInfoBase::Initialize(helper); |
46 | } |
47 | |
48 | void HostInfoWindows::Terminate() { |
49 | HostInfoBase::Terminate(); |
50 | ::CoUninitialize(); |
51 | } |
52 | |
53 | size_t HostInfoWindows::GetPageSize() { |
54 | SYSTEM_INFO systemInfo; |
55 | GetNativeSystemInfo(&systemInfo); |
56 | return systemInfo.dwPageSize; |
57 | } |
58 | |
59 | llvm::VersionTuple HostInfoWindows::GetOSVersion() { |
60 | OSVERSIONINFOEX info; |
61 | |
62 | ZeroMemory(&info, sizeof(OSVERSIONINFOEX)); |
63 | info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); |
64 | #pragma warning(push) |
65 | #pragma warning(disable : 4996) |
66 | // Starting with Microsoft SDK for Windows 8.1, this function is deprecated |
67 | // in favor of the new Windows Version Helper APIs. Since we don't specify a |
68 | // minimum SDK version, it's easier to simply disable the warning rather than |
69 | // try to support both APIs. |
70 | if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) |
71 | return llvm::VersionTuple(); |
72 | #pragma warning(pop) |
73 | |
74 | return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, |
75 | info.wServicePackMajor); |
76 | } |
77 | |
78 | std::optional<std::string> HostInfoWindows::GetOSBuildString() { |
79 | llvm::VersionTuple version = GetOSVersion(); |
80 | if (version.empty()) |
81 | return std::nullopt; |
82 | |
83 | return "Windows NT " + version.getAsString(); |
84 | } |
85 | |
86 | std::optional<std::string> HostInfoWindows::GetOSKernelDescription() { |
87 | return GetOSBuildString(); |
88 | } |
89 | |
90 | bool HostInfoWindows::GetHostname(std::string &s) { |
91 | wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1]; |
92 | DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1; |
93 | if (!::GetComputerNameW(buffer, &dwSize)) |
94 | return false; |
95 | |
96 | // The conversion requires an empty string. |
97 | s.clear(); |
98 | return llvm::convertWideToUTF8(Source: buffer, Result&: s); |
99 | } |
100 | |
101 | FileSpec HostInfoWindows::GetProgramFileSpec() { |
102 | static llvm::once_flag g_once_flag; |
103 | llvm::call_once(flag&: g_once_flag, F: []() { |
104 | std::vector<wchar_t> buffer(PATH_MAX); |
105 | ::GetModuleFileNameW(NULL, buffer.data(), buffer.size()); |
106 | std::string path; |
107 | llvm::convertWideToUTF8(Source: buffer.data(), Result&: path); |
108 | m_program_filespec.SetFile(path, style: FileSpec::Style::native); |
109 | }); |
110 | return m_program_filespec; |
111 | } |
112 | |
113 | FileSpec HostInfoWindows::GetDefaultShell() { |
114 | // Try to retrieve ComSpec from the environment. On the rare occasion |
115 | // that it fails, try a well-known path for ComSpec instead. |
116 | |
117 | std::string shell; |
118 | if (GetEnvironmentVar(var_name: "ComSpec" , var&: shell)) |
119 | return FileSpec(shell); |
120 | |
121 | return FileSpec("C:\\Windows\\system32\\cmd.exe" ); |
122 | } |
123 | |
124 | bool HostInfoWindows::GetEnvironmentVar(const std::string &var_name, |
125 | std::string &var) { |
126 | std::wstring wvar_name; |
127 | if (!llvm::ConvertUTF8toWide(Source: var_name, Result&: wvar_name)) |
128 | return false; |
129 | |
130 | if (const wchar_t *wvar = _wgetenv(wvar_name.c_str())) |
131 | return llvm::convertWideToUTF8(Source: wvar, Result&: var); |
132 | return false; |
133 | } |
134 | |
135 | static llvm::ManagedStatic<WindowsUserIDResolver> g_user_id_resolver; |
136 | |
137 | UserIDResolver &HostInfoWindows::GetUserIDResolver() { |
138 | return *g_user_id_resolver; |
139 | } |
140 | |