[KERNEL32] Implement system firmware functions properly

This commit is contained in:
Stanislav Motylkov 2018-08-05 11:48:25 +03:00 committed by Mark Jansen
parent b851d7e1d3
commit 844483504b

View file

@ -7,7 +7,8 @@
* Christoph von Wittich * Christoph von Wittich
* Thomas Weidenmueller * Thomas Weidenmueller
* Gunnar Andre Dalsnes * Gunnar Andre Dalsnes
* Stanislav Motylkov * Stanislav Motylkov (x86corez@gmail.com)
* Mark Jansen (mark.jansen@reactos.org)
*/ */
/* INCLUDES *******************************************************************/ /* INCLUDES *******************************************************************/
@ -75,80 +76,50 @@ GetSystemInfoInternal(IN PSYSTEM_BASIC_INFORMATION BasicInfo,
} }
} }
static
UINT UINT
WINAPI BaseQuerySystemFirmware(IN DWORD FirmwareTableProviderSignature,
GetRawSMBiosTableFromRegistry(OUT PVOID pData) 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"; SYSTEM_FIRMWARE_TABLE_INFORMATION* SysFirmwareInfo;
static const LPCWSTR ValueNameStr = L"SMBiosData"; ULONG Result = 0, ReturnedSize;
ULONG TotalSize = BufferSize + sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION);
PKEY_VALUE_PARTIAL_INFORMATION KeyInfo = NULL;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
UNICODE_STRING ValueName;
HANDLE KeyHandle;
ULONG KeyInfoSize;
ULONG ReturnSize = 0;
NTSTATUS Status; NTSTATUS Status;
RtlInitUnicodeString(&KeyName, RegistryKey); SysFirmwareInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, TotalSize);
InitializeObjectAttributes(&ObjectAttributes, if (!SysFirmwareInfo)
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtOpenKey(&KeyHandle,
KEY_READ,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{ {
SetLastError(ERROR_INVALID_PARAMETER);
return 0; return 0;
} }
_SEH2_TRY
// 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)
{ {
NtClose(KeyHandle); SysFirmwareInfo->ProviderSignature = FirmwareTableProviderSignature;
goto cleanup; SysFirmwareInfo->TableID = FirmwareTableID;
SysFirmwareInfo->Action = Action;
SysFirmwareInfo->TableBufferLength = BufferSize;
Status = NtQuerySystemInformation(SystemFirmwareTableInformation, SysFirmwareInfo, TotalSize, &ReturnedSize);
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
Result = SysFirmwareInfo->TableBufferLength;
if (NT_SUCCESS(Status) && pFirmwareTableBuffer)
{
RtlCopyMemory(pFirmwareTableBuffer, SysFirmwareInfo->TableBuffer, SysFirmwareInfo->TableBufferLength);
}
} }
_SEH2_FINALLY
RtlInitUnicodeString(&ValueName, ValueNameStr);
Status = NtQueryValueKey(KeyHandle,
&ValueName,
KeyValuePartialInformation,
KeyInfo,
KeyInfoSize,
&ReturnSize);
NtClose(KeyHandle);
ReturnSize = 0;
if (!NT_SUCCESS(Status))
{ {
goto cleanup; RtlFreeHeap(RtlGetProcessHeap(), 0, SysFirmwareInfo);
} }
_SEH2_END;
if (KeyInfo->Type != REG_BINARY) BaseSetLastNTError(Status);
{ return Result;
goto cleanup;
}
ReturnSize = KeyInfo->DataLength;
if (pData)
{
RtlCopyMemory(pData, KeyInfo->Data, KeyInfo->DataLength);
}
cleanup:
if (KeyInfo)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
}
return ReturnSize;
} }
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
@ -533,69 +504,11 @@ EnumSystemFirmwareTables(IN DWORD FirmwareTableProviderSignature,
OUT PVOID pFirmwareTableBuffer, OUT PVOID pFirmwareTableBuffer,
IN DWORD BufferSize) IN DWORD BufferSize)
{ {
UINT uSize = 0; return BaseQuerySystemFirmware(FirmwareTableProviderSignature,
UINT uCount = 0; 0,
DWORD dwError = ERROR_SUCCESS; pFirmwareTableBuffer,
PDWORD pBuffer = NULL; BufferSize,
SystemFirmwareTable_Enumerate);
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;
} }
/** /**
@ -639,81 +552,11 @@ GetSystemFirmwareTable(IN DWORD FirmwareTableProviderSignature,
OUT PVOID pFirmwareTableBuffer, OUT PVOID pFirmwareTableBuffer,
IN DWORD BufferSize) IN DWORD BufferSize)
{ {
/* This function currently obtains data using a hack (registry workaround) return BaseQuerySystemFirmware(FirmwareTableProviderSignature,
which is located here: drivers/input/i8042prt/hwhacks.c FirmwareTableID,
i8042StoreSMBiosTables is responsible for writing SMBIOS table into registry pFirmwareTableBuffer,
BufferSize,
Should be implemented correctly using NtQuerySystemInformation SystemFirmwareTable_Get);
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;
} }
/* /*