///////////////////////////////////////////////////////////////////////////////
// MuldeR's Utilities for Qt
-// Copyright (C) 2004-2015 LoRd_MuldeR <MuldeR2@GMX.de>
+// Copyright (C) 2004-2016 LoRd_MuldeR <MuldeR2@GMX.de>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
{ MUtils::OS::Version::WINDOWS_WIN70, "Windows 7 or Windows Server 2008 R2" }, //7
{ MUtils::OS::Version::WINDOWS_WIN80, "Windows 8 or Windows Server 2012" }, //8
{ MUtils::OS::Version::WINDOWS_WIN81, "Windows 8.1 or Windows Server 2012 R2" }, //8.1
- { MUtils::OS::Version::WINDOWS_WN100, "Windows 10 or Windows Server 2014 (Preview)" }, //10
+ { MUtils::OS::Version::WINDOWS_WN100, "Windows 10 or Windows Server 2016" }, //10
{ MUtils::OS::Version::UNKNOWN_OPSYS, "N/A" }
};
bool os_version_t::operator<= (const os_version_t &rhs) const { return (type == rhs.type) && ((versionMajor < rhs.versionMajor) || ((versionMajor == rhs.versionMajor) && (versionMinor <= rhs.versionMinor))); }
//Known Windows NT versions
- const os_version_t WINDOWS_WIN2K = { OS_WINDOWS, 5, 0 }; // 2000
- const os_version_t WINDOWS_WINXP = { OS_WINDOWS, 5, 1 }; // XP
- const os_version_t WINDOWS_XPX64 = { OS_WINDOWS, 5, 2 }; // XP_x64
- const os_version_t WINDOWS_VISTA = { OS_WINDOWS, 6, 0 }; // Vista
- const os_version_t WINDOWS_WIN70 = { OS_WINDOWS, 6, 1 }; // 7
- const os_version_t WINDOWS_WIN80 = { OS_WINDOWS, 6, 2 }; // 8
- const os_version_t WINDOWS_WIN81 = { OS_WINDOWS, 6, 3 }; // 8.1
- const os_version_t WINDOWS_WN100 = { OS_WINDOWS, 10, 0 }; // 10
+ const os_version_t WINDOWS_WIN2K = { OS_WINDOWS, 5, 0, 2195 }; // 2000
+ const os_version_t WINDOWS_WINXP = { OS_WINDOWS, 5, 1, 2600 }; // XP
+ const os_version_t WINDOWS_XPX64 = { OS_WINDOWS, 5, 2, 3790 }; // XP_x64
+ const os_version_t WINDOWS_VISTA = { OS_WINDOWS, 6, 0, 6000 }; // Vista
+ const os_version_t WINDOWS_WIN70 = { OS_WINDOWS, 6, 1, 7600 }; // 7
+ const os_version_t WINDOWS_WIN80 = { OS_WINDOWS, 6, 2, 9200 }; // 8
+ const os_version_t WINDOWS_WIN81 = { OS_WINDOWS, 6, 3, 9600 }; // 8.1
+ const os_version_t WINDOWS_WN100 = { OS_WINDOWS, 10, 0, 10240 }; // 10
//Unknown OS
- const os_version_t UNKNOWN_OPSYS = { OS_UNKNOWN, 0, 0 }; // N/A
+ const os_version_t UNKNOWN_OPSYS = { OS_UNKNOWN, 0, 0, 0 }; // N/A
}
}
}
+static inline DWORD SAFE_ADD(const DWORD &a, const DWORD &b, const DWORD &limit = MAXDWORD)
+{
+ return ((a >= limit) || (b >= limit) || ((limit - a) <= b)) ? limit : (a + b);
+}
+
+
+static void initialize_os_version(OSVERSIONINFOEXW *const osInfo)
+{
+ memset(osInfo, 0, sizeof(OSVERSIONINFOEXW));
+ osInfo->dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
+}
+
+static inline DWORD initialize_step_size(const DWORD &limit)
+{
+ DWORD result = 1;
+ while (result < limit)
+ {
+ result = SAFE_ADD(result, result);
+ }
+ return result;
+}
+
+static bool rtl_get_version(OSVERSIONINFOEXW *const osInfo)
+{
+ typedef LONG(__stdcall *RtlGetVersion)(LPOSVERSIONINFOEXW);
+ if (const HMODULE ntdll = GetModuleHandleW(L"ntdll"))
+ {
+ if (const RtlGetVersion pRtlGetVersion = (RtlGetVersion)GetProcAddress(ntdll, "RtlGetVersion"))
+ {
+ initialize_os_version(osInfo);
+ if (pRtlGetVersion(osInfo) == 0)
+ {
+ return true;
+ }
+ }
+ }
+
+ //Fallback
+ initialize_os_version(osInfo);
+ return (GetVersionExW((LPOSVERSIONINFOW)osInfo) != FALSE);
+}
+
+static bool rtl_verify_version(OSVERSIONINFOEXW *const osInfo, const ULONG typeMask, const ULONGLONG condMask)
+{
+ typedef LONG(__stdcall *RtlVerifyVersionInfo)(LPOSVERSIONINFOEXW, ULONG, ULONGLONG);
+ if (const HMODULE ntdll = GetModuleHandleW(L"ntdll"))
+ {
+ if (const RtlVerifyVersionInfo pRtlVerifyVersionInfo = (RtlVerifyVersionInfo)GetProcAddress(ntdll, "RtlVerifyVersionInfo"))
+ {
+ if (pRtlVerifyVersionInfo(osInfo, typeMask, condMask) == 0)
+ {
+ return true;
+ }
+ }
+ }
+
+ //Fallback
+ return (VerifyVersionInfoW(osInfo, typeMask, condMask) != FALSE);
+}
+
static bool verify_os_version(const DWORD major, const DWORD minor)
{
OSVERSIONINFOEXW osvi;
DWORDLONG dwlConditionMask = 0;
+ initialize_os_version(&osvi);
//Initialize the OSVERSIONINFOEX structure
- memset(&osvi, 0, sizeof(OSVERSIONINFOEXW));
- osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
osvi.dwMajorVersion = major;
osvi.dwMinorVersion = minor;
osvi.dwPlatformId = VER_PLATFORM_WIN32_NT;
VER_SET_CONDITION(dwlConditionMask, VER_PLATFORMID, VER_EQUAL);
// Perform the test
- const BOOL ret = VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, dwlConditionMask);
+ const BOOL ret = rtl_verify_version(&osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, dwlConditionMask);
//Error checking
if(!ret)
return (ret != FALSE);
}
-static bool get_real_os_version(unsigned int *major, unsigned int *minor, bool *pbOverride)
+static bool verify_os_build(const DWORD build)
+{
+ OSVERSIONINFOEXW osvi;
+ DWORDLONG dwlConditionMask = 0;
+ initialize_os_version(&osvi);
+
+ //Initialize the OSVERSIONINFOEX structure
+ osvi.dwBuildNumber = build;
+ osvi.dwPlatformId = VER_PLATFORM_WIN32_NT;
+
+ //Initialize the condition mask
+ VER_SET_CONDITION(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL);
+ VER_SET_CONDITION(dwlConditionMask, VER_PLATFORMID, VER_EQUAL);
+
+ // Perform the test
+ const BOOL ret = rtl_verify_version(&osvi, VER_BUILDNUMBER | VER_PLATFORMID, dwlConditionMask);
+
+ //Error checking
+ if (!ret)
+ {
+ if (GetLastError() != ERROR_OLD_WIN_VERSION)
+ {
+ qWarning("VerifyVersionInfo() system call has failed!");
+ }
+ }
+
+ return (ret != FALSE);
+}
+
+static bool get_real_os_version(unsigned int *major, unsigned int *minor, unsigned int *build, bool *pbOverride)
{
- *major = *minor = 0;
+ static const DWORD MAX_VERSION = 0xFFFF;
+ static const DWORD MAX_BUILDNO = MAXINT;
+
+ *major = *minor = *build = 0;
*pbOverride = false;
//Initialize local variables
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
//Try GetVersionEx() first
- if(GetVersionExW((LPOSVERSIONINFOW)&osvi) == FALSE)
+ if(rtl_get_version(&osvi) == FALSE)
{
qWarning("GetVersionEx() has failed, cannot detect Windows version!");
return false;
{
*major = osvi.dwMajorVersion;
*minor = osvi.dwMinorVersion;
+ *build = osvi.dwBuildNumber;
}
else
{
- qWarning("Not running on Windows NT, unsupported operating system!");
- return false;
+ if (verify_os_version(4, 0))
+ {
+ *major = 4;
+ *build = 1381;
+ *pbOverride = true;
+ }
+ else
+ {
+ qWarning("Not running on Windows NT, unsupported operating system!");
+ return false;
+ }
}
- //Determine the real *major* version first
- forever
+ //Major Version
+ for (DWORD nextMajor = (*major) + 1; nextMajor <= MAX_VERSION; nextMajor++)
{
- const DWORD nextMajor = (*major) + 1;
- if(verify_os_version(nextMajor, 0))
+ if (verify_os_version(nextMajor, 0))
{
- *pbOverride = true;
*major = nextMajor;
*minor = 0;
+ *pbOverride = true;
continue;
}
break;
}
- //Now also determine the real *minor* version
- forever
+ //Minor Version
+ for (DWORD nextMinor = (*minor) + 1; nextMinor <= MAX_VERSION; nextMinor++)
{
- const DWORD nextMinor = (*minor) + 1;
- if(verify_os_version((*major), nextMinor))
+ if (verify_os_version((*major), nextMinor))
{
- *pbOverride = true;
*minor = nextMinor;
+ *pbOverride = true;
continue;
}
break;
}
- //Workaround for the mess that is sometimes referred to as "Windows 10"
- if(((*major) > 6) || (((*major) == 6) && ((*minor) >= 2)))
+ //Build Version
+ if (verify_os_build(SAFE_ADD((*build), 1, MAX_BUILDNO)))
{
- quint16 kernel32_major, kernel32_minor;
- if(MUtils::OS::get_file_version(QLatin1String("kernel32"), &kernel32_major, &kernel32_minor))
+ DWORD stepSize = initialize_step_size(MAX_BUILDNO);
+ for (DWORD nextBuildNo = SAFE_ADD((*build), stepSize, MAX_BUILDNO); (*build) < MAX_BUILDNO; nextBuildNo = SAFE_ADD((*build), stepSize, MAX_BUILDNO))
{
- if((kernel32_major > (*major)) || ((kernel32_major == (*major)) && (kernel32_minor > (*minor))))
+ if (verify_os_build(nextBuildNo))
{
- *major = kernel32_major;
- *minor = kernel32_minor;
+ *build = nextBuildNo;
*pbOverride = true;
+ continue;
+ }
+ if (stepSize > 1)
+ {
+ stepSize = stepSize / 2;
+ continue;
}
+ break;
}
}
}
//Detect OS version
- unsigned int major, minor; bool overrideFlg;
- if(get_real_os_version(&major, &minor, &overrideFlg))
+ unsigned int major, minor, build; bool overrideFlg;
+ if(get_real_os_version(&major, &minor, &build, &overrideFlg))
{
g_os_version_info.type = Version::OS_WINDOWS;
g_os_version_info.versionMajor = major;
g_os_version_info.versionMinor = minor;
+ g_os_version_info.versionBuild = build;
g_os_version_info.overrideFlag = overrideFlg;
}
else
return list;
}
-static QString &get_file_path_translate(QString &path)
+static void get_file_path_translate(QString &path)
{
- static const DWORD BUFSIZE = 4096;
+ static const DWORD BUFSIZE = 2048;
wchar_t buffer[BUFSIZE], drive[3];
const QString driveList = get_file_path_drive_list();
}
}
}
-
- return path;
}
static QString get_file_path_fallback(const HANDLE &hFile)
const HANDLE hFileMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 1, NULL);
if (hFileMap)
{
- void* pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
+ void *const pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);
if (pMem)
{
- static const DWORD BUFSIZE = 4096;
- wchar_t buffer[BUFSIZE];
- if (GetMappedFileNameW(GetCurrentProcess(), pMem, buffer, BUFSIZE))
+ static const size_t BUFFSIZE = 2048;
+ wchar_t buffer[BUFFSIZE];
+ if (GetMappedFileNameW(GetCurrentProcess(), pMem, buffer, BUFFSIZE) > 0)
{
- filePath = get_file_path_translate(MUTILS_QSTR(buffer));
+ filePath = MUTILS_QSTR(buffer);
}
UnmapViewOfFile(pMem);
}
CloseHandle(hFileMap);
}
+ if (!filePath.isEmpty())
+ {
+ get_file_path_translate(filePath);
+ }
+
return filePath;
}
const GetPathNameByHandleFun getPathNameByHandleFun = MUtils::Win32Utils::resolve<GetPathNameByHandleFun>(QLatin1String("kernel32"), QLatin1String("GetFinalPathNameByHandleW"));
if (!getPathNameByHandleFun)
{
- qWarning("MUtils::OS::get_file_path() --> fallback!");
return get_file_path_fallback((HANDLE)_get_osfhandle(fd));
}
// EXECUTABLE CHECK
///////////////////////////////////////////////////////////////////////////////
+static int g_library_as_image_resource_supported = -1;
+static QReadWriteLock g_library_as_image_resource_supported_lock;
+
+static bool library_as_image_resource_supported()
+{
+ QReadLocker readLocker(&g_library_as_image_resource_supported_lock);
+ if (g_library_as_image_resource_supported >= 0)
+ {
+ return (g_library_as_image_resource_supported > 0);
+ }
+
+ readLocker.unlock();
+ QWriteLocker writeLocker(&g_library_as_image_resource_supported_lock);
+
+ if (g_library_as_image_resource_supported < 0)
+ {
+ g_library_as_image_resource_supported = 0;
+ OSVERSIONINFOEXW osvi;
+ if (rtl_get_version(&osvi))
+ {
+ if ((osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osvi.dwMajorVersion >= 6U))
+ {
+ g_library_as_image_resource_supported = 1;
+ }
+ }
+ }
+
+ return (g_library_as_image_resource_supported > 0);
+}
+
bool MUtils::OS::is_executable_file(const QString &path)
{
- bool bIsExecutable = false;
DWORD binaryType;
if(GetBinaryType(MUTILS_WCHR(QDir::toNativeSeparators(path)), &binaryType))
{
- bIsExecutable = (binaryType == SCS_32BIT_BINARY || binaryType == SCS_64BIT_BINARY);
+ return ((binaryType == SCS_32BIT_BINARY) || (binaryType == SCS_64BIT_BINARY));
+ }
+
+ const DWORD errorCode = GetLastError();
+ qWarning("GetBinaryType() failed with error: 0x%08X", errorCode);
+ return false;
+}
+
+bool MUtils::OS::is_library_file(const QString &path)
+{
+ const DWORD flags = library_as_image_resource_supported() ? (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE) : (LOAD_LIBRARY_AS_DATAFILE | DONT_RESOLVE_DLL_REFERENCES);
+ if (const HMODULE hMod = LoadLibraryEx(MUTILS_WCHR(QDir::toNativeSeparators(path)), NULL, flags))
+ {
+ FreeLibrary(hMod);
+ return true;
}
- return bIsExecutable;
+
+ const DWORD errorCode = GetLastError();
+ qWarning("LoadLibraryEx() failed with error: 0x%08X", errorCode);
+ return false;
}
///////////////////////////////////////////////////////////////////////////////