Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546/* * 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 * Copyright 2018 Mark Jansen */
#include "precomp.h"
#include <pseh/pseh2.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 UINTCallNt(IN DWORD FirmwareTableProviderSignature, IN DWORD FirmwareTableID, OUT PVOID pFirmwareTableBuffer, IN DWORD BufferSize, IN SYSTEM_FIRMWARE_TABLE_ACTION Action){ SYSTEM_FIRMWARE_TABLE_INFORMATION* SysFirmwareInfo; ULONG Result = 0, ReturnedSize; ULONG TotalSize = BufferSize + sizeof(SYSTEM_FIRMWARE_TABLE_INFORMATION); NTSTATUS Status;
SysFirmwareInfo = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, TotalSize); if (!SysFirmwareInfo) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } _SEH2_TRY { SysFirmwareInfo->ProviderSignature = FirmwareTableProviderSignature; SysFirmwareInfo->TableID = FirmwareTableID; SysFirmwareInfo->Action = Action; SysFirmwareInfo->TableBufferLength = BufferSize;
Status = NtQuerySystemInformation(SystemFirmwareTableInformation, SysFirmwareInfo, TotalSize, &ReturnedSize);
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL) Result = SysFirmwareInfo->TableBufferLength;
if (NT_SUCCESS(Status) && pFirmwareTableBuffer) { memcpy(pFirmwareTableBuffer, SysFirmwareInfo->TableBuffer, SysFirmwareInfo->TableBufferLength); } } _SEH2_FINALLY { RtlFreeHeap(RtlGetProcessHeap(), 0, SysFirmwareInfo); } _SEH2_END;
SetLastError(RtlNtStatusToDosError(Status)); return Result;}
UINTWINAPIfEnumSystemFirmwareTables(IN DWORD FirmwareTableProviderSignature, OUT PVOID pFirmwareTableBuffer, IN DWORD BufferSize){ return CallNt(FirmwareTableProviderSignature, 0, pFirmwareTableBuffer, BufferSize, SystemFirmwareTable_Enumerate);}
UINTWINAPIfGetSystemFirmwareTable(IN DWORD FirmwareTableProviderSignature, IN DWORD FirmwareTableID, OUT PVOID pFirmwareTableBuffer, IN DWORD BufferSize){ return CallNt(FirmwareTableProviderSignature, FirmwareTableID, pFirmwareTableBuffer, BufferSize, SystemFirmwareTable_Get);}
staticVOIDtest_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 || dwError == ERROR_INVALID_FUNCTION, "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 || dwError == ERROR_INVALID_FUNCTION, "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(dwError == ERROR_SUCCESS ? dwException : STATUS_SUCCESS); // Windows Vista+: 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 Vista+: returns ERROR_NOACCESS here ok(dwError == 0xbeeffeed || dwError == ERROR_NOACCESS, "GetLastError() returned %ld, expected %u\n", dwError, 0xbeeffeed); // Windows Vista+: returns correct size here ok(uResultSize == 0 || uResultSize == dwBufferSize, "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; }}
staticVOIDtest_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 = (GetNTVersion() >= 0xA00) ? ERROR_INVALID_FUNCTION : 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) || dwError == ERROR_INVALID_FUNCTION, "GetLastError() returned %ld, expected %ld\n", dwError, (TestFakeID ? dwErrCase : ErrInsuff)); if (ErrSuccess == ERROR_SUCCESS && (!TestFakeID || dwErrCase == ErrInsuff)) { ok(uResultSize > 0 || uResultSize == 0, // FIXME: This is broken "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) || dwError == ERROR_INVALID_FUNCTION, "GetLastError() returned %ld, expected %ld\n", dwError, (TestFakeID ? dwErrCase : ErrInsuff)); if (ErrSuccess == ERROR_SUCCESS && (!TestFakeID || dwErrCase == ErrInsuff)) { ok(uResultSize > 0 || uResultSize == 0, // FIXME: This is broken "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*/ ExceptionStatus); // Windows Vista+: 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 Vista+: returns ERROR_NOACCESS here ok(dwError == 0xbeeffeed || dwError == ERROR_NOACCESS, "GetLastError() returned %ld, expected %u\n", dwError, 0xbeeffeed); // Windows Vista+: returns correct size here ok(uResultSize == 0 || uResultSize == dwBufferSize, "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"); } }}
staticVOIDtest_Functions(){ 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 }, }; CHAR Buffer[262144]; // 256 KiB should be enough CHAR Sign[sizeof(DWORD) + 1]; UINT TableCount[_countof(Entries)]; DWORD FirstTableID[_countof(Entries)]; int i;
// 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 *)(LONG_PTR)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 *)(LONG_PTR)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 *)(LONG_PTR)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); }}
START_TEST(SystemFirmware){ HANDLE hKernel;
hKernel = GetModuleHandleW(L"kernel32.dll"); if (!hKernel) { skip("kernel32.dll module not found. Can't proceed\n"); return; }
pEnumSystemFirmwareTables = (void *)fEnumSystemFirmwareTables; pGetSystemFirmwareTable = (void *)fGetSystemFirmwareTable;
//test_Functions(); // FIXME: This test is broken!
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_Functions();}