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>
15 #define UNICODIZE1(x) L##x
16 #define UNICODIZE(x) UNICODIZE1(x)
18 static UNICODE_STRING KeyName
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version");
19 static UNICODE_STRING ValName
= RTL_CONSTANT_STRING(L
"ReportAsWorkstation");
21 /* FUNCTIONS ******************************************************************/
25 SetRosSpecificInfo(LPOSVERSIONINFOW lpVersionInformation
)
27 PKEY_VALUE_PARTIAL_INFORMATION kvpInfo
= NULL
;
28 OBJECT_ATTRIBUTES ObjectAttributes
;
29 DWORD ReportAsWorkstation
= 0;
35 TRACE("Setting Ros Specific version info\n");
37 if (!lpVersionInformation
)
40 /* Only the EX version has a product type */
41 if (lpVersionInformation
->dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXW
))
43 /* Allocate memory for our reg query */
44 dwSize
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) + sizeof(DWORD
);
45 kvpInfo
= (PKEY_VALUE_PARTIAL_INFORMATION
)HeapAlloc(GetProcessHeap(), 0, dwSize
);
49 InitializeObjectAttributes(&ObjectAttributes
,
51 OBJ_OPENIF
| OBJ_CASE_INSENSITIVE
,
55 /* Don't change anything if the key doesn't exist */
56 Status
= NtOpenKey(&hKey
,
59 if (NT_SUCCESS(Status
))
61 /* Get the value from the registry */
62 Status
= NtQueryValueKey(hKey
,
64 KeyValuePartialInformation
,
68 if (NT_SUCCESS(Status
))
70 /* It should be a DWORD */
71 if (kvpInfo
->Type
== REG_DWORD
)
73 /* Copy the value for ease of use */
74 RtlMoveMemory(&ReportAsWorkstation
,
78 /* Is the value set? */
79 if (((LPOSVERSIONINFOEXW
)lpVersionInformation
)->wProductType
== VER_NT_SERVER
&&
82 /* It is, modify the product type to report a workstation */
83 ((LPOSVERSIONINFOEXW
)lpVersionInformation
)->wProductType
= VER_NT_WORKSTATION
;
84 TRACE("We modified the reported OS from NtProductServer to NtProductWinNt\n");
92 HeapFree(GetProcessHeap(), 0, kvpInfo
);
96 /* Append a reactos specific string to the szCSDVersion string ... very hackish ... */
97 /* FIXME: Does anything even use this??? I think not.... - Ged */
98 ln
= wcslen(lpVersionInformation
->szCSDVersion
) + 1;
99 maxlen
= (sizeof(lpVersionInformation
->szCSDVersion
) / sizeof(lpVersionInformation
->szCSDVersion
[0]) - 1);
102 PWCHAR szVer
= lpVersionInformation
->szCSDVersion
+ ln
;
103 RtlZeroMemory(szVer
, (maxlen
- ln
+ 1) * sizeof(WCHAR
));
105 L
"ReactOS " UNICODIZE(KERNEL_VERSION_STR
) L
" (Build " UNICODIZE(KERNEL_VERSION_BUILD_STR
) L
")",
118 PPEB pPeb
= NtCurrentPeb();
121 nVersion
= MAKEWORD(pPeb
->OSMajorVersion
, pPeb
->OSMinorVersion
);
123 /* behave consistently when posing as another operating system build number */
124 if(pPeb
->OSPlatformId
!= VER_PLATFORM_WIN32_WINDOWS
)
125 nVersion
|= ((DWORD
)(pPeb
->OSBuildNumber
)) << 16;
127 /* non-NT platform flag */
128 if(pPeb
->OSPlatformId
!= VER_PLATFORM_WIN32_NT
)
129 nVersion
|= 0x80000000;
139 GetVersionExW(LPOSVERSIONINFOW lpVersionInformation
)
143 if(lpVersionInformation
->dwOSVersionInfoSize
!= sizeof(OSVERSIONINFOW
) &&
144 lpVersionInformation
->dwOSVersionInfoSize
!= sizeof(OSVERSIONINFOEXW
))
146 /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
147 enough but doesn't match the exact sizes supported, ERROR_INVALID_PARAMETER
148 would've been much more appropriate... */
149 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
153 Status
= RtlGetVersion((PRTL_OSVERSIONINFOW
)lpVersionInformation
);
154 if(NT_SUCCESS(Status
))
156 /* ReactOS specific changes */
157 SetRosSpecificInfo(lpVersionInformation
);
171 GetVersionExA(LPOSVERSIONINFOA lpVersionInformation
)
173 OSVERSIONINFOEXW viw
;
175 RtlZeroMemory(&viw
, sizeof(viw
));
177 switch(lpVersionInformation
->dwOSVersionInfoSize
)
179 case sizeof(OSVERSIONINFOA
):
180 viw
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOW
);
183 case sizeof(OSVERSIONINFOEXA
):
184 viw
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEXW
);
188 /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
189 enough but doesn't match the exact sizes supported, ERROR_INVALID_PARAMETER
190 would've been much more appropriate... */
191 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
195 if(GetVersionExW((LPOSVERSIONINFOW
)&viw
))
197 ANSI_STRING CSDVersionA
;
198 UNICODE_STRING CSDVersionW
;
200 /* copy back fields that match both supported structures */
201 lpVersionInformation
->dwMajorVersion
= viw
.dwMajorVersion
;
202 lpVersionInformation
->dwMinorVersion
= viw
.dwMinorVersion
;
203 lpVersionInformation
->dwBuildNumber
= viw
.dwBuildNumber
;
204 lpVersionInformation
->dwPlatformId
= viw
.dwPlatformId
;
206 /* convert the win version string */
207 RtlInitUnicodeString(&CSDVersionW
, viw
.szCSDVersion
);
209 CSDVersionA
.Length
= 0;
210 CSDVersionA
.MaximumLength
= sizeof(lpVersionInformation
->szCSDVersion
);
211 CSDVersionA
.Buffer
= lpVersionInformation
->szCSDVersion
;
213 RtlUnicodeStringToAnsiString(&CSDVersionA
, &CSDVersionW
, FALSE
);
215 /* convert the ReactOS version string */
216 CSDVersionW
.Buffer
= viw
.szCSDVersion
+ CSDVersionW
.Length
/ sizeof(WCHAR
) + 1;
217 CSDVersionW
.MaximumLength
= sizeof(viw
.szCSDVersion
) - (CSDVersionW
.Length
+ sizeof(WCHAR
));
218 CSDVersionW
.Length
= wcslen(CSDVersionW
.Buffer
) * sizeof(WCHAR
);
219 CSDVersionA
.Buffer
= lpVersionInformation
->szCSDVersion
+ CSDVersionA
.Length
+ 1;
220 CSDVersionA
.MaximumLength
= sizeof(lpVersionInformation
->szCSDVersion
) - (CSDVersionA
.Length
+ 1);
221 CSDVersionA
.Length
= 0;
223 RtlUnicodeStringToAnsiString(&CSDVersionA
, &CSDVersionW
, FALSE
);
225 /* copy back the extended fields */
226 if(viw
.dwOSVersionInfoSize
== sizeof(OSVERSIONINFOEXW
))
228 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wServicePackMajor
= viw
.wServicePackMajor
;
229 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wServicePackMinor
= viw
.wServicePackMinor
;
230 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wSuiteMask
= viw
.wSuiteMask
;
231 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wProductType
= viw
.wProductType
;
232 ((LPOSVERSIONINFOEXA
)lpVersionInformation
)->wReserved
= viw
.wReserved
;
247 VerifyVersionInfoW(LPOSVERSIONINFOEXW lpVersionInformation
,
249 DWORDLONG dwlConditionMask
)
253 Status
= RtlVerifyVersionInfo((PRTL_OSVERSIONINFOEXW
)lpVersionInformation
,
258 case STATUS_INVALID_PARAMETER
:
259 SetLastError(ERROR_BAD_ARGUMENTS
);
262 case STATUS_REVISION_MISMATCH
:
263 SetLastError(ERROR_OLD_WIN_VERSION
);
267 /* RtlVerifyVersionInfo shouldn't report any other failure code! */
268 ASSERT(NT_SUCCESS(Status
));
270 /* ReactOS specific changes */
271 SetRosSpecificInfo((LPOSVERSIONINFOW
)lpVersionInformation
);
283 VerifyVersionInfoA(LPOSVERSIONINFOEXA lpVersionInformation
,
285 DWORDLONG dwlConditionMask
)
287 OSVERSIONINFOEXW viex
;
289 viex
.dwOSVersionInfoSize
= sizeof(viex
);
290 viex
.dwMajorVersion
= lpVersionInformation
->dwMajorVersion
;
291 viex
.dwMinorVersion
= lpVersionInformation
->dwMinorVersion
;
292 viex
.dwBuildNumber
= lpVersionInformation
->dwBuildNumber
;
293 viex
.dwPlatformId
= lpVersionInformation
->dwPlatformId
;
294 /* NOTE: szCSDVersion is ignored, we don't need to convert it to unicode */
295 viex
.wServicePackMajor
= lpVersionInformation
->wServicePackMajor
;
296 viex
.wServicePackMinor
= lpVersionInformation
->wServicePackMinor
;
297 viex
.wSuiteMask
= lpVersionInformation
->wSuiteMask
;
298 viex
.wProductType
= lpVersionInformation
->wProductType
;
299 viex
.wReserved
= lpVersionInformation
->wReserved
;
301 return VerifyVersionInfoW(&viex
, dwTypeMask
, dwlConditionMask
);