[HAL]
[reactos.git] / reactos / lib / rtl / version.c
1 /* COPYRIGHT: See COPYING in the top level directory
2 * PROJECT: ReactOS system libraries
3 * PURPOSE: Runtime code
4 * FILE: lib/rtl/version.c
5 * PROGRAMER: Filip Navara
6 */
7
8 /* INCLUDES *****************************************************************/
9
10 #include <rtl.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS ******************************************************************/
16
17 NTSTATUS
18 NTAPI
19 RtlGetVersion(
20 OUT PRTL_OSVERSIONINFOW lpVersionInformation
21 );
22
23 /* FUNCTIONS ****************************************************************/
24
25 static inline NTSTATUS version_compare_values(ULONG left, ULONG right, UCHAR condition)
26 {
27 switch (condition) {
28 case VER_EQUAL:
29 if (left != right) return STATUS_REVISION_MISMATCH;
30 break;
31 case VER_GREATER:
32 if (left <= right) return STATUS_REVISION_MISMATCH;
33 break;
34 case VER_GREATER_EQUAL:
35 if (left < right) return STATUS_REVISION_MISMATCH;
36 break;
37 case VER_LESS:
38 if (left >= right) return STATUS_REVISION_MISMATCH;
39 break;
40 case VER_LESS_EQUAL:
41 if (left > right) return STATUS_REVISION_MISMATCH;
42 break;
43 default:
44 return STATUS_REVISION_MISMATCH;
45 }
46 return STATUS_SUCCESS;
47 }
48
49 /*
50 * @implemented
51 */
52 NTSTATUS
53 NTAPI
54 RtlVerifyVersionInfo(
55 IN PRTL_OSVERSIONINFOEXW VersionInfo,
56 IN ULONG TypeMask,
57 IN ULONGLONG ConditionMask
58 )
59 {
60 RTL_OSVERSIONINFOEXW ver;
61 NTSTATUS status;
62
63 /* FIXME:
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.
68 */
69
70 ver.dwOSVersionInfoSize = sizeof(ver);
71 status = RtlGetVersion( (PRTL_OSVERSIONINFOW)&ver );
72 if (status != STATUS_SUCCESS) return status;
73
74 if(!(TypeMask && ConditionMask)) return STATUS_INVALID_PARAMETER;
75
76 if(TypeMask & VER_PRODUCT_TYPE)
77 {
78 status = version_compare_values(ver.wProductType, VersionInfo->wProductType, ConditionMask >> 7 * VER_NUM_BITS_PER_CONDITION_MASK & VER_CONDITION_MASK);
79 if (status != STATUS_SUCCESS)
80 return status;
81 }
82 if(TypeMask & VER_SUITENAME)
83 {
84 switch(ConditionMask >> 6 * VER_NUM_BITS_PER_CONDITION_MASK & VER_CONDITION_MASK)
85 {
86 case VER_AND:
87 if((VersionInfo->wSuiteMask & ver.wSuiteMask) != VersionInfo->wSuiteMask)
88 return STATUS_REVISION_MISMATCH;
89 break;
90 case VER_OR:
91 if(!(VersionInfo->wSuiteMask & ver.wSuiteMask) && VersionInfo->wSuiteMask)
92 return STATUS_REVISION_MISMATCH;
93 break;
94 default:
95 return STATUS_INVALID_PARAMETER;
96 }
97 }
98 if(TypeMask & VER_PLATFORMID)
99 {
100 status = version_compare_values(ver.dwPlatformId, VersionInfo->dwPlatformId, ConditionMask >> 3 * VER_NUM_BITS_PER_CONDITION_MASK & VER_CONDITION_MASK);
101 if (status != STATUS_SUCCESS)
102 return status;
103 }
104 if(TypeMask & VER_BUILDNUMBER)
105 {
106 status = version_compare_values(ver.dwBuildNumber, VersionInfo->dwBuildNumber, ConditionMask >> 2 * VER_NUM_BITS_PER_CONDITION_MASK & VER_CONDITION_MASK);
107 if (status != STATUS_SUCCESS)
108 return status;
109 }
110 if(TypeMask & (VER_MAJORVERSION|VER_MINORVERSION|VER_SERVICEPACKMAJOR|VER_SERVICEPACKMINOR))
111 {
112 unsigned char condition = 0;
113 BOOLEAN do_next_check = TRUE;
114
115 if(TypeMask & VER_MAJORVERSION)
116 condition = ConditionMask >> 1 * VER_NUM_BITS_PER_CONDITION_MASK & VER_CONDITION_MASK;
117 else if(TypeMask & VER_MINORVERSION)
118 condition = ConditionMask >> 0 * VER_NUM_BITS_PER_CONDITION_MASK & VER_CONDITION_MASK;
119 else if(TypeMask & VER_SERVICEPACKMAJOR)
120 condition = ConditionMask >> 5 * VER_NUM_BITS_PER_CONDITION_MASK & VER_CONDITION_MASK;
121 else if(TypeMask & VER_SERVICEPACKMINOR)
122 condition = ConditionMask >> 4 * VER_NUM_BITS_PER_CONDITION_MASK & VER_CONDITION_MASK;
123
124 if(TypeMask & VER_MAJORVERSION)
125 {
126 status = version_compare_values(ver.dwMajorVersion, VersionInfo->dwMajorVersion, condition);
127 do_next_check = (ver.dwMajorVersion == VersionInfo->dwMajorVersion) &&
128 ((condition != VER_EQUAL) || (status == STATUS_SUCCESS));
129 }
130 if((TypeMask & VER_MINORVERSION) && do_next_check)
131 {
132 status = version_compare_values(ver.dwMinorVersion, VersionInfo->dwMinorVersion, condition);
133 do_next_check = (ver.dwMinorVersion == VersionInfo->dwMinorVersion) &&
134 ((condition != VER_EQUAL) || (status == STATUS_SUCCESS));
135 }
136 if((TypeMask & VER_SERVICEPACKMAJOR) && do_next_check)
137 {
138 status = version_compare_values(ver.wServicePackMajor, VersionInfo->wServicePackMajor, condition);
139 do_next_check = (ver.wServicePackMajor == VersionInfo->wServicePackMajor) &&
140 ((condition != VER_EQUAL) || (status == STATUS_SUCCESS));
141 }
142 if((TypeMask & VER_SERVICEPACKMINOR) && do_next_check)
143 {
144 status = version_compare_values(ver.wServicePackMinor, VersionInfo->wServicePackMinor, condition);
145 }
146
147 if (status != STATUS_SUCCESS)
148 return status;
149 }
150
151 return STATUS_SUCCESS;
152 }
153
154 /*
155 * @implemented
156 */
157 ULONGLONG NTAPI
158 VerSetConditionMask(IN ULONGLONG dwlConditionMask,
159 IN DWORD dwTypeBitMask,
160 IN BYTE dwConditionMask)
161 {
162 if(dwTypeBitMask == 0)
163 return dwlConditionMask;
164
165 dwConditionMask &= VER_CONDITION_MASK;
166
167 if(dwConditionMask == 0)
168 return dwlConditionMask;
169
170 if(dwTypeBitMask & VER_PRODUCT_TYPE)
171 dwlConditionMask |= dwConditionMask << 7 * VER_NUM_BITS_PER_CONDITION_MASK;
172 else if(dwTypeBitMask & VER_SUITENAME)
173 dwlConditionMask |= dwConditionMask << 6 * VER_NUM_BITS_PER_CONDITION_MASK;
174 else if(dwTypeBitMask & VER_SERVICEPACKMAJOR)
175 dwlConditionMask |= dwConditionMask << 5 * VER_NUM_BITS_PER_CONDITION_MASK;
176 else if(dwTypeBitMask & VER_SERVICEPACKMINOR)
177 dwlConditionMask |= dwConditionMask << 4 * VER_NUM_BITS_PER_CONDITION_MASK;
178 else if(dwTypeBitMask & VER_PLATFORMID)
179 dwlConditionMask |= dwConditionMask << 3 * VER_NUM_BITS_PER_CONDITION_MASK;
180 else if(dwTypeBitMask & VER_BUILDNUMBER)
181 dwlConditionMask |= dwConditionMask << 2 * VER_NUM_BITS_PER_CONDITION_MASK;
182 else if(dwTypeBitMask & VER_MAJORVERSION)
183 dwlConditionMask |= dwConditionMask << 1 * VER_NUM_BITS_PER_CONDITION_MASK;
184 else if(dwTypeBitMask & VER_MINORVERSION)
185 dwlConditionMask |= dwConditionMask << 0 * VER_NUM_BITS_PER_CONDITION_MASK;
186
187 return dwlConditionMask;
188 }
189
190 /* EOF */