From 844483504b94b6f187b22209c42cece07077a43a Mon Sep 17 00:00:00 2001 From: Stanislav Motylkov Date: Sun, 5 Aug 2018 11:48:25 +0300 Subject: [PATCH] [KERNEL32] Implement system firmware functions properly --- dll/win32/kernel32/client/sysinfo.c | 239 +++++----------------------- 1 file changed, 41 insertions(+), 198 deletions(-) diff --git a/dll/win32/kernel32/client/sysinfo.c b/dll/win32/kernel32/client/sysinfo.c index 92474d050a7..0e588b3e449 100644 --- a/dll/win32/kernel32/client/sysinfo.c +++ b/dll/win32/kernel32/client/sysinfo.c @@ -7,7 +7,8 @@ * Christoph von Wittich * Thomas Weidenmueller * Gunnar Andre Dalsnes - * Stanislav Motylkov + * Stanislav Motylkov (x86corez@gmail.com) + * Mark Jansen (mark.jansen@reactos.org) */ /* INCLUDES *******************************************************************/ @@ -75,80 +76,50 @@ GetSystemInfoInternal(IN PSYSTEM_BASIC_INFORMATION BasicInfo, } } +static UINT -WINAPI -GetRawSMBiosTableFromRegistry(OUT PVOID pData) +BaseQuerySystemFirmware(IN DWORD FirmwareTableProviderSignature, + IN DWORD FirmwareTableID, + OUT PVOID pFirmwareTableBuffer, + IN DWORD BufferSize, + IN SYSTEM_FIRMWARE_TABLE_ACTION Action) { - static const LPCWSTR RegistryKey = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\mssmbios\\Data"; - static const LPCWSTR ValueNameStr = L"SMBiosData"; - - PKEY_VALUE_PARTIAL_INFORMATION KeyInfo = NULL; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING KeyName; - UNICODE_STRING ValueName; - HANDLE KeyHandle; - ULONG KeyInfoSize; - ULONG ReturnSize = 0; + SYSTEM_FIRMWARE_TABLE_INFORMATION* SysFirmwareInfo; + ULONG Result = 0, ReturnedSize; + ULONG TotalSize = BufferSize + sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION); NTSTATUS Status; - RtlInitUnicodeString(&KeyName, RegistryKey); - InitializeObjectAttributes(&ObjectAttributes, - &KeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = NtOpenKey(&KeyHandle, - KEY_READ, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) + SysFirmwareInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, TotalSize); + if (!SysFirmwareInfo) { + SetLastError(ERROR_INVALID_PARAMETER); return 0; } - - // 256 KiB is more than enough for raw SMBIOS dump - KeyInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 256 * 1024; - KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, KeyInfoSize); - if (KeyInfo == NULL) + _SEH2_TRY { - NtClose(KeyHandle); - goto cleanup; - } + SysFirmwareInfo->ProviderSignature = FirmwareTableProviderSignature; + SysFirmwareInfo->TableID = FirmwareTableID; + SysFirmwareInfo->Action = Action; + SysFirmwareInfo->TableBufferLength = BufferSize; - RtlInitUnicodeString(&ValueName, ValueNameStr); + Status = NtQuerySystemInformation(SystemFirmwareTableInformation, SysFirmwareInfo, TotalSize, &ReturnedSize); - Status = NtQueryValueKey(KeyHandle, - &ValueName, - KeyValuePartialInformation, - KeyInfo, - KeyInfoSize, - &ReturnSize); - - NtClose(KeyHandle); - ReturnSize = 0; - - if (!NT_SUCCESS(Status)) - { - goto cleanup; - } + if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL) + Result = SysFirmwareInfo->TableBufferLength; - if (KeyInfo->Type != REG_BINARY) - { - goto cleanup; + if (NT_SUCCESS(Status) && pFirmwareTableBuffer) + { + RtlCopyMemory(pFirmwareTableBuffer, SysFirmwareInfo->TableBuffer, SysFirmwareInfo->TableBufferLength); + } } - - ReturnSize = KeyInfo->DataLength; - if (pData) + _SEH2_FINALLY { - RtlCopyMemory(pData, KeyInfo->Data, KeyInfo->DataLength); + RtlFreeHeap(RtlGetProcessHeap(), 0, SysFirmwareInfo); } + _SEH2_END; -cleanup: - if (KeyInfo) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo); - } - return ReturnSize; + BaseSetLastNTError(Status); + return Result; } /* PUBLIC FUNCTIONS ***********************************************************/ @@ -533,69 +504,11 @@ EnumSystemFirmwareTables(IN DWORD FirmwareTableProviderSignature, OUT PVOID pFirmwareTableBuffer, IN DWORD BufferSize) { - UINT uSize = 0; - UINT uCount = 0; - DWORD dwError = ERROR_SUCCESS; - PDWORD pBuffer = NULL; - - switch (FirmwareTableProviderSignature) - { - case 'ACPI': - { - /* FIXME: Not implemented yet */ - dwError = ERROR_CALL_NOT_IMPLEMENTED; - break; - } - case 'FIRM': - { - /* FIXME: Not implemented yet */ - dwError = ERROR_CALL_NOT_IMPLEMENTED; - break; - } - case 'RSMB': - { - if (GetRawSMBiosTableFromRegistry(NULL) > 0) - { - uCount = 1; - uSize = uCount * sizeof(DWORD); - pBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, uSize); - if (!pBuffer) - { - SetLastError(ERROR_OUTOFMEMORY); - return 0; - } - *pBuffer = 0; - } - break; - } - default: - { - dwError = ERROR_INVALID_FUNCTION; - } - } - - if (dwError == ERROR_SUCCESS) - { - if (uSize > 0 && BufferSize >= uSize) - { - /* Write to buffer */ - if (pFirmwareTableBuffer) - { - RtlMoveMemory(pFirmwareTableBuffer, pBuffer, uSize); - } - } - else if (BufferSize < uSize) - { - dwError = ERROR_INSUFFICIENT_BUFFER; - } - } - - if (pBuffer) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, pBuffer); - } - SetLastError(dwError); - return uSize; + return BaseQuerySystemFirmware(FirmwareTableProviderSignature, + 0, + pFirmwareTableBuffer, + BufferSize, + SystemFirmwareTable_Enumerate); } /** @@ -639,81 +552,11 @@ GetSystemFirmwareTable(IN DWORD FirmwareTableProviderSignature, OUT PVOID pFirmwareTableBuffer, IN DWORD BufferSize) { - /* This function currently obtains data using a hack (registry workaround) - which is located here: drivers/input/i8042prt/hwhacks.c - i8042StoreSMBiosTables is responsible for writing SMBIOS table into registry - - Should be implemented correctly using NtQuerySystemInformation - along with SystemFirmwareTableInformation class - - Reference: https://github.com/hfiref0x/VMDE/blob/master/src/vmde/sup.c - */ - - UINT uSize = 0; - DWORD dwError = ERROR_SUCCESS; - PVOID pBuffer = NULL; - - switch (FirmwareTableProviderSignature) - { - case 'ACPI': - { - /* FIXME: Not implemented yet */ - dwError = ERROR_CALL_NOT_IMPLEMENTED; - break; - } - case 'FIRM': - { - /* FIXME: Not implemented yet */ - dwError = ERROR_CALL_NOT_IMPLEMENTED; - break; - } - case 'RSMB': - { - uSize = GetRawSMBiosTableFromRegistry(NULL); - if (uSize > 0) - { - pBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, uSize); - if (!pBuffer) - { - SetLastError(ERROR_OUTOFMEMORY); - return 0; - } - GetRawSMBiosTableFromRegistry(pBuffer); - } - else - { - dwError = ERROR_NOT_FOUND; - } - break; - } - default: - { - dwError = ERROR_INVALID_FUNCTION; - } - } - - if (dwError == ERROR_SUCCESS) - { - if (uSize > 0 && BufferSize >= uSize) - { - /* Write to buffer */ - if (pFirmwareTableBuffer) - { - RtlMoveMemory(pFirmwareTableBuffer, pBuffer, uSize); - } - } - else if (BufferSize < uSize) - { - dwError = ERROR_INSUFFICIENT_BUFFER; - } - } - - if (pBuffer) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, pBuffer); - } - SetLastError(dwError); - return uSize; + return BaseQuerySystemFirmware(FirmwareTableProviderSignature, + FirmwareTableID, + pFirmwareTableBuffer, + BufferSize, + SystemFirmwareTable_Get); } /* -- 2.17.1