2012-09-20 19:53:14 +00:00
|
|
|
/*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
2005-09-08 00:09:32 +00:00
|
|
|
* PROJECT: ReactOS system libraries
|
|
|
|
* PURPOSE: Runtime code
|
|
|
|
* FILE: lib/rtl/version.c
|
2012-09-20 20:46:08 +00:00
|
|
|
* PROGRAMERS: Filip Navara
|
|
|
|
* Hermes BELUSCA - MAITO
|
2004-05-31 19:33:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
2005-06-17 07:57:37 +00:00
|
|
|
|
2005-07-26 08:39:07 +00:00
|
|
|
#include <rtl.h>
|
2004-05-31 19:33:59 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
|
|
|
#include <debug.h>
|
|
|
|
|
2004-08-05 18:17:37 +00:00
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
|
2005-03-29 15:22:44 +00:00
|
|
|
NTSTATUS
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2005-03-29 15:22:44 +00:00
|
|
|
RtlGetVersion(
|
|
|
|
OUT PRTL_OSVERSIONINFOW lpVersionInformation
|
|
|
|
);
|
2004-05-31 19:33:59 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2012-09-20 20:46:08 +00:00
|
|
|
static BYTE
|
|
|
|
RtlpVerGetCondition(IN ULONGLONG dwlConditionMask,
|
|
|
|
IN DWORD dwTypeBitMask);
|
|
|
|
|
2012-09-20 19:53:14 +00:00
|
|
|
static BOOLEAN
|
|
|
|
RtlpVerCompare(ULONG left, ULONG right, UCHAR condition)
|
2008-07-23 11:19:01 +00:00
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
switch (condition)
|
|
|
|
{
|
2008-07-23 11:19:01 +00:00
|
|
|
case VER_EQUAL:
|
2012-09-20 19:53:14 +00:00
|
|
|
return (left == right);
|
2008-07-23 11:19:01 +00:00
|
|
|
case VER_GREATER:
|
2012-09-20 19:53:14 +00:00
|
|
|
return (left > right);
|
2008-07-23 11:19:01 +00:00
|
|
|
case VER_GREATER_EQUAL:
|
2012-09-20 19:53:14 +00:00
|
|
|
return (left >= right);
|
2008-07-23 11:19:01 +00:00
|
|
|
case VER_LESS:
|
2012-09-20 19:53:14 +00:00
|
|
|
return (left < right);
|
2008-07-23 11:19:01 +00:00
|
|
|
case VER_LESS_EQUAL:
|
2012-09-20 19:53:14 +00:00
|
|
|
return (left <= right);
|
2008-07-23 11:19:01 +00:00
|
|
|
default:
|
2012-09-20 19:53:14 +00:00
|
|
|
break;
|
2008-07-23 11:19:01 +00:00
|
|
|
}
|
2012-09-20 19:53:14 +00:00
|
|
|
return FALSE;
|
2008-07-23 11:19:01 +00:00
|
|
|
}
|
|
|
|
|
2004-08-05 18:17:37 +00:00
|
|
|
/*
|
2005-03-29 15:22:44 +00:00
|
|
|
* @implemented
|
2004-08-05 18:17:37 +00:00
|
|
|
*/
|
|
|
|
NTSTATUS
|
2005-10-19 17:03:38 +00:00
|
|
|
NTAPI
|
2004-08-05 18:17:37 +00:00
|
|
|
RtlVerifyVersionInfo(
|
2008-07-23 11:19:01 +00:00
|
|
|
IN PRTL_OSVERSIONINFOEXW VersionInfo,
|
|
|
|
IN ULONG TypeMask,
|
|
|
|
IN ULONGLONG ConditionMask
|
|
|
|
)
|
2004-08-05 18:17:37 +00:00
|
|
|
{
|
2005-03-29 15:22:44 +00:00
|
|
|
RTL_OSVERSIONINFOEXW ver;
|
|
|
|
NTSTATUS status;
|
2012-09-20 19:53:14 +00:00
|
|
|
BOOLEAN comparison;
|
2005-03-29 15:22:44 +00:00
|
|
|
|
|
|
|
/* FIXME:
|
|
|
|
- Check the following special case on Windows (various versions):
|
|
|
|
o lp->wSuiteMask == 0 and ver.wSuiteMask != 0 and VER_AND/VER_OR
|
|
|
|
o lp->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW)
|
|
|
|
- MSDN talks about some tests being impossible. Check what really happens.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ver.dwOSVersionInfoSize = sizeof(ver);
|
2012-09-20 20:46:08 +00:00
|
|
|
status = RtlGetVersion((PRTL_OSVERSIONINFOW)&ver);
|
2008-07-23 11:19:01 +00:00
|
|
|
if (status != STATUS_SUCCESS) return status;
|
2005-03-29 15:22:44 +00:00
|
|
|
|
2012-09-20 19:53:14 +00:00
|
|
|
if (!TypeMask || !ConditionMask) return STATUS_INVALID_PARAMETER;
|
2005-03-29 15:22:44 +00:00
|
|
|
|
2012-09-20 19:53:14 +00:00
|
|
|
if (TypeMask & VER_PRODUCT_TYPE)
|
2008-07-23 11:19:01 +00:00
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
comparison = RtlpVerCompare(ver.wProductType,
|
|
|
|
VersionInfo->wProductType,
|
2012-09-20 20:46:08 +00:00
|
|
|
RtlpVerGetCondition(ConditionMask, VER_PRODUCT_TYPE));
|
2012-09-20 19:53:14 +00:00
|
|
|
if (!comparison)
|
|
|
|
return STATUS_REVISION_MISMATCH;
|
2008-07-23 11:19:01 +00:00
|
|
|
}
|
2012-09-20 19:53:14 +00:00
|
|
|
|
|
|
|
if (TypeMask & VER_SUITENAME)
|
2008-07-23 11:19:01 +00:00
|
|
|
{
|
2012-09-20 20:46:08 +00:00
|
|
|
switch (RtlpVerGetCondition(ConditionMask, VER_SUITENAME))
|
2005-03-29 15:22:44 +00:00
|
|
|
{
|
|
|
|
case VER_AND:
|
2012-09-20 19:53:14 +00:00
|
|
|
if ((VersionInfo->wSuiteMask & ver.wSuiteMask) != VersionInfo->wSuiteMask)
|
|
|
|
{
|
2005-03-29 15:22:44 +00:00
|
|
|
return STATUS_REVISION_MISMATCH;
|
2012-09-20 19:53:14 +00:00
|
|
|
}
|
2005-03-29 15:22:44 +00:00
|
|
|
break;
|
|
|
|
case VER_OR:
|
2012-09-20 19:53:14 +00:00
|
|
|
if (!(VersionInfo->wSuiteMask & ver.wSuiteMask) && VersionInfo->wSuiteMask)
|
|
|
|
{
|
2005-03-29 15:22:44 +00:00
|
|
|
return STATUS_REVISION_MISMATCH;
|
2012-09-20 19:53:14 +00:00
|
|
|
}
|
2005-03-29 15:22:44 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return STATUS_INVALID_PARAMETER;
|
|
|
|
}
|
2008-07-23 11:19:01 +00:00
|
|
|
}
|
2012-09-20 19:53:14 +00:00
|
|
|
|
|
|
|
if (TypeMask & VER_PLATFORMID)
|
2008-07-23 11:19:01 +00:00
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
comparison = RtlpVerCompare(ver.dwPlatformId,
|
|
|
|
VersionInfo->dwPlatformId,
|
2012-09-20 20:46:08 +00:00
|
|
|
RtlpVerGetCondition(ConditionMask, VER_PLATFORMID));
|
2012-09-20 19:53:14 +00:00
|
|
|
if (!comparison)
|
|
|
|
return STATUS_REVISION_MISMATCH;
|
2008-07-23 11:19:01 +00:00
|
|
|
}
|
2012-09-20 19:53:14 +00:00
|
|
|
|
|
|
|
if (TypeMask & VER_BUILDNUMBER)
|
2008-07-23 11:19:01 +00:00
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
comparison = RtlpVerCompare(ver.dwBuildNumber,
|
|
|
|
VersionInfo->dwBuildNumber,
|
2012-09-20 20:46:08 +00:00
|
|
|
RtlpVerGetCondition(ConditionMask, VER_BUILDNUMBER));
|
2012-09-20 19:53:14 +00:00
|
|
|
if (!comparison)
|
|
|
|
return STATUS_REVISION_MISMATCH;
|
2008-07-23 11:19:01 +00:00
|
|
|
}
|
2012-09-20 19:53:14 +00:00
|
|
|
|
2012-09-20 20:46:08 +00:00
|
|
|
TypeMask &= VER_MAJORVERSION|VER_MINORVERSION|VER_SERVICEPACKMAJOR|VER_SERVICEPACKMINOR;
|
|
|
|
if (TypeMask)
|
2008-07-23 11:19:01 +00:00
|
|
|
{
|
|
|
|
BOOLEAN do_next_check = TRUE;
|
2012-09-20 20:46:08 +00:00
|
|
|
/*
|
|
|
|
* Select the leading comparison operator (for example, the comparison
|
|
|
|
* operator for VER_MAJORVERSION supersedes the others for VER_MINORVERSION,
|
|
|
|
* VER_SERVICEPACKMAJOR and VER_SERVICEPACKMINOR).
|
|
|
|
*/
|
|
|
|
BYTE condition = RtlpVerGetCondition(ConditionMask, TypeMask);
|
2008-07-23 11:19:01 +00:00
|
|
|
|
2012-09-20 19:53:14 +00:00
|
|
|
comparison = TRUE;
|
|
|
|
if (TypeMask & VER_MAJORVERSION)
|
2005-03-29 15:22:44 +00:00
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
comparison = RtlpVerCompare(ver.dwMajorVersion,
|
|
|
|
VersionInfo->dwMajorVersion,
|
|
|
|
condition);
|
2008-07-23 11:19:01 +00:00
|
|
|
do_next_check = (ver.dwMajorVersion == VersionInfo->dwMajorVersion) &&
|
2012-09-20 19:53:14 +00:00
|
|
|
((condition != VER_EQUAL) || comparison);
|
2005-03-29 15:22:44 +00:00
|
|
|
}
|
2012-09-20 19:53:14 +00:00
|
|
|
if ((TypeMask & VER_MINORVERSION) && do_next_check)
|
2005-03-29 15:22:44 +00:00
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
comparison = RtlpVerCompare(ver.dwMinorVersion,
|
|
|
|
VersionInfo->dwMinorVersion,
|
|
|
|
condition);
|
2008-07-23 11:19:01 +00:00
|
|
|
do_next_check = (ver.dwMinorVersion == VersionInfo->dwMinorVersion) &&
|
2012-09-20 19:53:14 +00:00
|
|
|
((condition != VER_EQUAL) || comparison);
|
2005-03-29 15:22:44 +00:00
|
|
|
}
|
2012-09-20 19:53:14 +00:00
|
|
|
if ((TypeMask & VER_SERVICEPACKMAJOR) && do_next_check)
|
2005-03-29 15:22:44 +00:00
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
comparison = RtlpVerCompare(ver.wServicePackMajor,
|
|
|
|
VersionInfo->wServicePackMajor,
|
|
|
|
condition);
|
2008-07-23 11:19:01 +00:00
|
|
|
do_next_check = (ver.wServicePackMajor == VersionInfo->wServicePackMajor) &&
|
2012-09-20 19:53:14 +00:00
|
|
|
((condition != VER_EQUAL) || comparison);
|
2005-03-29 15:22:44 +00:00
|
|
|
}
|
2012-09-20 19:53:14 +00:00
|
|
|
if ((TypeMask & VER_SERVICEPACKMINOR) && do_next_check)
|
2005-03-29 15:22:44 +00:00
|
|
|
{
|
2012-09-20 19:53:14 +00:00
|
|
|
comparison = RtlpVerCompare(ver.wServicePackMinor,
|
|
|
|
VersionInfo->wServicePackMinor,
|
|
|
|
condition);
|
2005-03-29 15:22:44 +00:00
|
|
|
}
|
|
|
|
|
2012-09-20 19:53:14 +00:00
|
|
|
if (!comparison)
|
|
|
|
return STATUS_REVISION_MISMATCH;
|
2008-07-23 11:19:01 +00:00
|
|
|
}
|
|
|
|
|
2005-03-29 15:22:44 +00:00
|
|
|
return STATUS_SUCCESS;
|
2004-08-05 18:17:37 +00:00
|
|
|
}
|
2005-03-29 15:22:44 +00:00
|
|
|
|
2012-09-20 20:46:08 +00:00
|
|
|
static BYTE
|
|
|
|
RtlpVerGetCondition(IN ULONGLONG dwlConditionMask,
|
|
|
|
IN DWORD dwTypeBitMask)
|
|
|
|
{
|
|
|
|
BYTE bConditionMask = 0;
|
|
|
|
|
|
|
|
if (dwTypeBitMask & VER_PRODUCT_TYPE)
|
|
|
|
bConditionMask |= dwlConditionMask >> 7 * VER_NUM_BITS_PER_CONDITION_MASK;
|
|
|
|
else if (dwTypeBitMask & VER_SUITENAME)
|
|
|
|
bConditionMask |= dwlConditionMask >> 6 * VER_NUM_BITS_PER_CONDITION_MASK;
|
|
|
|
else if (dwTypeBitMask & VER_PLATFORMID)
|
|
|
|
bConditionMask |= dwlConditionMask >> 3 * VER_NUM_BITS_PER_CONDITION_MASK;
|
|
|
|
else if (dwTypeBitMask & VER_BUILDNUMBER)
|
|
|
|
bConditionMask |= dwlConditionMask >> 2 * VER_NUM_BITS_PER_CONDITION_MASK;
|
|
|
|
/*
|
|
|
|
* We choose here the lexicographical order on the 4D space
|
|
|
|
* {(Major ; Minor ; SP Major ; SP Minor)} to select the
|
|
|
|
* appropriate comparison operator.
|
|
|
|
* Therefore the following 'else if' instructions must be in this order.
|
|
|
|
*/
|
|
|
|
else if (dwTypeBitMask & VER_MAJORVERSION)
|
|
|
|
bConditionMask |= dwlConditionMask >> 1 * VER_NUM_BITS_PER_CONDITION_MASK;
|
|
|
|
else if (dwTypeBitMask & VER_MINORVERSION)
|
|
|
|
bConditionMask |= dwlConditionMask >> 0 * VER_NUM_BITS_PER_CONDITION_MASK;
|
|
|
|
else if (dwTypeBitMask & VER_SERVICEPACKMAJOR)
|
|
|
|
bConditionMask |= dwlConditionMask >> 5 * VER_NUM_BITS_PER_CONDITION_MASK;
|
|
|
|
else if (dwTypeBitMask & VER_SERVICEPACKMINOR)
|
|
|
|
bConditionMask |= dwlConditionMask >> 4 * VER_NUM_BITS_PER_CONDITION_MASK;
|
|
|
|
|
|
|
|
bConditionMask &= VER_CONDITION_MASK;
|
|
|
|
|
|
|
|
return bConditionMask;
|
|
|
|
}
|
|
|
|
|
2004-11-07 18:45:52 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2012-09-19 12:20:39 +00:00
|
|
|
ULONGLONG
|
|
|
|
NTAPI
|
2005-02-22 17:58:19 +00:00
|
|
|
VerSetConditionMask(IN ULONGLONG dwlConditionMask,
|
|
|
|
IN DWORD dwTypeBitMask,
|
2012-09-20 20:46:08 +00:00
|
|
|
IN BYTE bConditionMask)
|
2004-11-07 18:45:52 +00:00
|
|
|
{
|
2012-09-19 12:20:39 +00:00
|
|
|
if (dwTypeBitMask == 0)
|
|
|
|
return dwlConditionMask;
|
|
|
|
|
2012-09-20 20:46:08 +00:00
|
|
|
bConditionMask &= VER_CONDITION_MASK;
|
2012-09-19 12:20:39 +00:00
|
|
|
|
2012-09-20 20:46:08 +00:00
|
|
|
if (bConditionMask == 0)
|
2012-09-19 12:20:39 +00:00
|
|
|
return dwlConditionMask;
|
|
|
|
|
|
|
|
if (dwTypeBitMask & VER_PRODUCT_TYPE)
|
2012-09-20 20:46:08 +00:00
|
|
|
dwlConditionMask |= bConditionMask << 7 * VER_NUM_BITS_PER_CONDITION_MASK;
|
2012-09-19 12:20:39 +00:00
|
|
|
else if (dwTypeBitMask & VER_SUITENAME)
|
2012-09-20 20:46:08 +00:00
|
|
|
dwlConditionMask |= bConditionMask << 6 * VER_NUM_BITS_PER_CONDITION_MASK;
|
2012-09-19 12:20:39 +00:00
|
|
|
else if (dwTypeBitMask & VER_SERVICEPACKMAJOR)
|
2012-09-20 20:46:08 +00:00
|
|
|
dwlConditionMask |= bConditionMask << 5 * VER_NUM_BITS_PER_CONDITION_MASK;
|
2012-09-19 12:20:39 +00:00
|
|
|
else if (dwTypeBitMask & VER_SERVICEPACKMINOR)
|
2012-09-20 20:46:08 +00:00
|
|
|
dwlConditionMask |= bConditionMask << 4 * VER_NUM_BITS_PER_CONDITION_MASK;
|
2012-09-19 12:20:39 +00:00
|
|
|
else if (dwTypeBitMask & VER_PLATFORMID)
|
2012-09-20 20:46:08 +00:00
|
|
|
dwlConditionMask |= bConditionMask << 3 * VER_NUM_BITS_PER_CONDITION_MASK;
|
2012-09-19 12:20:39 +00:00
|
|
|
else if (dwTypeBitMask & VER_BUILDNUMBER)
|
2012-09-20 20:46:08 +00:00
|
|
|
dwlConditionMask |= bConditionMask << 2 * VER_NUM_BITS_PER_CONDITION_MASK;
|
2012-09-19 12:20:39 +00:00
|
|
|
else if (dwTypeBitMask & VER_MAJORVERSION)
|
2012-09-20 20:46:08 +00:00
|
|
|
dwlConditionMask |= bConditionMask << 1 * VER_NUM_BITS_PER_CONDITION_MASK;
|
2012-09-19 12:20:39 +00:00
|
|
|
else if (dwTypeBitMask & VER_MINORVERSION)
|
2012-09-20 20:46:08 +00:00
|
|
|
dwlConditionMask |= bConditionMask << 0 * VER_NUM_BITS_PER_CONDITION_MASK;
|
2005-02-22 17:58:19 +00:00
|
|
|
|
|
|
|
return dwlConditionMask;
|
2004-11-07 18:45:52 +00:00
|
|
|
}
|
|
|
|
|
2004-05-31 19:33:59 +00:00
|
|
|
/* EOF */
|