2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: dll/win32/kernel32/misc/version.c
5 * PURPOSE: Version functions
6 * PROGRAMMER: Ariadne (ariadne@xs4all.nl)
7 Ged Murphy (gedmurphy@reactos.org)
11 #include <reactos/buildno.h>
13 #include <wine/debug.h>
15 WINE_DEFAULT_DEBUG_CHANNEL(kernel32Ver
);
17 #define UNICODIZE1(x) L##x
18 #define UNICODIZE(x) UNICODIZE1(x)
20 static UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version");
21 static UNICODE_STRING ValName
= RTL_CONSTANT_STRING(L
"ReportAsWorkstation");
23 /* FUNCTIONS ******************************************************************/
27 SetRosSpecificInfo(LPOSVERSIONINFOW lpVersionInformation
)
29 PKEY_VALUE_PARTIAL_INFORMATION kvpInfo
= NULL
;
30 OBJECT_ATTRIBUTES ObjectAttributes
;
31 DWORD ReportAsWorkstation
= 0;
37 TRACE("Setting Ros Specific version info\n");
39 if (!lpVersionInformation
)
42 /* Only the EX version has a product type */
43 if (lpVersionInformation
->dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXW
))
45 /* Allocate memory for our reg query */
46 dwSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(DWORD
);
47 kvpInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)HeapAlloc(GetProcessHeap(), 0, dwSize
);
51 InitializeObjectAttributes(&ObjectAttributes
,
53 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
57 /* Don't change anything if the key doesn't exist */
58 Status
= NtOpenKey(&hKey
,
61 if (NT_SUCCESS(Status
))
63 /* Get the value from the registry */
64 Status
= NtQueryValueKey(hKey
,
66 KeyValuePartialInformation
,
70 if (NT_SUCCESS(Status
))
72 /* It should be a DWORD */
73 if (kvpInfo
->Type
== REG_DWORD
)
75 /* Copy the value for ease of use */
76 RtlMoveMemory(&ReportAsWorkstation
,
80 /* Is the value set? */
81 if (((LPOSVERSIONINFOEXW
)lpVersionInformation
)->wProductType
== VER_NT_SERVER
&&
84 /* It is, modify the product type to report a workstation */
85 ((LPOSVERSIONINFOEXW
)lpVersionInformation
)->wProductType
= VER_NT_WORKSTATION
;
86 TRACE("We modified the reported OS from NtProductServer to NtProductWinNt\n");
94 HeapFree(GetProcessHeap(), 0, kvpInfo
);
98 /* Append a reactos specific string to the szCSDVersion string ... very hackish ... */
99 /* FIXME: Does anything even use this??? I think not.... - Ged */
100 ln
= wcslen(lpVersionInformation
->szCSDVersion
) + 1;
101 maxlen
= (sizeof(lpVersionInformation
->szCSDVersion
) / sizeof(lpVersionInformation
->szCSDVersion
[0]) - 1);
104 PWCHAR szVer
= lpVersionInformation
->szCSDVersion
+ ln
;
105 RtlZeroMemory(szVer
, (maxlen
- ln
+ 1) * sizeof(WCHAR
));
107 L
"ReactOS " UNICODIZE(KERNEL_VERSION_STR
) L
" (Build " UNICODIZE(KERNEL_VERSION_BUILD_STR
) L
")",
120 PPEB pPeb
= NtCurrentPeb();
123 nVersion
= MAKEWORD(pPeb
->OSMajorVersion
, pPeb
->OSMinorVersion
);
125 /* behave consistently when posing as another operating system build number */
126 if(pPeb
->OSPlatformId
!= VER_PLATFORM_WIN32_WINDOWS
)
127 nVersion
|= ((DWORD
)(pPeb
->OSBuildNumber
)) << 16;
129 /* non-NT platform flag */
130 if(pPeb
->OSPlatformId
!= VER_PLATFORM_WIN32_NT
)
131 nVersion
|= 0x80000000;
141 GetVersionExW(LPOSVERSIONINFOW lpVersionInformation
)
145 if(lpVersionInformation
->dwOSVersionInfoSize
!= sizeof(OSVERSIONINFOW
) &&
146 lpVersionInformation
->dwOSVersionInfoSize
!= sizeof(OSVERSIONINFOEXW
))
148 /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
149 enough but doesn't match the exact sizes supported, ERROR_INVALID_PARAMETER
150 would've been much more appropriate... */
151 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
155 Status
= RtlGetVersion((PRTL_OSVERSIONINFOW
)lpVersionInformation
);
156 if(NT_SUCCESS(Status
))
158 /* ReactOS specific changes */
159 SetRosSpecificInfo(lpVersionInformation
);
173 GetVersionExA(LPOSVERSIONINFOA lpVersionInformation
)
175 OSVERSIONINFOEXW viw
;
177 RtlZeroMemory(&viw
, sizeof(viw
));
179 switch(lpVersionInformation
->dwOSVersionInfoSize
)
181 case sizeof(OSVERSIONINFOA
):
182 viw
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOW
);
185 case sizeof(OSVERSIONINFOEXA
):
186 viw
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEXW
);
190 /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
191 enough but doesn't match the exact sizes supported, ERROR_INVALID_PARAMETER
192 would've been much more appropriate... */
193 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
197 if(GetVersionExW((LPOSVERSIONINFOW
)&viw
))
199 ANSI_STRING CSDVersionA
;
200 UNICODE_STRING CSDVersionW
;
202 /* copy back fields that match both supported structures */
203 lpVersionInformation
->dwMajorVersion
= viw
.dwMajorVersion
;
204 lpVersionInformation
->dwMinorVersion
= viw
.dwMinorVersion
;
205 lpVersionInformation
->dwBuildNumber
= viw
.dwBuildNumber
;
206 lpVersionInformation
->dwPlatformId
= viw
.dwPlatformId
;
208 /* convert the win version string */
209 RtlInitUnicodeString(&CSDVersionW
, viw
.szCSDVersion
);
211 CSDVersionA
.Length
= 0;
212 CSDVersionA
.MaximumLength
= sizeof(lpVersionInformation
->szCSDVersion
);
213 CSDVersionA
.Buffer
= lpVersionInformation
->szCSDVersion
;
215 RtlUnicodeStringToAnsiString(&CSDVersionA
, &CSDVersionW
, FALSE
);
217 /* convert the ReactOS version string */
218 CSDVersionW
.Buffer
= viw
.szCSDVersion
+ CSDVersionW
.Length
/ sizeof(WCHAR
) + 1;
219 CSDVersionW
.MaximumLength
= sizeof(viw
.szCSDVersion
) - (CSDVersionW
.Length
+ sizeof(WCHAR
));
220 CSDVersionW
.Length
= wcslen(CSDVersionW
.Buffer
) * sizeof(WCHAR
);
221 CSDVersionA
.Buffer
= lpVersionInformation
->szCSDVersion
+ CSDVersionA
.Length
+ 1;
222 CSDVersionA
.MaximumLength
= sizeof(lpVersionInformation
->szCSDVersion
) - (CSDVersionA
.Length
+ 1);
223 CSDVersionA
.Length
= 0;
225 RtlUnicodeStringToAnsiString(&CSDVersionA
, &CSDVersionW
, FALSE
);
227 /* copy back the extended fields */
228 if(viw
.dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXW
))
230 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wServicePackMajor
= viw
.wServicePackMajor
;
231 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wServicePackMinor
= viw
.wServicePackMinor
;
232 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wSuiteMask
= viw
.wSuiteMask
;
233 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wProductType
= viw
.wProductType
;
234 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wReserved
= viw
.wReserved
;
249 VerifyVersionInfoW(LPOSVERSIONINFOEXW lpVersionInformation
,
251 DWORDLONG dwlConditionMask
)
255 Status
= RtlVerifyVersionInfo((PRTL_OSVERSIONINFOEXW
)lpVersionInformation
,
260 case STATUS_INVALID_PARAMETER
:
261 SetLastError(ERROR_BAD_ARGUMENTS
);
264 case STATUS_REVISION_MISMATCH
:
265 SetLastError(ERROR_OLD_WIN_VERSION
);
269 /* RtlVerifyVersionInfo shouldn't report any other failure code! */
270 ASSERT(NT_SUCCESS(Status
));
272 /* ReactOS specific changes */
273 SetRosSpecificInfo((LPOSVERSIONINFOW
)lpVersionInformation
);
285 VerifyVersionInfoA(LPOSVERSIONINFOEXA lpVersionInformation
,
287 DWORDLONG dwlConditionMask
)
289 OSVERSIONINFOEXW viex
;
291 viex
.dwOSVersionInfoSize
= sizeof(viex
);
292 viex
.dwMajorVersion
= lpVersionInformation
->dwMajorVersion
;
293 viex
.dwMinorVersion
= lpVersionInformation
->dwMinorVersion
;
294 viex
.dwBuildNumber
= lpVersionInformation
->dwBuildNumber
;
295 viex
.dwPlatformId
= lpVersionInformation
->dwPlatformId
;
296 /* NOTE: szCSDVersion is ignored, we don't need to convert it to unicode */
297 viex
.wServicePackMajor
= lpVersionInformation
->wServicePackMajor
;
298 viex
.wServicePackMinor
= lpVersionInformation
->wServicePackMinor
;
299 viex
.wSuiteMask
= lpVersionInformation
->wSuiteMask
;
300 viex
.wProductType
= lpVersionInformation
->wProductType
;
301 viex
.wReserved
= lpVersionInformation
->wReserved
;
303 return VerifyVersionInfoW(&viex
, dwTypeMask
, dwlConditionMask
);