v2: - Simplified if statements - Switched to Windows type names in structs
Alex Henrie (4): kernel32: Return BIOS info from GetSystemFirmwareTable on Linux kernel32: Return system info from GetSystemFirmwareTable on Linux kernel32: Return board info from GetSystemFirmwareTable on Linux kernel32: Return chassis info from GetSystemFirmwareTable on Linux
dlls/kernel32/process.c | 294 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 293 insertions(+), 1 deletion(-)
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/kernel32/process.c | 130 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 129 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index ff56e9a692..6797475438 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -81,6 +81,30 @@ typedef struct DWORD dwReserved; } LOADPARMS32;
+#include "pshpack1.h" + +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 manufacturer; + BYTE version; + WORD start; + BYTE date; + BYTE size; + UINT64 characteristics; +}; + +#include "poppack.h" + static DWORD shutdown_flags = 0; static DWORD shutdown_priority = 0x280; static BOOL is_wow64; @@ -102,6 +126,11 @@ const WCHAR *DIR_SysWow64 = NULL; #define PDB32_FILE_APIS_OEM 0x0040 /* File APIs are OEM */ #define PDB32_WIN32S_PROC 0x8000 /* Win32s process */
+/* Firmware table providers */ +#define ACPI 0x41435049 +#define FIRM 0x4649524D +#define RSMB 0x52534D42 + static const WCHAR exeW[] = {'.','e','x','e',0}; static const WCHAR comW[] = {'.','c','o','m',0}; static const WCHAR batW[] = {'.','b','a','t',0}; @@ -4126,12 +4155,111 @@ HRESULT WINAPI UnregisterApplicationRestart(void) return S_OK; }
+static inline void copy_smbios_string(void **buffer, char *string, size_t string_size) +{ + if (!string) return; + strcpy(*buffer, string); + *buffer = (char*)(*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 + /*********************************************************************** * GetSystemFirmwareTable (KERNEL32.@) */ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size) { - FIXME("(%d %d %p %d):stub\n", provider, id, buffer, size); + FIXME("(%08x %08x %p %d): semi-stub\n", provider, id, buffer, size); + switch (provider) + { + case RSMB: + { +#ifdef linux + char *bios_manufacturer, *bios_version, *bios_date; + size_t bios_manufacturer_size, bios_version_size, bios_date_size; + size_t required_size = sizeof(struct smbios_prologue); + BYTE string_count; + struct smbios_prologue *prologue; + struct smbios_bios *bios; + + bios_manufacturer = get_smbios_string("/sys/class/dmi/id/bios_vendor", &bios_manufacturer_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); + + required_size += sizeof(struct smbios_bios); + if (bios_manufacturer_size || bios_version_size || bios_date_size) + required_size += bios_manufacturer_size + bios_version_size + bios_date_size + 1; + else + required_size += 2; + + if (required_size > size) + return required_size; + + prologue = (struct smbios_prologue*)buffer; + prologue->calling_method = 0; + prologue->major_version = 2; + prologue->minor_version = 0; + prologue->revision = 0; + prologue->length = required_size - sizeof(struct smbios_prologue); + buffer = (char*)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->manufacturer = bios_manufacturer ? ++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 = (char*)buffer + sizeof(struct smbios_bios); + + if (string_count) + { + copy_smbios_string(&buffer, bios_manufacturer, bios_manufacturer_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_manufacturer); + free(bios_version); + free(bios_date); + + return required_size; +#endif + } + } SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; }
On Mon, May 28, 2018 at 10:05:26PM -0600, Alex Henrie wrote:
/***********************************************************************
GetSystemFirmwareTable (KERNEL32.@)
*/ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size) {
- FIXME("(%d %d %p %d):stub\n", provider, id, buffer, size);
- FIXME("(%08x %08x %p %d): semi-stub\n", provider, id, buffer, size);
This should probably be forwarded to NtQuerySystemInformation(SystemFirmwareTableInformation, ...).
Huw.
On Thu, Jun 7, 2018 at 7:25 AM Huw Davies huw@codeweavers.com wrote:
On Mon, May 28, 2018 at 10:05:26PM -0600, Alex Henrie wrote:
/***********************************************************************
GetSystemFirmwareTable (KERNEL32.@)
*/ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size) {
- FIXME("(%d %d %p %d):stub\n", provider, id, buffer, size);
- FIXME("(%08x %08x %p %d): semi-stub\n", provider, id, buffer, size);
This should probably be forwarded to NtQuerySystemInformation(SystemFirmwareTableInformation, ...).
NtQuerySystemInformation(SystemFirmwareTableInformation, ...) just returns STATUS_NOT_IMPLEMENTED on Windows.
-Alex
On 13 Jun 2018, at 15:32, Alex Henrie alexhenrie24@gmail.com wrote:
On Thu, Jun 7, 2018 at 7:25 AM Huw Davies huw@codeweavers.com wrote:
On Mon, May 28, 2018 at 10:05:26PM -0600, Alex Henrie wrote:
/***********************************************************************
GetSystemFirmwareTable (KERNEL32.@)
*/ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size) {
- FIXME("(%d %d %p %d):stub\n", provider, id, buffer, size);
- FIXME("(%08x %08x %p %d): semi-stub\n", provider, id, buffer, size);
This should probably be forwarded to NtQuerySystemInformation(SystemFirmwareTableInformation, ...).
NtQuerySystemInformation(SystemFirmwareTableInformation, ...) just returns STATUS_NOT_IMPLEMENTED on Windows.
You’re probably not calling it correctly. See: https://testbot.winehq.org/JobDetails.pl?Key=39104
(for some reason the 32-bit tests crash before my change, but you should get the idea).
Huw.
On Wed, Jun 13, 2018 at 9:36 AM Huw Davies huw@codeweavers.com wrote:
On 13 Jun 2018, at 15:32, Alex Henrie alexhenrie24@gmail.com wrote:
On Thu, Jun 7, 2018 at 7:25 AM Huw Davies huw@codeweavers.com wrote:
On Mon, May 28, 2018 at 10:05:26PM -0600, Alex Henrie wrote:
/***********************************************************************
GetSystemFirmwareTable (KERNEL32.@)
*/ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size) {
- FIXME("(%d %d %p %d):stub\n", provider, id, buffer, size);
- FIXME("(%08x %08x %p %d): semi-stub\n", provider, id, buffer, size);
This should probably be forwarded to NtQuerySystemInformation(SystemFirmwareTableInformation, ...).
NtQuerySystemInformation(SystemFirmwareTableInformation, ...) just returns STATUS_NOT_IMPLEMENTED on Windows.
You’re probably not calling it correctly. See: https://testbot.winehq.org/JobDetails.pl?Key=39104
You're right, thanks for the example! I was getting STATUS_NOT_IMPLEMENTED because I had not filled in the _SYSTEM_FIRMWARE_TABLE_INFORMATION struct. In fact, I didn't even know that anyone had figured out that struct's definition. Looks like you got it from http://www.exploit-monday.com/2013_06_16_archive.html.
I'll send a revised patch set tonight.
-Alex
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/kernel32/process.c | 54 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 6797475438..1a4a2c3243 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -103,6 +103,16 @@ struct smbios_bios { UINT64 characteristics; };
+struct smbios_system { + BYTE type; + BYTE length; + WORD handle; + BYTE manufacturer; + BYTE product; + BYTE version; + BYTE serial; +}; + #include "poppack.h"
static DWORD shutdown_flags = 0; @@ -4201,14 +4211,21 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD #ifdef linux char *bios_manufacturer, *bios_version, *bios_date; size_t bios_manufacturer_size, bios_version_size, bios_date_size; + char *system_manufacturer, *system_product, *system_version, *system_serial; + size_t system_manufacturer_size, system_product_size, system_version_size, system_serial_size; size_t required_size = sizeof(struct smbios_prologue); BYTE string_count; struct smbios_prologue *prologue; struct smbios_bios *bios; + struct smbios_system *system;
bios_manufacturer = get_smbios_string("/sys/class/dmi/id/bios_vendor", &bios_manufacturer_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_manufacturer = get_smbios_string("/sys/class/dmi/id/sys_vendor", &system_manufacturer_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);
required_size += sizeof(struct smbios_bios); if (bios_manufacturer_size || bios_version_size || bios_date_size) @@ -4216,6 +4233,13 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD else required_size += 2;
+ required_size += sizeof(struct smbios_system); + if (system_manufacturer_size || system_product_size || system_version_size || system_serial_size) + required_size += system_manufacturer_size + system_product_size + system_version_size + + system_serial_size + 1; + else + required_size += 2; + if (required_size > size) return required_size;
@@ -4246,6 +4270,32 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD copy_smbios_string(&buffer, bios_version, bios_version_size); copy_smbios_string(&buffer, bios_date, bios_date_size); memset(buffer, 0, 1); + buffer = (char*)buffer + 1; + } + else + { + memset(buffer, 0, 2); + buffer = (char*)buffer + 2; + } + + string_count = 0; + system = (struct smbios_system*)buffer; + system->type = 1; + system->length = sizeof(struct smbios_system); + system->handle = 0; + system->manufacturer = system_manufacturer ? ++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 = (char*)buffer + sizeof(struct smbios_system); + + if (string_count) + { + copy_smbios_string(&buffer, system_manufacturer, system_manufacturer_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 { @@ -4255,6 +4305,10 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD free(bios_manufacturer); free(bios_version); free(bios_date); + free(system_manufacturer); + free(system_product); + free(system_version); + free(system_serial);
return required_size; #endif
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/kernel32/process.c | 54 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 1a4a2c3243..b9942b9ec9 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -113,6 +113,16 @@ struct smbios_system { BYTE serial; };
+struct smbios_board { + BYTE type; + BYTE length; + WORD handle; + BYTE manufacturer; + BYTE product; + BYTE version; + BYTE serial; +}; + #include "poppack.h"
static DWORD shutdown_flags = 0; @@ -4213,11 +4223,14 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size_t bios_manufacturer_size, bios_version_size, bios_date_size; char *system_manufacturer, *system_product, *system_version, *system_serial; size_t system_manufacturer_size, system_product_size, system_version_size, system_serial_size; + char *board_manufacturer, *board_product, *board_version, *board_serial; + size_t board_manufacturer_size, board_product_size, board_version_size, board_serial_size; size_t required_size = sizeof(struct smbios_prologue); BYTE string_count; struct smbios_prologue *prologue; struct smbios_bios *bios; struct smbios_system *system; + struct smbios_board *board;
bios_manufacturer = get_smbios_string("/sys/class/dmi/id/bios_vendor", &bios_manufacturer_size); bios_version = get_smbios_string("/sys/class/dmi/id/bios_version", &bios_version_size); @@ -4226,6 +4239,10 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD 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_manufacturer = get_smbios_string("/sys/class/dmi/id/board_vendor", &board_manufacturer_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);
required_size += sizeof(struct smbios_bios); if (bios_manufacturer_size || bios_version_size || bios_date_size) @@ -4240,6 +4257,13 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD else required_size += 2;
+ required_size += sizeof(struct smbios_board); + if (board_manufacturer_size || board_product_size || board_version_size || board_serial_size) + required_size += board_manufacturer_size + board_product_size + board_version_size + + board_serial_size + 1; + else + required_size += 2; + if (required_size > size) return required_size;
@@ -4296,6 +4320,32 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD copy_smbios_string(&buffer, system_version, system_version_size); copy_smbios_string(&buffer, system_serial, system_serial_size); memset(buffer, 0, 1); + buffer = (char*)buffer + 1; + } + else + { + memset(buffer, 0, 2); + buffer = (char*)buffer + 2; + } + + string_count = 0; + board = (struct smbios_board*)buffer; + board->type = 2; + board->length = sizeof(struct smbios_board); + board->handle = 0; + board->manufacturer = board_manufacturer ? ++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 = (char*)buffer + sizeof(struct smbios_board); + + if (string_count) + { + copy_smbios_string(&buffer, board_manufacturer, board_manufacturer_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 { @@ -4309,6 +4359,10 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD free(system_product); free(system_version); free(system_serial); + free(board_manufacturer); + free(board_product); + free(board_version); + free(board_serial);
return required_size; #endif
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/kernel32/process.c | 56 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index b9942b9ec9..f257b4c191 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -123,6 +123,17 @@ struct smbios_board { BYTE serial; };
+struct smbios_chassis { + BYTE type; + BYTE length; + WORD handle; + BYTE manufacturer; + BYTE shape; + BYTE version; + BYTE serial; + BYTE asset_tag; +}; + #include "poppack.h"
static DWORD shutdown_flags = 0; @@ -4225,12 +4236,15 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD size_t system_manufacturer_size, system_product_size, system_version_size, system_serial_size; char *board_manufacturer, *board_product, *board_version, *board_serial; size_t board_manufacturer_size, board_product_size, board_version_size, board_serial_size; + char *chassis_manufacturer, *chassis_version, *chassis_serial, *chassis_asset_tag; + size_t chassis_manufacturer_size, chassis_version_size, chassis_serial_size, chassis_asset_tag_size; size_t required_size = sizeof(struct smbios_prologue); BYTE string_count; struct smbios_prologue *prologue; struct smbios_bios *bios; struct smbios_system *system; struct smbios_board *board; + struct smbios_chassis *chassis;
bios_manufacturer = get_smbios_string("/sys/class/dmi/id/bios_vendor", &bios_manufacturer_size); bios_version = get_smbios_string("/sys/class/dmi/id/bios_version", &bios_version_size); @@ -4243,6 +4257,10 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD 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_manufacturer = get_smbios_string("/sys/class/dmi/id/chassis_vendor", &chassis_manufacturer_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);
required_size += sizeof(struct smbios_bios); if (bios_manufacturer_size || bios_version_size || bios_date_size) @@ -4264,6 +4282,13 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD else required_size += 2;
+ required_size += sizeof(struct smbios_chassis); + if (chassis_manufacturer_size || chassis_version_size || chassis_serial_size || chassis_asset_tag_size) + required_size += chassis_manufacturer_size + chassis_version_size + chassis_serial_size + + chassis_asset_tag_size + 1; + else + required_size += 2; + if (required_size > size) return required_size;
@@ -4346,6 +4371,33 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD copy_smbios_string(&buffer, board_version, board_version_size); copy_smbios_string(&buffer, board_serial, board_serial_size); memset(buffer, 0, 1); + buffer = (char*)buffer + 1; + } + else + { + memset(buffer, 0, 2); + buffer = (char*)buffer + 2; + } + + string_count = 0; + chassis = (struct smbios_chassis*)buffer; + chassis->type = 3; + chassis->length = sizeof(struct smbios_chassis); + chassis->handle = 0; + chassis->manufacturer = chassis_manufacturer ? ++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 = (char*)buffer + sizeof(struct smbios_chassis); + + if (string_count) + { + copy_smbios_string(&buffer, chassis_manufacturer, chassis_manufacturer_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 { @@ -4363,6 +4415,10 @@ UINT WINAPI GetSystemFirmwareTable(DWORD provider, DWORD id, PVOID buffer, DWORD free(board_product); free(board_version); free(board_serial); + free(chassis_manufacturer); + free(chassis_version); + free(chassis_serial); + free(chassis_asset_tag);
return required_size; #endif