[KERNEL32_APITEST] Add SystemFirmware tests
authorStanislav Motylkov <x86corez@gmail.com>
Sun, 29 Jul 2018 14:43:10 +0000 (17:43 +0300)
committerMark Jansen <mark.jansen@reactos.org>
Thu, 2 Aug 2018 19:15:28 +0000 (21:15 +0200)
CORE-12105

modules/rostests/apitests/kernel32/CMakeLists.txt
modules/rostests/apitests/kernel32/SystemFirmware.c [new file with mode: 0644]
modules/rostests/apitests/kernel32/testlist.c

index c329031..37c5b6a 100644 (file)
@@ -28,6 +28,7 @@ list(APPEND SOURCE
     SetConsoleWindowInfo.c
     SetCurrentDirectory.c
     SetUnhandledExceptionFilter.c
+    SystemFirmware.c
     TerminateProcess.c
     TunnelCache.c
     WideCharToMultiByte.c
diff --git a/modules/rostests/apitests/kernel32/SystemFirmware.c b/modules/rostests/apitests/kernel32/SystemFirmware.c
new file mode 100644 (file)
index 0000000..5ba946d
--- /dev/null
@@ -0,0 +1,466 @@
+/*
+ * PROJECT:     ReactOS API Tests
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Tests for System Firmware functions
+ * COPYRIGHT:   Copyright 2018 Stanislav Motylkov
+ */
+
+#include "precomp.h"
+
+static UINT (WINAPI * pEnumSystemFirmwareTables)(DWORD, PVOID, DWORD);
+static UINT (WINAPI * pGetSystemFirmwareTable)(DWORD, DWORD, PVOID, DWORD);
+
+typedef struct ENTRY
+{
+    DWORD Signature;
+    DWORD ErrInsuff;
+    DWORD ErrSuccess;
+} ENTRY;
+
+static
+VOID
+test_EnumBuffer(
+    DWORD Signature,
+    PVOID Buffer,
+    DWORD dwSize,
+    UINT * pTableCount,
+    DWORD * pFirstTableID,
+    DWORD ErrInsuff,
+    DWORD ErrSuccess
+)
+{
+    DWORD dwError;
+    DWORD dwBufferSize;
+    DWORD dwException;
+    UINT uResultSize;
+
+    dwException = Buffer && IsBadWritePtr(Buffer, dwSize) ? STATUS_ACCESS_VIOLATION : STATUS_SUCCESS;
+
+    // Test size = 0
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        FillMemory(Buffer, dwSize, 0xFF);
+    }
+    SetLastError(0xbeeffeed);
+    dwError = GetLastError();
+    dwBufferSize = 0;
+    uResultSize = 0;
+    StartSeh()
+        uResultSize = pEnumSystemFirmwareTables(Signature, Buffer, dwBufferSize);
+        dwError = GetLastError();
+    EndSeh(STATUS_SUCCESS);
+
+    if (uResultSize > 0)
+    {
+        ok(dwError == ErrInsuff,
+           "GetLastError() returned %ld, expected %ld\n",
+           dwError, ErrInsuff);
+    }
+    else
+    {
+        ok(dwError == ErrSuccess,
+           "GetLastError() returned %ld, expected %ld\n",
+           dwError, ErrSuccess);
+    }
+    if (ErrSuccess == ERROR_SUCCESS)
+    {
+        ok(uResultSize % sizeof(DWORD) == 0,
+           "uResultSize is %u, expected %% sizeof(DWORD)\n",
+           uResultSize);
+    }
+    else
+    {
+        ok(uResultSize == 0,
+           "uResultSize is %u, expected == 0\n",
+           uResultSize);
+    }
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        ok(*(BYTE *)Buffer == 0xFF,
+           "Buffer should be clean at offset 0, got %x\n",
+           *(BYTE *)Buffer);
+    }
+
+    // Test size = 2
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        FillMemory(Buffer, dwSize, 0xFF);
+    }
+    SetLastError(0xbeeffeed);
+    dwError = GetLastError();
+    dwBufferSize = 2;
+    uResultSize = 0;
+    StartSeh()
+        uResultSize = pEnumSystemFirmwareTables(Signature, Buffer, dwBufferSize);
+        dwError = GetLastError();
+    EndSeh(STATUS_SUCCESS);
+
+    if (uResultSize > 0)
+    {
+        ok(dwError == ErrInsuff,
+           "GetLastError() returned %ld, expected %ld\n",
+           dwError, ErrInsuff);
+    }
+    else
+    {
+        ok(dwError == ErrSuccess,
+           "GetLastError() returned %ld, expected %ld\n",
+           dwError, ErrSuccess);
+    }
+    if (ErrSuccess == ERROR_SUCCESS)
+    {
+        ok(uResultSize % sizeof(DWORD) == 0,
+           "uResultSize is %u, expected %% sizeof(DWORD)\n",
+           uResultSize);
+    }
+    else
+    {
+        ok(uResultSize == 0,
+           "uResultSize is %u, expected == 0\n",
+           uResultSize);
+    }
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        ok(*(WORD *)Buffer == 0xFFFF,
+           "Buffer should be clean at offset 0, got %x\n",
+           *(WORD *)Buffer);
+    }
+
+    // Test full size
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        FillMemory(Buffer, dwSize, 0xFF);
+    }
+    if (uResultSize > 0)
+    {
+        SetLastError(0xbeeffeed);
+        dwError = GetLastError();
+        dwBufferSize = uResultSize;
+        uResultSize = 0;
+        StartSeh()
+            uResultSize = pEnumSystemFirmwareTables(Signature, Buffer, dwBufferSize);
+            dwError = GetLastError();
+        EndSeh(ErrSuccess == ERROR_SUCCESS ? dwException : STATUS_SUCCESS);
+        // Windows 7: does not throw exception here
+
+        if (dwException == STATUS_SUCCESS || ErrSuccess == ERROR_INVALID_FUNCTION)
+        {
+            ok(dwError == ErrSuccess,
+               "GetLastError() returned %ld, expected %ld\n",
+               dwError, ErrSuccess);
+            if (ErrSuccess == ERROR_SUCCESS)
+            {
+                ok(uResultSize == dwBufferSize,
+                   "uResultSize is not equal dwBufferSize, expected %ld\n",
+                   dwBufferSize);
+            }
+            else
+            {
+                ok(uResultSize == 0,
+                   "uResultSize is %u, expected == 0\n",
+                   uResultSize);
+            }
+        }
+        else
+        {
+            // Windows 7: returns ERROR_NOACCESS here
+            ok(dwError == 0xbeeffeed,
+               "GetLastError() returned %ld, expected %u\n",
+               dwError, 0xbeeffeed);
+            // Windows 7: returns correct size here
+            ok(uResultSize == 0,
+               "uResultSize is %u, expected == 0\n",
+               uResultSize);
+        }
+    }
+
+    if (pTableCount && pFirstTableID)
+    {
+        if (uResultSize > 0)
+        {
+            if (Signature == 'RSMB')
+            {
+                // Raw SMBIOS have only one table with ID 0
+                ok(*(DWORD *)Buffer == 0,
+                   "Buffer should be filled at offset 0, got %lx\n",
+                   *(DWORD *)Buffer);
+            }
+            else
+            {
+                // In other cases ID can be different
+                if (ErrSuccess == ERROR_SUCCESS)
+                {
+                    ok(*(DWORD *)Buffer != 0xFFFFFFFF,
+                       "Buffer should be filled at offset 0\n");
+                }
+                else
+                {
+                    ok(*(DWORD *)Buffer == 0xFFFFFFFF,
+                       "Buffer should be clean at offset 0\n");
+                }
+            }
+        }
+        *pTableCount = uResultSize / sizeof(DWORD);
+        *pFirstTableID = *(DWORD *)Buffer;
+    }
+}
+
+static
+VOID
+test_GetBuffer(
+    DWORD Signature,
+    DWORD TableID,
+    PVOID Buffer,
+    DWORD dwSize,
+    BOOL TestFakeID,
+    DWORD ErrInsuff,
+    DWORD ErrSuccess
+)
+{
+    DWORD dwError;
+    DWORD dwBufferSize;
+    DWORD dwException;
+    DWORD dwErrCase;
+    UINT uResultSize;
+
+    dwException = Buffer && IsBadWritePtr(Buffer, dwSize) ? STATUS_ACCESS_VIOLATION : STATUS_SUCCESS;
+    switch (Signature)
+    {
+        case 'ACPI':
+        {
+            dwErrCase = ERROR_NOT_FOUND;
+            break;
+        }
+        case 'FIRM':
+        {
+            dwErrCase = ERROR_INVALID_PARAMETER;
+            break;
+        }
+        default:
+        {
+            dwErrCase = ErrInsuff;
+        }
+    }
+
+    // Test size = 0
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        FillMemory(Buffer, dwSize, 0xFF);
+    }
+    SetLastError(0xbeeffeed);
+    dwError = GetLastError();
+    dwBufferSize = 0;
+    uResultSize = 0;
+    StartSeh()
+        uResultSize = pGetSystemFirmwareTable(Signature, TableID, Buffer, dwBufferSize);
+        dwError = GetLastError();
+    EndSeh(STATUS_SUCCESS);
+
+    ok(dwError == (TestFakeID ? dwErrCase : ErrInsuff),
+       "GetLastError() returned %ld, expected %ld\n",
+       dwError, (TestFakeID ? dwErrCase : ErrInsuff));
+    if (ErrSuccess == ERROR_SUCCESS && (!TestFakeID || dwErrCase == ErrInsuff))
+    {
+        ok(uResultSize > 0,
+           "uResultSize is %u, expected > 0\n",
+           uResultSize);
+    }
+    else
+    {
+        ok(uResultSize == 0,
+           "uResultSize is %u, expected == 0\n",
+           uResultSize);
+    }
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        ok(*(BYTE *)Buffer == 0xFF,
+           "Buffer should be clean at offset 0, got %x\n",
+           *(BYTE *)Buffer);
+    }
+
+    // Test size = 2
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        FillMemory(Buffer, dwSize, 0xFF);
+    }
+    SetLastError(0xbeeffeed);
+    dwError = GetLastError();
+    dwBufferSize = 2;
+    uResultSize = 0;
+    StartSeh()
+        uResultSize = pGetSystemFirmwareTable(Signature, TableID, Buffer, dwBufferSize);
+        dwError = GetLastError();
+    EndSeh(STATUS_SUCCESS);
+
+    ok(dwError == (TestFakeID ? dwErrCase : ErrInsuff),
+       "GetLastError() returned %ld, expected %ld\n",
+       dwError, (TestFakeID ? dwErrCase : ErrInsuff));
+    if (ErrSuccess == ERROR_SUCCESS && (!TestFakeID || dwErrCase == ErrInsuff))
+    {
+        ok(uResultSize > 0,
+           "uResultSize is %u, expected > 0\n",
+           uResultSize);
+    }
+    else
+    {
+        ok(uResultSize == 0,
+           "uResultSize is %u, expected == 0\n",
+           uResultSize);
+    }
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        ok(*(WORD *)Buffer == 0xFFFF,
+           "Buffer should be clean at offset 0, got %x\n",
+           *(WORD *)Buffer);
+    }
+
+    // Test full size
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        FillMemory(Buffer, dwSize, 0xFF);
+    }
+    if (uResultSize == 0)
+    {
+        return;
+    }
+    SetLastError(0xbeeffeed);
+    dwError = GetLastError();
+    dwBufferSize = uResultSize;
+    uResultSize = 0;
+    StartSeh()
+        uResultSize = pGetSystemFirmwareTable(Signature, TableID, Buffer, dwBufferSize);
+        dwError = GetLastError();
+    EndSeh(ErrSuccess == ERROR_SUCCESS ? dwException : STATUS_SUCCESS);
+    // Windows 7: does not throw exception here
+
+    if (dwException == STATUS_SUCCESS || ErrSuccess == ERROR_INVALID_FUNCTION)
+    {
+        ok(dwError == ErrSuccess,
+           "GetLastError() returned %ld, expected %ld\n",
+           dwError, ErrSuccess);
+        if (ErrSuccess == ERROR_SUCCESS)
+        {
+            ok(uResultSize == dwBufferSize,
+               "uResultSize is not equal dwBufferSize, expected %ld\n",
+               dwBufferSize);
+        }
+        else
+        {
+            ok(uResultSize == 0,
+               "uResultSize is %u, expected == 0\n",
+               uResultSize);
+        }
+    }
+    else
+    {
+        // Windows 7: returns ERROR_NOACCESS here
+        ok(dwError == 0xbeeffeed,
+           "GetLastError() returned %ld, expected %u\n",
+           dwError, 0xbeeffeed);
+        // Windows 7: returns correct size here
+        ok(uResultSize == 0,
+           "uResultSize is %u, expected == 0\n",
+           uResultSize);
+    }
+
+    if (Buffer && dwException == STATUS_SUCCESS)
+    {
+        if (ErrSuccess == ERROR_SUCCESS)
+        {
+            ok(*(DWORD *)Buffer != 0xFFFFFFFF,
+               "Buffer should be filled at offset 0\n");
+        }
+        else
+        {
+            ok(*(DWORD *)Buffer == 0xFFFFFFFF,
+               "Buffer should be clean at offset 0\n");
+        }
+    }
+}
+
+START_TEST(SystemFirmware)
+{
+    static const ENTRY Entries[] =
+    {
+        { 'ACPI', ERROR_INSUFFICIENT_BUFFER, ERROR_SUCCESS },
+        { 'FIRM', ERROR_INSUFFICIENT_BUFFER, ERROR_SUCCESS },
+        { 'RSMB', ERROR_INSUFFICIENT_BUFFER, ERROR_SUCCESS },
+        /* This entry should be last */
+        { 0xDEAD, ERROR_INVALID_FUNCTION, ERROR_INVALID_FUNCTION },
+    };
+    HANDLE hKernel;
+    CHAR Buffer[262144]; // 256 KiB should be enough
+    CHAR Sign[sizeof(DWORD) + 1];
+    UINT TableCount[_countof(Entries)];
+    DWORD FirstTableID[_countof(Entries)];
+    int i;
+
+    hKernel = GetModuleHandleW(L"kernel32.dll");
+    if (!hKernel)
+    {
+        skip("kernel32.dll module not found. Can't proceed\n");
+        return;
+    }
+
+    pEnumSystemFirmwareTables = (void *)GetProcAddress(hKernel, "EnumSystemFirmwareTables");
+    pGetSystemFirmwareTable = (void *)GetProcAddress(hKernel, "GetSystemFirmwareTable");
+
+    if (!pEnumSystemFirmwareTables)
+    {
+        skip("EnumSystemFirmwareTables not found. Can't proceed\n");
+        return;
+    }
+    if (!pGetSystemFirmwareTable)
+    {
+        skip("GetSystemFirmwareTable not found. Can't proceed\n");
+        return;
+    }
+
+    // Test EnumSystemFirmwareTables
+    for (i = 0; i < _countof(Entries); i++)
+    {
+        // Test with NULL buffer
+        test_EnumBuffer(Entries[i].Signature, NULL, sizeof(Buffer), NULL, NULL,
+                        Entries[i].ErrInsuff, Entries[i].ErrSuccess);
+        // Test with wrong buffer
+        test_EnumBuffer(Entries[i].Signature, (PVOID *)0xbeeffeed, sizeof(Buffer), NULL, NULL,
+                        Entries[i].ErrInsuff, Entries[i].ErrSuccess);
+        // Test with correct buffer
+        test_EnumBuffer(Entries[i].Signature, &Buffer, sizeof(Buffer), &TableCount[i], &FirstTableID[i],
+                        Entries[i].ErrInsuff, Entries[i].ErrSuccess);
+    }
+
+    // Test GetSystemFirmwareTable
+    for (i = 0; i < _countof(Entries); i++)
+    {
+        // Test with fake ID and NULL buffer
+        test_GetBuffer(Entries[i].Signature, 0xbeeffeed, NULL, sizeof(Buffer),
+                       TRUE, Entries[i].ErrInsuff, Entries[i].ErrSuccess);
+        // Test with fake ID and wrong buffer
+        test_GetBuffer(Entries[i].Signature, 0xbeeffeed, (PVOID *)0xbeeffeed, sizeof(Buffer),
+                       TRUE, Entries[i].ErrInsuff, Entries[i].ErrSuccess);
+        // Test with fake ID and correct buffer
+        test_GetBuffer(Entries[i].Signature, 0xbeeffeed, &Buffer, sizeof(Buffer),
+                       TRUE, Entries[i].ErrInsuff, Entries[i].ErrSuccess);
+        if (TableCount[i] == 0)
+        {
+            if (i < _countof(Entries) - 1)
+            {
+                ZeroMemory(&Sign, sizeof(Sign));
+                *(DWORD *)&Sign = _byteswap_ulong(Entries[i].Signature);
+                skip("No tables for %s found. Skipping\n",
+                     Sign);
+            }
+            continue;
+        }
+        // Test with correct ID and NULL buffer
+        test_GetBuffer(Entries[i].Signature, FirstTableID[i], NULL, sizeof(Buffer),
+                       FALSE, Entries[i].ErrInsuff, Entries[i].ErrSuccess);
+        // Test with correct ID and wrong buffer
+        test_GetBuffer(Entries[i].Signature, FirstTableID[i], (PVOID *)0xbeeffeed, sizeof(Buffer),
+                       FALSE, Entries[i].ErrInsuff, Entries[i].ErrSuccess);
+        // Test with correct ID and correct buffer
+        test_GetBuffer(Entries[i].Signature, FirstTableID[i], &Buffer, sizeof(Buffer),
+                       FALSE, Entries[i].ErrInsuff, Entries[i].ErrSuccess);
+    }
+}
index 0bf5e42..6364cab 100644 (file)
@@ -27,6 +27,7 @@ extern void func_PrivMoveFileIdentityW(void);
 extern void func_SetConsoleWindowInfo(void);
 extern void func_SetCurrentDirectory(void);
 extern void func_SetUnhandledExceptionFilter(void);
+extern void func_SystemFirmware(void);
 extern void func_TerminateProcess(void);
 extern void func_TunnelCache(void);
 extern void func_WideCharToMultiByte(void);
@@ -57,6 +58,7 @@ const struct test winetest_testlist[] =
     { "SetConsoleWindowInfo",        func_SetConsoleWindowInfo },
     { "SetCurrentDirectory",         func_SetCurrentDirectory },
     { "SetUnhandledExceptionFilter", func_SetUnhandledExceptionFilter },
+    { "SystemFirmware",              func_SystemFirmware },
     { "TerminateProcess",            func_TerminateProcess },
     { "TunnelCache",                 func_TunnelCache },
     { "WideCharToMultiByte",         func_WideCharToMultiByte },