1 //===-- HostInfoWindows.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "lldb/Host/windows/windows.h"
11 
12 #include <objbase.h>
13 
14 #include <mutex> // std::once
15 
16 #include "lldb/Host/windows/HostInfoWindows.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/Support/ConvertUTF.h"
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/raw_ostream.h"
22 
23 using namespace lldb_private;
24 
25 FileSpec HostInfoWindows::m_program_filespec;
26 
27 void
28 HostInfoWindows::Initialize()
29 {
30     ::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
31     HostInfoBase::Initialize();
32 }
33 
34 void
35 HostInfoWindows::Terminate()
36 {
37     HostInfoBase::Terminate();
38     ::CoUninitialize();
39 }
40 
41 size_t
42 HostInfoWindows::GetPageSize()
43 {
44     SYSTEM_INFO systemInfo;
45     GetNativeSystemInfo(&systemInfo);
46     return systemInfo.dwPageSize;
47 }
48 
49 bool
50 HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update)
51 {
52     OSVERSIONINFOEX info;
53 
54     ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
55     info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
56 #pragma warning(push)
57 #pragma warning(disable : 4996)
58     // Starting with Microsoft SDK for Windows 8.1, this function is deprecated in favor of the
59     // new Windows Version Helper APIs.  Since we don't specify a minimum SDK version, it's easier
60     // to simply disable the warning rather than try to support both APIs.
61     if (GetVersionEx((LPOSVERSIONINFO)&info) == 0)
62     {
63         return false;
64     }
65 #pragma warning(pop)
66 
67     major = info.dwMajorVersion;
68     minor = info.dwMinorVersion;
69     update = info.wServicePackMajor;
70 
71     return true;
72 }
73 
74 bool
75 HostInfoWindows::GetOSBuildString(std::string &s)
76 {
77     s.clear();
78     uint32_t major, minor, update;
79     if (!GetOSVersion(major, minor, update))
80         return false;
81 
82     llvm::raw_string_ostream stream(s);
83     stream << "Windows NT " << major << "." << minor << "." << update;
84     return true;
85 }
86 
87 bool
88 HostInfoWindows::GetOSKernelDescription(std::string &s)
89 {
90     return GetOSBuildString(s);
91 }
92 
93 bool
94 HostInfoWindows::GetHostname(std::string &s)
95 {
96     wchar_t buffer[MAX_COMPUTERNAME_LENGTH + 1];
97     DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
98     if (!::GetComputerNameW(buffer, &dwSize))
99         return false;
100 
101     return llvm::convertWideToUTF8(buffer, s);
102 }
103 
104 FileSpec
105 HostInfoWindows::GetProgramFileSpec()
106 {
107     static std::once_flag g_once_flag;
108     std::call_once(g_once_flag, []() {
109         std::vector<wchar_t> buffer(PATH_MAX);
110         ::GetModuleFileNameW(NULL, buffer.data(), buffer.size());
111         std::string path;
112         llvm::convertWideToUTF8(buffer.data(), path);
113         m_program_filespec.SetFile(path, false);
114     });
115     return m_program_filespec;
116 }
117 
118 FileSpec
119 HostInfoWindows::GetDefaultShell()
120 {
121     std::string shell;
122     GetEnvironmentVar("ComSpec", shell);
123     return FileSpec(shell, false);
124 }
125 
126 bool
127 HostInfoWindows::ComputePythonDirectory(FileSpec &file_spec)
128 {
129     FileSpec lldb_file_spec;
130     if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
131         return false;
132     llvm::SmallString<64> path(lldb_file_spec.GetDirectory().AsCString());
133     llvm::sys::path::remove_filename(path);
134     llvm::sys::path::append(path, "lib", "site-packages");
135     std::replace(path.begin(), path.end(), '\\', '/');
136     file_spec.GetDirectory().SetString(path.c_str());
137     return true;
138 }
139 
140 bool
141 HostInfoWindows::GetEnvironmentVar(const std::string &var_name, std::string &var)
142 {
143     std::wstring wvar_name;
144     if (!llvm::ConvertUTF8toWide(var_name, wvar_name))
145         return false;
146 
147     if (const wchar_t *wvar = _wgetenv(wvar_name.c_str()))
148         return llvm::convertWideToUTF8(wvar, var);
149     return false;
150 }
151