[CRT] spawn: define a unicode environment when needed
[reactos.git] / sdk / lib / udmihelp / udmihelp.c
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 }