Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

version.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1989 Microsoft Corporation 00004 00005 Module Name: 00006 00007 Version.c 00008 00009 Abstract: 00010 00011 This module implements a function to compare OS versions. Its the basis for 00012 VerifyVersionInfoW API. The Rtl version can be called from device drivers. 00013 00014 Author: 00015 00016 Nar Ganapathy [Narg] 19-Oct-1998 00017 00018 Environment: 00019 00020 Pure utility routine 00021 00022 Revision History: 00023 00024 --*/ 00025 00026 #include <stdio.h> 00027 #include <ntrtlp.h> 00028 #if !defined(NTOS_KERNEL_RUNTIME) 00029 #include <winerror.h> 00030 #endif 00031 00032 #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME) 00033 #pragma alloc_text(PAGE, RtlGetVersion) 00034 #endif 00035 00036 // 00037 // The following comment explains the old and the new style layouts for the 00038 // condition masks. The condition mask is passed as a parameter to the 00039 // VerifyVersionInfo API. The condition mask encodes conditions like VER_AND, 00040 // VER_OR, VER_EQUAL for various types like VER_PLATFORMID, VER_MINORVERSION 00041 // etc., When the API was originally designed the application used a macro 00042 // called VER_SET_CONDTION which was defined to be _m_=(_m_|(_c_<<(1<<_t_))). 00043 // where _c_ is the condition and _t_ is the type. This macro is buggy for 00044 // types >= VER_PLATFORMID. Unfortunately a lot of application code already 00045 // uses this buggy macro (notably this terminal server) and have been shipped. 00046 // To fix this bug, a new API VerSetConditionMask is defined which has a new 00047 // bit layout. To provide backwards compatibility, we need to know if a 00048 // specific condition mask is a new style mask (has the new bit layout) or is 00049 // an old style mask. In both bit layouts bit 64 can never be set. 00050 // So the new API sets this bit to indicate that the condition mask is a new 00051 // style condition mask. So the code in this function that extracts the 00052 // condition uses the new bit layout if bit 63 is set and the old layout if 00053 // bit 63 is not set. This should allow applications that was compiled with 00054 // the old macro to work. 00055 // 00056 00057 // 00058 // Use bit 63 to indicate that the new style bit layout is followed. 00059 // 00060 #define NEW_STYLE_BIT_MASK 0x8000000000000000 00061 00062 00063 // 00064 // Condition extractor for the old style mask. 00065 // 00066 #define OLD_CONDITION(_m_,_t_) (ULONG)((_m_&(0xff<<(1<<_t_)))>>(1<<_t_)) 00067 00068 // 00069 // Test to see if the mask is an old style mask. 00070 // 00071 #define OLD_STYLE_CONDITION_MASK(_m_) (((_m_) & NEW_STYLE_BIT_MASK) == 0) 00072 00073 #define RTL_GET_CONDITION(_m_, _t_) \ 00074 (OLD_STYLE_CONDITION_MASK(_m_) ? (OLD_CONDITION(_m_,_t_)) : \ 00075 RtlpVerGetConditionMask((_m_), (_t_))) 00076 00077 #define LEXICAL_COMPARISON 1 /* Do string comparison. Used for minor numbers */ 00078 #define MAX_STRING_LENGTH 20 /* Maximum number of digits for sprintf */ 00079 00080 ULONG 00081 RtlpVerGetConditionMask( 00082 ULONGLONG ConditionMask, 00083 ULONG TypeMask 00084 ); 00085 00086 00087 /*++ 00088 00089 Routine Description: 00090 00091 This function retrieves the OS version information. Its the kernel equivalent of 00092 the GetVersionExW win 32 API. 00093 00094 Arguments: 00095 00096 lpVersionInformation - Supplies a pointer to the version info structure. 00097 In the kernel always assume that the structure is of type 00098 PRTL_OSVERSIONINFOEXW as its not exported to drivers. The signature 00099 is kept the same as for the user level RtlGetVersion. 00100 00101 Return Value: 00102 00103 Always succeeds and returns STATUS_SUCCESS. 00104 --*/ 00105 #if defined(NTOS_KERNEL_RUNTIME) 00106 NTSTATUS 00107 RtlGetVersion ( 00108 OUT PRTL_OSVERSIONINFOW lpVersionInformation 00109 ) 00110 { 00111 NT_PRODUCT_TYPE NtProductType; 00112 RTL_PAGED_CODE(); 00113 00114 lpVersionInformation->dwMajorVersion = NtMajorVersion; 00115 lpVersionInformation->dwMinorVersion = NtMinorVersion; 00116 lpVersionInformation->dwBuildNumber = (USHORT)(NtBuildNumber & 0x3FFF); 00117 lpVersionInformation->dwPlatformId = 2; // VER_PLATFORM_WIN32_NT from winbase.h 00118 if (lpVersionInformation->dwOSVersionInfoSize == sizeof( RTL_OSVERSIONINFOEXW )) { 00119 ((PRTL_OSVERSIONINFOEXW)lpVersionInformation)->wServicePackMajor = ((USHORT)CmNtCSDVersion >> 8) & (0xFF); 00120 ((PRTL_OSVERSIONINFOEXW)lpVersionInformation)->wServicePackMinor = (USHORT)CmNtCSDVersion & 0xFF; 00121 ((PRTL_OSVERSIONINFOEXW)lpVersionInformation)->wSuiteMask = (USHORT)(USER_SHARED_DATA->SuiteMask&0xffff); 00122 ((PRTL_OSVERSIONINFOEXW)lpVersionInformation)->wProductType = (RtlGetNtProductType(&NtProductType) ? NtProductType :0); 00123 00124 /* Not set as its not needed by VerifyVersionInfoW */ 00125 ((PRTL_OSVERSIONINFOEXW)lpVersionInformation)->wReserved = (UCHAR)0; 00126 } 00127 00128 return STATUS_SUCCESS; 00129 } 00130 #else 00131 NTSTATUS 00132 RtlGetVersion( 00133 OUT PRTL_OSVERSIONINFOW lpVersionInformation 00134 ) 00135 { 00136 PPEB Peb; 00137 NT_PRODUCT_TYPE NtProductType; 00138 00139 Peb = NtCurrentPeb(); 00140 lpVersionInformation->dwMajorVersion = Peb->OSMajorVersion; 00141 lpVersionInformation->dwMinorVersion = Peb->OSMinorVersion; 00142 lpVersionInformation->dwBuildNumber = Peb->OSBuildNumber; 00143 lpVersionInformation->dwPlatformId = Peb->OSPlatformId; 00144 if (lpVersionInformation->dwOSVersionInfoSize == sizeof( OSVERSIONINFOEXW )) 00145 { 00146 ((POSVERSIONINFOEXW)lpVersionInformation)->wServicePackMajor = (Peb->OSCSDVersion >> 8) & 0xFF; 00147 ((POSVERSIONINFOEXW)lpVersionInformation)->wServicePackMinor = Peb->OSCSDVersion & 0xFF; 00148 ((POSVERSIONINFOEXW)lpVersionInformation)->wSuiteMask = (USHORT)(USER_SHARED_DATA->SuiteMask&0xffff); 00149 ((POSVERSIONINFOEXW)lpVersionInformation)->wProductType = 0; 00150 if (RtlGetNtProductType( &NtProductType )) { 00151 ((POSVERSIONINFOEXW)lpVersionInformation)->wProductType = (UCHAR)NtProductType; 00152 } 00153 } 00154 00155 return STATUS_SUCCESS; 00156 } 00157 #endif 00158 00159 00160 BOOLEAN 00161 RtlpVerCompare( 00162 LONG Condition, 00163 LONG Value1, 00164 LONG Value2, 00165 BOOLEAN *Equal, 00166 int Flags 00167 ) 00168 { 00169 char String1[MAX_STRING_LENGTH]; 00170 char String2[MAX_STRING_LENGTH]; 00171 LONG Comparison; 00172 00173 if (Flags & LEXICAL_COMPARISON) { 00174 sprintf(String1, "%d", Value1); 00175 sprintf(String2, "%d", Value2); 00176 Comparison = strcmp(String2, String1); 00177 Value1 = 0; 00178 Value2 = Comparison; 00179 } 00180 *Equal = (Value1 == Value2); 00181 switch (Condition) { 00182 case VER_EQUAL: 00183 return (Value2 == Value1); 00184 00185 case VER_GREATER: 00186 return (Value2 > Value1); 00187 00188 case VER_LESS: 00189 return (Value2 < Value1); 00190 00191 case VER_GREATER_EQUAL: 00192 return (Value2 >= Value1); 00193 00194 case VER_LESS_EQUAL: 00195 return (Value2 <= Value1); 00196 00197 default: 00198 break; 00199 } 00200 00201 return FALSE; 00202 } 00203 00204 00205 00206 NTSTATUS 00207 RtlVerifyVersionInfo( 00208 IN PRTL_OSVERSIONINFOEXW VersionInfo, 00209 IN ULONG TypeMask, 00210 IN ULONGLONG ConditionMask 00211 ) 00212 00213 /*+++ 00214 This function verifies a version condition. Basically, this 00215 function lets an app query the system to see if the app is 00216 running on a specific version combination. 00217 00218 00219 Arguments: 00220 00221 VersionInfo - a version structure containing the comparison data 00222 TypeMask - a mask comtaining the data types to look at 00223 ConditionMask - a mask containing conditionals for doing the comparisons 00224 00225 00226 Return Value: 00227 00228 STATUS_INVALID_PARAMETER if the parameters are not valid. 00229 STATUS_REVISION_MISMATCH if the versions don't match. 00230 STATUS_SUCCESS if the versions match. 00231 00232 --*/ 00233 00234 { 00235 ULONG i; 00236 OSVERSIONINFOEXW CurrVersion; 00237 BOOLEAN SuiteFound = FALSE; 00238 BOOLEAN Equal; 00239 NTSTATUS Status; 00240 ULONG Condition; 00241 00242 00243 if (TypeMask == 0) { 00244 return STATUS_INVALID_PARAMETER; 00245 } 00246 00247 RtlZeroMemory( &CurrVersion, sizeof(OSVERSIONINFOEXW) ); 00248 CurrVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW); 00249 00250 Status = RtlGetVersion((PRTL_OSVERSIONINFOW)&CurrVersion); 00251 if (Status != STATUS_SUCCESS) 00252 return Status; 00253 00254 if (VersionInfo->wSuiteMask != 0) { 00255 for (i=0; i<16; i++) { 00256 if (VersionInfo->wSuiteMask&(1<<i)) { 00257 switch (RTL_GET_CONDITION(ConditionMask,VER_SUITENAME)) { 00258 case VER_AND: 00259 if (!(CurrVersion.wSuiteMask&(1<<i))) { 00260 return STATUS_REVISION_MISMATCH; 00261 } 00262 break; 00263 00264 case VER_OR: 00265 if (CurrVersion.wSuiteMask&(1<<i)) { 00266 SuiteFound = TRUE; 00267 } 00268 break; 00269 00270 default: 00271 return STATUS_INVALID_PARAMETER; 00272 } 00273 } 00274 } 00275 if ((RtlpVerGetConditionMask(ConditionMask,VER_SUITENAME) == VER_OR) && (SuiteFound == FALSE)) { 00276 return STATUS_REVISION_MISMATCH; 00277 } 00278 } 00279 00280 Equal = TRUE; 00281 Condition = VER_EQUAL; 00282 if (TypeMask & VER_MAJORVERSION) { 00283 Condition = RTL_GET_CONDITION( ConditionMask, VER_MAJORVERSION); 00284 if (RtlpVerCompare( 00285 Condition, 00286 VersionInfo->dwMajorVersion, 00287 CurrVersion.dwMajorVersion, 00288 &Equal, 00289 0 00290 ) == FALSE) 00291 { 00292 if (!Equal) { 00293 return STATUS_REVISION_MISMATCH; 00294 } 00295 } 00296 } 00297 00298 if (Equal) { 00299 ASSERT(Condition); 00300 if (TypeMask & VER_MINORVERSION) { 00301 if (Condition == VER_EQUAL) { 00302 Condition = RTL_GET_CONDITION(ConditionMask, VER_MINORVERSION); 00303 } 00304 if (RtlpVerCompare( 00305 Condition, 00306 VersionInfo->dwMinorVersion, 00307 CurrVersion.dwMinorVersion, 00308 &Equal, 00309 LEXICAL_COMPARISON 00310 ) == FALSE) 00311 { 00312 if (!Equal) { 00313 return STATUS_REVISION_MISMATCH; 00314 } 00315 } 00316 } 00317 00318 if (Equal) { 00319 if (TypeMask & VER_SERVICEPACKMAJOR) { 00320 if (Condition == VER_EQUAL) { 00321 Condition = RTL_GET_CONDITION(ConditionMask, VER_SERVICEPACKMAJOR); 00322 } 00323 if (RtlpVerCompare( 00324 Condition, 00325 VersionInfo->wServicePackMajor, 00326 CurrVersion.wServicePackMajor, 00327 &Equal, 00328 0 00329 ) == FALSE) 00330 { 00331 if (!Equal) { 00332 return STATUS_REVISION_MISMATCH; 00333 } 00334 } 00335 } 00336 if (Equal) { 00337 if (TypeMask & VER_SERVICEPACKMINOR) { 00338 if (Condition == VER_EQUAL) { 00339 Condition = RTL_GET_CONDITION(ConditionMask, VER_SERVICEPACKMINOR); 00340 } 00341 if (RtlpVerCompare( 00342 Condition, 00343 (ULONG)VersionInfo->wServicePackMinor, 00344 (ULONG)CurrVersion.wServicePackMinor, 00345 &Equal, 00346 LEXICAL_COMPARISON 00347 ) == FALSE) 00348 { 00349 return STATUS_REVISION_MISMATCH; 00350 } 00351 } 00352 } 00353 } 00354 } 00355 00356 if ((TypeMask & VER_BUILDNUMBER) && 00357 RtlpVerCompare( 00358 RTL_GET_CONDITION( ConditionMask, VER_BUILDNUMBER), 00359 VersionInfo->dwBuildNumber, 00360 CurrVersion.dwBuildNumber, 00361 &Equal, 00362 0 00363 ) == FALSE) 00364 { 00365 return STATUS_REVISION_MISMATCH; 00366 } 00367 00368 if ((TypeMask & VER_PLATFORMID) && 00369 RtlpVerCompare( 00370 RTL_GET_CONDITION( ConditionMask, VER_PLATFORMID), 00371 VersionInfo->dwPlatformId, 00372 CurrVersion.dwPlatformId, 00373 &Equal, 00374 0 00375 ) == FALSE) 00376 { 00377 return STATUS_REVISION_MISMATCH; 00378 } 00379 00380 00381 if ((TypeMask & VER_PRODUCT_TYPE) && 00382 RtlpVerCompare( 00383 RTL_GET_CONDITION( ConditionMask, VER_PRODUCT_TYPE), 00384 VersionInfo->wProductType, 00385 CurrVersion.wProductType, 00386 &Equal, 00387 0 00388 ) == FALSE) 00389 { 00390 return STATUS_REVISION_MISMATCH; 00391 } 00392 00393 return STATUS_SUCCESS; 00394 } 00395 00396 ULONG 00397 RtlpVerGetConditionMask( 00398 ULONGLONG ConditionMask, 00399 ULONG TypeMask 00400 ) 00401 { 00402 ULONG NumBitsToShift; 00403 ULONG Condition = 0; 00404 00405 if (!TypeMask) { 00406 return 0; 00407 } 00408 00409 for (NumBitsToShift = 0; TypeMask; NumBitsToShift++) { 00410 TypeMask >>= 1; 00411 } 00412 00413 Condition |= (ConditionMask) >> ((NumBitsToShift - 1) 00414 * VER_NUM_BITS_PER_CONDITION_MASK); 00415 Condition &= VER_CONDITION_MASK; 00416 return Condition; 00417 } 00418 00419 00420 ULONGLONG 00421 VerSetConditionMask( 00422 ULONGLONG ConditionMask, 00423 ULONG TypeMask, 00424 UCHAR Condition 00425 ) 00426 { 00427 int NumBitsToShift; 00428 00429 Condition &= VER_CONDITION_MASK; 00430 00431 if (!TypeMask) { 00432 return 0; 00433 } 00434 00435 for (NumBitsToShift = 0; TypeMask; NumBitsToShift++) { 00436 TypeMask >>= 1; 00437 } 00438 00439 // 00440 // Mark that we are using a new style condition mask 00441 // 00442 ConditionMask |= NEW_STYLE_BIT_MASK; 00443 ConditionMask |= (Condition) << ((NumBitsToShift - 1) 00444 * VER_NUM_BITS_PER_CONDITION_MASK); 00445 00446 return ConditionMask; 00447 }

Generated on Sat May 15 19:42:23 2004 for test by doxygen 1.3.7