/* * PROJECT: ReactOS User-mode DMI/SMBIOS Helper Functions * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) * PURPOSE: SMBIOS table parsing functions * COPYRIGHT: Copyright 2018 Stanislav Motylkov */ #include "precomp.h" static UINT (WINAPI * pGetSystemFirmwareTable)(DWORD, DWORD, PVOID, DWORD); static BOOL bInitAPI = FALSE; static VOID InitializeAPI() { HANDLE hKernel; pGetSystemFirmwareTable = NULL; hKernel = GetModuleHandleW(L"kernel32.dll"); if (!hKernel) return; pGetSystemFirmwareTable = (void *)GetProcAddress(hKernel, "GetSystemFirmwareTable"); } /* Load SMBIOS Data */ PVOID LoadSMBiosData( _Inout_updates_(ID_STRINGS_MAX) PCHAR * Strings) { PVOID pBuffer = NULL; HKEY hKey; DWORD dwType, dwCheck, dwBytes = 0; if (!bInitAPI) { InitializeAPI(); bInitAPI = TRUE; } /* Try using GetSystemFirmwareTable (works on NT 5.2 and higher) */ if (pGetSystemFirmwareTable) { dwBytes = pGetSystemFirmwareTable('RSMB', 0, NULL, 0); if (dwBytes > 0) { pBuffer = HeapAlloc(GetProcessHeap(), 0, dwBytes); if (!pBuffer) { return NULL; } dwCheck = pGetSystemFirmwareTable('RSMB', 0, pBuffer, dwBytes); if (dwCheck != dwBytes) { HeapFree(GetProcessHeap(), 0, pBuffer); return NULL; } } } if (dwBytes == 0) { /* Try using registry (works on NT 5.1) */ if (RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\mssmbios\\Data", &hKey) != ERROR_SUCCESS) { return NULL; } if (RegQueryValueExW(hKey, L"SMBiosData", NULL, &dwType, NULL, &dwBytes) != ERROR_SUCCESS || dwType != REG_BINARY) { RegCloseKey(hKey); return NULL; } pBuffer = HeapAlloc(GetProcessHeap(), 0, dwBytes); if (!pBuffer) { RegCloseKey(hKey); return NULL; } if (RegQueryValueExW(hKey, L"SMBiosData", NULL, &dwType, pBuffer, &dwBytes) != ERROR_SUCCESS || dwType != REG_BINARY) { HeapFree(GetProcessHeap(), 0, pBuffer); RegCloseKey(hKey); return NULL; } RegCloseKey(hKey); } ParseSMBiosTables(pBuffer, dwBytes, Strings); return pBuffer; } /* Trim converted DMI string */ VOID TrimDmiStringW( _Inout_ PWSTR pStr) { SIZE_T Length; UINT i = 0; if (!pStr) return; Length = wcslen(pStr); if (Length == 0) return; /* Trim leading spaces */ while (i < Length && pStr[i] <= L' ') { i++; } if (i > 0) { Length -= i; memmove(pStr, pStr + i, (Length + 1) * sizeof(WCHAR)); } /* Trim trailing spaces */ while (Length && pStr[Length-1] <= L' ') { pStr[Length-1] = L'\0'; --Length; } } /* Convert string from SMBIOS */ SIZE_T GetSMBiosStringW( _In_ PCSTR DmiString, _Out_ PWSTR pBuf, _In_ DWORD cchBuf, _In_ BOOL bTrim) { SIZE_T cChars; if (!DmiString) { if (cchBuf >= 1) { *pBuf = 0; } return 0; } cChars = MultiByteToWideChar(CP_OEMCP, 0, DmiString, -1, pBuf, cchBuf); /* NULL-terminate string */ pBuf[min(cchBuf-1, cChars)] = L'\0'; if (bTrim) { TrimDmiStringW(pBuf); } return wcslen(pBuf); } /* Free SMBIOS Data */ VOID FreeSMBiosData( _In_ PVOID Buffer) { if (!Buffer) return; HeapFree(GetProcessHeap(), 0, Buffer); }