From 2ce152beaf5ce5a5192a2e94603528ddcb9b4101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 4 Mar 2026 10:00:06 +0800 Subject: [PATCH] SmbiosHelper (Windows): prefers `NtQuerySystemInformation` --- src/common/impl/smbiosHelper.c | 44 ++++++++++++++++++++++------------ src/common/windows/nt.h | 17 +++++++++++++ 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/common/impl/smbiosHelper.c b/src/common/impl/smbiosHelper.c index ba573b181..0e58535bb 100644 --- a/src/common/impl/smbiosHelper.c +++ b/src/common/impl/smbiosHelper.c @@ -434,7 +434,7 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable() return &table; } #elif defined(_WIN32) -#include +#include "common/windows/nt.h" #pragma GCC diagnostic ignored "-Wmultichar" @@ -450,36 +450,50 @@ typedef struct FFRawSmbiosData const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable() { - static FFRawSmbiosData* buffer; + static SYSTEM_FIRMWARE_TABLE_INFORMATION* buffer; static FFSmbiosHeaderTable table; if (!buffer) { FF_DEBUG("Initializing Windows SMBIOS buffer"); - const DWORD signature = 'RSMB'; + FF_DEBUG("Querying system firmware table size with signature 'RSMB'"); - uint32_t bufSize = GetSystemFirmwareTable(signature, 0, NULL, 0); - if (bufSize <= sizeof(FFRawSmbiosData)) { - FF_DEBUG("Invalid firmware table size: %u (must be > %zu)", - bufSize, sizeof(FFRawSmbiosData)); + SYSTEM_FIRMWARE_TABLE_INFORMATION sfti = { + .ProviderSignature = 'RSMB', + .Action = SystemFirmwareTableGet, + }; + ULONG bufSize = 0; + NtQuerySystemInformation(SystemFirmwareTableInformation, &sfti, sizeof(sfti), &bufSize); + if (bufSize <= sizeof(FFRawSmbiosData) + sizeof(sfti)) { + FF_DEBUG("Invalid firmware table size: %lu (must be > %zu)", bufSize, sizeof(FFRawSmbiosData) + sizeof(sfti)); return NULL; } - FF_DEBUG("Firmware table size: %u bytes", bufSize); + if (bufSize != sfti.TableBufferLength + (ULONG) sizeof(sfti)) { + FF_DEBUG("Firmware table size mismatch: NtQuerySystemInformation returned %lu but expected %lu", + bufSize, sfti.TableBufferLength + (ULONG) sizeof(sfti)); + return NULL; + } + FF_DEBUG("Firmware table size: %lu bytes", bufSize); - buffer = (FFRawSmbiosData*) malloc(bufSize); - assert(buffer); + buffer = malloc(bufSize); + *buffer = sfti; FF_DEBUG("Allocated buffer for SMBIOS data"); - FF_MAYBE_UNUSED uint32_t resultSize = GetSystemFirmwareTable(signature, 0, buffer, bufSize); - assert(resultSize == bufSize); + if (!NT_SUCCESS(NtQuerySystemInformation(SystemFirmwareTableInformation, buffer, bufSize, &bufSize))) + { + FF_DEBUG("NtQuerySystemInformation(SystemFirmwareTableInformation) failed"); + return NULL; + } + FFRawSmbiosData* rawData = (FFRawSmbiosData*) buffer->TableBuffer; + FF_DEBUG("Successfully retrieved SMBIOS data: version %u.%u, length %u bytes", - buffer->SMBIOSMajorVersion, buffer->SMBIOSMinorVersion, buffer->Length); + rawData->SMBIOSMajorVersion, rawData->SMBIOSMinorVersion, rawData->Length); FF_DEBUG("Parsing SMBIOS table structures"); FF_MAYBE_UNUSED int structureCount = 0; for ( - const FFSmbiosHeader* header = (const FFSmbiosHeader*) buffer->SMBIOSTableData; - (const uint8_t*) header < buffer->SMBIOSTableData + buffer->Length; + const FFSmbiosHeader* header = (const FFSmbiosHeader*) rawData->SMBIOSTableData; + (const uint8_t*) header < rawData->SMBIOSTableData + rawData->Length; header = ffSmbiosNextEntry(header) ) { diff --git a/src/common/windows/nt.h b/src/common/windows/nt.h index 91c03c2d9..416b461ff 100644 --- a/src/common/windows/nt.h +++ b/src/common/windows/nt.h @@ -5,6 +5,7 @@ enum { SystemModuleInformation = 11, + SystemFirmwareTableInformation = 76, SystemBootEnvironmentInformation = 90, SystemLogicalProcessorAndGroupInformation = 107, SystemSecureBootInformation = 146, @@ -405,3 +406,19 @@ NTSTATUS NTAPI NtQuerySystemInformationEx( _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength ); + +typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION +{ + SystemFirmwareTableEnumerate, + SystemFirmwareTableGet, + SystemFirmwareTableMax +} SYSTEM_FIRMWARE_TABLE_ACTION; + +typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION +{ + ULONG ProviderSignature; // (same as the GetSystemFirmwareTable function) + SYSTEM_FIRMWARE_TABLE_ACTION Action; + ULONG TableID; + ULONG TableBufferLength; + _Field_size_bytes_(TableBufferLength) UCHAR TableBuffer[]; +} SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION;