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>
16 #define UNICODIZE1(x) L##x
17 #define UNICODIZE(x) UNICODIZE1(x)
19 static UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version");
20 static UNICODE_STRING ValName
= RTL_CONSTANT_STRING(L
"ReportAsWorkstation");
22 /* FUNCTIONS ******************************************************************/
26 SetRosSpecificInfo(LPOSVERSIONINFOW lpVersionInformation
)
28 PKEY_VALUE_PARTIAL_INFORMATION kvpInfo
= NULL
;
29 OBJECT_ATTRIBUTES ObjectAttributes
;
30 DWORD ReportAsWorkstation
= 0;
36 TRACE("Setting Ros Specific version info\n");
38 if (!lpVersionInformation
)
41 /* Only the EX version has a product type */
42 if (lpVersionInformation
->dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXW
))
44 /* Allocate memory for our reg query */
45 dwSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(DWORD
);
46 kvpInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)HeapAlloc(GetProcessHeap(), 0, dwSize
);
50 InitializeObjectAttributes(&ObjectAttributes
,
52 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
56 /* Don't change anything if the key doesn't exist */
57 Status
= NtOpenKey(&hKey
,
60 if (NT_SUCCESS(Status
))
62 /* Get the value from the registry */
63 Status
= NtQueryValueKey(hKey
,
65 KeyValuePartialInformation
,
69 if (NT_SUCCESS(Status
))
71 /* It should be a DWORD */
72 if (kvpInfo
->Type
== REG_DWORD
)
74 /* Copy the value for ease of use */
75 RtlMoveMemory(&ReportAsWorkstation
,
79 /* Is the value set? */
80 if (((LPOSVERSIONINFOEXW
)lpVersionInformation
)->wProductType
== VER_NT_SERVER
&&
83 /* It is, modify the product type to report a workstation */
84 ((LPOSVERSIONINFOEXW
)lpVersionInformation
)->wProductType
= VER_NT_WORKSTATION
;
85 TRACE("We modified the reported OS from NtProductServer to NtProductWinNt\n");
93 HeapFree(GetProcessHeap(), 0, kvpInfo
);
97 /* Append a reactos specific string to the szCSDVersion string ... very hackish ... */
98 /* FIXME: Does anything even use this??? I think not.... - Ged */
99 ln
= wcslen(lpVersionInformation
->szCSDVersion
) + 1;
100 maxlen
= (sizeof(lpVersionInformation
->szCSDVersion
) / sizeof(lpVersionInformation
->szCSDVersion
[0]) - 1);
103 PWCHAR szVer
= lpVersionInformation
->szCSDVersion
+ ln
;
104 RtlZeroMemory(szVer
, (maxlen
- ln
+ 1) * sizeof(WCHAR
));
106 L
"ReactOS " UNICODIZE(KERNEL_VERSION_STR
) L
" (Build " UNICODIZE(KERNEL_VERSION_BUILD_STR
) L
")",
119 PPEB pPeb
= NtCurrentPeb();
122 nVersion
= MAKEWORD(pPeb
->OSMajorVersion
, pPeb
->OSMinorVersion
);
124 /* behave consistently when posing as another operating system build number */
125 if(pPeb
->OSPlatformId
!= VER_PLATFORM_WIN32_WINDOWS
)
126 nVersion
|= ((DWORD
)(pPeb
->OSBuildNumber
)) << 16;
128 /* non-NT platform flag */
129 if(pPeb
->OSPlatformId
!= VER_PLATFORM_WIN32_NT
)
130 nVersion
|= 0x80000000;
140 GetVersionExW(LPOSVERSIONINFOW lpVersionInformation
)
144 if(lpVersionInformation
->dwOSVersionInfoSize
!= sizeof(OSVERSIONINFOW
) &&
145 lpVersionInformation
->dwOSVersionInfoSize
!= sizeof(OSVERSIONINFOEXW
))
147 /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
148 enough but doesn't match the exact sizes supported, ERROR_INVALID_PARAMETER
149 would've been much more appropriate... */
150 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
154 Status
= RtlGetVersion((PRTL_OSVERSIONINFOW
)lpVersionInformation
);
155 if(NT_SUCCESS(Status
))
157 /* ReactOS specific changes */
158 SetRosSpecificInfo(lpVersionInformation
);
172 GetVersionExA(LPOSVERSIONINFOA lpVersionInformation
)
174 OSVERSIONINFOEXW viw
;
176 RtlZeroMemory(&viw
, sizeof(viw
));
178 switch(lpVersionInformation
->dwOSVersionInfoSize
)
180 case sizeof(OSVERSIONINFOA
):
181 viw
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOW
);
184 case sizeof(OSVERSIONINFOEXA
):
185 viw
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEXW
);
189 /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
190 enough but doesn't match the exact sizes supported, ERROR_INVALID_PARAMETER
191 would've been much more appropriate... */
192 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
196 if(GetVersionExW((LPOSVERSIONINFOW
)&viw
))
198 ANSI_STRING CSDVersionA
;
199 UNICODE_STRING CSDVersionW
;
201 /* copy back fields that match both supported structures */
202 lpVersionInformation
->dwMajorVersion
= viw
.dwMajorVersion
;
203 lpVersionInformation
->dwMinorVersion
= viw
.dwMinorVersion
;
204 lpVersionInformation
->dwBuildNumber
= viw
.dwBuildNumber
;
205 lpVersionInformation
->dwPlatformId
= viw
.dwPlatformId
;
207 /* convert the win version string */
208 RtlInitUnicodeString(&CSDVersionW
, viw
.szCSDVersion
);
210 CSDVersionA
.Length
= 0;
211 CSDVersionA
.MaximumLength
= sizeof(lpVersionInformation
->szCSDVersion
);
212 CSDVersionA
.Buffer
= lpVersionInformation
->szCSDVersion
;
214 RtlUnicodeStringToAnsiString(&CSDVersionA
, &CSDVersionW
, FALSE
);
216 /* convert the ReactOS version string */
217 CSDVersionW
.Buffer
= viw
.szCSDVersion
+ CSDVersionW
.Length
/ sizeof(WCHAR
) + 1;
218 CSDVersionW
.MaximumLength
= sizeof(viw
.szCSDVersion
) - (CSDVersionW
.Length
+ sizeof(WCHAR
));
219 CSDVersionW
.Length
= wcslen(CSDVersionW
.Buffer
) * sizeof(WCHAR
);
220 CSDVersionA
.Buffer
= lpVersionInformation
->szCSDVersion
+ CSDVersionA
.Length
+ 1;
221 CSDVersionA
.MaximumLength
= sizeof(lpVersionInformation
->szCSDVersion
) - (CSDVersionA
.Length
+ 1);
222 CSDVersionA
.Length
= 0;
224 RtlUnicodeStringToAnsiString(&CSDVersionA
, &CSDVersionW
, FALSE
);
226 /* copy back the extended fields */
227 if(viw
.dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXW
))
229 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wServicePackMajor
= viw
.wServicePackMajor
;
230 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wServicePackMinor
= viw
.wServicePackMinor
;
231 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wSuiteMask
= viw
.wSuiteMask
;
232 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wProductType
= viw
.wProductType
;
233 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wReserved
= viw
.wReserved
;
248 VerifyVersionInfoW(LPOSVERSIONINFOEXW lpVersionInformation
,
250 DWORDLONG dwlConditionMask
)
254 Status
= RtlVerifyVersionInfo((PRTL_OSVERSIONINFOEXW
)lpVersionInformation
,
259 case STATUS_INVALID_PARAMETER
:
260 SetLastError(ERROR_BAD_ARGUMENTS
);
263 case STATUS_REVISION_MISMATCH
:
264 SetLastError(ERROR_OLD_WIN_VERSION
);
268 /* RtlVerifyVersionInfo shouldn't report any other failure code! */
269 ASSERT(NT_SUCCESS(Status
));
271 /* ReactOS specific changes */
272 SetRosSpecificInfo((LPOSVERSIONINFOW
)lpVersionInformation
);
284 VerifyVersionInfoA(LPOSVERSIONINFOEXA lpVersionInformation
,
286 DWORDLONG dwlConditionMask
)
288 OSVERSIONINFOEXW viex
;
290 viex
.dwOSVersionInfoSize
= sizeof(viex
);
291 viex
.dwMajorVersion
= lpVersionInformation
->dwMajorVersion
;
292 viex
.dwMinorVersion
= lpVersionInformation
->dwMinorVersion
;
293 viex
.dwBuildNumber
= lpVersionInformation
->dwBuildNumber
;
294 viex
.dwPlatformId
= lpVersionInformation
->dwPlatformId
;
295 /* NOTE: szCSDVersion is ignored, we don't need to convert it to unicode */
296 viex
.wServicePackMajor
= lpVersionInformation
->wServicePackMajor
;
297 viex
.wServicePackMinor
= lpVersionInformation
->wServicePackMinor
;
298 viex
.wSuiteMask
= lpVersionInformation
->wSuiteMask
;
299 viex
.wProductType
= lpVersionInformation
->wProductType
;
300 viex
.wReserved
= lpVersionInformation
->wReserved
;
302 return VerifyVersionInfoW(&viex
, dwTypeMask
, dwlConditionMask
);