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