Files
reactos/reactos/lib/rtl/version.c
T
Hermès Bélusca-Maïto c32ac4bd68 [BOOTDATA]
- Remove hardcoded registry values: CurrentVersion, CSDVersion and CurrentBuildNumber from HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion. They are computed and stored there by the kernel.
- All the versioning is controlled by the two values: CSDReleaseType and CSDVersion in HKLM\SYSTEM\CurrentControlSet\Control\Windows. Currently we target SP1.

[NTDLL]
The lpVersionInformation->szCSDVersion string should not be built by RtlGetVersion, but instead retrieved from the Peb->CSDVersion string that in turn is initialized by the NTDLL PE Loader. Normally this is a App-Compatibility-dependent string, but for now we somewhat hardcode it (it is built using the actual Peb->OSCSDVersion number).

[RTL]: Rename some variables "à la NT" and use adequate types (but no code changes otherwise).

[NTOS]
- Fix PsGetVersion that should use the CmCSDVersionString variable. This API also returns TRUE if we are in checked build mode (the high byte of NtBuildNumber is flagged).
- The kernel should initialize the CurrentVersion, CSDVersion and CurrentBuildNumber registry values (and few other ones) from the two main CSDReleaseType and CSDVersion values.
- Fix the ReactOS-specific version+revision display in SOS mode.

CORE-6611 CORE-7889 CORE-8877

svn path=/trunk/; revision=66735
2015-03-16 03:14:16 +00:00

249 lines
8.3 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* PURPOSE: Runtime code
* FILE: lib/rtl/version.c
* PROGRAMERS: Filip Navara
* Hermes Belusca-Maito ([email protected])
*/
/* INCLUDES *****************************************************************/
#include <rtl.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS ******************************************************************/
NTSTATUS
NTAPI
RtlGetVersion(OUT PRTL_OSVERSIONINFOW lpVersionInformation);
/* FUNCTIONS ****************************************************************/
static UCHAR
RtlpVerGetCondition(IN ULONGLONG ConditionMask,
IN ULONG TypeMask);
static BOOLEAN
RtlpVerCompare(ULONG left, ULONG right, UCHAR Condition)
{
switch (Condition)
{
case VER_EQUAL:
return (left == right);
case VER_GREATER:
return (left > right);
case VER_GREATER_EQUAL:
return (left >= right);
case VER_LESS:
return (left < right);
case VER_LESS_EQUAL:
return (left <= right);
default:
break;
}
return FALSE;
}
/*
* @implemented
*/
NTSTATUS
NTAPI
RtlVerifyVersionInfo(IN PRTL_OSVERSIONINFOEXW VersionInfo,
IN ULONG TypeMask,
IN ULONGLONG ConditionMask)
{
NTSTATUS Status;
RTL_OSVERSIONINFOEXW ver;
BOOLEAN Comparison;
/* 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);
Status = RtlGetVersion((PRTL_OSVERSIONINFOW)&ver);
if (Status != STATUS_SUCCESS) return Status;
if (!TypeMask || !ConditionMask) return STATUS_INVALID_PARAMETER;
if (TypeMask & VER_PRODUCT_TYPE)
{
Comparison = RtlpVerCompare(ver.wProductType,
VersionInfo->wProductType,
RtlpVerGetCondition(ConditionMask, VER_PRODUCT_TYPE));
if (!Comparison)
return STATUS_REVISION_MISMATCH;
}
if (TypeMask & VER_SUITENAME)
{
switch (RtlpVerGetCondition(ConditionMask, VER_SUITENAME))
{
case VER_AND:
if ((VersionInfo->wSuiteMask & ver.wSuiteMask) != VersionInfo->wSuiteMask)
{
return STATUS_REVISION_MISMATCH;
}
break;
case VER_OR:
if (!(VersionInfo->wSuiteMask & ver.wSuiteMask) && VersionInfo->wSuiteMask)
{
return STATUS_REVISION_MISMATCH;
}
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
if (TypeMask & VER_PLATFORMID)
{
Comparison = RtlpVerCompare(ver.dwPlatformId,
VersionInfo->dwPlatformId,
RtlpVerGetCondition(ConditionMask, VER_PLATFORMID));
if (!Comparison)
return STATUS_REVISION_MISMATCH;
}
if (TypeMask & VER_BUILDNUMBER)
{
Comparison = RtlpVerCompare(ver.dwBuildNumber,
VersionInfo->dwBuildNumber,
RtlpVerGetCondition(ConditionMask, VER_BUILDNUMBER));
if (!Comparison)
return STATUS_REVISION_MISMATCH;
}
TypeMask &= VER_MAJORVERSION|VER_MINORVERSION|VER_SERVICEPACKMAJOR|VER_SERVICEPACKMINOR;
if (TypeMask)
{
BOOLEAN do_next_check = TRUE;
/*
* Select the leading comparison operator (for example, the comparison
* operator for VER_MAJORVERSION supersedes the others for VER_MINORVERSION,
* VER_SERVICEPACKMAJOR and VER_SERVICEPACKMINOR).
*/
UCHAR Condition = RtlpVerGetCondition(ConditionMask, TypeMask);
Comparison = TRUE;
if (TypeMask & VER_MAJORVERSION)
{
Comparison = RtlpVerCompare(ver.dwMajorVersion,
VersionInfo->dwMajorVersion,
Condition);
do_next_check = (ver.dwMajorVersion == VersionInfo->dwMajorVersion) &&
((Condition != VER_EQUAL) || Comparison);
}
if ((TypeMask & VER_MINORVERSION) && do_next_check)
{
Comparison = RtlpVerCompare(ver.dwMinorVersion,
VersionInfo->dwMinorVersion,
Condition);
do_next_check = (ver.dwMinorVersion == VersionInfo->dwMinorVersion) &&
((Condition != VER_EQUAL) || Comparison);
}
if ((TypeMask & VER_SERVICEPACKMAJOR) && do_next_check)
{
Comparison = RtlpVerCompare(ver.wServicePackMajor,
VersionInfo->wServicePackMajor,
Condition);
do_next_check = (ver.wServicePackMajor == VersionInfo->wServicePackMajor) &&
((Condition != VER_EQUAL) || Comparison);
}
if ((TypeMask & VER_SERVICEPACKMINOR) && do_next_check)
{
Comparison = RtlpVerCompare(ver.wServicePackMinor,
VersionInfo->wServicePackMinor,
Condition);
}
if (!Comparison)
return STATUS_REVISION_MISMATCH;
}
return STATUS_SUCCESS;
}
static UCHAR
RtlpVerGetCondition(IN ULONGLONG ConditionMask,
IN ULONG TypeMask)
{
UCHAR Condition = 0;
if (TypeMask & VER_PRODUCT_TYPE)
Condition |= ConditionMask >> (7 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_SUITENAME)
Condition |= ConditionMask >> (6 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_PLATFORMID)
Condition |= ConditionMask >> (3 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_BUILDNUMBER)
Condition |= ConditionMask >> (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 (TypeMask & VER_MAJORVERSION)
Condition |= ConditionMask >> (1 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_MINORVERSION)
Condition |= ConditionMask >> (0 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_SERVICEPACKMAJOR)
Condition |= ConditionMask >> (5 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_SERVICEPACKMINOR)
Condition |= ConditionMask >> (4 * VER_NUM_BITS_PER_CONDITION_MASK);
Condition &= VER_CONDITION_MASK;
return Condition;
}
/*
* @implemented
*/
ULONGLONG
NTAPI
VerSetConditionMask(IN ULONGLONG ConditionMask,
IN ULONG TypeMask,
IN UCHAR Condition)
{
ULONGLONG ullCondMask;
if (TypeMask == 0)
return ConditionMask;
Condition &= VER_CONDITION_MASK;
if (Condition == 0)
return ConditionMask;
ullCondMask = Condition;
if (TypeMask & VER_PRODUCT_TYPE)
ConditionMask |= ullCondMask << (7 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_SUITENAME)
ConditionMask |= ullCondMask << (6 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_SERVICEPACKMAJOR)
ConditionMask |= ullCondMask << (5 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_SERVICEPACKMINOR)
ConditionMask |= ullCondMask << (4 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_PLATFORMID)
ConditionMask |= ullCondMask << (3 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_BUILDNUMBER)
ConditionMask |= ullCondMask << (2 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_MAJORVERSION)
ConditionMask |= ullCondMask << (1 * VER_NUM_BITS_PER_CONDITION_MASK);
else if (TypeMask & VER_MINORVERSION)
ConditionMask |= ullCondMask << (0 * VER_NUM_BITS_PER_CONDITION_MASK);
return ConditionMask;
}
/* EOF */