WindowsSupport.h 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- WindowsSupport.h - Common Windows Include File -----------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file defines things specific to Windows implementations. In addition to
  15. // providing some helpers for working with win32 APIs, this header wraps
  16. // <windows.h> with some portability macros. Always include WindowsSupport.h
  17. // instead of including <windows.h> directly.
  18. //
  19. //===----------------------------------------------------------------------===//
  20. //===----------------------------------------------------------------------===//
  21. //=== WARNING: Implementation here must contain only generic Win32 code that
  22. //=== is guaranteed to work on *all* Win32 variants.
  23. //===----------------------------------------------------------------------===//
  24. #ifndef LLVM_SUPPORT_WINDOWSSUPPORT_H
  25. #define LLVM_SUPPORT_WINDOWSSUPPORT_H
  26. // mingw-w64 tends to define it as 0x0502 in its headers.
  27. #undef _WIN32_WINNT
  28. #undef _WIN32_IE
  29. // 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.
  32. #define WIN32_LEAN_AND_MEAN
  33. #ifndef NOMINMAX
  34. #define NOMINMAX
  35. #endif
  36. #include "llvm/ADT/SmallVector.h"
  37. #include "llvm/ADT/StringExtras.h"
  38. #include "llvm/ADT/StringRef.h"
  39. #include "llvm/ADT/Twine.h"
  40. #include "llvm/Config/llvm-config.h" // Get build system configuration settings
  41. #include "llvm/Support/Allocator.h"
  42. #include "llvm/Support/Chrono.h"
  43. #include "llvm/Support/Compiler.h"
  44. #include "llvm/Support/ErrorHandling.h"
  45. #include "llvm/Support/VersionTuple.h"
  46. #include <cassert>
  47. #include <string>
  48. #include <system_error>
  49. #include <windows.h>
  50. // Must be included after windows.h
  51. #include <wincrypt.h>
  52. namespace llvm {
  53. /// Determines if the program is running on Windows 8 or newer. This
  54. /// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
  55. /// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't
  56. /// yet have VersionHelpers.h, so we have our own helper.
  57. bool RunningWindows8OrGreater();
  58. /// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
  59. /// RtlGetVersion or GetVersionEx under the hood depending on what is available.
  60. /// GetVersionEx is deprecated, but this API exposes the build number which can
  61. /// be useful for working around certain kernel bugs.
  62. llvm::VersionTuple GetWindowsOSVersion();
  63. bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix);
  64. // Include GetLastError() in a fatal error message.
  65. [[noreturn]] inline void ReportLastErrorFatal(const char *Msg) {
  66. std::string ErrMsg;
  67. MakeErrMsg(&ErrMsg, Msg);
  68. llvm::report_fatal_error(Twine(ErrMsg));
  69. }
  70. template <typename HandleTraits>
  71. class ScopedHandle {
  72. typedef typename HandleTraits::handle_type handle_type;
  73. handle_type Handle;
  74. ScopedHandle(const ScopedHandle &other) = delete;
  75. void operator=(const ScopedHandle &other) = delete;
  76. public:
  77. ScopedHandle()
  78. : Handle(HandleTraits::GetInvalid()) {}
  79. explicit ScopedHandle(handle_type h)
  80. : Handle(h) {}
  81. ~ScopedHandle() {
  82. if (HandleTraits::IsValid(Handle))
  83. HandleTraits::Close(Handle);
  84. }
  85. handle_type take() {
  86. handle_type t = Handle;
  87. Handle = HandleTraits::GetInvalid();
  88. return t;
  89. }
  90. ScopedHandle &operator=(handle_type h) {
  91. if (HandleTraits::IsValid(Handle))
  92. HandleTraits::Close(Handle);
  93. Handle = h;
  94. return *this;
  95. }
  96. // True if Handle is valid.
  97. explicit operator bool() const {
  98. return HandleTraits::IsValid(Handle) ? true : false;
  99. }
  100. operator handle_type() const {
  101. return Handle;
  102. }
  103. };
  104. struct CommonHandleTraits {
  105. typedef HANDLE handle_type;
  106. static handle_type GetInvalid() {
  107. return INVALID_HANDLE_VALUE;
  108. }
  109. static void Close(handle_type h) {
  110. ::CloseHandle(h);
  111. }
  112. static bool IsValid(handle_type h) {
  113. return h != GetInvalid();
  114. }
  115. };
  116. struct JobHandleTraits : CommonHandleTraits {
  117. static handle_type GetInvalid() {
  118. return NULL;
  119. }
  120. };
  121. struct CryptContextTraits : CommonHandleTraits {
  122. typedef HCRYPTPROV handle_type;
  123. static handle_type GetInvalid() {
  124. return 0;
  125. }
  126. static void Close(handle_type h) {
  127. ::CryptReleaseContext(h, 0);
  128. }
  129. static bool IsValid(handle_type h) {
  130. return h != GetInvalid();
  131. }
  132. };
  133. struct RegTraits : CommonHandleTraits {
  134. typedef HKEY handle_type;
  135. static handle_type GetInvalid() {
  136. return NULL;
  137. }
  138. static void Close(handle_type h) {
  139. ::RegCloseKey(h);
  140. }
  141. static bool IsValid(handle_type h) {
  142. return h != GetInvalid();
  143. }
  144. };
  145. struct FindHandleTraits : CommonHandleTraits {
  146. static void Close(handle_type h) {
  147. ::FindClose(h);
  148. }
  149. };
  150. struct FileHandleTraits : CommonHandleTraits {};
  151. typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
  152. typedef ScopedHandle<FileHandleTraits> ScopedFileHandle;
  153. typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
  154. typedef ScopedHandle<RegTraits> ScopedRegHandle;
  155. typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
  156. typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;
  157. template <class T>
  158. class SmallVectorImpl;
  159. template <class T>
  160. typename SmallVectorImpl<T>::const_pointer
  161. c_str(SmallVectorImpl<T> &str) {
  162. str.push_back(0);
  163. str.pop_back();
  164. return str.data();
  165. }
  166. namespace sys {
  167. inline std::chrono::nanoseconds toDuration(FILETIME Time) {
  168. ULARGE_INTEGER TimeInteger;
  169. TimeInteger.LowPart = Time.dwLowDateTime;
  170. TimeInteger.HighPart = Time.dwHighDateTime;
  171. // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
  172. return std::chrono::nanoseconds(100 * TimeInteger.QuadPart);
  173. }
  174. inline TimePoint<> toTimePoint(FILETIME Time) {
  175. ULARGE_INTEGER TimeInteger;
  176. TimeInteger.LowPart = Time.dwLowDateTime;
  177. TimeInteger.HighPart = Time.dwHighDateTime;
  178. // Adjust for different epoch
  179. TimeInteger.QuadPart -= 11644473600ll * 10000000;
  180. // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
  181. return TimePoint<>(std::chrono::nanoseconds(100 * TimeInteger.QuadPart));
  182. }
  183. inline FILETIME toFILETIME(TimePoint<> TP) {
  184. ULARGE_INTEGER TimeInteger;
  185. TimeInteger.QuadPart = TP.time_since_epoch().count() / 100;
  186. TimeInteger.QuadPart += 11644473600ll * 10000000;
  187. FILETIME Time;
  188. Time.dwLowDateTime = TimeInteger.LowPart;
  189. Time.dwHighDateTime = TimeInteger.HighPart;
  190. return Time;
  191. }
  192. namespace windows {
  193. // Returns command line arguments. Unlike arguments given to main(),
  194. // this function guarantees that the returned arguments are encoded in
  195. // UTF-8 regardless of the current code page setting.
  196. std::error_code GetCommandLineArguments(SmallVectorImpl<const char *> &Args,
  197. BumpPtrAllocator &Alloc);
  198. /// Convert UTF-8 path to a suitable UTF-16 path for use with the Win32 Unicode
  199. /// File API.
  200. std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16,
  201. size_t MaxPathLen = MAX_PATH);
  202. } // end namespace windows
  203. } // end namespace sys
  204. } // end namespace llvm.
  205. #endif
  206. #ifdef __GNUC__
  207. #pragma GCC diagnostic pop
  208. #endif