Author: ion
Date: Thu Jul 28 23:58:29 2011
New Revision: 52990
URL:
http://svn.reactos.org/svn/reactos?rev=52990&view=rev
Log:
[KERNEL32]: Cleanup and fix multiple bugs in the Version APIs. Code is neater, more
efficient, and more compatible.
Modified:
trunk/reactos/dll/win32/kernel32/client/version.c
Modified: trunk/reactos/dll/win32/kernel32/client/version.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/kernel32/client/…
==============================================================================
--- trunk/reactos/dll/win32/kernel32/client/version.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/kernel32/client/version.c [iso-8859-1] Thu Jul 28 23:58:29
2011
@@ -8,106 +8,62 @@
*/
#include <k32.h>
-#include <reactos/buildno.h>
+
#define NDEBUG
#include <debug.h>
-DEBUG_CHANNEL(kernel32ver);
-
-#define UNICODIZE1(x) L##x
-#define UNICODIZE(x) UNICODIZE1(x)
-
-static UNICODE_STRING KeyName =
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version");
-static UNICODE_STRING ValName = RTL_CONSTANT_STRING(L"ReportAsWorkstation");
/* FUNCTIONS ******************************************************************/
-
-static VOID
-SetRosSpecificInfo(LPOSVERSIONINFOW lpVersionInformation)
-{
- PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = NULL;
+VOID
+NTAPI
+SetRosSpecificInfo(IN LPOSVERSIONINFOEXW VersionInformation)
+{
+ CHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD)];
+ PKEY_VALUE_PARTIAL_INFORMATION kvpInfo = (PVOID)Buffer;
OBJECT_ATTRIBUTES ObjectAttributes;
DWORD ReportAsWorkstation = 0;
HANDLE hKey;
DWORD dwSize;
- INT ln, maxlen;
- NTSTATUS Status;
-
- TRACE("Setting Ros Specific version info\n");
-
- if (!lpVersionInformation)
- return;
-
- /* Only the EX version has a product type */
- if (lpVersionInformation->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW))
- {
- /* Allocate memory for our reg query */
- dwSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(DWORD);
- kvpInfo = (PKEY_VALUE_PARTIAL_INFORMATION)HeapAlloc(GetProcessHeap(), 0,
dwSize);
- if (!kvpInfo)
- return;
-
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
- NULL,
- NULL);
-
- /* Don't change anything if the key doesn't exist */
- Status = NtOpenKey(&hKey,
- KEY_READ,
- &ObjectAttributes);
- if (NT_SUCCESS(Status))
+ NTSTATUS Status;
+ UNICODE_STRING KeyName =
RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version");
+ UNICODE_STRING ValName = RTL_CONSTANT_STRING(L"ReportAsWorkstation");
+
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ /* Don't change anything if the key doesn't exist */
+ Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
+ if (NT_SUCCESS(Status))
+ {
+ /* Get the value from the registry and make sure it's a 32-bit value */
+ Status = NtQueryValueKey(hKey,
+ &ValName,
+ KeyValuePartialInformation,
+ kvpInfo,
+ sizeof(Buffer),
+ &dwSize);
+ if ((NT_SUCCESS(Status)) &&
+ (kvpInfo->Type == REG_DWORD) &&
+ (kvpInfo->DataLength == sizeof(DWORD)))
{
- /* Get the value from the registry */
- Status = NtQueryValueKey(hKey,
- &ValName,
- KeyValuePartialInformation,
- kvpInfo,
- dwSize,
- &dwSize);
- if (NT_SUCCESS(Status))
+ /* Is the value set? */
+ ReportAsWorkstation = *(PULONG)kvpInfo->Data;
+ if ((VersionInformation->wProductType == VER_NT_SERVER) &&
+ (ReportAsWorkstation))
{
- /* It should be a DWORD */
- if (kvpInfo->Type == REG_DWORD)
- {
- /* Copy the value for ease of use */
- RtlMoveMemory(&ReportAsWorkstation,
- kvpInfo->Data,
- kvpInfo->DataLength);
-
- /* Is the value set? */
- if (((LPOSVERSIONINFOEXW)lpVersionInformation)->wProductType ==
VER_NT_SERVER &&
- ReportAsWorkstation)
- {
- /* It is, modify the product type to report a workstation */
- ((LPOSVERSIONINFOEXW)lpVersionInformation)->wProductType =
VER_NT_WORKSTATION;
- TRACE("We modified the reported OS from NtProductServer to
NtProductWinNt\n");
- }
- }
+ /* It is, modify the product type to report a workstation */
+ VersionInformation->wProductType = VER_NT_WORKSTATION;
+ DPRINT1("We modified the reported OS from NtProductServer to
NtProductWinNt\n");
}
-
- NtClose(hKey);
- }
-
- HeapFree(GetProcessHeap(), 0, kvpInfo);
- }
-
-
- /* Append a reactos specific string to the szCSDVersion string ... very hackish ...
*/
- /* FIXME: Does anything even use this??? I think not.... - Ged */
- ln = wcslen(lpVersionInformation->szCSDVersion) + 1;
- maxlen = (sizeof(lpVersionInformation->szCSDVersion) /
sizeof(lpVersionInformation->szCSDVersion[0]) - 1);
- if(maxlen > ln)
- {
- PWCHAR szVer = lpVersionInformation->szCSDVersion + ln;
- RtlZeroMemory(szVer, (maxlen - ln + 1) * sizeof(WCHAR));
- wcsncpy(szVer,
- L"ReactOS " UNICODIZE(KERNEL_VERSION_STR) L" (Build "
UNICODIZE(KERNEL_VERSION_BUILD_STR) L")",
- maxlen - ln);
- }
-}
-
+ }
+
+ /* Close the handle */
+ NtClose(hKey);
+ }
+}
/*
* @implemented
@@ -116,46 +72,43 @@
WINAPI
GetVersion(VOID)
{
- PPEB pPeb = NtCurrentPeb();
- DWORD nVersion;
-
- nVersion = MAKEWORD(pPeb->OSMajorVersion, pPeb->OSMinorVersion);
-
- /* behave consistently when posing as another operating system build number */
- if(pPeb->OSPlatformId != VER_PLATFORM_WIN32_WINDOWS)
- nVersion |= ((DWORD)(pPeb->OSBuildNumber)) << 16;
-
- /* non-NT platform flag */
- if(pPeb->OSPlatformId != VER_PLATFORM_WIN32_NT)
- nVersion |= 0x80000000;
-
- return nVersion;
-}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-GetVersionExW(LPOSVERSIONINFOW lpVersionInformation)
-{
- NTSTATUS Status;
-
- if(lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOW) &&
- lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW))
- {
- /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
- enough but doesn't match the exact sizes supported,
ERROR_INVALID_PARAMETER
- would've been much more appropriate... */
+ PPEB Peb = NtCurrentPeb();
+ DWORD Result;
+
+ Result = MAKELONG(MAKEWORD(Peb->OSMajorVersion, Peb->OSMinorVersion),
+ (Peb->OSPlatformId ^ 2) << 14);
+ Result |= LOWORD(Peb->OSBuildNumber) << 16;
+ return Result;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetVersionExW(IN LPOSVERSIONINFOW lpVersionInformation)
+{
+ NTSTATUS Status;
+ LPOSVERSIONINFOEXW lpVersionInformationEx;
+
+ if ((lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOW))
&&
+ (lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXW)))
+ {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
Status = RtlGetVersion((PRTL_OSVERSIONINFOW)lpVersionInformation);
- if(NT_SUCCESS(Status))
- {
- /* ReactOS specific changes */
- SetRosSpecificInfo(lpVersionInformation);
+ if (Status == STATUS_SUCCESS)
+ {
+ if (lpVersionInformation->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW))
+ {
+ lpVersionInformationEx = (PVOID)lpVersionInformation;
+ lpVersionInformationEx->wReserved = 0;
+
+ /* ReactOS specific changes */
+ SetRosSpecificInfo(lpVersionInformationEx);
+ }
return TRUE;
}
@@ -163,141 +116,108 @@
return FALSE;
}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-GetVersionExA(LPOSVERSIONINFOA lpVersionInformation)
-{
- OSVERSIONINFOEXW viw;
-
- RtlZeroMemory(&viw, sizeof(viw));
-
- switch(lpVersionInformation->dwOSVersionInfoSize)
- {
- case sizeof(OSVERSIONINFOA):
- viw.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
- break;
-
- case sizeof(OSVERSIONINFOEXA):
- viw.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
- break;
-
- default:
- /* for some reason win sets ERROR_INSUFFICIENT_BUFFER even if it is large
- enough but doesn't match the exact sizes supported,
ERROR_INVALID_PARAMETER
- would've been much more appropriate... */
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+GetVersionExA(IN LPOSVERSIONINFOA lpVersionInformation)
+{
+ OSVERSIONINFOEXW VersionInformation;
+ LPOSVERSIONINFOEXA lpVersionInformationEx;
+ UNICODE_STRING CsdVersionW;
+ NTSTATUS Status;
+ ANSI_STRING CsdVersionA;
+
+ if ((lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOA))
&&
+ (lpVersionInformation->dwOSVersionInfoSize != sizeof(OSVERSIONINFOEXA)))
+ {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
- if(GetVersionExW((LPOSVERSIONINFOW)&viw))
- {
- ANSI_STRING CSDVersionA;
- UNICODE_STRING CSDVersionW;
-
- /* copy back fields that match both supported structures */
- lpVersionInformation->dwMajorVersion = viw.dwMajorVersion;
- lpVersionInformation->dwMinorVersion = viw.dwMinorVersion;
- lpVersionInformation->dwBuildNumber = viw.dwBuildNumber;
- lpVersionInformation->dwPlatformId = viw.dwPlatformId;
-
- /* convert the win version string */
- RtlInitUnicodeString(&CSDVersionW, viw.szCSDVersion);
-
- CSDVersionA.Length = 0;
- CSDVersionA.MaximumLength = sizeof(lpVersionInformation->szCSDVersion);
- CSDVersionA.Buffer = lpVersionInformation->szCSDVersion;
-
- RtlUnicodeStringToAnsiString(&CSDVersionA, &CSDVersionW, FALSE);
-
- /* convert the ReactOS version string */
- CSDVersionW.Buffer = viw.szCSDVersion + CSDVersionW.Length / sizeof(WCHAR) + 1;
- CSDVersionW.MaximumLength = sizeof(viw.szCSDVersion) - (CSDVersionW.Length +
sizeof(WCHAR));
- CSDVersionW.Length = wcslen(CSDVersionW.Buffer) * sizeof(WCHAR);
- CSDVersionA.Buffer = lpVersionInformation->szCSDVersion + CSDVersionA.Length +
1;
- CSDVersionA.MaximumLength = sizeof(lpVersionInformation->szCSDVersion) -
(CSDVersionA.Length + 1);
- CSDVersionA.Length = 0;
-
- RtlUnicodeStringToAnsiString(&CSDVersionA, &CSDVersionW, FALSE);
-
- /* copy back the extended fields */
- if(viw.dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXW))
- {
- ((LPOSVERSIONINFOEXA)lpVersionInformation)->wServicePackMajor =
viw.wServicePackMajor;
- ((LPOSVERSIONINFOEXA)lpVersionInformation)->wServicePackMinor =
viw.wServicePackMinor;
- ((LPOSVERSIONINFOEXA)lpVersionInformation)->wSuiteMask = viw.wSuiteMask;
- ((LPOSVERSIONINFOEXA)lpVersionInformation)->wProductType =
viw.wProductType;
- ((LPOSVERSIONINFOEXA)lpVersionInformation)->wReserved = viw.wReserved;
- }
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-VerifyVersionInfoW(LPOSVERSIONINFOEXW lpVersionInformation,
- DWORD dwTypeMask,
- DWORDLONG dwlConditionMask)
+ VersionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXW);
+
+ if (!GetVersionExW((LPOSVERSIONINFOW)&VersionInformation)) return FALSE;
+
+ /* Copy back fields that match both supported structures */
+ lpVersionInformation->dwMajorVersion = VersionInformation.dwMajorVersion;
+ lpVersionInformation->dwMinorVersion = VersionInformation.dwMinorVersion;
+ lpVersionInformation->dwBuildNumber = VersionInformation.dwBuildNumber;
+ lpVersionInformation->dwPlatformId = VersionInformation.dwPlatformId;
+
+ if (lpVersionInformation->dwOSVersionInfoSize == sizeof(OSVERSIONINFOEXA))
+ {
+ lpVersionInformationEx = (PVOID)lpVersionInformation;
+ lpVersionInformationEx->wServicePackMajor =
VersionInformation.wServicePackMajor;
+ lpVersionInformationEx->wServicePackMinor =
VersionInformation.wServicePackMinor;
+ lpVersionInformationEx->wSuiteMask = VersionInformation.wSuiteMask;
+ lpVersionInformationEx->wProductType = VersionInformation.wProductType;
+ lpVersionInformationEx->wReserved = VersionInformation.wReserved;
+ }
+
+ /* Convert the CSD string */
+ RtlInitEmptyAnsiString(&CsdVersionA,
+ lpVersionInformation->szCSDVersion,
+ sizeof(lpVersionInformation->szCSDVersion));
+ RtlInitUnicodeString(&CsdVersionW, VersionInformation.szCSDVersion);
+ Status = RtlUnicodeStringToAnsiString(&CsdVersionA, &CsdVersionW, FALSE);
+ return (NT_SUCCESS(Status));
+}
+
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+VerifyVersionInfoW(IN LPOSVERSIONINFOEXW lpVersionInformation,
+ IN DWORD dwTypeMask,
+ IN DWORDLONG dwlConditionMask)
{
NTSTATUS Status;
Status = RtlVerifyVersionInfo((PRTL_OSVERSIONINFOEXW)lpVersionInformation,
dwTypeMask,
dwlConditionMask);
- switch(Status)
+ switch (Status)
{
case STATUS_INVALID_PARAMETER:
SetLastError(ERROR_BAD_ARGUMENTS);
return FALSE;
case STATUS_REVISION_MISMATCH:
- SetLastError(ERROR_OLD_WIN_VERSION);
- return FALSE;
+ DPRINT1("ReactOS returning version mismatch. Investigate!\n");
+ SetLastError(ERROR_OLD_WIN_VERSION);
+ return FALSE;
default:
/* RtlVerifyVersionInfo shouldn't report any other failure code! */
ASSERT(NT_SUCCESS(Status));
-
- /* ReactOS specific changes */
- SetRosSpecificInfo((LPOSVERSIONINFOW)lpVersionInformation);
-
return TRUE;
}
}
-
-/*
- * @implemented
- */
-BOOL
-WINAPI
-VerifyVersionInfoA(LPOSVERSIONINFOEXA lpVersionInformation,
- DWORD dwTypeMask,
- DWORDLONG dwlConditionMask)
+/*
+ * @implemented
+ */
+BOOL
+WINAPI
+VerifyVersionInfoA(IN LPOSVERSIONINFOEXA lpVersionInformation,
+ IN DWORD dwTypeMask,
+ IN DWORDLONG dwlConditionMask)
{
OSVERSIONINFOEXW viex;
+ /* NOTE: szCSDVersion is ignored, we don't need to convert it to Unicode */
viex.dwOSVersionInfoSize = sizeof(viex);
viex.dwMajorVersion = lpVersionInformation->dwMajorVersion;
viex.dwMinorVersion = lpVersionInformation->dwMinorVersion;
viex.dwBuildNumber = lpVersionInformation->dwBuildNumber;
viex.dwPlatformId = lpVersionInformation->dwPlatformId;
- /* NOTE: szCSDVersion is ignored, we don't need to convert it to unicode */
viex.wServicePackMajor = lpVersionInformation->wServicePackMajor;
viex.wServicePackMinor = lpVersionInformation->wServicePackMinor;
viex.wSuiteMask = lpVersionInformation->wSuiteMask;
viex.wProductType = lpVersionInformation->wProductType;
viex.wReserved = lpVersionInformation->wReserved;
-
return VerifyVersionInfoW(&viex, dwTypeMask, dwlConditionMask);
}