WindowsSupport.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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. /// Determines if the program is running on Windows 11 or Windows Server 2022.
  59. bool RunningWindows11OrGreater();
  60. /// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
  61. /// RtlGetVersion or GetVersionEx under the hood depending on what is available.
  62. /// GetVersionEx is deprecated, but this API exposes the build number which can
  63. /// be useful for working around certain kernel bugs.
  64. llvm::VersionTuple GetWindowsOSVersion();
  65. bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix);
  66. // Include GetLastError() in a fatal error message.
  67. [[noreturn]] inline void ReportLastErrorFatal(const char *Msg) {
  68. std::string ErrMsg;
  69. MakeErrMsg(&ErrMsg, Msg);
  70. llvm::report_fatal_error(Twine(ErrMsg));
  71. }
  72. template <typename HandleTraits>
  73. class ScopedHandle {
  74. typedef typename HandleTraits::handle_type handle_type;
  75. handle_type Handle;
  76. ScopedHandle(const ScopedHandle &other) = delete;
  77. void operator=(const ScopedHandle &other) = delete;
  78. public:
  79. ScopedHandle()
  80. : Handle(HandleTraits::GetInvalid()) {}
  81. explicit ScopedHandle(handle_type h)
  82. : Handle(h) {}
  83. ~ScopedHandle() {
  84. if (HandleTraits::IsValid(Handle))
  85. HandleTraits::Close(Handle);
  86. }
  87. handle_type take() {
  88. handle_type t = Handle;
  89. Handle = HandleTraits::GetInvalid();
  90. return t;
  91. }
  92. ScopedHandle &operator=(handle_type h) {
  93. if (HandleTraits::IsValid(Handle))
  94. HandleTraits::Close(Handle);
  95. Handle = h;
  96. return *this;
  97. }
  98. // True if Handle is valid.
  99. explicit operator bool() const {
  100. return HandleTraits::IsValid(Handle) ? true : false;
  101. }
  102. operator handle_type() const {
  103. return Handle;
  104. }
  105. };
  106. struct CommonHandleTraits {
  107. typedef HANDLE handle_type;
  108. static handle_type GetInvalid() {
  109. return INVALID_HANDLE_VALUE;
  110. }
  111. static void Close(handle_type h) {
  112. ::CloseHandle(h);
  113. }
  114. static bool IsValid(handle_type h) {
  115. return h != GetInvalid();
  116. }
  117. };
  118. struct JobHandleTraits : CommonHandleTraits {
  119. static handle_type GetInvalid() {
  120. return NULL;
  121. }
  122. };
  123. struct CryptContextTraits : CommonHandleTraits {
  124. typedef HCRYPTPROV handle_type;
  125. static handle_type GetInvalid() {
  126. return 0;
  127. }
  128. static void Close(handle_type h) {
  129. ::CryptReleaseContext(h, 0);
  130. }
  131. static bool IsValid(handle_type h) {
  132. return h != GetInvalid();
  133. }
  134. };
  135. struct RegTraits : CommonHandleTraits {
  136. typedef HKEY handle_type;
  137. static handle_type GetInvalid() {
  138. return NULL;
  139. }
  140. static void Close(handle_type h) {
  141. ::RegCloseKey(h);
  142. }
  143. static bool IsValid(handle_type h) {
  144. return h != GetInvalid();
  145. }
  146. };
  147. struct FindHandleTraits : CommonHandleTraits {
  148. static void Close(handle_type h) {
  149. ::FindClose(h);
  150. }
  151. };
  152. struct FileHandleTraits : CommonHandleTraits {};
  153. typedef ScopedHandle<CommonHandleTraits> ScopedCommonHandle;
  154. typedef ScopedHandle<FileHandleTraits> ScopedFileHandle;
  155. typedef ScopedHandle<CryptContextTraits> ScopedCryptContext;
  156. typedef ScopedHandle<RegTraits> ScopedRegHandle;
  157. typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
  158. typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;
  159. template <class T>
  160. class SmallVectorImpl;
  161. template <class T>
  162. typename SmallVectorImpl<T>::const_pointer
  163. c_str(SmallVectorImpl<T> &str) {
  164. str.push_back(0);
  165. str.pop_back();
  166. return str.data();
  167. }
  168. namespace sys {
  169. inline std::chrono::nanoseconds toDuration(FILETIME Time) {
  170. ULARGE_INTEGER TimeInteger;
  171. TimeInteger.LowPart = Time.dwLowDateTime;
  172. TimeInteger.HighPart = Time.dwHighDateTime;
  173. // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
  174. return std::chrono::nanoseconds(100 * TimeInteger.QuadPart);
  175. }
  176. inline TimePoint<> toTimePoint(FILETIME Time) {
  177. ULARGE_INTEGER TimeInteger;
  178. TimeInteger.LowPart = Time.dwLowDateTime;
  179. TimeInteger.HighPart = Time.dwHighDateTime;
  180. // Adjust for different epoch
  181. TimeInteger.QuadPart -= 11644473600ll * 10000000;
  182. // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
  183. return TimePoint<>(std::chrono::nanoseconds(100 * TimeInteger.QuadPart));
  184. }
  185. inline FILETIME toFILETIME(TimePoint<> TP) {
  186. ULARGE_INTEGER TimeInteger;
  187. TimeInteger.QuadPart = TP.time_since_epoch().count() / 100;
  188. TimeInteger.QuadPart += 11644473600ll * 10000000;
  189. FILETIME Time;
  190. Time.dwLowDateTime = TimeInteger.LowPart;
  191. Time.dwHighDateTime = TimeInteger.HighPart;
  192. return Time;
  193. }
  194. namespace windows {
  195. // Returns command line arguments. Unlike arguments given to main(),
  196. // this function guarantees that the returned arguments are encoded in
  197. // UTF-8 regardless of the current code page setting.
  198. std::error_code GetCommandLineArguments(SmallVectorImpl<const char *> &Args,
  199. BumpPtrAllocator &Alloc);
  200. /// Convert UTF-8 path to a suitable UTF-16 path for use with the Win32 Unicode
  201. /// File API.
  202. std::error_code widenPath(const Twine &Path8, SmallVectorImpl<wchar_t> &Path16,
  203. size_t MaxPathLen = MAX_PATH);
  204. } // end namespace windows
  205. } // end namespace sys
  206. } // end namespace llvm.
  207. #endif
  208. #ifdef __GNUC__
  209. #pragma GCC diagnostic pop
  210. #endif