- Update to r53061
[reactos.git] / dll / win32 / kernel32 / client / version.c
1 /*
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)
8 */
9
10 #include <k32.h>
11
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS ******************************************************************/
16
17 VOID
18 NTAPI
19 SetRosSpecificInfo(IN LPOSVERSIONINFOEXW VersionInformation)
20 {
21 CHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)];
22 PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = (PVOID)Buffer;
23 OBJECT_ATTRIBUTES ObjectAttributes;
24 DWORD ReportAsWorkstation = 0;
25 HANDLE hKey;
26 DWORD dwSize;
27 NTSTATUS Status;
28 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version");
29 UNICODE_STRING ValName = RTL_CONSTANT_STRING(L"ReportAsWorkstation");
30
31 InitializeObjectAttributes(&ObjectAttributes,
32 &KeyName,
33 OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
34 NULL,
35 NULL);
36
37 /* Don't change anything if the key doesn't exist */
38 Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
39 if (NT_SUCCESS(Status))
40 {
41 /* Get the value from the registry and make sure it's a 32-bit value */
42 Status = NtQueryValueKey(hKey,
43 &ValName,
44 KeyValuePartialInformation,
45 kvpInfo,
46 sizeof(Buffer),
47 &dwSize);
48 if ((NT_SUCCESS(Status)) &&
49 (kvpInfo->Type == REG_DWORD) &&
50 (kvpInfo->DataLength == sizeof(DWORD)))
51 {
52 /* Is the value set? */
53 ReportAsWorkstation = *(PULONG)kvpInfo->Data;
54 if ((VersionInformation->wProductType == VER_NT_SERVER) &&
55 (ReportAsWorkstation))
56 {
57 /* It is, modify the product type to report a workstation */
58 VersionInformation->wProductType = VER_NT_WORKSTATION;
59 DPRINT1("We modified the reported OS from NtProductServer to NtProductWinNt\n");
60 }
61 }
62
63 /* Close the handle */
64 NtClose(hKey);
65 }
66 }
67
68 /*
69 * @implemented
70 */
71 DWORD
72 WINAPI
73 GetVersion(VOID)
74 {
75 PPEB Peb = NtCurrentPeb();
76 DWORD Result;
77
78 Result = MAKELONG(MAKEWORD(Peb->OSMajorVersion, Peb->OSMinorVersion),
79 (Peb->OSPlatformId ^ 2) << 14);
80 Result |= LOWORD(Peb->OSBuildNumber) << 16;
81 return Result;
82 }
83
84 /*
85 * @implemented
86 */
87 BOOL
88 WINAPI
89 GetVersionExW(IN LPOSVERSIONINFOW lpVersionInformation)
90 {
91 NTSTATUS Status;
92 LPOSVERSIONINFOEXW lpVersionInformationEx;
93
94 if ((lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOW)) &&
95 (lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW)))
96 {
97 SetLastError(ERROR_INSUFFICIENT_BUFFER);
98 return FALSE;
99 }
100
101 Status = RtlGetVersion((PRTL_OSVERSIONINFOW)lpVersionInformation);
102 if (Status == STATUS_SUCCESS)
103 {
104 if (lpVersionInformation->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW))
105 {
106 lpVersionInformationEx = (PVOID)lpVersionInformation;
107 lpVersionInformationEx->wReserved = 0;
108
109 /* ReactOS specific changes */
110 SetRosSpecificInfo(lpVersionInformationEx);
111 }
112
113 return TRUE;
114 }
115
116 return FALSE;
117 }
118
119 /*
120 * @implemented
121 */
122 BOOL
123 WINAPI
124 GetVersionExA(IN LPOSVERSIONINFOA lpVersionInformation)
125 {
126 OSVERSIONINFOEXW VersionInformation;
127 LPOSVERSIONINFOEXA lpVersionInformationEx;
128 UNICODE_STRING CsdVersionW;
129 NTSTATUS Status;
130 ANSI_STRING CsdVersionA;
131
132 if ((lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOA)) &&
133 (lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXA)))
134 {
135 SetLastError(ERROR_INSUFFICIENT_BUFFER);
136 return FALSE;
137 }
138
139 VersionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
140
141 if (!GetVersionExW((LPOSVERSIONINFOW)&VersionInformation)) return FALSE;
142
143 /* Copy back fields that match both supported structures */
144 lpVersionInformation->dwMajorVersion = VersionInformation.dwMajorVersion;
145 lpVersionInformation->dwMinorVersion = VersionInformation.dwMinorVersion;
146 lpVersionInformation->dwBuildNumber = VersionInformation.dwBuildNumber;
147 lpVersionInformation->dwPlatformId = VersionInformation.dwPlatformId;
148
149 if (lpVersionInformation->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA))
150 {
151 lpVersionInformationEx = (PVOID)lpVersionInformation;
152 lpVersionInformationEx->wServicePackMajor = VersionInformation.wServicePackMajor;
153 lpVersionInformationEx->wServicePackMinor = VersionInformation.wServicePackMinor;
154 lpVersionInformationEx->wSuiteMask = VersionInformation.wSuiteMask;
155 lpVersionInformationEx->wProductType = VersionInformation.wProductType;
156 lpVersionInformationEx->wReserved = VersionInformation.wReserved;
157 }
158
159 /* Convert the CSD string */
160 RtlInitEmptyAnsiString(&CsdVersionA,
161 lpVersionInformation->szCSDVersion,
162 sizeof(lpVersionInformation->szCSDVersion));
163 RtlInitUnicodeString(&CsdVersionW, VersionInformation.szCSDVersion);
164 Status = RtlUnicodeStringToAnsiString(&CsdVersionA, &CsdVersionW, FALSE);
165 return (NT_SUCCESS(Status));
166 }
167
168 /*
169 * @implemented
170 */
171 BOOL
172 WINAPI
173 VerifyVersionInfoW(IN LPOSVERSIONINFOEXW lpVersionInformation,
174 IN DWORD dwTypeMask,
175 IN DWORDLONG dwlConditionMask)
176 {
177 NTSTATUS Status;
178
179 Status = RtlVerifyVersionInfo((PRTL_OSVERSIONINFOEXW)lpVersionInformation,
180 dwTypeMask,
181 dwlConditionMask);
182 switch (Status)
183 {
184 case STATUS_INVALID_PARAMETER:
185 SetLastError(ERROR_BAD_ARGUMENTS);
186 return FALSE;
187
188 case STATUS_REVISION_MISMATCH:
189 DPRINT1("ReactOS returning version mismatch. Investigate!\n");
190 SetLastError(ERROR_OLD_WIN_VERSION);
191 return FALSE;
192
193 default:
194 /* RtlVerifyVersionInfo shouldn't report any other failure code! */
195 ASSERT(NT_SUCCESS(Status));
196 return TRUE;
197 }
198 }
199
200 /*
201 * @implemented
202 */
203 BOOL
204 WINAPI
205 VerifyVersionInfoA(IN LPOSVERSIONINFOEXA lpVersionInformation,
206 IN DWORD dwTypeMask,
207 IN DWORDLONG dwlConditionMask)
208 {
209 OSVERSIONINFOEXW viex;
210
211 /* NOTE: szCSDVersion is ignored, we don't need to convert it to Unicode */
212 viex.dwOSVersionInfoSize = sizeof(viex);
213 viex.dwMajorVersion = lpVersionInformation->dwMajorVersion;
214 viex.dwMinorVersion = lpVersionInformation->dwMinorVersion;
215 viex.dwBuildNumber = lpVersionInformation->dwBuildNumber;
216 viex.dwPlatformId = lpVersionInformation->dwPlatformId;
217 viex.wServicePackMajor = lpVersionInformation->wServicePackMajor;
218 viex.wServicePackMinor = lpVersionInformation->wServicePackMinor;
219 viex.wSuiteMask = lpVersionInformation->wSuiteMask;
220 viex.wProductType = lpVersionInformation->wProductType;
221 viex.wReserved = lpVersionInformation->wReserved;
222 return VerifyVersionInfoW(&viex, dwTypeMask, dwlConditionMask);
223 }