1 /* 2 * PROJECT: ReactOS User-mode DMI/SMBIOS Helper Functions 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: SMBIOS table parsing functions 5 * COPYRIGHT: Copyright 2018 Stanislav Motylkov 6 */ 7 8 #include "precomp.h" 9 10 static UINT (WINAPI * pGetSystemFirmwareTable)(DWORD, DWORD, PVOID, DWORD); 11 static BOOL bInitAPI = FALSE; 12 13 static 14 VOID 15 InitializeAPI() 16 { 17 HANDLE hKernel; 18 19 pGetSystemFirmwareTable = NULL; 20 21 hKernel = GetModuleHandleW(L"kernel32.dll"); 22 if (!hKernel) 23 return; 24 25 pGetSystemFirmwareTable = (void *)GetProcAddress(hKernel, "GetSystemFirmwareTable"); 26 } 27 28 /* Load SMBIOS Data */ 29 PVOID 30 LoadSMBiosData( 31 _Inout_updates_(ID_STRINGS_MAX) PCHAR * Strings) 32 { 33 PVOID pBuffer = NULL; 34 HKEY hKey; 35 DWORD dwType, dwCheck, dwBytes = 0; 36 37 if (!bInitAPI) 38 { 39 InitializeAPI(); 40 bInitAPI = TRUE; 41 } 42 43 /* Try using GetSystemFirmwareTable (works on NT 5.2 and higher) */ 44 if (pGetSystemFirmwareTable) 45 { 46 dwBytes = pGetSystemFirmwareTable('RSMB', 0, NULL, 0); 47 if (dwBytes > 0) 48 { 49 pBuffer = HeapAlloc(GetProcessHeap(), 0, dwBytes); 50 if (!pBuffer) 51 { 52 return NULL; 53 } 54 dwCheck = pGetSystemFirmwareTable('RSMB', 0, pBuffer, dwBytes); 55 if (dwCheck != dwBytes) 56 { 57 HeapFree(GetProcessHeap(), 0, pBuffer); 58 return NULL; 59 } 60 } 61 } 62 if (dwBytes == 0) 63 { 64 /* Try using registry (works on NT 5.1) */ 65 if (RegOpenKeyW(HKEY_LOCAL_MACHINE, 66 L"SYSTEM\\CurrentControlSet\\Services\\mssmbios\\Data", 67 &hKey) != ERROR_SUCCESS) 68 { 69 return NULL; 70 } 71 72 if (RegQueryValueExW(hKey, 73 L"SMBiosData", 74 NULL, 75 &dwType, 76 NULL, 77 &dwBytes) != ERROR_SUCCESS || dwType != REG_BINARY) 78 { 79 RegCloseKey(hKey); 80 return NULL; 81 } 82 83 pBuffer = HeapAlloc(GetProcessHeap(), 0, dwBytes); 84 if (!pBuffer) 85 { 86 RegCloseKey(hKey); 87 return NULL; 88 } 89 90 if (RegQueryValueExW(hKey, 91 L"SMBiosData", 92 NULL, 93 &dwType, 94 pBuffer, 95 &dwBytes) != ERROR_SUCCESS || dwType != REG_BINARY) 96 { 97 HeapFree(GetProcessHeap(), 0, pBuffer); 98 RegCloseKey(hKey); 99 return NULL; 100 } 101 102 RegCloseKey(hKey); 103 } 104 ParseSMBiosTables(pBuffer, dwBytes, Strings); 105 return pBuffer; 106 } 107 108 /* Trim converted DMI string */ 109 VOID 110 TrimDmiStringW( 111 _Inout_ PWSTR pStr) 112 { 113 SIZE_T Length; 114 UINT i = 0; 115 116 if (!pStr) 117 return; 118 119 Length = wcslen(pStr); 120 if (Length == 0) 121 return; 122 123 /* Trim leading spaces */ 124 while (i < Length && pStr[i] <= L' ') 125 { 126 i++; 127 } 128 129 if (i > 0) 130 { 131 Length -= i; 132 memmove(pStr, pStr + i, (Length + 1) * sizeof(WCHAR)); 133 } 134 135 /* Trim trailing spaces */ 136 while (Length && pStr[Length-1] <= L' ') 137 { 138 pStr[Length-1] = L'\0'; 139 --Length; 140 } 141 } 142 143 /* Convert string from SMBIOS */ 144 SIZE_T 145 GetSMBiosStringW( 146 _In_ PCSTR DmiString, 147 _Out_ PWSTR pBuf, 148 _In_ DWORD cchBuf, 149 _In_ BOOL bTrim) 150 { 151 SIZE_T cChars; 152 153 if (!DmiString) 154 { 155 if (cchBuf >= 1) 156 { 157 *pBuf = 0; 158 } 159 return 0; 160 } 161 162 cChars = MultiByteToWideChar(CP_OEMCP, 0, DmiString, -1, pBuf, cchBuf); 163 164 /* NULL-terminate string */ 165 pBuf[min(cchBuf-1, cChars)] = L'\0'; 166 167 if (bTrim) 168 { 169 TrimDmiStringW(pBuf); 170 } 171 172 return wcslen(pBuf); 173 } 174 175 /* Free SMBIOS Data */ 176 VOID 177 FreeSMBiosData( 178 _In_ PVOID Buffer) 179 { 180 if (!Buffer) 181 return; 182 183 HeapFree(GetProcessHeap(), 0, Buffer); 184 } 185