xref: /reactos/sdk/lib/udmihelp/udmihelp.c (revision 58aee30e)
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