blob: d4599dca044e9172ce718f0dd1e727ba38ea7b8c [file] [log] [blame]
Reid Klecknerd59e2fa2014-02-12 21:26:20 +00001//===- WindowsSupport.h - Common Windows Include File -----------*- C++ -*-===//
Misha Brukman10468d82005-04-21 22:55:34 +00002//
Reid Spencer0f0c5cf2004-09-15 05:48:11 +00003// The LLVM Compiler Infrastructure
4//
Chris Lattnerf3ebc3f2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Misha Brukman10468d82005-04-21 22:55:34 +00007//
Reid Spencer0f0c5cf2004-09-15 05:48:11 +00008//===----------------------------------------------------------------------===//
9//
Reid Klecknerd59e2fa2014-02-12 21:26:20 +000010// This file defines things specific to Windows implementations. In addition to
11// providing some helpers for working with win32 APIs, this header wraps
12// <windows.h> with some portability macros. Always include WindowsSupport.h
13// instead of including <windows.h> directly.
Reid Spencer0f0c5cf2004-09-15 05:48:11 +000014//
15//===----------------------------------------------------------------------===//
16
17//===----------------------------------------------------------------------===//
Jeff Cohen3800a282005-07-13 02:15:18 +000018//=== WARNING: Implementation here must contain only generic Win32 code that
19//=== is guaranteed to work on *all* Win32 variants.
Reid Spencer0f0c5cf2004-09-15 05:48:11 +000020//===----------------------------------------------------------------------===//
21
Yaron Keren3f02c142015-01-21 16:20:38 +000022#ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H
23#define LLVM_SUPPORT_WINDOWSSUPPORT_H
24
NAKAMURA Takumiaeb4c0d2011-02-09 04:18:30 +000025// mingw-w64 tends to define it as 0x0502 in its headers.
26#undef _WIN32_WINNT
Aaron Ballman42f66222014-02-03 17:20:26 +000027#undef _WIN32_IE
NAKAMURA Takumiaeb4c0d2011-02-09 04:18:30 +000028
Pawel Bylica6b129bd2015-10-15 14:50:31 +000029// Require at least Windows 7 API.
30#define _WIN32_WINNT 0x0601
31#define _WIN32_IE 0x0800 // MinGW at it again. FIXME: verify if still needed.
Michael J. Spencerbb6e51c2010-11-09 15:11:07 +000032#define WIN32_LEAN_AND_MEAN
Yunzhong Gaod7009f32016-01-06 01:36:45 +000033#ifndef NOMINMAX
Yunzhong Gaofb2a9c42016-01-06 00:50:06 +000034#define NOMINMAX
Yunzhong Gaod7009f32016-01-06 01:36:45 +000035#endif
Jeff Cohen3800a282005-07-13 02:15:18 +000036
Rui Ueyama471d0c52013-09-10 19:45:51 +000037#include "llvm/ADT/SmallVector.h"
Paul Robinsonaf19bc32015-11-23 17:34:20 +000038#include "llvm/ADT/StringExtras.h"
Rui Ueyama471d0c52013-09-10 19:45:51 +000039#include "llvm/ADT/StringRef.h"
Paul Robinsonc38deee2014-11-24 18:05:29 +000040#include "llvm/ADT/Twine.h"
Michael J. Spencer4b263dd2010-11-09 15:10:29 +000041#include "llvm/Config/config.h" // Get build system configuration settings
Pavel Labath757ca882016-10-24 10:59:17 +000042#include "llvm/Support/Chrono.h"
Timur Iskhodzhanov05885132013-05-15 09:00:30 +000043#include "llvm/Support/Compiler.h"
Reid Spencer0f0c5cf2004-09-15 05:48:11 +000044#include <cassert>
45#include <string>
Pavel Labath757ca882016-10-24 10:59:17 +000046#include <system_error>
Chandler Carruth6bda14b2017-06-06 11:49:48 +000047#include <windows.h>
Reid Spencer0f0c5cf2004-09-15 05:48:11 +000048
Chandler Carruth185ddef2017-06-06 12:11:24 +000049// Must be included after windows.h
50#include <wincrypt.h>
51
Reid Klecknerffbe12f2016-01-11 20:35:45 +000052/// Determines if the program is running on Windows 8 or newer. This
Reid Kleckner5fb7a582016-01-11 23:33:03 +000053/// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
54/// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't
55/// yet have VersionHelpers.h, so we have our own helper.
56inline bool RunningWindows8OrGreater() {
57 // Windows 8 is version 6.2, service pack 0.
58 OSVERSIONINFOEXW osvi = {};
Yunzhong Gaofb2a9c42016-01-06 00:50:06 +000059 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
Reid Kleckner5fb7a582016-01-11 23:33:03 +000060 osvi.dwMajorVersion = 6;
61 osvi.dwMinorVersion = 2;
62 osvi.wServicePackMajor = 0;
63
64 DWORDLONG Mask = 0;
65 Mask = VerSetConditionMask(Mask, VER_MAJORVERSION, VER_GREATER_EQUAL);
66 Mask = VerSetConditionMask(Mask, VER_MINORVERSION, VER_GREATER_EQUAL);
67 Mask = VerSetConditionMask(Mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL);
68
69 return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION |
70 VER_SERVICEPACKMAJOR,
71 Mask) != FALSE;
Yunzhong Gaofb2a9c42016-01-06 00:50:06 +000072}
Yunzhong Gaofb2a9c42016-01-06 00:50:06 +000073
Aaron Ballman0da8b2e2016-06-23 14:45:54 +000074inline bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) {
Reid Spencer42bcf6e2006-08-21 06:02:44 +000075 if (!ErrMsg)
Reid Spencer879ed5a2006-08-23 07:30:48 +000076 return true;
Reid Spencer42bcf6e2006-08-21 06:02:44 +000077 char *buffer = NULL;
Paul Robinsonaf19bc32015-11-23 17:34:20 +000078 DWORD LastError = GetLastError();
Aaron Ballman0da8b2e2016-06-23 14:45:54 +000079 DWORD R = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
80 FORMAT_MESSAGE_FROM_SYSTEM |
81 FORMAT_MESSAGE_MAX_WIDTH_MASK,
82 NULL, LastError, 0, (LPSTR)&buffer, 1, NULL);
Aaron Ballman69c55ed2013-11-18 17:43:22 +000083 if (R)
Paul Robinsonaf19bc32015-11-23 17:34:20 +000084 *ErrMsg = prefix + ": " + buffer;
Aaron Ballman69c55ed2013-11-18 17:43:22 +000085 else
Paul Robinsonaf19bc32015-11-23 17:34:20 +000086 *ErrMsg = prefix + ": Unknown error";
87 *ErrMsg += " (0x" + llvm::utohexstr(LastError) + ")";
Aaron Ballman69c55ed2013-11-18 17:43:22 +000088
Reid Spencer42bcf6e2006-08-21 06:02:44 +000089 LocalFree(buffer);
Aaron Ballman69c55ed2013-11-18 17:43:22 +000090 return R != 0;
Reid Spencer42bcf6e2006-08-21 06:02:44 +000091}
Jeff Cohena531d042007-03-05 05:22:08 +000092
Michael J. Spencer513f1b62011-12-12 06:03:33 +000093template <typename HandleTraits>
Michael J. Spencer39c46212010-12-06 04:28:13 +000094class ScopedHandle {
Michael J. Spencer513f1b62011-12-12 06:03:33 +000095 typedef typename HandleTraits::handle_type handle_type;
96 handle_type Handle;
Michael J. Spencer39c46212010-12-06 04:28:13 +000097
Michael J. Spencer513f1b62011-12-12 06:03:33 +000098 ScopedHandle(const ScopedHandle &other); // = delete;
99 void operator=(const ScopedHandle &other); // = delete;
Michael J. Spencer39c46212010-12-06 04:28:13 +0000100public:
Michael J. Spencer513f1b62011-12-12 06:03:33 +0000101 ScopedHandle()
102 : Handle(HandleTraits::GetInvalid()) {}
103
104 explicit ScopedHandle(handle_type h)
105 : Handle(h) {}
Michael J. Spencer39c46212010-12-06 04:28:13 +0000106
107 ~ScopedHandle() {
Michael J. Spencer513f1b62011-12-12 06:03:33 +0000108 if (HandleTraits::IsValid(Handle))
109 HandleTraits::Close(Handle);
Michael J. Spencer39c46212010-12-06 04:28:13 +0000110 }
111
Michael J. Spencer513f1b62011-12-12 06:03:33 +0000112 handle_type take() {
113 handle_type t = Handle;
114 Handle = HandleTraits::GetInvalid();
115 return t;
Michael J. Spencer39c46212010-12-06 04:28:13 +0000116 }
117
Michael J. Spencer513f1b62011-12-12 06:03:33 +0000118 ScopedHandle &operator=(handle_type h) {
119 if (HandleTraits::IsValid(Handle))
120 HandleTraits::Close(Handle);
121 Handle = h;
Michael J. Spencer39c46212010-12-06 04:28:13 +0000122 return *this;
123 }
124
Michael J. Spencer39c46212010-12-06 04:28:13 +0000125 // True if Handle is valid.
Aaron Ballmanb46962f2015-02-15 22:00:20 +0000126 explicit operator bool() const {
Michael J. Spencer513f1b62011-12-12 06:03:33 +0000127 return HandleTraits::IsValid(Handle) ? true : false;
Michael J. Spencer39c46212010-12-06 04:28:13 +0000128 }
129
Michael J. Spencer513f1b62011-12-12 06:03:33 +0000130 operator handle_type() const {
131 return Handle;
Michael J. Spencer7ecd94c2010-12-06 04:28:42 +0000132 }
Michael J. Spencer39c46212010-12-06 04:28:13 +0000133};
Michael J. Spencer7ecd94c2010-12-06 04:28:42 +0000134
Michael J. Spencer513f1b62011-12-12 06:03:33 +0000135struct CommonHandleTraits {
136 typedef HANDLE handle_type;
137
138 static handle_type GetInvalid() {
139 return INVALID_HANDLE_VALUE;
140 }
141
142 static void Close(handle_type h) {
143 ::CloseHandle(h);
144 }
145
146 static bool IsValid(handle_type h) {
147 return h != GetInvalid();
148 }
149};
150
151struct JobHandleTraits : CommonHandleTraits {
152 static handle_type GetInvalid() {
153 return NULL;
154 }
155};
156
157struct CryptContextTraits : CommonHandleTraits {
158 typedef HCRYPTPROV handle_type;
159
160 static handle_type GetInvalid() {
161 return 0;
162 }
163
164 static void Close(handle_type h) {
165 ::CryptReleaseContext(h, 0);
166 }
167
168 static bool IsValid(handle_type h) {
169 return h != GetInvalid();
170 }
171};
172
Leny Kholodov1b73e662016-05-04 16:56:51 +0000173struct RegTraits : CommonHandleTraits {
174 typedef HKEY handle_type;
175
176 static handle_type GetInvalid() {
177 return NULL;
178 }
179
180 static void Close(handle_type h) {
181 ::RegCloseKey(h);
182 }
183
184 static bool IsValid(handle_type h) {
185 return h != GetInvalid();
186 }
187};
188
Michael J. Spencer513f1b62011-12-12 06:03:33 +0000189struct FindHandleTraits : CommonHandleTraits {
190 static void Close(handle_type h) {
191 ::FindClose(h);
192 }
193};
194
195struct FileHandleTraits : CommonHandleTraits {};
196
197typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
198typedef ScopedHandle<FileHandleTraits> ScopedFileHandle;
199typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
Leny Kholodov1b73e662016-05-04 16:56:51 +0000200typedef ScopedHandle<RegTraits> ScopedRegHandle;
Michael J. Spencer513f1b62011-12-12 06:03:33 +0000201typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
202typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;
Michael J. Spencer751e9aa2010-12-09 17:37:18 +0000203
204namespace llvm {
205template <class T>
206class SmallVectorImpl;
207
208template <class T>
209typename SmallVectorImpl<T>::const_pointer
210c_str(SmallVectorImpl<T> &str) {
211 str.push_back(0);
212 str.pop_back();
213 return str.data();
214}
Rui Ueyama471d0c52013-09-10 19:45:51 +0000215
216namespace sys {
Pavel Labath757ca882016-10-24 10:59:17 +0000217
218inline std::chrono::nanoseconds toDuration(FILETIME Time) {
219 ULARGE_INTEGER TimeInteger;
220 TimeInteger.LowPart = Time.dwLowDateTime;
221 TimeInteger.HighPart = Time.dwHighDateTime;
222
223 // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
224 return std::chrono::nanoseconds(100 * TimeInteger.QuadPart);
225}
226
227inline TimePoint<> toTimePoint(FILETIME Time) {
228 ULARGE_INTEGER TimeInteger;
229 TimeInteger.LowPart = Time.dwLowDateTime;
230 TimeInteger.HighPart = Time.dwHighDateTime;
231
232 // Adjust for different epoch
233 TimeInteger.QuadPart -= 11644473600ll * 10000000;
234
235 // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
236 return TimePoint<>(std::chrono::nanoseconds(100 * TimeInteger.QuadPart));
237}
238
239inline FILETIME toFILETIME(TimePoint<> TP) {
240 ULARGE_INTEGER TimeInteger;
241 TimeInteger.QuadPart = TP.time_since_epoch().count() / 100;
242 TimeInteger.QuadPart += 11644473600ll * 10000000;
243
244 FILETIME Time;
245 Time.dwLowDateTime = TimeInteger.LowPart;
246 Time.dwHighDateTime = TimeInteger.HighPart;
247 return Time;
248}
249
Paul Robinsonc38deee2014-11-24 18:05:29 +0000250namespace path {
251std::error_code widenPath(const Twine &Path8,
252 SmallVectorImpl<wchar_t> &Path16);
253} // end namespace path
254
Rui Ueyama471d0c52013-09-10 19:45:51 +0000255namespace windows {
Rafael Espindola885719f2014-06-12 17:49:35 +0000256std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16);
257std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
258 SmallVectorImpl<char> &utf8);
Rafael Espindola9c359662014-09-03 20:02:00 +0000259/// Convert from UTF16 to the current code page used in the system
260std::error_code UTF16ToCurCP(const wchar_t *utf16, size_t utf16_len,
261 SmallVectorImpl<char> &utf8);
Rui Ueyama471d0c52013-09-10 19:45:51 +0000262} // end namespace windows
263} // end namespace sys
Michael J. Spencer751e9aa2010-12-09 17:37:18 +0000264} // end namespace llvm.
Yaron Keren3f02c142015-01-21 16:20:38 +0000265
266#endif