1 /* 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) 8 */ 9 10 /* INCLUDES *****************************************************************/ 11 12 #include <rtl.h> 13 14 #define NDEBUG 15 #include <debug.h> 16 17 /* GLOBALS ******************************************************************/ 18 19 NTSTATUS 20 NTAPI 21 RtlGetVersion(OUT PRTL_OSVERSIONINFOW lpVersionInformation); 22 23 /* FUNCTIONS ****************************************************************/ 24 25 static UCHAR 26 RtlpVerGetCondition(IN ULONGLONG ConditionMask, 27 IN ULONG TypeMask); 28 29 static BOOLEAN 30 RtlpVerCompare(ULONG left, ULONG right, UCHAR Condition) 31 { 32 switch (Condition) 33 { 34 case VER_EQUAL: 35 return (left == right); 36 case VER_GREATER: 37 return (left > right); 38 case VER_GREATER_EQUAL: 39 return (left >= right); 40 case VER_LESS: 41 return (left < right); 42 case VER_LESS_EQUAL: 43 return (left <= right); 44 default: 45 break; 46 } 47 return FALSE; 48 } 49 50 /* 51 * @implemented 52 */ 53 NTSTATUS 54 NTAPI 55 RtlVerifyVersionInfo(IN PRTL_OSVERSIONINFOEXW VersionInfo, 56 IN ULONG TypeMask, 57 IN ULONGLONG ConditionMask) 58 { 59 RTL_OSVERSIONINFOEXW Version; 60 BOOLEAN Comparison; 61 BOOLEAN DoNextCheck; 62 NTSTATUS Status; 63 UCHAR Condition; 64 65 /* FIXME: 66 - Check the following special case on Windows (various versions): 67 o lp->wSuiteMask == 0 and ver.wSuiteMask != 0 and VER_AND/VER_OR 68 o lp->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW) 69 - MSDN talks about some tests being impossible. Check what really happens. 70 */ 71 72 Version.dwOSVersionInfoSize = sizeof(Version); 73 74 Status = RtlGetVersion((PRTL_OSVERSIONINFOW)&Version); 75 if (Status != STATUS_SUCCESS) 76 { 77 return Status; 78 } 79 80 if (!TypeMask || !ConditionMask) 81 { 82 return STATUS_INVALID_PARAMETER; 83 } 84 85 if (TypeMask & VER_PRODUCT_TYPE) 86 { 87 Comparison = RtlpVerCompare(Version.wProductType, 88 VersionInfo->wProductType, 89 RtlpVerGetCondition(ConditionMask, VER_PRODUCT_TYPE)); 90 if (!Comparison) 91 { 92 return STATUS_REVISION_MISMATCH; 93 } 94 } 95 96 if (TypeMask & VER_SUITENAME) 97 { 98 switch (RtlpVerGetCondition(ConditionMask, VER_SUITENAME)) 99 { 100 case VER_AND: 101 { 102 if ((VersionInfo->wSuiteMask & Version.wSuiteMask) != VersionInfo->wSuiteMask) 103 { 104 return STATUS_REVISION_MISMATCH; 105 } 106 } 107 break; 108 109 case VER_OR: 110 { 111 if (!(VersionInfo->wSuiteMask & Version.wSuiteMask) && VersionInfo->wSuiteMask) 112 { 113 return STATUS_REVISION_MISMATCH; 114 } 115 break; 116 } 117 118 default: 119 { 120 return STATUS_INVALID_PARAMETER; 121 } 122 } 123 } 124 125 if (TypeMask & VER_PLATFORMID) 126 { 127 Comparison = RtlpVerCompare(Version.dwPlatformId, 128 VersionInfo->dwPlatformId, 129 RtlpVerGetCondition(ConditionMask, VER_PLATFORMID)); 130 if (!Comparison) 131 { 132 return STATUS_REVISION_MISMATCH; 133 } 134 } 135 136 if (TypeMask & VER_BUILDNUMBER) 137 { 138 Comparison = RtlpVerCompare(Version.dwBuildNumber, 139 VersionInfo->dwBuildNumber, 140 RtlpVerGetCondition(ConditionMask, VER_BUILDNUMBER)); 141 if (!Comparison) 142 { 143 return STATUS_REVISION_MISMATCH; 144 } 145 } 146 147 DoNextCheck = TRUE; 148 Condition = VER_EQUAL; 149 150 if (TypeMask & VER_MAJORVERSION) 151 { 152 Condition = RtlpVerGetCondition(ConditionMask, VER_MAJORVERSION); 153 DoNextCheck = (VersionInfo->dwMajorVersion == Version.dwMajorVersion); 154 Comparison = RtlpVerCompare(Version.dwMajorVersion, 155 VersionInfo->dwMajorVersion, 156 Condition); 157 158 if (!Comparison && !DoNextCheck) 159 { 160 return STATUS_REVISION_MISMATCH; 161 } 162 } 163 164 if (DoNextCheck) 165 { 166 if (TypeMask & VER_MINORVERSION) 167 { 168 if (Condition == VER_EQUAL) 169 { 170 Condition = RtlpVerGetCondition(ConditionMask, VER_MINORVERSION); 171 } 172 173 DoNextCheck = (VersionInfo->dwMinorVersion == Version.dwMinorVersion); 174 Comparison = RtlpVerCompare(Version.dwMinorVersion, 175 VersionInfo->dwMinorVersion, 176 Condition); 177 178 if (!Comparison && !DoNextCheck) 179 { 180 return STATUS_REVISION_MISMATCH; 181 } 182 } 183 184 if (DoNextCheck && (TypeMask & VER_SERVICEPACKMAJOR)) 185 { 186 if (Condition == VER_EQUAL) 187 { 188 Condition = RtlpVerGetCondition(ConditionMask, VER_SERVICEPACKMAJOR); 189 } 190 191 DoNextCheck = (VersionInfo->wServicePackMajor == Version.wServicePackMajor); 192 Comparison = RtlpVerCompare(Version.wServicePackMajor, 193 VersionInfo->wServicePackMajor, 194 Condition); 195 196 if (!Comparison && !DoNextCheck) 197 { 198 return STATUS_REVISION_MISMATCH; 199 } 200 201 if (DoNextCheck && (TypeMask & VER_SERVICEPACKMINOR)) 202 { 203 if (Condition == VER_EQUAL) 204 { 205 Condition = RtlpVerGetCondition(ConditionMask, VER_SERVICEPACKMINOR); 206 } 207 208 Comparison = RtlpVerCompare(Version.wServicePackMinor, 209 VersionInfo->wServicePackMinor, 210 Condition); 211 212 if (!Comparison) 213 { 214 return STATUS_REVISION_MISMATCH; 215 } 216 } 217 } 218 } 219 220 return STATUS_SUCCESS; 221 } 222 223 static UCHAR 224 RtlpVerGetCondition(IN ULONGLONG ConditionMask, 225 IN ULONG TypeMask) 226 { 227 UCHAR Condition = 0; 228 229 if (TypeMask & VER_PRODUCT_TYPE) 230 Condition |= ConditionMask >> (7 * VER_NUM_BITS_PER_CONDITION_MASK); 231 else if (TypeMask & VER_SUITENAME) 232 Condition |= ConditionMask >> (6 * VER_NUM_BITS_PER_CONDITION_MASK); 233 else if (TypeMask & VER_PLATFORMID) 234 Condition |= ConditionMask >> (3 * VER_NUM_BITS_PER_CONDITION_MASK); 235 else if (TypeMask & VER_BUILDNUMBER) 236 Condition |= ConditionMask >> (2 * VER_NUM_BITS_PER_CONDITION_MASK); 237 /* 238 * We choose here the lexicographical order on the 4D space 239 * {(Major ; Minor ; SP Major ; SP Minor)} to select the 240 * appropriate comparison operator. 241 * Therefore the following 'else if' instructions must be in this order. 242 */ 243 else if (TypeMask & VER_MAJORVERSION) 244 Condition |= ConditionMask >> (1 * VER_NUM_BITS_PER_CONDITION_MASK); 245 else if (TypeMask & VER_MINORVERSION) 246 Condition |= ConditionMask >> (0 * VER_NUM_BITS_PER_CONDITION_MASK); 247 else if (TypeMask & VER_SERVICEPACKMAJOR) 248 Condition |= ConditionMask >> (5 * VER_NUM_BITS_PER_CONDITION_MASK); 249 else if (TypeMask & VER_SERVICEPACKMINOR) 250 Condition |= ConditionMask >> (4 * VER_NUM_BITS_PER_CONDITION_MASK); 251 252 Condition &= VER_CONDITION_MASK; 253 254 return Condition; 255 } 256 257 /* 258 * @implemented 259 */ 260 ULONGLONG 261 NTAPI 262 VerSetConditionMask(IN ULONGLONG ConditionMask, 263 IN ULONG TypeMask, 264 IN UCHAR Condition) 265 { 266 ULONGLONG ullCondMask; 267 268 if (TypeMask == 0) 269 return ConditionMask; 270 271 Condition &= VER_CONDITION_MASK; 272 273 if (Condition == 0) 274 return ConditionMask; 275 276 ullCondMask = Condition; 277 if (TypeMask & VER_PRODUCT_TYPE) 278 ConditionMask |= ullCondMask << (7 * VER_NUM_BITS_PER_CONDITION_MASK); 279 else if (TypeMask & VER_SUITENAME) 280 ConditionMask |= ullCondMask << (6 * VER_NUM_BITS_PER_CONDITION_MASK); 281 else if (TypeMask & VER_SERVICEPACKMAJOR) 282 ConditionMask |= ullCondMask << (5 * VER_NUM_BITS_PER_CONDITION_MASK); 283 else if (TypeMask & VER_SERVICEPACKMINOR) 284 ConditionMask |= ullCondMask << (4 * VER_NUM_BITS_PER_CONDITION_MASK); 285 else if (TypeMask & VER_PLATFORMID) 286 ConditionMask |= ullCondMask << (3 * VER_NUM_BITS_PER_CONDITION_MASK); 287 else if (TypeMask & VER_BUILDNUMBER) 288 ConditionMask |= ullCondMask << (2 * VER_NUM_BITS_PER_CONDITION_MASK); 289 else if (TypeMask & VER_MAJORVERSION) 290 ConditionMask |= ullCondMask << (1 * VER_NUM_BITS_PER_CONDITION_MASK); 291 else if (TypeMask & VER_MINORVERSION) 292 ConditionMask |= ullCondMask << (0 * VER_NUM_BITS_PER_CONDITION_MASK); 293 294 return ConditionMask; 295 } 296 297 /* EOF */ 298