Sync to trunk (r44371)
[reactos.git] / reactos / dll / win32 / kernel32 / misc / version.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/kernel32/misc/version.c
6 * PURPOSE: Version functions
7 * PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
8 * UPDATE HISTORY:
9 * Created 01/11/98
10 */
11
12 #include <k32.h>
13 #include <reactos/buildno.h>
14
15 #define NDEBUG
16 #include <debug.h>
17
18 #define UNICODIZE1(x) L##x
19 #define UNICODIZE(x) UNICODIZE1(x)
20
21 /* FUNCTIONS ******************************************************************/
22
23
24 /*
25 * @implemented
26 */
27 DWORD
28 WINAPI
29 GetVersion(VOID)
30 {
31 PPEB pPeb = NtCurrentPeb();
32 DWORD nVersion;
33
34 nVersion = MAKEWORD(pPeb->OSMajorVersion, pPeb->OSMinorVersion);
35
36 /* behave consistently when posing as another operating system */
37 /* build number */
38 if(pPeb->OSPlatformId != VER_PLATFORM_WIN32_WINDOWS)
39 nVersion |= ((DWORD)(pPeb->OSBuildNumber)) << 16;
40
41 /* non-NT platform flag */
42 if(pPeb->OSPlatformId != VER_PLATFORM_WIN32_NT)
43 nVersion |= 0x80000000;
44
45 return nVersion;
46 }
47
48 /*
49 * @implemented
50 */
51 BOOL
52 WINAPI
53 GetVersionExW(
54 LPOSVERSIONINFOW lpVersionInformation
55 )
56 {
57 NTSTATUS Status;
58
59 if(lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOW) &&
60 lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW))
61 {
62 /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
63 enough but doesn't match the exact sizes supported, ERROR_INVALID_PARAMETER
64 would've been much more appropriate... */
65 SetLastError(ERROR_INSUFFICIENT_BUFFER);
66 return FALSE;
67 }
68
69 Status = RtlGetVersion((PRTL_OSVERSIONINFOW)lpVersionInformation);
70 if(NT_SUCCESS(Status))
71 {
72 int ln, maxlen;
73
74 /* append a reactos specific string to the szCSDVersion string */
75
76 /* FIXME - we shouldn't do this when there is a (ros-specific) compatibility
77 flag set so we don't screw applications that might depend on a
78 certain string */
79
80 ln = wcslen(lpVersionInformation->szCSDVersion) + 1;
81 maxlen = (sizeof(lpVersionInformation->szCSDVersion) / sizeof(lpVersionInformation->szCSDVersion[0]) - 1);
82 if(maxlen > ln)
83 {
84 PWCHAR szVer = lpVersionInformation->szCSDVersion + ln;
85 RtlZeroMemory(szVer, (maxlen - ln + 1) * sizeof(WCHAR));
86 wcsncpy(szVer,
87 L"ReactOS " UNICODIZE(KERNEL_VERSION_STR) L" (Build " UNICODIZE(KERNEL_VERSION_BUILD_STR) L")",
88 maxlen - ln);
89 }
90
91 return TRUE;
92 }
93
94 return FALSE;
95 }
96
97
98 /*
99 * @implemented
100 */
101 BOOL
102 WINAPI
103 GetVersionExA(
104 LPOSVERSIONINFOA lpVersionInformation
105 )
106 {
107 OSVERSIONINFOEXW viw;
108
109 RtlZeroMemory(&viw, sizeof(viw));
110
111 switch(lpVersionInformation->dwOSVersionInfoSize)
112 {
113 case sizeof(OSVERSIONINFOA):
114 viw.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
115 break;
116
117 case sizeof(OSVERSIONINFOEXA):
118 viw.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
119 break;
120
121 default:
122 /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
123 enough but doesn't match the exact sizes supported, ERROR_INVALID_PARAMETER
124 would've been much more appropriate... */
125 SetLastError(ERROR_INSUFFICIENT_BUFFER);
126 return FALSE;
127 }
128
129 if(GetVersionExW((LPOSVERSIONINFOW)&viw))
130 {
131 ANSI_STRING CSDVersionA;
132 UNICODE_STRING CSDVersionW;
133
134 /* copy back fields that match both supported structures */
135 lpVersionInformation->dwMajorVersion = viw.dwMajorVersion;
136 lpVersionInformation->dwMinorVersion = viw.dwMinorVersion;
137 lpVersionInformation->dwBuildNumber = viw.dwBuildNumber;
138 lpVersionInformation->dwPlatformId = viw.dwPlatformId;
139
140 /* convert the win version string */
141 RtlInitUnicodeString(&CSDVersionW, viw.szCSDVersion);
142
143 CSDVersionA.Length = 0;
144 CSDVersionA.MaximumLength = sizeof(lpVersionInformation->szCSDVersion);
145 CSDVersionA.Buffer = lpVersionInformation->szCSDVersion;
146
147 RtlUnicodeStringToAnsiString(&CSDVersionA, &CSDVersionW, FALSE);
148
149 /* convert the ReactOS version string */
150 CSDVersionW.Buffer = viw.szCSDVersion + CSDVersionW.Length / sizeof(WCHAR) + 1;
151 CSDVersionW.MaximumLength = sizeof(viw.szCSDVersion) - (CSDVersionW.Length + sizeof(WCHAR));
152 CSDVersionW.Length = wcslen(CSDVersionW.Buffer) * sizeof(WCHAR);
153 CSDVersionA.Buffer = lpVersionInformation->szCSDVersion + CSDVersionA.Length + 1;
154 CSDVersionA.MaximumLength = sizeof(lpVersionInformation->szCSDVersion) - (CSDVersionA.Length + 1);
155 CSDVersionA.Length = 0;
156
157 RtlUnicodeStringToAnsiString(&CSDVersionA, &CSDVersionW, FALSE);
158
159 /* copy back the extended fields */
160 if(viw.dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW))
161 {
162 ((LPOSVERSIONINFOEXA)lpVersionInformation)->wServicePackMajor = viw.wServicePackMajor;
163 ((LPOSVERSIONINFOEXA)lpVersionInformation)->wServicePackMinor = viw.wServicePackMinor;
164 ((LPOSVERSIONINFOEXA)lpVersionInformation)->wSuiteMask = viw.wSuiteMask;
165 ((LPOSVERSIONINFOEXA)lpVersionInformation)->wProductType = viw.wProductType;
166 ((LPOSVERSIONINFOEXA)lpVersionInformation)->wReserved = viw.wReserved;
167 }
168
169 return TRUE;
170 }
171
172 return FALSE;
173 }
174
175
176 /*
177 * @implemented
178 */
179 BOOL
180 WINAPI
181 VerifyVersionInfoW(
182 LPOSVERSIONINFOEXW lpVersionInformation,
183 DWORD dwTypeMask,
184 DWORDLONG dwlConditionMask
185 )
186 {
187 NTSTATUS Status;
188
189 Status = RtlVerifyVersionInfo((PRTL_OSVERSIONINFOEXW)lpVersionInformation,
190 dwTypeMask,
191 dwlConditionMask);
192 switch(Status)
193 {
194 case STATUS_INVALID_PARAMETER:
195 SetLastError(ERROR_BAD_ARGUMENTS);
196 return FALSE;
197
198 case STATUS_REVISION_MISMATCH:
199 SetLastError(ERROR_OLD_WIN_VERSION);
200 return FALSE;
201
202 default:
203 /* RtlVerifyVersionInfo shouldn't report any other failure code! */
204 ASSERT(NT_SUCCESS(Status));
205 return TRUE;
206 }
207 }
208
209
210 /*
211 * @implemented
212 */
213 BOOL
214 WINAPI
215 VerifyVersionInfoA(
216 LPOSVERSIONINFOEXA lpVersionInformation,
217 DWORD dwTypeMask,
218 DWORDLONG dwlConditionMask
219 )
220 {
221 OSVERSIONINFOEXW viex;
222
223 viex.dwOSVersionInfoSize = sizeof(viex);
224 viex.dwMajorVersion = lpVersionInformation->dwMajorVersion;
225 viex.dwMinorVersion = lpVersionInformation->dwMinorVersion;
226 viex.dwBuildNumber = lpVersionInformation->dwBuildNumber;
227 viex.dwPlatformId = lpVersionInformation->dwPlatformId;
228 /* NOTE: szCSDVersion is ignored, we don't need to convert it to unicode */
229 viex.wServicePackMajor = lpVersionInformation->wServicePackMajor;
230 viex.wServicePackMinor = lpVersionInformation->wServicePackMinor;
231 viex.wSuiteMask = lpVersionInformation->wSuiteMask;
232 viex.wProductType = lpVersionInformation->wProductType;
233 viex.wReserved = lpVersionInformation->wReserved;
234
235 return VerifyVersionInfoW(&viex, dwTypeMask, dwlConditionMask);
236 }
237
238 /* EOF */