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/v... ============================================================================== --- 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); }