[Windows] Simplify WindowsSupport.h

Sink Windows version detection code from WindowsSupport.h to Path.inc.
These functions don't need to be inlined. I randomly picked Process.inc
for the Windows version helpers, since that's the most related file.

Sink MakeErrMsg to Program.inc since it's the main client.

Move those functions into the llvm namespace, and delete the scoped
handle copy and assignment operators.

Reviewers: zturner, aganea

Differential Revision: https://reviews.llvm.org/D54182

llvm-svn: 346280
This commit is contained in:
Reid Kleckner 2018-11-06 23:39:59 +00:00
parent 39b6ba9f33
commit c30932248f
3 changed files with 54 additions and 82 deletions

View File

@ -460,3 +460,27 @@ unsigned Process::GetRandomNumber() {
ReportLastErrorFatal("Could not generate a random number"); ReportLastErrorFatal("Could not generate a random number");
return Ret; return Ret;
} }
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
llvm::VersionTuple llvm::GetWindowsOSVersion() {
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
if (hMod) {
auto getVer = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
if (getVer) {
RTL_OSVERSIONINFOEXW info{};
info.dwOSVersionInfoSize = sizeof(info);
if (getVer((PRTL_OSVERSIONINFOW)&info) == STATUS_SUCCESS) {
return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, 0,
info.dwBuildNumber);
}
}
}
return llvm::VersionTuple(0, 0, 0, 0);
}
bool llvm::RunningWindows8OrGreater() {
// Windows 8 is version 6.2, service pack 0.
return GetWindowsOSVersion() >= llvm::VersionTuple(6, 2, 0, 0);
}

View File

@ -105,6 +105,25 @@ ErrorOr<std::string> sys::findProgramByName(StringRef Name,
return std::string(U8Result.begin(), U8Result.end()); return std::string(U8Result.begin(), U8Result.end());
} }
bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) {
if (!ErrMsg)
return true;
char *buffer = NULL;
DWORD LastError = GetLastError();
DWORD R = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL, LastError, 0, (LPSTR)&buffer, 1, NULL);
if (R)
*ErrMsg = prefix + ": " + buffer;
else
*ErrMsg = prefix + ": Unknown error";
*ErrMsg += " (0x" + llvm::utohexstr(LastError) + ")";
LocalFree(buffer);
return R != 0;
}
static HANDLE RedirectIO(Optional<StringRef> Path, int fd, static HANDLE RedirectIO(Optional<StringRef> Path, int fd,
std::string *ErrMsg) { std::string *ErrMsg) {
HANDLE h; HANDLE h;

View File

@ -50,99 +50,29 @@
// Must be included after windows.h // Must be included after windows.h
#include <wincrypt.h> #include <wincrypt.h>
namespace llvm {
/// Determines if the program is running on Windows 8 or newer. This /// Determines if the program is running on Windows 8 or newer. This
/// reimplements one of the helpers in the Windows 8.1 SDK, which are intended /// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
/// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't /// to supercede raw calls to GetVersionEx. Old SDKs, Cygwin, and MinGW don't
/// yet have VersionHelpers.h, so we have our own helper. /// yet have VersionHelpers.h, so we have our own helper.
inline bool RunningWindows8OrGreater() { bool RunningWindows8OrGreater();
// Windows 8 is version 6.2, service pack 0.
OSVERSIONINFOEXW osvi = {};
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
osvi.dwMajorVersion = 6;
osvi.dwMinorVersion = 2;
osvi.wServicePackMajor = 0;
DWORDLONG Mask = 0; /// Returns the Windows version as Major.Minor.0.BuildNumber. Uses
Mask = VerSetConditionMask(Mask, VER_MAJORVERSION, VER_GREATER_EQUAL); /// RtlGetVersion or GetVersionEx under the hood depending on what is available.
Mask = VerSetConditionMask(Mask, VER_MINORVERSION, VER_GREATER_EQUAL); /// GetVersionEx is deprecated, but this API exposes the build number which can
Mask = VerSetConditionMask(Mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); /// be useful for working around certain kernel bugs.
llvm::VersionTuple GetWindowsOSVersion();
return VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix);
VER_SERVICEPACKMAJOR,
Mask) != FALSE;
}
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
inline llvm::VersionTuple GetWindowsOSVersion() {
HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
if (hMod) {
auto getVer = (RtlGetVersionPtr)::GetProcAddress(hMod, "RtlGetVersion");
if (getVer) {
RTL_OSVERSIONINFOEXW info{};
info.dwOSVersionInfoSize = sizeof(info);
if (getVer((PRTL_OSVERSIONINFOW)&info) == STATUS_SUCCESS) {
return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, 0,
info.dwBuildNumber);
}
}
}
OSVERSIONINFOEX info;
ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996)
#endif // _MSC_VER
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
#endif // __clang__
// Starting with Microsoft SDK for Windows 8.1, this function is deprecated
// in favor of the new Windows Version Helper APIs. Since we don't specify a
// minimum SDK version, it's easier to simply disable the warning rather than
// try to support both APIs.
if (GetVersionEx((LPOSVERSIONINFO)&info) == 0)
return llvm::VersionTuple();
#if defined(__clang__)
#pragma clang diagnostic pop
#endif // __clang__
#if defined(_MSC_VER)
#pragma warning(pop)
#endif // _MSC_VER
return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion, 0,
info.dwBuildNumber);
}
inline bool MakeErrMsg(std::string *ErrMsg, const std::string &prefix) {
if (!ErrMsg)
return true;
char *buffer = NULL;
DWORD LastError = GetLastError();
DWORD R = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL, LastError, 0, (LPSTR)&buffer, 1, NULL);
if (R)
*ErrMsg = prefix + ": " + buffer;
else
*ErrMsg = prefix + ": Unknown error";
*ErrMsg += " (0x" + llvm::utohexstr(LastError) + ")";
LocalFree(buffer);
return R != 0;
}
template <typename HandleTraits> template <typename HandleTraits>
class ScopedHandle { class ScopedHandle {
typedef typename HandleTraits::handle_type handle_type; typedef typename HandleTraits::handle_type handle_type;
handle_type Handle; handle_type Handle;
ScopedHandle(const ScopedHandle &other); // = delete; ScopedHandle(const ScopedHandle &other) = delete;
void operator=(const ScopedHandle &other); // = delete; void operator=(const ScopedHandle &other) = delete;
public: public:
ScopedHandle() ScopedHandle()
: Handle(HandleTraits::GetInvalid()) {} : Handle(HandleTraits::GetInvalid()) {}
@ -247,7 +177,6 @@ typedef ScopedHandle<RegTraits> ScopedRegHandle;
typedef ScopedHandle<FindHandleTraits> ScopedFindHandle; typedef ScopedHandle<FindHandleTraits> ScopedFindHandle;
typedef ScopedHandle<JobHandleTraits> ScopedJobHandle; typedef ScopedHandle<JobHandleTraits> ScopedJobHandle;
namespace llvm {
template <class T> template <class T>
class SmallVectorImpl; class SmallVectorImpl;