1 //===- WindowsSupport.h - Common Windows Include File -----------*- 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 // 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.
14 //
15 //===----------------------------------------------------------------------===//
16
17 //===----------------------------------------------------------------------===//
18 //=== WARNING: Implementation here must contain only generic Win32 code that
19 //=== is guaranteed to work on *all* Win32 variants.
20 //===----------------------------------------------------------------------===//
21
22 // mingw-w64 tends to define it as 0x0502 in its headers.
23 #undef _WIN32_WINNT
24 #undef _WIN32_IE
25
26 // Require at least Windows XP(5.1) API.
27 #define _WIN32_WINNT 0x0501
28 #define _WIN32_IE 0x0600 // MinGW at it again.
29 #define WIN32_LEAN_AND_MEAN
30
31 #include "llvm/ADT/SmallVector.h"
32 #include "llvm/ADT/StringRef.h"
33 #include "llvm/Config/config.h" // Get build system configuration settings
34 #include "llvm/Support/Compiler.h"
35 #include <system_error>
36 #include <windows.h>
37 #include <wincrypt.h>
38 #include <cassert>
39 #include <string>
40 #include <vector>
41
MakeErrMsg(std::string * ErrMsg,const std::string & prefix)42 inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) {
43 if (!ErrMsg)
44 return true;
45 char *buffer = NULL;
46 DWORD R = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
47 FORMAT_MESSAGE_FROM_SYSTEM,
48 NULL, GetLastError(), 0, (LPSTR)&buffer, 1, NULL);
49 if (R)
50 *ErrMsg = prefix + buffer;
51 else
52 *ErrMsg = prefix + "Unknown error";
53
54 LocalFree(buffer);
55 return R != 0;
56 }
57
58 template <typename HandleTraits>
59 class ScopedHandle {
60 typedef typename HandleTraits::handle_type handle_type;
61 handle_type Handle;
62
63 ScopedHandle(const ScopedHandle &other); // = delete;
64 void operator=(const ScopedHandle &other); // = delete;
65 public:
ScopedHandle()66 ScopedHandle()
67 : Handle(HandleTraits::GetInvalid()) {}
68
ScopedHandle(handle_type h)69 explicit ScopedHandle(handle_type h)
70 : Handle(h) {}
71
~ScopedHandle()72 ~ScopedHandle() {
73 if (HandleTraits::IsValid(Handle))
74 HandleTraits::Close(Handle);
75 }
76
take()77 handle_type take() {
78 handle_type t = Handle;
79 Handle = HandleTraits::GetInvalid();
80 return t;
81 }
82
83 ScopedHandle &operator=(handle_type h) {
84 if (HandleTraits::IsValid(Handle))
85 HandleTraits::Close(Handle);
86 Handle = h;
87 return *this;
88 }
89
90 // True if Handle is valid.
91 LLVM_EXPLICIT operator bool() const {
92 return HandleTraits::IsValid(Handle) ? true : false;
93 }
94
handle_type()95 operator handle_type() const {
96 return Handle;
97 }
98 };
99
100 struct CommonHandleTraits {
101 typedef HANDLE handle_type;
102
GetInvalidCommonHandleTraits103 static handle_type GetInvalid() {
104 return INVALID_HANDLE_VALUE;
105 }
106
CloseCommonHandleTraits107 static void Close(handle_type h) {
108 ::CloseHandle(h);
109 }
110
IsValidCommonHandleTraits111 static bool IsValid(handle_type h) {
112 return h != GetInvalid();
113 }
114 };
115
116 struct JobHandleTraits : CommonHandleTraits {
GetInvalidJobHandleTraits117 static handle_type GetInvalid() {
118 return NULL;
119 }
120 };
121
122 struct CryptContextTraits : CommonHandleTraits {
123 typedef HCRYPTPROV handle_type;
124
GetInvalidCryptContextTraits125 static handle_type GetInvalid() {
126 return 0;
127 }
128
CloseCryptContextTraits129 static void Close(handle_type h) {
130 ::CryptReleaseContext(h, 0);
131 }
132
IsValidCryptContextTraits133 static bool IsValid(handle_type h) {
134 return h != GetInvalid();
135 }
136 };
137
138 struct FindHandleTraits : CommonHandleTraits {
CloseFindHandleTraits139 static void Close(handle_type h) {
140 ::FindClose(h);
141 }
142 };
143
144 struct FileHandleTraits : CommonHandleTraits {};
145
146 typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
147 typedef ScopedHandle<FileHandleTraits> ScopedFileHandle;
148 typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
149 typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
150 typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;
151
152 namespace llvm {
153 template <class T>
154 class SmallVectorImpl;
155
156 template <class T>
157 typename SmallVectorImpl<T>::const_pointer
c_str(SmallVectorImpl<T> & str)158 c_str(SmallVectorImpl<T> &str) {
159 str.push_back(0);
160 str.pop_back();
161 return str.data();
162 }
163
164 namespace sys {
165 namespace windows {
166 std::error_code UTF8ToUTF16(StringRef utf8, SmallVectorImpl<wchar_t> &utf16);
167 std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t utf16_len,
168 SmallVectorImpl<char> &utf8);
169 } // end namespace windows
170 } // end namespace sys
171 } // end namespace llvm.
172