[SDK] Add user-mode DMI/SMBIOS helper library
authorStanislav Motylkov <x86corez@gmail.com>
Tue, 31 Jul 2018 15:48:32 +0000 (18:48 +0300)
committerHermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
Sun, 12 Aug 2018 12:21:56 +0000 (14:21 +0200)
CORE-5961

sdk/lib/CMakeLists.txt
sdk/lib/udmihelp/CMakeLists.txt [new file with mode: 0644]
sdk/lib/udmihelp/precomp.h [new file with mode: 0644]
sdk/lib/udmihelp/udmihelp.c [new file with mode: 0644]
sdk/lib/udmihelp/udmihelp.h [new file with mode: 0644]

index 99c6849..e5d2d92 100644 (file)
@@ -47,6 +47,7 @@ add_subdirectory(skiplist)
 add_subdirectory(strmiids)
 add_subdirectory(smlib)
 add_subdirectory(tdilib)
+add_subdirectory(udmihelp)
 add_subdirectory(uuid)
 add_subdirectory(wdmguid)
 
diff --git a/sdk/lib/udmihelp/CMakeLists.txt b/sdk/lib/udmihelp/CMakeLists.txt
new file mode 100644 (file)
index 0000000..270c234
--- /dev/null
@@ -0,0 +1,12 @@
+
+include_directories(
+    ${REACTOS_SOURCE_DIR}/sdk/lib/dmilib)
+
+list(APPEND SOURCE
+    udmihelp.c
+    precomp.h)
+
+add_library(udmihelp ${SOURCE})
+target_link_libraries(udmihelp dmilib)
+add_pch(udmihelp precomp.h SOURCE)
+add_dependencies(udmihelp psdk)
diff --git a/sdk/lib/udmihelp/precomp.h b/sdk/lib/udmihelp/precomp.h
new file mode 100644 (file)
index 0000000..ee1c7a5
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _UDMIHELP_PCH_
+#define _UDMIHELP_PCH_
+
+#include <windows.h>
+#include <dmilib.h>
+#include "udmihelp.h"
+
+#endif /* _UDMIHELP_PCH_ */
diff --git a/sdk/lib/udmihelp/udmihelp.c b/sdk/lib/udmihelp/udmihelp.c
new file mode 100644 (file)
index 0000000..a7070eb
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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)
+        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);
+}
diff --git a/sdk/lib/udmihelp/udmihelp.h b/sdk/lib/udmihelp/udmihelp.h
new file mode 100644 (file)
index 0000000..8ed59d9
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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
+ */
+
+#pragma once
+
+PVOID
+LoadSMBiosData(
+    _Inout_updates_(ID_STRINGS_MAX) PCHAR * Strings);
+
+VOID
+TrimDmiStringW(
+    _Inout_ PWSTR pStr);
+
+SIZE_T
+GetSMBiosStringW(
+    _In_ PCSTR DmiString,
+    _Out_ PWSTR pBuf,
+    _In_ DWORD cchBuf,
+    _In_ BOOL bTrim);
+
+VOID
+FreeSMBiosData(
+    _In_ PVOID Buffer);