mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[KERNEL32] Implement System Firmware functions
- Implement EnumSystemFirmwareTables - Implement GetSystemFirmwareTable These functions currently using registry workaround and can be improved later. CORE-12105
This commit is contained in:
parent
8acc68dd98
commit
d956eafda8
1 changed files with 274 additions and 8 deletions
|
@ -7,6 +7,7 @@
|
||||||
* Christoph von Wittich
|
* Christoph von Wittich
|
||||||
* Thomas Weidenmueller
|
* Thomas Weidenmueller
|
||||||
* Gunnar Andre Dalsnes
|
* Gunnar Andre Dalsnes
|
||||||
|
* Stanislav Motylkov
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *******************************************************************/
|
/* INCLUDES *******************************************************************/
|
||||||
|
@ -74,6 +75,82 @@ GetSystemInfoInternal(IN PSYSTEM_BASIC_INFORMATION BasicInfo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT
|
||||||
|
WINAPI
|
||||||
|
GetRawSMBiosTableFromRegistry(OUT PVOID pData)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
NTSTATUS Status;
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&KeyName, RegistryKey);
|
||||||
|
InitializeObjectAttributes(&ObjectAttributes,
|
||||||
|
&KeyName,
|
||||||
|
OBJ_CASE_INSENSITIVE,
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
Status = NtOpenKey(&KeyHandle,
|
||||||
|
KEY_READ,
|
||||||
|
&ObjectAttributes);
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
NtClose(KeyHandle);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlInitUnicodeString(&ValueName, ValueNameStr);
|
||||||
|
|
||||||
|
Status = NtQueryValueKey(KeyHandle,
|
||||||
|
&ValueName,
|
||||||
|
KeyValuePartialInformation,
|
||||||
|
KeyInfo,
|
||||||
|
KeyInfoSize,
|
||||||
|
&ReturnSize);
|
||||||
|
|
||||||
|
NtClose(KeyHandle);
|
||||||
|
ReturnSize = 0;
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KeyInfo->Type != REG_BINARY)
|
||||||
|
{
|
||||||
|
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 ***********************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -423,8 +500,32 @@ SetFirmwareEnvironmentVariableA(IN LPCSTR lpName,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* @unimplemented
|
* @name EnumSystemFirmwareTables
|
||||||
|
* @implemented
|
||||||
|
*
|
||||||
|
* Obtains firmware table identifiers.
|
||||||
|
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms724259(v=vs.85).aspx
|
||||||
|
*
|
||||||
|
* @param FirmwareTableProviderSignature
|
||||||
|
* Can be either ACPI, FIRM, or RSMB.
|
||||||
|
*
|
||||||
|
* @param pFirmwareTableBuffer
|
||||||
|
* Pointer to the output buffer, can be NULL.
|
||||||
|
*
|
||||||
|
* @param BufferSize
|
||||||
|
* Size of the output buffer.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Actual size of the data in case of success, 0 otherwise.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Data would be written to buffer only if the specified size is
|
||||||
|
* larger or equal to the actual size, in the other case Last Error
|
||||||
|
* value would be set to ERROR_INSUFFICIENT_BUFFER.
|
||||||
|
* In case of incorrect provider signature, Last Error value would be
|
||||||
|
* set to ERROR_INVALID_FUNCTION.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
UINT
|
UINT
|
||||||
WINAPI
|
WINAPI
|
||||||
|
@ -432,12 +533,104 @@ EnumSystemFirmwareTables(IN DWORD FirmwareTableProviderSignature,
|
||||||
OUT PVOID pFirmwareTableBuffer,
|
OUT PVOID pFirmwareTableBuffer,
|
||||||
IN DWORD BufferSize)
|
IN DWORD BufferSize)
|
||||||
{
|
{
|
||||||
STUB;
|
UINT uSize = 0;
|
||||||
return 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* @unimplemented
|
* @name GetSystemFirmwareTable
|
||||||
|
* @implemented
|
||||||
|
*
|
||||||
|
* Obtains the firmware table data.
|
||||||
|
* https://msdn.microsoft.com/en-us/library/windows/desktop/ms724379(v=vs.85).aspx
|
||||||
|
*
|
||||||
|
* @param FirmwareTableProviderSignature
|
||||||
|
* Can be either ACPI, FIRM, or RSMB.
|
||||||
|
*
|
||||||
|
* @param FirmwareTableID
|
||||||
|
* Correct table identifier.
|
||||||
|
*
|
||||||
|
* @param pFirmwareTableBuffer
|
||||||
|
* Pointer to the output buffer, can be NULL.
|
||||||
|
*
|
||||||
|
* @param BufferSize
|
||||||
|
* Size of the output buffer.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Actual size of the data in case of success, 0 otherwise.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* Data would be written to buffer only if the specified size is
|
||||||
|
* larger or equal to the actual size, in the other case Last Error
|
||||||
|
* value would be set to ERROR_INSUFFICIENT_BUFFER.
|
||||||
|
* In case of incorrect provider signature, Last Error value would be
|
||||||
|
* set to ERROR_INVALID_FUNCTION.
|
||||||
|
* Also Last Error value becomes ERROR_NOT_FOUND if incorrect
|
||||||
|
* table identifier was specified along with ACPI provider, and
|
||||||
|
* ERROR_INVALID_PARAMETER along with FIRM provider. The RSMB provider
|
||||||
|
* accepts any table identifier.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
UINT
|
UINT
|
||||||
WINAPI
|
WINAPI
|
||||||
|
@ -446,8 +639,81 @@ GetSystemFirmwareTable(IN DWORD FirmwareTableProviderSignature,
|
||||||
OUT PVOID pFirmwareTableBuffer,
|
OUT PVOID pFirmwareTableBuffer,
|
||||||
IN DWORD BufferSize)
|
IN DWORD BufferSize)
|
||||||
{
|
{
|
||||||
STUB;
|
/* This function currently obtains data using a hack (registry workaround)
|
||||||
return 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue