Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- include/winternl.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/include/winternl.h b/include/winternl.h index 58c475dfff..6e0bd987b6 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1579,6 +1579,23 @@ typedef struct _SYSTEM_TIME_ADJUSTMENT { BOOLEAN TimeAdjustmentDisabled; } SYSTEM_TIME_ADJUSTMENT, *PSYSTEM_TIME_ADJUSTMENT;
+typedef enum _SYSTEM_FIRMWARE_TABLE_ACTION +{ + SystemFirmwareTable_Enumerate = 0, + SystemFirmwareTable_Get = 1 +} SYSTEM_FIRMWARE_TABLE_ACTION, *PSYSTEM_FIRMWARE_TABLE_ACTION; + +/* System Information Class 0x4C */ + +typedef struct _SYSTEM_FIRMWARE_TABLE_INFORMATION +{ + ULONG ProviderSignature; + SYSTEM_FIRMWARE_TABLE_ACTION Action; + ULONG TableID; + ULONG TableBufferLength; + UCHAR TableBuffer[1]; +} SYSTEM_FIRMWARE_TABLE_INFORMATION, *PSYSTEM_FIRMWARE_TABLE_INFORMATION; + typedef struct _TIME_FIELDS { CSHORT Year; CSHORT Month;
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/tests/info.c | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 6c93c3cd58..804a0ac902 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -54,6 +54,11 @@ static DWORD one_before_last_pid = 0; } \ } while(0)
+/* Firmware table providers */ +#define ACPI 0x41435049 +#define FIRM 0x4649524D +#define RSMB 0x52534D42 + static BOOL InitFunctionPtrs(void) { /* All needed functions are NT based, so using GetModuleHandle is a good check */ @@ -826,6 +831,57 @@ static void test_query_logicalprocex(void) } }
+static void test_query_firmware(void) +{ + ULONG len1, len2; + NTSTATUS status; + SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti; + int i; + + sfti = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16); + ok(!!sfti, "Failed to allocate memory\n"); + + status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, 15, &len1); +todo_wine + ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* xp */, + "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status); + if (len1 == 0) /* xp, 2003 */ + { + skip("SystemFirmwareTableInformation is not available\n"); + HeapFree(GetProcessHeap(), 0, sfti); + return; + } + ok(len1 == 16, "Expected length 16, got %u\n", len1); + + status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, 16, &len1); + ok(status == STATUS_NOT_IMPLEMENTED, "Expected STATUS_NOT_IMPLEMENTED, got %08x\n", status); + ok(len1 == 0, "Expected length 0, got %u\n", len1); + + sfti->ProviderSignature = RSMB; + sfti->Action = SystemFirmwareTable_Get; + sfti->TableID = 0; + + status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, 16, &len1); + ok(status == STATUS_BUFFER_TOO_SMALL, "Expected STATUS_BUFFER_TOO_SMALL, got %08x\n", status); + ok(len1 >= 16, "Expected length >= 16, got %u\n", len1); + ok(sfti->TableBufferLength == len1 - 16, "Expected length %u, got %u\n", len1 - 16, sfti->TableBufferLength); + + sfti = HeapReAlloc(GetProcessHeap(), 0, sfti, len1); + ok(!!sfti, "Failed to allocate memory\n"); + + for (i = 0; i < 100; i++) + { + sfti->TableID = i; + status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, len1, &len2); + ok(status == STATUS_SUCCESS, "Table %u: Expected STATUS_SUCCESS, got %08x\n", i, status); + ok(len2 == len1, "Table %u: Expected length %u, got %u\n", i, len1, len2); + ok(sfti->TableBufferLength == len1 - 16, + "Table %u: Expected length %u, got %u\n", i, len1 - 16, sfti->TableBufferLength); + } + + HeapFree(GetProcessHeap(), 0, sfti); +} + static void test_query_processor_power_info(void) { NTSTATUS status; @@ -2267,6 +2323,10 @@ START_TEST(info) trace("Starting test_process_debug_flags()\n"); test_query_process_debug_flags(argc, argv);
+ /* 0x4C SystemFirmwareTableInformation */ + trace("Starting test_query_firmware()\n"); + test_query_firmware(); + /* belongs to its own file */ trace("Starting test_readvirtualmemory()\n"); test_readvirtualmemory();
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=39216
Your paranoid android.
=== wvistau64 (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022 0890:info: unhandled exception c0000005 at 002D0000
=== wvistau64_zh_CN (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022 0bcc:info: unhandled exception c0000005 at 00590000
=== wvistau64_fr (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022 072c:info: unhandled exception c0000005 at 00370000
=== wvistau64_he (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022 0be4:info: unhandled exception c0000005 at 003C0000
=== w2008s64 (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022 0ac8:info: unhandled exception c0000005 at 003D0000
=== w7u (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022
=== w7pro64 (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022 0a98:info: unhandled exception c0000005 at 003C0000
=== w8 (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022 0e78:info: unhandled exception c0000005 at 005A0000
=== w864 (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022 09e8:info: unhandled exception c0000005 at 00350000
=== w1064 (32 bit info) === info.c:1848: Test failed: Expected STATUS_SUCCESS, got c0000022 0a10:info: unhandled exception c0000005 at 003A0000
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/kernel32/tests/version.c | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+)
diff --git a/dlls/kernel32/tests/version.c b/dlls/kernel32/tests/version.c index eb78a383d2..08e8f0fb58 100644 --- a/dlls/kernel32/tests/version.c +++ b/dlls/kernel32/tests/version.c @@ -26,11 +26,17 @@ #include "winternl.h"
static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *); +static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, void *, ULONG, ULONG *); static NTSTATUS (WINAPI * pRtlGetVersion)(RTL_OSVERSIONINFOEXW *);
#define GET_PROC(func) \ p##func = (void *)GetProcAddress(hmod, #func);
+/* Firmware table providers */ +#define ACPI 0x41435049 +#define FIRM 0x4649524D +#define RSMB 0x52534D42 + static void init_function_pointers(void) { HMODULE hmod; @@ -41,6 +47,7 @@ static void init_function_pointers(void)
hmod = GetModuleHandleA("ntdll.dll");
+ GET_PROC(NtQuerySystemInformation); GET_PROC(RtlGetVersion); }
@@ -697,6 +704,39 @@ static void test_VerifyVersionInfo(void) ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError()); }
+void test_GetSystemFirmwareTable(void) +{ + ULONG expected_len, i; + UINT len; + SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16); + UCHAR *smbios_table = NULL; + + ok(!!sfti, "Failed to allocate memory\n"); + sfti->ProviderSignature = RSMB; + sfti->Action = SystemFirmwareTable_Get; + pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, 16, &expected_len); + if (expected_len == 0) /* xp, 2003 */ + { + skip("SystemFirmwareTableInformation is not available\n"); + HeapFree(GetProcessHeap(), 0, sfti); + return; + } + sfti = HeapReAlloc(GetProcessHeap(), 0, sfti, expected_len); + ok(!!sfti, "Failed to allocate memory\n"); + pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, expected_len, &expected_len); + + expected_len -= 16; + smbios_table = HeapAlloc(GetProcessHeap(), 0, expected_len); + for (i = 0; i < 100; i++) + { + len = GetSystemFirmwareTable(RSMB, i, smbios_table, expected_len); + ok(len == expected_len, "Table %u: Expected length %u, got %u\n", i, expected_len, len); + } + + HeapFree(GetProcessHeap(), 0, sfti); + HeapFree(GetProcessHeap(), 0, smbios_table); +} + START_TEST(version) { init_function_pointers(); @@ -704,4 +744,5 @@ START_TEST(version) test_GetProductInfo(); test_GetVersionEx(); test_VerifyVersionInfo(); + test_GetSystemFirmwareTable(); }
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/nt.c | 172 ++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/tests/info.c | 11 ++- 2 files changed, 181 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index dc0ce04f42..40e36c0ffd 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -66,6 +66,35 @@
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
+#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 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 +1879,127 @@ static NTSTATUS create_logical_proc_info(SYSTEM_LOGICAL_PROCESSOR_INFORMATION ** } #endif
+static inline void copy_smbios_string(char **buffer, char *s, size_t len) +{ + if (!len) return; + strcpy(*buffer, s); + *buffer += len + 1; +} + +#ifdef linux + +#define FWSS 128 /* firmware string size */ + +static void get_smbios_string(const char *path, char *s, size_t *len) +{ + FILE *file = fopen(path, "r"); + if (!file) + { + *len = 0; + return; + } + + *len = fread(s, 1, FWSS - 1, file); + fclose(file); + + if (*len >= 1 && s[*len - 1] == '\n') + { + s[*len - 1] = 0; + (*len)--; + } + else + { + s[*len] = 0; + } +} + +static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, + ULONG available_len, ULONG *required_len) +{ + switch (sfti->ProviderSignature) + { + case RSMB: + { + char bios_vendor[FWSS], bios_version[FWSS], bios_date[FWSS]; + size_t bios_vendor_len, bios_version_len, bios_date_len; + char *buffer = (char*)sfti->TableBuffer; + BYTE string_count; + struct smbios_prologue *prologue; + struct smbios_bios *bios; + + get_smbios_string("/sys/class/dmi/id/bios_vendor", bios_vendor, &bios_vendor_len); + get_smbios_string("/sys/class/dmi/id/bios_version", bios_version, &bios_version_len); + get_smbios_string("/sys/class/dmi/id/bios_date", bios_date, &bios_date_len); + + *required_len = sizeof(struct smbios_prologue); + + *required_len += sizeof(struct smbios_bios); + *required_len += max(bios_vendor_len + bios_version_len + bios_date_len + 4, 2); + + sfti->TableBufferLength = *required_len; + + *required_len += FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer); + + if (available_len < *required_len) + { + return STATUS_BUFFER_TOO_SMALL; + } + + 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_len ? ++string_count : 0; + bios->version = bios_version_len ? ++string_count : 0; + bios->start = 0; + bios->date = bios_date_len ? ++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_len); + copy_smbios_string(&buffer, bios_version, bios_version_len); + copy_smbios_string(&buffer, bios_date, bios_date_len); + memset(buffer, 0, 1); + } + else + { + memset(buffer, 0, 2); + } + + return STATUS_SUCCESS; + } + default: + { + FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION\n"); + return STATUS_NOT_IMPLEMENTED; + } + } +} + +#else + +static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti, + ULONG available_len, ULONG *required_len) +{ + FIXME("info_class SYSTEM_FIRMWARE_TABLE_INFORMATION\n"); + sfti->TableBufferLength = 0; + return STATUS_NOT_IMPLEMENTED; +} + +#endif + /****************************************************************************** * NtQuerySystemInformation [NTDLL.@] * ZwQuerySystemInformation [NTDLL.@] @@ -2359,6 +2509,28 @@ 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: + ret = get_firmware_info(sfti, Length, &len); + break; + default: + len = 0; + 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); diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 804a0ac902..d1c451157d 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -59,6 +59,12 @@ static DWORD one_before_last_pid = 0; #define FIRM 0x4649524D #define RSMB 0x52534D42
+#ifdef linux +static const int firmware_todo = 0; +#else +static const int firmware_todo = 1; +#endif + static BOOL InitFunctionPtrs(void) { /* All needed functions are NT based, so using GetModuleHandle is a good check */ @@ -842,12 +848,11 @@ static void test_query_firmware(void) ok(!!sfti, "Failed to allocate memory\n");
status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, 15, &len1); -todo_wine ok(status == STATUS_INFO_LENGTH_MISMATCH || broken(status == STATUS_INVALID_INFO_CLASS) /* xp */, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status); if (len1 == 0) /* xp, 2003 */ { - skip("SystemFirmwareTableInformation is not available\n"); + win_skip("SystemFirmwareTableInformation is not available\n"); HeapFree(GetProcessHeap(), 0, sfti); return; } @@ -862,6 +867,7 @@ todo_wine sfti->TableID = 0;
status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, 16, &len1); +todo_wine_if(firmware_todo) ok(status == STATUS_BUFFER_TOO_SMALL, "Expected STATUS_BUFFER_TOO_SMALL, got %08x\n", status); ok(len1 >= 16, "Expected length >= 16, got %u\n", len1); ok(sfti->TableBufferLength == len1 - 16, "Expected length %u, got %u\n", len1 - 16, sfti->TableBufferLength); @@ -873,6 +879,7 @@ todo_wine { sfti->TableID = i; status = pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, len1, &len2); +todo_wine_if(firmware_todo) ok(status == STATUS_SUCCESS, "Table %u: Expected STATUS_SUCCESS, got %08x\n", i, status); ok(len2 == len1, "Table %u: Expected length %u, got %u\n", i, len1, len2); ok(sfti->TableBufferLength == len1 - 16,
On Mon, Jun 18, 2018 at 05:09:32AM -0600, Alex Henrie wrote:
Signed-off-by: Alex Henrie alexhenrie24@gmail.com
dlls/ntdll/nt.c | 172 ++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/tests/info.c | 11 ++- 2 files changed, 181 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index dc0ce04f42..40e36c0ffd 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -1850,6 +1879,127 @@ static NTSTATUS create_logical_proc_info(SYSTEM_LOGICAL_PROCESSOR_INFORMATION ** } #endif
+static inline void copy_smbios_string(char **buffer, char *s, size_t len) +{
- if (!len) return;
- strcpy(*buffer, s);
- *buffer += len + 1;
+}
+#ifdef linux
+#define FWSS 128 /* firmware string size */
+static void get_smbios_string(const char *path, char *s, size_t *len) +{
- FILE *file = fopen(path, "r");
- if (!file)
- {
*len = 0;
return;
- }
- *len = fread(s, 1, FWSS - 1, file);
That's pretty ugly. This function really shouldn't assume the size of the buffer is has to play with.
- fclose(file);
- if (*len >= 1 && s[*len - 1] == '\n')
- {
s[*len - 1] = 0;
(*len)--;
- }
- else
- {
s[*len] = 0;
- }
+}
+static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti,
ULONG available_len, ULONG *required_len)
+{
- switch (sfti->ProviderSignature)
- {
- case RSMB:
{
char bios_vendor[FWSS], bios_version[FWSS], bios_date[FWSS];
size_t bios_vendor_len, bios_version_len, bios_date_len;
char *buffer = (char*)sfti->TableBuffer;
BYTE string_count;
struct smbios_prologue *prologue;
struct smbios_bios *bios;
get_smbios_string("/sys/class/dmi/id/bios_vendor", bios_vendor, &bios_vendor_len);
get_smbios_string("/sys/class/dmi/id/bios_version", bios_version, &bios_version_len);
get_smbios_string("/sys/class/dmi/id/bios_date", bios_date, &bios_date_len);
On Mon, Jun 18, 2018 at 12:21:52PM +0100, Huw Davies wrote:
On Mon, Jun 18, 2018 at 05:09:32AM -0600, Alex Henrie wrote:
Signed-off-by: Alex Henrie alexhenrie24@gmail.com
dlls/ntdll/nt.c | 172 ++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/tests/info.c | 11 ++- 2 files changed, 181 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index dc0ce04f42..40e36c0ffd 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -1850,6 +1879,127 @@ static NTSTATUS create_logical_proc_info(SYSTEM_LOGICAL_PROCESSOR_INFORMATION ** } #endif
+static inline void copy_smbios_string(char **buffer, char *s, size_t len) +{
- if (!len) return;
- strcpy(*buffer, s);
- *buffer += len + 1;
+}
+#ifdef linux
+#define FWSS 128 /* firmware string size */
+static void get_smbios_string(const char *path, char *s, size_t *len) +{
- FILE *file = fopen(path, "r");
- if (!file)
- {
*len = 0;
return;
- }
- *len = fread(s, 1, FWSS - 1, file);
That's pretty ugly. This function really shouldn't assume the size of the buffer is has to play with.
Note, it may be more convenient to use a separate 'size' [in] parameter rather than use len as [in,out].
Huw.
On Mon, Jun 18, 2018 at 5:26 AM Huw Davies huw@codeweavers.com wrote:
On Mon, Jun 18, 2018 at 12:21:52PM +0100, Huw Davies wrote:
On Mon, Jun 18, 2018 at 05:09:32AM -0600, Alex Henrie wrote:
Signed-off-by: Alex Henrie alexhenrie24@gmail.com
dlls/ntdll/nt.c | 172 ++++++++++++++++++++++++++++++++++++++++ dlls/ntdll/tests/info.c | 11 ++- 2 files changed, 181 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index dc0ce04f42..40e36c0ffd 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -1850,6 +1879,127 @@ static NTSTATUS create_logical_proc_info(SYSTEM_LOGICAL_PROCESSOR_INFORMATION ** } #endif
+static inline void copy_smbios_string(char **buffer, char *s, size_t len) +{
- if (!len) return;
- strcpy(*buffer, s);
- *buffer += len + 1;
+}
+#ifdef linux
+#define FWSS 128 /* firmware string size */
+static void get_smbios_string(const char *path, char *s, size_t *len) +{
- FILE *file = fopen(path, "r");
- if (!file)
- {
*len = 0;
return;
- }
- *len = fread(s, 1, FWSS - 1, file);
That's pretty ugly. This function really shouldn't assume the size of the buffer is has to play with.
We're talking about Linux-specific code, and FWSS is used in both get_smbios_string and get_firmware_info, so it's not much of an assumption.
Note, it may be more convenient to use a separate 'size' [in] parameter rather than use len as [in,out].
The helper function doesn't need to support more than one buffer size, so passing the buffer size is redundant.
I'd want to hear at least one more Wine developer's opinion before making a change.
-Alex
Alex Henrie alexhenrie24@gmail.com writes:
The helper function doesn't need to support more than one buffer size, so passing the buffer size is redundant.
I'd want to hear at least one more Wine developer's opinion before making a change.
It's indeed ugly to make that sort of assumption in the helper function. Also you could return the resulting length instead of having an out variable.
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=39218
Your paranoid android.
=== wvistau64 (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022 0890:info: unhandled exception c0000005 at 002D0000
=== wvistau64_zh_CN (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022 0bb8:info: unhandled exception c0000005 at 00370000
=== wvistau64_fr (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022 0830:info: unhandled exception c0000005 at 00340000
=== wvistau64_he (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022 0bd8:info: unhandled exception c0000005 at 002D0000
=== w2008s64 (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022 086c:info: unhandled exception c0000005 at 003D0000
=== w7u (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022
=== w7pro64 (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022 0ab8:info: unhandled exception c0000005 at 00340000
=== w8 (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022 0f4c:info: unhandled exception c0000005 at 00310000
=== w864 (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022 0a18:info: unhandled exception c0000005 at 003D0000
=== w1064 (32 bit info) === info.c:1855: Test failed: Expected STATUS_SUCCESS, got c0000022 0a10:info: unhandled exception c0000005 at 00390000
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/kernel32/cpu.c | 29 +++++++++++++++++++++++++++++ dlls/kernel32/process.c | 10 ---------- dlls/kernel32/tests/version.c | 2 +- 3 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/dlls/kernel32/cpu.c b/dlls/kernel32/cpu.c index ec1fd0f90d..8397fbe729 100644 --- a/dlls/kernel32/cpu.c +++ b/dlls/kernel32/cpu.c @@ -336,3 +336,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; diff --git a/dlls/kernel32/tests/version.c b/dlls/kernel32/tests/version.c index 08e8f0fb58..e33ce9cd42 100644 --- a/dlls/kernel32/tests/version.c +++ b/dlls/kernel32/tests/version.c @@ -717,7 +717,7 @@ void test_GetSystemFirmwareTable(void) pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, 16, &expected_len); if (expected_len == 0) /* xp, 2003 */ { - skip("SystemFirmwareTableInformation is not available\n"); + win_skip("SystemFirmwareTableInformation is not available\n"); HeapFree(GetProcessHeap(), 0, sfti); return; }
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/nt.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 40e36c0ffd..401e3b473d 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -88,6 +88,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 */ @@ -1922,20 +1932,31 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti { char bios_vendor[FWSS], bios_version[FWSS], bios_date[FWSS]; size_t bios_vendor_len, bios_version_len, bios_date_len; + char system_vendor[FWSS], system_product[FWSS], system_version[FWSS], system_serial[FWSS]; + size_t system_vendor_len, system_product_len, system_version_len, system_serial_len; char *buffer = (char*)sfti->TableBuffer; BYTE string_count; struct smbios_prologue *prologue; struct smbios_bios *bios; + struct smbios_system *system;
get_smbios_string("/sys/class/dmi/id/bios_vendor", bios_vendor, &bios_vendor_len); get_smbios_string("/sys/class/dmi/id/bios_version", bios_version, &bios_version_len); get_smbios_string("/sys/class/dmi/id/bios_date", bios_date, &bios_date_len); + get_smbios_string("/sys/class/dmi/id/sys_vendor", system_vendor, &system_vendor_len); + get_smbios_string("/sys/class/dmi/id/product", system_product, &system_product_len); + get_smbios_string("/sys/class/dmi/id/product_version", system_version, &system_version_len); + get_smbios_string("/sys/class/dmi/id/product_serial", system_serial, &system_serial_len);
*required_len = sizeof(struct smbios_prologue);
*required_len += sizeof(struct smbios_bios); *required_len += max(bios_vendor_len + bios_version_len + bios_date_len + 4, 2);
+ *required_len += sizeof(struct smbios_system); + *required_len += max(system_vendor_len + system_product_len + system_version_len + + system_serial_len + 5, 2); + sfti->TableBufferLength = *required_len;
*required_len += FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer); @@ -1972,6 +1993,32 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti copy_smbios_string(&buffer, bios_version, bios_version_len); copy_smbios_string(&buffer, bios_date, bios_date_len); 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_len ? ++string_count : 0; + system->product = system_product_len ? ++string_count : 0; + system->version = system_version_len ? ++string_count : 0; + system->serial = system_serial_len ? ++string_count : 0; + buffer += sizeof(struct smbios_system); + + if (string_count) + { + copy_smbios_string(&buffer, system_vendor, system_vendor_len); + copy_smbios_string(&buffer, system_product, system_product_len); + copy_smbios_string(&buffer, system_version, system_version_len); + copy_smbios_string(&buffer, system_serial, system_serial_len); + memset(buffer, 0, 1); } else {
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/nt.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index 401e3b473d..bce7348ba6 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -98,6 +98,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 */ @@ -1934,11 +1944,14 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti size_t bios_vendor_len, bios_version_len, bios_date_len; char system_vendor[FWSS], system_product[FWSS], system_version[FWSS], system_serial[FWSS]; size_t system_vendor_len, system_product_len, system_version_len, system_serial_len; + char board_vendor[FWSS], board_product[FWSS], board_version[FWSS], board_serial[FWSS]; + size_t board_vendor_len, board_product_len, board_version_len, board_serial_len; char *buffer = (char*)sfti->TableBuffer; BYTE string_count; struct smbios_prologue *prologue; struct smbios_bios *bios; struct smbios_system *system; + struct smbios_board *board;
get_smbios_string("/sys/class/dmi/id/bios_vendor", bios_vendor, &bios_vendor_len); get_smbios_string("/sys/class/dmi/id/bios_version", bios_version, &bios_version_len); @@ -1947,6 +1960,10 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti get_smbios_string("/sys/class/dmi/id/product", system_product, &system_product_len); get_smbios_string("/sys/class/dmi/id/product_version", system_version, &system_version_len); get_smbios_string("/sys/class/dmi/id/product_serial", system_serial, &system_serial_len); + get_smbios_string("/sys/class/dmi/id/board_vendor", board_vendor, &board_vendor_len); + get_smbios_string("/sys/class/dmi/id/board_name", board_product, &board_product_len); + get_smbios_string("/sys/class/dmi/id/board_version", board_version, &board_version_len); + get_smbios_string("/sys/class/dmi/id/board_serial", board_serial, &board_serial_len);
*required_len = sizeof(struct smbios_prologue);
@@ -1957,6 +1974,9 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti *required_len += max(system_vendor_len + system_product_len + system_version_len + system_serial_len + 5, 2);
+ *required_len += sizeof(struct smbios_board); + *required_len += max(board_vendor_len + board_product_len + board_version_len + board_serial_len + 5, 2); + sfti->TableBufferLength = *required_len;
*required_len += FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer); @@ -2019,6 +2039,32 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti copy_smbios_string(&buffer, system_version, system_version_len); copy_smbios_string(&buffer, system_serial, system_serial_len); 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_len ? ++string_count : 0; + board->product = board_product_len ? ++string_count : 0; + board->version = board_version_len ? ++string_count : 0; + board->serial = board_serial_len ? ++string_count : 0; + buffer += sizeof(struct smbios_board); + + if (string_count) + { + copy_smbios_string(&buffer, board_vendor, board_vendor_len); + copy_smbios_string(&buffer, board_product, board_product_len); + copy_smbios_string(&buffer, board_version, board_version_len); + copy_smbios_string(&buffer, board_serial, board_serial_len); + memset(buffer, 0, 1); } else {
Signed-off-by: Alex Henrie alexhenrie24@gmail.com --- dlls/ntdll/nt.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/dlls/ntdll/nt.c b/dlls/ntdll/nt.c index bce7348ba6..9fcb9a8155 100644 --- a/dlls/ntdll/nt.c +++ b/dlls/ntdll/nt.c @@ -108,6 +108,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 */ @@ -1946,12 +1957,15 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti size_t system_vendor_len, system_product_len, system_version_len, system_serial_len; char board_vendor[FWSS], board_product[FWSS], board_version[FWSS], board_serial[FWSS]; size_t board_vendor_len, board_product_len, board_version_len, board_serial_len; + char chassis_vendor[FWSS], chassis_version[FWSS], chassis_serial[FWSS], chassis_asset_tag[FWSS]; + size_t chassis_vendor_len, chassis_version_len, chassis_serial_len, chassis_asset_tag_len; 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;
get_smbios_string("/sys/class/dmi/id/bios_vendor", bios_vendor, &bios_vendor_len); get_smbios_string("/sys/class/dmi/id/bios_version", bios_version, &bios_version_len); @@ -1964,6 +1978,10 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti get_smbios_string("/sys/class/dmi/id/board_name", board_product, &board_product_len); get_smbios_string("/sys/class/dmi/id/board_version", board_version, &board_version_len); get_smbios_string("/sys/class/dmi/id/board_serial", board_serial, &board_serial_len); + get_smbios_string("/sys/class/dmi/id/chassis_vendor", chassis_vendor, &chassis_vendor_len); + get_smbios_string("/sys/class/dmi/id/chassis_version", chassis_version, &chassis_version_len); + get_smbios_string("/sys/class/dmi/id/chassis_serial", chassis_serial, &chassis_serial_len); + get_smbios_string("/sys/class/dmi/id/chassis_tag", chassis_asset_tag, &chassis_asset_tag_len);
*required_len = sizeof(struct smbios_prologue);
@@ -1977,6 +1995,10 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti *required_len += sizeof(struct smbios_board); *required_len += max(board_vendor_len + board_product_len + board_version_len + board_serial_len + 5, 2);
+ *required_len += sizeof(struct smbios_chassis); + *required_len += max(chassis_vendor_len + chassis_version_len + chassis_serial_len + + chassis_asset_tag_len + 5, 2); + sfti->TableBufferLength = *required_len;
*required_len += FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer); @@ -2065,6 +2087,33 @@ static inline NTSTATUS get_firmware_info(SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti copy_smbios_string(&buffer, board_version, board_version_len); copy_smbios_string(&buffer, board_serial, board_serial_len); 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_len ? ++string_count : 0; + chassis->shape = 0x2; /* unknown */ + chassis->version = chassis_version_len ? ++string_count : 0; + chassis->serial = chassis_serial_len ? ++string_count : 0; + chassis->asset_tag = chassis_asset_tag_len ? ++string_count : 0; + buffer += sizeof(struct smbios_chassis); + + if (string_count) + { + copy_smbios_string(&buffer, chassis_vendor, chassis_vendor_len); + copy_smbios_string(&buffer, chassis_version, chassis_version_len); + copy_smbios_string(&buffer, chassis_serial, chassis_serial_len); + copy_smbios_string(&buffer, chassis_asset_tag, chassis_asset_tag_len); + memset(buffer, 0, 1); } else {