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