2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Runtime code
5 * FILE: lib/rtl/version.c
6 * PROGRAMERS: Filip Navara
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *****************************************************************/
17 /* GLOBALS ******************************************************************/
21 RtlGetVersion(OUT PRTL_OSVERSIONINFOW lpVersionInformation
);
23 /* FUNCTIONS ****************************************************************/
26 RtlpVerGetCondition(IN ULONGLONG dwlConditionMask
,
27 IN DWORD dwTypeBitMask
);
30 RtlpVerCompare(ULONG left
, ULONG right
, UCHAR condition
)
35 return (left
== right
);
37 return (left
> right
);
38 case VER_GREATER_EQUAL
:
39 return (left
>= right
);
41 return (left
< right
);
43 return (left
<= right
);
55 RtlVerifyVersionInfo(IN PRTL_OSVERSIONINFOEXW VersionInfo
,
57 IN ULONGLONG ConditionMask
)
59 RTL_OSVERSIONINFOEXW ver
;
64 - Check the following special case on Windows (various versions):
65 o lp->wSuiteMask == 0 and ver.wSuiteMask != 0 and VER_AND/VER_OR
66 o lp->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW)
67 - MSDN talks about some tests being impossible. Check what really happens.
70 ver
.dwOSVersionInfoSize
= sizeof(ver
);
71 status
= RtlGetVersion((PRTL_OSVERSIONINFOW
)&ver
);
72 if (status
!= STATUS_SUCCESS
) return status
;
74 if (!TypeMask
|| !ConditionMask
) return STATUS_INVALID_PARAMETER
;
76 if (TypeMask
& VER_PRODUCT_TYPE
)
78 comparison
= RtlpVerCompare(ver
.wProductType
,
79 VersionInfo
->wProductType
,
80 RtlpVerGetCondition(ConditionMask
, VER_PRODUCT_TYPE
));
82 return STATUS_REVISION_MISMATCH
;
85 if (TypeMask
& VER_SUITENAME
)
87 switch (RtlpVerGetCondition(ConditionMask
, VER_SUITENAME
))
90 if ((VersionInfo
->wSuiteMask
& ver
.wSuiteMask
) != VersionInfo
->wSuiteMask
)
92 return STATUS_REVISION_MISMATCH
;
96 if (!(VersionInfo
->wSuiteMask
& ver
.wSuiteMask
) && VersionInfo
->wSuiteMask
)
98 return STATUS_REVISION_MISMATCH
;
102 return STATUS_INVALID_PARAMETER
;
106 if (TypeMask
& VER_PLATFORMID
)
108 comparison
= RtlpVerCompare(ver
.dwPlatformId
,
109 VersionInfo
->dwPlatformId
,
110 RtlpVerGetCondition(ConditionMask
, VER_PLATFORMID
));
112 return STATUS_REVISION_MISMATCH
;
115 if (TypeMask
& VER_BUILDNUMBER
)
117 comparison
= RtlpVerCompare(ver
.dwBuildNumber
,
118 VersionInfo
->dwBuildNumber
,
119 RtlpVerGetCondition(ConditionMask
, VER_BUILDNUMBER
));
121 return STATUS_REVISION_MISMATCH
;
124 TypeMask
&= VER_MAJORVERSION
|VER_MINORVERSION
|VER_SERVICEPACKMAJOR
|VER_SERVICEPACKMINOR
;
127 BOOLEAN do_next_check
= TRUE
;
129 * Select the leading comparison operator (for example, the comparison
130 * operator for VER_MAJORVERSION supersedes the others for VER_MINORVERSION,
131 * VER_SERVICEPACKMAJOR and VER_SERVICEPACKMINOR).
133 BYTE condition
= RtlpVerGetCondition(ConditionMask
, TypeMask
);
136 if (TypeMask
& VER_MAJORVERSION
)
138 comparison
= RtlpVerCompare(ver
.dwMajorVersion
,
139 VersionInfo
->dwMajorVersion
,
141 do_next_check
= (ver
.dwMajorVersion
== VersionInfo
->dwMajorVersion
) &&
142 ((condition
!= VER_EQUAL
) || comparison
);
144 if ((TypeMask
& VER_MINORVERSION
) && do_next_check
)
146 comparison
= RtlpVerCompare(ver
.dwMinorVersion
,
147 VersionInfo
->dwMinorVersion
,
149 do_next_check
= (ver
.dwMinorVersion
== VersionInfo
->dwMinorVersion
) &&
150 ((condition
!= VER_EQUAL
) || comparison
);
152 if ((TypeMask
& VER_SERVICEPACKMAJOR
) && do_next_check
)
154 comparison
= RtlpVerCompare(ver
.wServicePackMajor
,
155 VersionInfo
->wServicePackMajor
,
157 do_next_check
= (ver
.wServicePackMajor
== VersionInfo
->wServicePackMajor
) &&
158 ((condition
!= VER_EQUAL
) || comparison
);
160 if ((TypeMask
& VER_SERVICEPACKMINOR
) && do_next_check
)
162 comparison
= RtlpVerCompare(ver
.wServicePackMinor
,
163 VersionInfo
->wServicePackMinor
,
168 return STATUS_REVISION_MISMATCH
;
171 return STATUS_SUCCESS
;
175 RtlpVerGetCondition(IN ULONGLONG dwlConditionMask
,
176 IN DWORD dwTypeBitMask
)
178 BYTE bConditionMask
= 0;
180 if (dwTypeBitMask
& VER_PRODUCT_TYPE
)
181 bConditionMask
|= dwlConditionMask
>> (7 * VER_NUM_BITS_PER_CONDITION_MASK
);
182 else if (dwTypeBitMask
& VER_SUITENAME
)
183 bConditionMask
|= dwlConditionMask
>> (6 * VER_NUM_BITS_PER_CONDITION_MASK
);
184 else if (dwTypeBitMask
& VER_PLATFORMID
)
185 bConditionMask
|= dwlConditionMask
>> (3 * VER_NUM_BITS_PER_CONDITION_MASK
);
186 else if (dwTypeBitMask
& VER_BUILDNUMBER
)
187 bConditionMask
|= dwlConditionMask
>> (2 * VER_NUM_BITS_PER_CONDITION_MASK
);
189 * We choose here the lexicographical order on the 4D space
190 * {(Major ; Minor ; SP Major ; SP Minor)} to select the
191 * appropriate comparison operator.
192 * Therefore the following 'else if' instructions must be in this order.
194 else if (dwTypeBitMask
& VER_MAJORVERSION
)
195 bConditionMask
|= dwlConditionMask
>> (1 * VER_NUM_BITS_PER_CONDITION_MASK
);
196 else if (dwTypeBitMask
& VER_MINORVERSION
)
197 bConditionMask
|= dwlConditionMask
>> (0 * VER_NUM_BITS_PER_CONDITION_MASK
);
198 else if (dwTypeBitMask
& VER_SERVICEPACKMAJOR
)
199 bConditionMask
|= dwlConditionMask
>> (5 * VER_NUM_BITS_PER_CONDITION_MASK
);
200 else if (dwTypeBitMask
& VER_SERVICEPACKMINOR
)
201 bConditionMask
|= dwlConditionMask
>> (4 * VER_NUM_BITS_PER_CONDITION_MASK
);
203 bConditionMask
&= VER_CONDITION_MASK
;
205 return bConditionMask
;
213 VerSetConditionMask(IN ULONGLONG dwlConditionMask
,
214 IN DWORD dwTypeBitMask
,
215 IN BYTE bConditionMask
)
217 ULONGLONG ullCondMask
;
219 if (dwTypeBitMask
== 0)
220 return dwlConditionMask
;
222 bConditionMask
&= VER_CONDITION_MASK
;
224 if (bConditionMask
== 0)
225 return dwlConditionMask
;
227 ullCondMask
= bConditionMask
;
228 if (dwTypeBitMask
& VER_PRODUCT_TYPE
)
229 dwlConditionMask
|= ullCondMask
<< (7 * VER_NUM_BITS_PER_CONDITION_MASK
);
230 else if (dwTypeBitMask
& VER_SUITENAME
)
231 dwlConditionMask
|= ullCondMask
<< (6 * VER_NUM_BITS_PER_CONDITION_MASK
);
232 else if (dwTypeBitMask
& VER_SERVICEPACKMAJOR
)
233 dwlConditionMask
|= ullCondMask
<< (5 * VER_NUM_BITS_PER_CONDITION_MASK
);
234 else if (dwTypeBitMask
& VER_SERVICEPACKMINOR
)
235 dwlConditionMask
|= ullCondMask
<< (4 * VER_NUM_BITS_PER_CONDITION_MASK
);
236 else if (dwTypeBitMask
& VER_PLATFORMID
)
237 dwlConditionMask
|= ullCondMask
<< (3 * VER_NUM_BITS_PER_CONDITION_MASK
);
238 else if (dwTypeBitMask
& VER_BUILDNUMBER
)
239 dwlConditionMask
|= ullCondMask
<< (2 * VER_NUM_BITS_PER_CONDITION_MASK
);
240 else if (dwTypeBitMask
& VER_MAJORVERSION
)
241 dwlConditionMask
|= ullCondMask
<< (1 * VER_NUM_BITS_PER_CONDITION_MASK
);
242 else if (dwTypeBitMask
& VER_MINORVERSION
)
243 dwlConditionMask
|= ullCondMask
<< (0 * VER_NUM_BITS_PER_CONDITION_MASK
);
245 return dwlConditionMask
;