[PATCH v4 1/5] ntdll: Return BIOS info from NtQuerySystemInformation on Linux

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[PATCH v4 1/5] ntdll: Return BIOS info from NtQuerySystemInformation on Linux

Alex Henrie
Signed-off-by: Alex Henrie <[hidden email]>
---
 dlls/ntdll/nt.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 169 insertions(+)

diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index dc0ce04f42..72ae381813 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -66,6 +66,50 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 
+#include "pshpack1.h"
+
+typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION
+{
+    SystemFirmwareTable_Enumerate = 0,
+    SystemFirmwareTable_Get = 1
+} SYSTEM_FIRMWARE_TABLE_ACTION;
+
+typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION
+{
+    ULONG ProviderSignature;
+    SYSTEM_FIRMWARE_TABLE_ACTION Action;
+    ULONG TableID;
+    ULONG TableBufferLength;
+    UCHAR TableBuffer[1];
+} SYSTEM_FIRMWARE_TABLE_INFORMATION;
+
+struct smbios_prologue {
+    BYTE calling_method;
+    BYTE major_version;
+    BYTE minor_version;
+    BYTE revision;
+    DWORD length;
+};
+
+struct smbios_bios {
+    BYTE type;
+    BYTE length;
+    WORD handle;
+    BYTE vendor;
+    BYTE version;
+    WORD start;
+    BYTE date;
+    BYTE size;
+    UINT64 characteristics;
+};
+
+#include "poppack.h"
+
+/* Firmware table providers */
+#define ACPI 0x41435049
+#define FIRM 0x4649524D
+#define RSMB 0x52534D42
+
 /*
  * Token
  */
@@ -1850,6 +1894,39 @@ static NTSTATUS create_logical_proc_info(SYSTEM_LOGICAL_PROCESSOR_INFORMATION **
 }
 #endif
 
+static inline void copy_smbios_string(char **buffer, char *string, size_t string_size)
+{
+    if (!string) return;
+    strcpy(*buffer, string);
+    *buffer += string_size;
+}
+
+#ifdef linux
+static char* get_smbios_string(const char *path, size_t *string_size)
+{
+    FILE *file = fopen(path, "r");
+    char *ret = NULL;
+    *string_size = 0;
+    if (file)
+    {
+        *string_size = getline(&ret, string_size, file) + 1;
+        fclose(file);
+        if (*string_size >= 2 && ret[*string_size - 2] == '\n')
+        {
+            ret[*string_size - 2] = 0;
+            (*string_size)--;
+        }
+        if (*string_size == 1)
+        {
+            free(ret);
+            ret = NULL;
+            *string_size = 0;
+        }
+    }
+    return ret;
+}
+#endif
+
 /******************************************************************************
  * NtQuerySystemInformation [NTDLL.@]
  * ZwQuerySystemInformation [NTDLL.@]
@@ -2359,6 +2436,97 @@ NTSTATUS WINAPI NtQuerySystemInformation(
             else ret = STATUS_INFO_LENGTH_MISMATCH;
         }
         break;
+    case SystemFirmwareTableInformation:
+        {
+            SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti = (SYSTEM_FIRMWARE_TABLE_INFORMATION*)SystemInformation;
+            len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
+            if (Length < len)
+            {
+                ret = STATUS_INFO_LENGTH_MISMATCH;
+                break;
+            }
+
+            switch (sfti->Action)
+            {
+            case SystemFirmwareTable_Get:
+                switch (sfti->ProviderSignature)
+                {
+                case RSMB:
+#ifdef linux
+                    {
+                        char *bios_vendor, *bios_version, *bios_date;
+                        size_t bios_vendor_size, bios_version_size, bios_date_size;
+                        char *buffer = (char*)sfti->TableBuffer;
+                        BYTE string_count;
+                        struct smbios_prologue *prologue;
+                        struct smbios_bios *bios;
+
+                        bios_vendor = get_smbios_string("/sys/class/dmi/id/bios_vendor", &bios_vendor_size);
+                        bios_version = get_smbios_string("/sys/class/dmi/id/bios_version", &bios_version_size);
+                        bios_date = get_smbios_string("/sys/class/dmi/id/bios_date", &bios_date_size);
+
+                        len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
+
+                        len += sizeof(struct smbios_prologue);
+
+                        len += sizeof(struct smbios_bios);
+                        len += max(bios_vendor_size + bios_version_size + bios_date_size + 1, 2);
+
+                        if (Length < len)
+                        {
+                            ret = STATUS_INFO_LENGTH_MISMATCH;
+                            goto finish;
+                        }
+
+                        sfti->TableBufferLength = len - FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
+
+                        prologue = (struct smbios_prologue*)buffer;
+                        prologue->calling_method = 0;
+                        prologue->major_version = 2;
+                        prologue->minor_version = 0;
+                        prologue->revision = 0;
+                        prologue->length = sfti->TableBufferLength - sizeof(struct smbios_prologue);
+                        buffer += sizeof(struct smbios_prologue);
+
+                        string_count = 0;
+                        bios = (struct smbios_bios*)buffer;
+                        bios->type = 0;
+                        bios->length = sizeof(struct smbios_bios);
+                        bios->handle = 0;
+                        bios->vendor = bios_vendor ? ++string_count : 0;
+                        bios->version = bios_version ? ++string_count : 0;
+                        bios->start = 0;
+                        bios->date = bios_date ? ++string_count : 0;
+                        bios->size = 0;
+                        bios->characteristics = 0x4; /* not supported */
+                        buffer += sizeof(struct smbios_bios);
+
+                        if (string_count)
+                        {
+                            copy_smbios_string(&buffer, bios_vendor, bios_vendor_size);
+                            copy_smbios_string(&buffer, bios_version, bios_version_size);
+                            copy_smbios_string(&buffer, bios_date, bios_date_size);
+                            memset(buffer, 0, 1);
+                        }
+                        else
+                        {
+                            memset(buffer, 0, 2);
+                        }
+
+                        free(bios_vendor);
+                        free(bios_version);
+                        free(bios_date);
+                    }
+                    goto finish;
+#endif
+                }
+                /* fall through */
+            default:
+                ret = STATUS_NOT_IMPLEMENTED;
+                FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION\n");
+            }
+        }
+        break;
     default:
  FIXME("(0x%08x,%p,0x%08x,%p) stub\n",
       SystemInformationClass,SystemInformation,Length,ResultLength);
@@ -2370,6 +2538,7 @@ NTSTATUS WINAPI NtQuerySystemInformation(
         ret = STATUS_INVALID_INFO_CLASS;
     }
 
+finish:
     if (ResultLength) *ResultLength = len;
 
     return ret;
--
2.17.1



Reply | Threaded
Open this post in threaded view
|

[PATCH v4 2/5] ntdll: Return system info from NtQuerySystemInformation on Linux

Alex Henrie
Signed-off-by: Alex Henrie <[hidden email]>
---
 dlls/ntdll/nt.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 72ae381813..162c7467c8 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -103,6 +103,16 @@ struct smbios_bios {
     UINT64 characteristics;
 };
 
+struct smbios_system {
+    BYTE type;
+    BYTE length;
+    WORD handle;
+    BYTE vendor;
+    BYTE product;
+    BYTE version;
+    BYTE serial;
+};
+
 #include "poppack.h"
 
 /* Firmware table providers */
@@ -2456,14 +2466,21 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                     {
                         char *bios_vendor, *bios_version, *bios_date;
                         size_t bios_vendor_size, bios_version_size, bios_date_size;
+                        char *system_vendor, *system_product, *system_version, *system_serial;
+                        size_t system_vendor_size, system_product_size, system_version_size, system_serial_size;
                         char *buffer = (char*)sfti->TableBuffer;
                         BYTE string_count;
                         struct smbios_prologue *prologue;
                         struct smbios_bios *bios;
+                        struct smbios_system *system;
 
                         bios_vendor = get_smbios_string("/sys/class/dmi/id/bios_vendor", &bios_vendor_size);
                         bios_version = get_smbios_string("/sys/class/dmi/id/bios_version", &bios_version_size);
                         bios_date = get_smbios_string("/sys/class/dmi/id/bios_date", &bios_date_size);
+                        system_vendor = get_smbios_string("/sys/class/dmi/id/sys_vendor", &system_vendor_size);
+                        system_product = get_smbios_string("/sys/class/dmi/id/product", &system_product_size);
+                        system_version = get_smbios_string("/sys/class/dmi/id/product_version", &system_version_size);
+                        system_serial = get_smbios_string("/sys/class/dmi/id/product_serial", &system_serial_size);
 
                         len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
 
@@ -2472,6 +2489,10 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         len += sizeof(struct smbios_bios);
                         len += max(bios_vendor_size + bios_version_size + bios_date_size + 1, 2);
 
+                        len += sizeof(struct smbios_system);
+                        len += max(system_vendor_size + system_product_size + system_version_size +
+                                   system_serial_size + 1, 2);
+
                         if (Length < len)
                         {
                             ret = STATUS_INFO_LENGTH_MISMATCH;
@@ -2507,6 +2528,32 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                             copy_smbios_string(&buffer, bios_version, bios_version_size);
                             copy_smbios_string(&buffer, bios_date, bios_date_size);
                             memset(buffer, 0, 1);
+                            buffer++;
+                        }
+                        else
+                        {
+                            memset(buffer, 0, 2);
+                            buffer += 2;
+                        }
+
+                        string_count = 0;
+                        system = (struct smbios_system*)buffer;
+                        system->type = 1;
+                        system->length = sizeof(struct smbios_system);
+                        system->handle = 0;
+                        system->vendor = system_vendor ? ++string_count : 0;
+                        system->product = system_product ? ++string_count : 0;
+                        system->version = system_version ? ++string_count : 0;
+                        system->serial = system_serial ? ++string_count : 0;
+                        buffer += sizeof(struct smbios_system);
+
+                        if (string_count)
+                        {
+                            copy_smbios_string(&buffer, system_vendor, system_vendor_size);
+                            copy_smbios_string(&buffer, system_product, system_product_size);
+                            copy_smbios_string(&buffer, system_version, system_version_size);
+                            copy_smbios_string(&buffer, system_serial, system_serial_size);
+                            memset(buffer, 0, 1);
                         }
                         else
                         {
@@ -2516,6 +2563,10 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         free(bios_vendor);
                         free(bios_version);
                         free(bios_date);
+                        free(system_vendor);
+                        free(system_product);
+                        free(system_version);
+                        free(system_serial);
                     }
                     goto finish;
 #endif
--
2.17.1



Reply | Threaded
Open this post in threaded view
|

[PATCH v4 3/5] ntdll: Return board info from NtQuerySystemInformation on Linux

Alex Henrie
In reply to this post by Alex Henrie
Signed-off-by: Alex Henrie <[hidden email]>
---
 dlls/ntdll/nt.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 162c7467c8..3c95992818 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -113,6 +113,16 @@ struct smbios_system {
     BYTE serial;
 };
 
+struct smbios_board {
+    BYTE type;
+    BYTE length;
+    WORD handle;
+    BYTE vendor;
+    BYTE product;
+    BYTE version;
+    BYTE serial;
+};
+
 #include "poppack.h"
 
 /* Firmware table providers */
@@ -2468,11 +2478,14 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         size_t bios_vendor_size, bios_version_size, bios_date_size;
                         char *system_vendor, *system_product, *system_version, *system_serial;
                         size_t system_vendor_size, system_product_size, system_version_size, system_serial_size;
+                        char *board_vendor, *board_product, *board_version, *board_serial;
+                        size_t board_vendor_size, board_product_size, board_version_size, board_serial_size;
                         char *buffer = (char*)sfti->TableBuffer;
                         BYTE string_count;
                         struct smbios_prologue *prologue;
                         struct smbios_bios *bios;
                         struct smbios_system *system;
+                        struct smbios_board *board;
 
                         bios_vendor = get_smbios_string("/sys/class/dmi/id/bios_vendor", &bios_vendor_size);
                         bios_version = get_smbios_string("/sys/class/dmi/id/bios_version", &bios_version_size);
@@ -2481,6 +2494,10 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         system_product = get_smbios_string("/sys/class/dmi/id/product", &system_product_size);
                         system_version = get_smbios_string("/sys/class/dmi/id/product_version", &system_version_size);
                         system_serial = get_smbios_string("/sys/class/dmi/id/product_serial", &system_serial_size);
+                        board_vendor = get_smbios_string("/sys/class/dmi/id/board_vendor", &board_vendor_size);
+                        board_product = get_smbios_string("/sys/class/dmi/id/board_name", &board_product_size);
+                        board_version = get_smbios_string("/sys/class/dmi/id/board_version", &board_version_size);
+                        board_serial = get_smbios_string("/sys/class/dmi/id/board_serial", &board_serial_size);
 
                         len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
 
@@ -2493,6 +2510,10 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         len += max(system_vendor_size + system_product_size + system_version_size +
                                    system_serial_size + 1, 2);
 
+                        len += sizeof(struct smbios_board);
+                        len += max(board_vendor_size + board_product_size + board_version_size +
+                                   board_serial_size + 1, 2);
+
                         if (Length < len)
                         {
                             ret = STATUS_INFO_LENGTH_MISMATCH;
@@ -2554,6 +2575,32 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                             copy_smbios_string(&buffer, system_version, system_version_size);
                             copy_smbios_string(&buffer, system_serial, system_serial_size);
                             memset(buffer, 0, 1);
+                            buffer++;
+                        }
+                        else
+                        {
+                            memset(buffer, 0, 2);
+                            buffer += 2;
+                        }
+
+                        string_count = 0;
+                        board = (struct smbios_board*)buffer;
+                        board->type = 2;
+                        board->length = sizeof(struct smbios_board);
+                        board->handle = 0;
+                        board->vendor = board_vendor ? ++string_count : 0;
+                        board->product = board_product ? ++string_count : 0;
+                        board->version = board_version ? ++string_count : 0;
+                        board->serial = board_serial ? ++string_count : 0;
+                        buffer += sizeof(struct smbios_board);
+
+                        if (string_count)
+                        {
+                            copy_smbios_string(&buffer, board_vendor, board_vendor_size);
+                            copy_smbios_string(&buffer, board_product, board_product_size);
+                            copy_smbios_string(&buffer, board_version, board_version_size);
+                            copy_smbios_string(&buffer, board_serial, board_serial_size);
+                            memset(buffer, 0, 1);
                         }
                         else
                         {
@@ -2567,6 +2614,10 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         free(system_product);
                         free(system_version);
                         free(system_serial);
+                        free(board_vendor);
+                        free(board_product);
+                        free(board_version);
+                        free(board_serial);
                     }
                     goto finish;
 #endif
--
2.17.1



Reply | Threaded
Open this post in threaded view
|

[PATCH v4 4/5] ntdll: Return chassis info from NtQuerySystemInformation on Linux

Alex Henrie
In reply to this post by Alex Henrie
Signed-off-by: Alex Henrie <[hidden email]>
---
 dlls/ntdll/nt.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 53 insertions(+)

diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c
index 3c95992818..a0177b4062 100644
--- a/dlls/ntdll/nt.c
+++ b/dlls/ntdll/nt.c
@@ -123,6 +123,17 @@ struct smbios_board {
     BYTE serial;
 };
 
+struct smbios_chassis {
+    BYTE type;
+    BYTE length;
+    WORD handle;
+    BYTE vendor;
+    BYTE shape;
+    BYTE version;
+    BYTE serial;
+    BYTE asset_tag;
+};
+
 #include "poppack.h"
 
 /* Firmware table providers */
@@ -2480,12 +2491,15 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         size_t system_vendor_size, system_product_size, system_version_size, system_serial_size;
                         char *board_vendor, *board_product, *board_version, *board_serial;
                         size_t board_vendor_size, board_product_size, board_version_size, board_serial_size;
+                        char *chassis_vendor, *chassis_version, *chassis_serial, *chassis_asset_tag;
+                        size_t chassis_vendor_size, chassis_version_size, chassis_serial_size, chassis_asset_tag_size;
                         char *buffer = (char*)sfti->TableBuffer;
                         BYTE string_count;
                         struct smbios_prologue *prologue;
                         struct smbios_bios *bios;
                         struct smbios_system *system;
                         struct smbios_board *board;
+                        struct smbios_chassis *chassis;
 
                         bios_vendor = get_smbios_string("/sys/class/dmi/id/bios_vendor", &bios_vendor_size);
                         bios_version = get_smbios_string("/sys/class/dmi/id/bios_version", &bios_version_size);
@@ -2498,6 +2512,10 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         board_product = get_smbios_string("/sys/class/dmi/id/board_name", &board_product_size);
                         board_version = get_smbios_string("/sys/class/dmi/id/board_version", &board_version_size);
                         board_serial = get_smbios_string("/sys/class/dmi/id/board_serial", &board_serial_size);
+                        chassis_vendor = get_smbios_string("/sys/class/dmi/id/chassis_vendor", &chassis_vendor_size);
+                        chassis_version = get_smbios_string("/sys/class/dmi/id/chassis_version", &chassis_version_size);
+                        chassis_serial = get_smbios_string("/sys/class/dmi/id/chassis_serial", &chassis_serial_size);
+                        chassis_asset_tag = get_smbios_string("/sys/class/dmi/id/chassis_tag", &chassis_asset_tag_size);
 
                         len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
 
@@ -2514,6 +2532,10 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         len += max(board_vendor_size + board_product_size + board_version_size +
                                    board_serial_size + 1, 2);
 
+                        len += sizeof(struct smbios_chassis);
+                        len += max(chassis_vendor_size + chassis_version_size + chassis_serial_size +
+                                   chassis_asset_tag_size + 1, 2);
+
                         if (Length < len)
                         {
                             ret = STATUS_INFO_LENGTH_MISMATCH;
@@ -2601,6 +2623,33 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                             copy_smbios_string(&buffer, board_version, board_version_size);
                             copy_smbios_string(&buffer, board_serial, board_serial_size);
                             memset(buffer, 0, 1);
+                            buffer++;
+                        }
+                        else
+                        {
+                            memset(buffer, 0, 2);
+                            buffer += 2;
+                        }
+
+                        string_count = 0;
+                        chassis = (struct smbios_chassis*)buffer;
+                        chassis->type = 3;
+                        chassis->length = sizeof(struct smbios_chassis);
+                        chassis->handle = 0;
+                        chassis->vendor = chassis_vendor ? ++string_count : 0;
+                        chassis->shape = 0x2; /* unknown */
+                        chassis->version = chassis_version ? ++string_count : 0;
+                        chassis->serial = chassis_serial ? ++string_count : 0;
+                        chassis->asset_tag = chassis_asset_tag ? ++string_count : 0;
+                        buffer += sizeof(struct smbios_chassis);
+
+                        if (string_count)
+                        {
+                            copy_smbios_string(&buffer, chassis_vendor, chassis_vendor_size);
+                            copy_smbios_string(&buffer, chassis_version, chassis_version_size);
+                            copy_smbios_string(&buffer, chassis_serial, chassis_serial_size);
+                            copy_smbios_string(&buffer, chassis_asset_tag, chassis_asset_tag_size);
+                            memset(buffer, 0, 1);
                         }
                         else
                         {
@@ -2618,6 +2667,10 @@ NTSTATUS WINAPI NtQuerySystemInformation(
                         free(board_product);
                         free(board_version);
                         free(board_serial);
+                        free(chassis_vendor);
+                        free(chassis_version);
+                        free(chassis_serial);
+                        free(chassis_asset_tag);
                     }
                     goto finish;
 #endif
--
2.17.1



Reply | Threaded
Open this post in threaded view
|

[PATCH v4 5/5] kernel32: Connect GetSystemFirmwareTable to NtQuerySystemInformation

Alex Henrie
In reply to this post by Alex Henrie
Signed-off-by: Alex Henrie <[hidden email]>
---
 dlls/kernel32/cpu.c     | 44 +++++++++++++++++++++++++++++++++++++++++
 dlls/kernel32/process.c | 10 ----------
 2 files changed, 44 insertions(+), 10 deletions(-)

diff --git a/dlls/kernel32/cpu.c b/dlls/kernel32/cpu.c
index ec1fd0f90d..fcc2aee539 100644
--- a/dlls/kernel32/cpu.c
+++ b/dlls/kernel32/cpu.c
@@ -46,6 +46,21 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(reg);
 
+typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION
+{
+    SystemFirmwareTable_Enumerate = 0,
+    SystemFirmwareTable_Get = 1
+} SYSTEM_FIRMWARE_TABLE_ACTION;
+
+typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION
+{
+    ULONG ProviderSignature;
+    SYSTEM_FIRMWARE_TABLE_ACTION Action;
+    ULONG TableID;
+    ULONG TableBufferLength;
+    UCHAR TableBuffer[1];
+} SYSTEM_FIRMWARE_TABLE_INFORMATION;
+
 #define SHARED_DATA     ((KSHARED_USER_DATA*)0x7ffe0000)
 
 /****************************************************************************
@@ -336,3 +351,32 @@ DWORD64 WINAPI GetEnabledXStateFeatures(void)
     FIXME("\n");
     return 0;
 }
+
+/***********************************************************************
+ *           GetSystemFirmwareTable (KERNEL32.@)
+ */
+UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, void *buffer, DWORD size)
+{
+    ULONG buffer_size = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer) + size;
+    SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti = HeapAlloc(GetProcessHeap(), 0, buffer_size);
+    NTSTATUS status;
+
+    if (!sfti)
+    {
+        SetLastError(ERROR_OUTOFMEMORY);
+        return 0;
+    }
+
+    sfti->ProviderSignature = provider;
+    sfti->Action = SystemFirmwareTable_Get;
+    sfti->TableID = id;
+
+    status = NtQuerySystemInformation(SystemFirmwareTableInformation, sfti, buffer_size, &buffer_size);
+    buffer_size -= FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
+    if (buffer_size <= size)
+        memcpy(buffer, sfti->TableBuffer, buffer_size);
+
+    if (status) SetLastError(RtlNtStatusToDosError(status));
+    HeapFree(GetProcessHeap(), 0, sfti);
+    return buffer_size;
+}
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index ff56e9a692..6adf08d257 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -4126,16 +4126,6 @@ HRESULT WINAPI UnregisterApplicationRestart(void)
     return S_OK;
 }
 
-/***********************************************************************
- *           GetSystemFirmwareTable       (KERNEL32.@)
- */
-UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size)
-{
-    FIXME("(%d %d %p %d):stub\n", provider, id, buffer, size);
-    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-    return 0;
-}
-
 struct proc_thread_attr
 {
     DWORD_PTR attr;
--
2.17.1