Merge branch 'firmware' into 'master'

Implement NtQuerySystemEnvironmentValueEx, NtQuerySystemInformation SystemBootEnvironmentInformation, GetFirmwareType, GetFirmwareEnvironmentVariable*

See merge request wine/wine!6423
This commit is contained in:
Grigory Vasilyev 2024-11-19 10:23:20 +00:00
commit b480be235d
9 changed files with 783 additions and 9 deletions

View file

@ -695,7 +695,9 @@
@ stdcall -import GetFileType(long) @ stdcall -import GetFileType(long)
@ stdcall -import GetFinalPathNameByHandleA(long ptr long long) @ stdcall -import GetFinalPathNameByHandleA(long ptr long long)
@ stdcall -import GetFinalPathNameByHandleW(long ptr long long) @ stdcall -import GetFinalPathNameByHandleW(long ptr long long)
@ stdcall GetFirmwareEnvironmentVariableExA(str str ptr long ptr)
@ stdcall GetFirmwareEnvironmentVariableA(str str ptr long) @ stdcall GetFirmwareEnvironmentVariableA(str str ptr long)
@ stdcall GetFirmwareEnvironmentVariableExW(wstr wstr ptr long ptr)
@ stdcall GetFirmwareEnvironmentVariableW(wstr wstr ptr long) @ stdcall GetFirmwareEnvironmentVariableW(wstr wstr ptr long)
@ stdcall GetFirmwareType(ptr) @ stdcall GetFirmwareType(ptr)
@ stdcall -import GetFullPathNameA(str long ptr ptr) @ stdcall -import GetFullPathNameA(str long ptr ptr)

View file

@ -719,13 +719,43 @@ WORD WINAPI GetMaximumProcessorGroupCount(void)
} }
/*********************************************************************** /***********************************************************************
* GetFirmwareEnvironmentVariableA (KERNEL32.@) * GetFirmwareEnvironmentVariableExW (KERNEL32.@)
*/ */
DWORD WINAPI GetFirmwareEnvironmentVariableA(LPCSTR name, LPCSTR guid, PVOID buffer, DWORD size) DWORD WINAPI GetFirmwareEnvironmentVariableExW(LPCWSTR name, LPCWSTR guid, PVOID buffer, DWORD size, PDWORD attributes)
{ {
FIXME("stub: %s %s %p %lu\n", debugstr_a(name), debugstr_a(guid), buffer, size); GUID vendor = {0};
SetLastError(ERROR_INVALID_FUNCTION); NTSTATUS status;
return 0; UNICODE_STRING uname;
UNICODE_STRING uguid;
DWORD ret_size = size;
if(!name || !guid || !attributes)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
RtlInitUnicodeString(&uguid, guid);
if (!set_ntstatus(RtlGUIDFromString(&uguid, &vendor)))
return 0;
RtlInitUnicodeString(&uname, name);
status = NtQuerySystemEnvironmentValueEx(&uname, &vendor, buffer,
&ret_size, attributes);
if (status)
{
if(status == STATUS_VARIABLE_NOT_FOUND)
SetLastError(ERROR_ENVVAR_NOT_FOUND);
else if(status == STATUS_NOT_IMPLEMENTED)
SetLastError(ERROR_INVALID_FUNCTION);
else
SetLastError(RtlNtStatusToDosError(status));
ret_size = 0;
}
return ret_size;
} }
/*********************************************************************** /***********************************************************************
@ -733,9 +763,61 @@ DWORD WINAPI GetFirmwareEnvironmentVariableA(LPCSTR name, LPCSTR guid, PVOID buf
*/ */
DWORD WINAPI GetFirmwareEnvironmentVariableW(LPCWSTR name, LPCWSTR guid, PVOID buffer, DWORD size) DWORD WINAPI GetFirmwareEnvironmentVariableW(LPCWSTR name, LPCWSTR guid, PVOID buffer, DWORD size)
{ {
FIXME("stub: %s %s %p %lu\n", debugstr_w(name), debugstr_w(guid), buffer, size); DWORD attributes;
SetLastError(ERROR_INVALID_FUNCTION); return GetFirmwareEnvironmentVariableExW(name, guid, buffer, size, &attributes);
return 0; }
/***********************************************************************
* GetFirmwareEnvironmentVariableExA (KERNEL32.@)
*/
DWORD WINAPI GetFirmwareEnvironmentVariableExA(LPCSTR name, LPCSTR guid, PVOID buffer, DWORD size, PDWORD attributes)
{
int nsize;
LPWSTR wname;
LPWSTR wguid;
DWORD ret_size;
if(!name || !guid || !attributes)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
nsize = MultiByteToWideChar(CP_ACP, 0, guid, -1, NULL, 0);
if (!(wguid = HeapAlloc(GetProcessHeap(), 0, nsize * sizeof(wguid))))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
MultiByteToWideChar(CP_ACP, 0, guid, -1, wguid, nsize);
nsize = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
if (!(wname = HeapAlloc(GetProcessHeap(), 0, nsize * sizeof(wname))))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
MultiByteToWideChar(CP_ACP, 0, name, -1, wname, nsize);
ret_size = GetFirmwareEnvironmentVariableExW(wname, wguid, buffer, size, attributes);
HeapFree(GetProcessHeap(), 0, wname);
HeapFree(GetProcessHeap(), 0, wguid);
return ret_size;
}
/***********************************************************************
* GetFirmwareEnvironmentVariableA (KERNEL32.@)
*/
DWORD WINAPI GetFirmwareEnvironmentVariableA(LPCSTR name, LPCSTR guid, PVOID buffer, DWORD size)
{
DWORD attributes;
return GetFirmwareEnvironmentVariableExA(name, guid, buffer, size, &attributes);
} }
/*********************************************************************** /***********************************************************************
@ -763,10 +845,20 @@ BOOL WINAPI SetFirmwareEnvironmentVariableW(const WCHAR *name, const WCHAR *guid
*/ */
BOOL WINAPI GetFirmwareType(FIRMWARE_TYPE *type) BOOL WINAPI GetFirmwareType(FIRMWARE_TYPE *type)
{ {
SYSTEM_BOOT_ENVIRONMENT_INFORMATION boot_info = {0};
if (!type) if (!type)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if(!set_ntstatus(NtQuerySystemInformation(SystemBootEnvironmentInformation,
&boot_info, sizeof(boot_info), NULL)))
return FALSE; return FALSE;
*type = FirmwareTypeUnknown; *type = boot_info.FirmwareType;
return TRUE; return TRUE;
} }

View file

@ -16,6 +16,7 @@ SOURCES = \
environ.c \ environ.c \
fiber.c \ fiber.c \
file.c \ file.c \
firmware.c \
format_msg.c \ format_msg.c \
generated.c \ generated.c \
heap.c \ heap.c \

View file

@ -0,0 +1,350 @@
/* Unit test suite for *Information* Registry API functions
*
* Copyright 2024 Grigory Vasilyev
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winuser.h"
#include "winternl.h"
static void test_get_firmware_type(void)
{
FIRMWARE_TYPE ft;
BOOL status;
status = GetFirmwareType(&ft);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
skip("GetFirmwareType not implemented.\n");
return;
}
ok(status == TRUE, "Expected TRUE.\n");
ok(ft == FirmwareTypeBios || ft == FirmwareTypeUefi,
"Expected FirmwareTypeBios or FirmwareTypeUefi, got %08x\n", ft);
status = GetFirmwareType(NULL);
ok(status == FALSE && GetLastError() == ERROR_INVALID_PARAMETER,
"Expected FALSE and GetLastError() == ERROR_INVALID_PARAMETER\n");
}
static BOOL EnableTokenPrivilege(HANDLE hToken, const char *pszPrivilegesName, BOOL bEnabled)
{
LUID luid;
TOKEN_PRIVILEGES tp;
if (!LookupPrivilegeValueA(NULL, pszPrivilegesName, &luid))
{
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = bEnabled ? SE_PRIVILEGE_ENABLED : 0;
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
{
return FALSE;
}
return TRUE;
}
static void test_get_firmware_environment(void)
{
int status;
BOOLEAN secureboot;
DWORD attributes;
HANDLE hToken;
HANDLE hProcess;
BOOL privileged = FALSE;
hProcess = GetCurrentProcess();
if(hProcess && OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)
&& EnableTokenPrivilege(hToken, SE_SYSTEM_ENVIRONMENT_NAME, TRUE))
privileged = TRUE;
/*
* GetFirmwareEnvironmentVariableA
*/
status = GetFirmwareEnvironmentVariableA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, sizeof(BOOLEAN));
if(!privileged && !status && GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
{
skip("GetFirmwareEnvironmentVariable* demand privileges SE_SYSTEM_ENVIRONMENT_NAME.\n");
return;
}
if (!status && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
skip("GetFirmwareEnvironmentVariableA call NtQuerySystemEnvironmentValueEx"
"and NtQuerySystemEnvironmentValueEx not implemented.\n");
goto get_firmware_environment_variable_w;
}
if (!status && GetLastError() == ERROR_INVALID_FUNCTION)
{
skip("GetFirmwareEnvironmentVariableA call NtQuerySystemEnvironmentValueEx"
" and NtQuerySystemEnvironmentValueEx returned ERROR_INVALID_FUNCTION.\n"
"This behavior matches the behavior of Windows for non-UEFI boots and older versions of Windows.\n");
goto get_firmware_environment_variable_w;
}
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0 or GetLastError() == ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableA(NULL, NULL, &secureboot, sizeof(secureboot));
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableA(NULL, "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, sizeof(secureboot));
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableA("SecureBoot", NULL, &secureboot, sizeof(secureboot));
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}", NULL, 0);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, 0);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
NULL, sizeof(secureboot));
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0 or GetLastError() == ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableA("DummyName", "{00000000-0000-0000-0000-000000000000}",
&secureboot, sizeof(secureboot));
ok(GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
/*
* GetFirmwareEnvironmentVariableW
*/
get_firmware_environment_variable_w:
status = GetFirmwareEnvironmentVariableW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, sizeof(BOOLEAN));
if (!status && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
skip("GetFirmwareEnvironmentVariableW call NtQuerySystemEnvironmentValueEx"
"and NtQuerySystemEnvironmentValueEx not implemented.\n");
goto get_firmware_environment_variable_ex_a;
}
if (!status && GetLastError() == ERROR_INVALID_FUNCTION)
{
skip("GetFirmwareEnvironmentVariableW call NtQuerySystemEnvironmentValueEx"
" and NtQuerySystemEnvironmentValueEx returned ERROR_INVALID_FUNCTION.\n"
"This behavior matches the behavior of Windows for non-UEFI boots and older versions of Windows.\n");
goto get_firmware_environment_variable_ex_a;
}
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0, got error %ld\n", GetLastError());
status = GetFirmwareEnvironmentVariableW(NULL, NULL, &secureboot, sizeof(secureboot));
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableW(NULL, L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, sizeof(secureboot));
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableW(L"SecureBoot", NULL, &secureboot, sizeof(secureboot));
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
NULL, 0);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, 0);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
NULL, sizeof(secureboot));
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0 or GetLastError() == ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableW(L"DummyName", L"{00000000-0000-0000-0000-000000000000}",
&secureboot, sizeof(secureboot));
ok(GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
/*
* GetFirmwareEnvironmentVariableExA
*/
get_firmware_environment_variable_ex_a:
status = GetFirmwareEnvironmentVariableExA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, sizeof(BOOLEAN), &attributes);
if (!status && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
skip("GetFirmwareEnvironmentVariableExA call NtQuerySystemEnvironmentValueEx"
"and NtQuerySystemEnvironmentValueEx not implemented.\n");
goto get_firmware_environment_variable_ex_w;
}
if (!status && GetLastError() == ERROR_INVALID_FUNCTION)
{
skip("GetFirmwareEnvironmentVariableExA call NtQuerySystemEnvironmentValueEx"
" and NtQuerySystemEnvironmentValueEx returned ERROR_INVALID_FUNCTION.\n"
"This behavior matches the behavior of Windows for non-UEFI boots and older versions of Windows.\n");
goto get_firmware_environment_variable_ex_w;
}
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0, got error %ld\n", GetLastError());
status = GetFirmwareEnvironmentVariableExA(NULL, NULL, &secureboot, sizeof(secureboot), &attributes);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExA(NULL, "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, sizeof(secureboot), &attributes);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExA("SecureBoot", NULL, &secureboot,
sizeof(secureboot), &attributes);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
NULL, 0, NULL);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, 0, NULL);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, 0, &attributes);
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0 or GetLastError() == ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
NULL, sizeof(secureboot), NULL);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExA("SecureBoot", "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
NULL, sizeof(secureboot), &attributes);
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0 or GetLastError() == ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExA("DummyName", "{00000000-0000-0000-0000-000000000000}",
&secureboot, sizeof(secureboot), &attributes);
ok(GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
/*
* GetFirmwareEnvironmentVariableExW
*/
get_firmware_environment_variable_ex_w:
status = GetFirmwareEnvironmentVariableExW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, sizeof(BOOLEAN), &attributes);
if (!status && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{
skip("GetFirmwareEnvironmentVariableExW call NtQuerySystemEnvironmentValueEx"
"and NtQuerySystemEnvironmentValueEx not implemented.\n");
return;
}
if (!status && GetLastError() == ERROR_INVALID_FUNCTION)
{
skip("GetFirmwareEnvironmentVariableExW call NtQuerySystemEnvironmentValueEx"
" and NtQuerySystemEnvironmentValueEx returned ERROR_INVALID_FUNCTION.\n"
"This behavior matches the behavior of Windows for non-UEFI boots and older versions of Windows.\n");
return;
}
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0, got error %ld\n", GetLastError());
status = GetFirmwareEnvironmentVariableExW(NULL, NULL, &secureboot, sizeof(secureboot), &attributes);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExW(NULL, L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, sizeof(secureboot), &attributes);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExW(L"SecureBoot", NULL, &secureboot, sizeof(secureboot), &attributes);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
NULL, 0, NULL);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, 0, NULL);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
&secureboot, 0, &attributes);
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0 or GetLastError() == ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
NULL, sizeof(secureboot), NULL);
ok(GetLastError() == ERROR_INVALID_PARAMETER,
"Expected ERROR_INVALID_PARAMETER, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExW(L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
NULL, sizeof(secureboot), &attributes);
ok(status > 0 || GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected status > 0 or GetLastError() == ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
status = GetFirmwareEnvironmentVariableExW(L"DummyName", L"{00000000-0000-0000-0000-000000000000}",
&secureboot, sizeof(secureboot), &attributes);
ok(GetLastError() == ERROR_ENVVAR_NOT_FOUND,
"Expected ERROR_ENVVAR_NOT_FOUND, got error %ld.\n", GetLastError());
}
START_TEST(firmware)
{
test_get_firmware_type();
test_get_firmware_environment();
}

View file

@ -34,6 +34,7 @@
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI * pNtSetSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG); static NTSTATUS (WINAPI * pNtSetSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG);
static NTSTATUS (WINAPI * pRtlGetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pRtlGetNativeSystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI * pNtQuerySystemEnvironmentValueEx)(PUNICODE_STRING, LPGUID, PVOID, PULONG, PULONG);
static NTSTATUS (WINAPI * pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*); static NTSTATUS (WINAPI * pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*);
static NTSTATUS (WINAPI * pNtPowerInformation)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG); static NTSTATUS (WINAPI * pNtPowerInformation)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
static NTSTATUS (WINAPI * pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG); static NTSTATUS (WINAPI * pNtQueryInformationThread)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG);
@ -91,6 +92,7 @@ static void InitFunctionPtrs(void)
NTDLL_GET_PROC(NtQuerySystemInformation); NTDLL_GET_PROC(NtQuerySystemInformation);
NTDLL_GET_PROC(NtQuerySystemInformationEx); NTDLL_GET_PROC(NtQuerySystemInformationEx);
NTDLL_GET_PROC(NtQuerySystemEnvironmentValueEx);
NTDLL_GET_PROC(NtSetSystemInformation); NTDLL_GET_PROC(NtSetSystemInformation);
NTDLL_GET_PROC(RtlGetNativeSystemInformation); NTDLL_GET_PROC(RtlGetNativeSystemInformation);
NTDLL_GET_PROC(NtPowerInformation); NTDLL_GET_PROC(NtPowerInformation);
@ -322,6 +324,83 @@ static void test_query_basic(void)
} }
} }
static void test_query_boot_and_system_env(void)
{
NTSTATUS status;
ULONG ret_size;
BOOLEAN secureboot;
DWORD attributes;
UNICODE_STRING secureboot_name;
GUID secureboot_guid = {0x8be4df61, 0x93ca, 0x11d2, {0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c}};
SYSTEM_BOOT_ENVIRONMENT_INFORMATION bi = {0};
/*
* NtQuerySystemInformation - SystemBootEnvironmentInformation
*/
status = pNtQuerySystemInformation(SystemBootEnvironmentInformation, &bi, sizeof(bi), &ret_size);
if (status == STATUS_NOT_IMPLEMENTED)
{
skip("NtQuerySystemInformation - SystemBootEnvironmentInformation not implemented.\n");
return;
}
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS.\n");
ok(ret_size == sizeof(bi), "Expected ret_size == sizeof(SYSTEM_BOOT_ENVIRONMENT_INFORMATION).\n");
ok(bi.FirmwareType == FirmwareTypeBios || bi.FirmwareType == FirmwareTypeUefi,
"Expected FirmwareTypeBios or FirmwareTypeUefi, got %02x\n", bi.FirmwareType);
ok(bi.BootIdentifier.Data1 != 0, "A non-zero BootIdentifier value is expected.\n");
status = pNtQuerySystemInformation(SystemBootEnvironmentInformation, NULL, sizeof(bi), NULL);
ok(status == STATUS_ACCESS_VIOLATION, "Expected STATUS_ACCESS_VIOLATION.\n");
status = pNtQuerySystemInformation(SystemBootEnvironmentInformation, NULL, 0, NULL);
ok(status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH.\n");
/*
* NtQuerySystemEnvironmentValueEx
*/
RtlInitUnicodeString(&secureboot_name, L"SecureBoot");
ret_size = sizeof(secureboot);
status = pNtQuerySystemEnvironmentValueEx(&secureboot_name, &secureboot_guid, &secureboot, &ret_size, &attributes);
if(bi.FirmwareType != FirmwareTypeUefi)
ok(status == STATUS_NOT_IMPLEMENTED, "Expected STATUS_NOT_IMPLEMENTED on non-UEFI boots.\n");
if (status == STATUS_NOT_IMPLEMENTED)
{
skip("NtQuerySystemEnvironmentValueEx not implemented.\n");
return;
}
ok(status == STATUS_SUCCESS || status == STATUS_VARIABLE_NOT_FOUND, "Expected STATUS_SUCCESS or STATUS_VARIABLE_NOT_FOUND.\n");
status = pNtQuerySystemEnvironmentValueEx(NULL, NULL, &secureboot, &ret_size, &attributes);
ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER.\n");
status = pNtQuerySystemEnvironmentValueEx(NULL, &secureboot_guid, &secureboot, &ret_size, &attributes);
ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER.\n");
status = pNtQuerySystemEnvironmentValueEx(&secureboot_name, NULL, &secureboot, &ret_size, &attributes);
ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER.\n");
status = pNtQuerySystemEnvironmentValueEx(&secureboot_name, &secureboot_guid, NULL, NULL, NULL);
ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER.\n");
status = pNtQuerySystemEnvironmentValueEx(&secureboot_name, &secureboot_guid, &secureboot, NULL, NULL);
ok(status == STATUS_INVALID_PARAMETER, "Expected STATUS_INVALID_PARAMETER.\n");
status = pNtQuerySystemEnvironmentValueEx(&secureboot_name, &secureboot_guid, &secureboot, NULL, &attributes);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS.\n");
status = pNtQuerySystemEnvironmentValueEx(&secureboot_name, &secureboot_guid, NULL, &ret_size, NULL);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS.\n");
status = pNtQuerySystemEnvironmentValueEx(&secureboot_name, &secureboot_guid, NULL, &ret_size, &attributes);
ok(status == STATUS_SUCCESS, "Expected STATUS_SUCCESS.\n");
}
static void test_query_cpu(void) static void test_query_cpu(void)
{ {
NTSTATUS status; NTSTATUS status;
@ -4103,6 +4182,7 @@ START_TEST(info)
/* NtQuerySystemInformation */ /* NtQuerySystemInformation */
test_query_basic(); test_query_basic();
test_query_boot_and_system_env();
test_query_cpu(); test_query_cpu();
test_query_performance(); test_query_performance();
test_query_timeofday(); test_query_timeofday();

View file

@ -30,6 +30,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -2950,6 +2951,101 @@ NTSTATUS WINAPI NtQuerySystemInformation( SYSTEM_INFORMATION_CLASS class,
break; break;
} }
case SystemBootEnvironmentInformation: /* 90 */
{
static SYSTEM_BOOT_ENVIRONMENT_INFORMATION boot_info = {0};
struct stat stat_info = {0};
ssize_t ssz;
#if defined(__linux__) || defined(__gnu_linux__)
int fd;
char buffer[32];
#endif
len = sizeof(boot_info);
if (size == len)
{
#if defined(__linux__) || defined(__gnu_linux__)
if (boot_info.FirmwareType == FirmwareTypeUnknown)
{
if (!stat("/sys/firmware/efi", &stat_info))
boot_info.FirmwareType = FirmwareTypeUefi;
else
boot_info.FirmwareType = FirmwareTypeBios;
}
#elif defined(__APPLE__)
/*
* Since 2006, Mac computers use Extensible Firmware Interface (EFI).
* Reference: https://support.apple.com/guide/security/uefi-firmware-security-in-an-intel-based-mac-seced055bcf6/web
*/
boot_info.FirmwareType = FirmwareTypeUefi;
#else
boot_info.FirmwareType = FirmwareTypeBios;
#endif
if (boot_info.BootIdentifier.Data1 == 0)
{
#if defined(__linux__) || defined(__gnu_linux__)
if (!stat("/etc/machine-id", &stat_info) && stat_info.st_size >= 32)
{
fd = open("/etc/machine-id", O_RDONLY);
if (fd == -1)
goto try_read_hostid;
ssz = read(fd, &buffer, 32);
if (ssz < 0)
{
close(fd);
goto try_read_hostid;
}
close(fd);
if (sscanf(buffer,
"%08X%04hX%04hX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX",
(unsigned int *)&boot_info.BootIdentifier.Data1, &boot_info.BootIdentifier.Data2,
&boot_info.BootIdentifier.Data3, &boot_info.BootIdentifier.Data4[0],
&boot_info.BootIdentifier.Data4[1], &boot_info.BootIdentifier.Data4[2],
&boot_info.BootIdentifier.Data4[3], &boot_info.BootIdentifier.Data4[4],
&boot_info.BootIdentifier.Data4[5], &boot_info.BootIdentifier.Data4[6],
&boot_info.BootIdentifier.Data4[7]) != 11)
goto try_read_hostid;
}
else
{
try_read_hostid:
#endif
#ifdef __APPLE__
if (!stat("/Users", &stat_info) || !stat("/System", &stat_info))
#else
if (!stat("/home", &stat_info) || !stat("/usr", &stat_info))
#endif
{
boot_info.BootIdentifier.Data1 = gethostid() & 0xFFFFFFFF;
boot_info.BootIdentifier.Data2 = stat_info.st_dev & 0xFFFF;
boot_info.BootIdentifier.Data3 = stat_info.st_ino & 0xFFFF;
boot_info.BootIdentifier.Data4[0] = 'W' ^ (boot_info.BootIdentifier.Data1 & 0xFF);
boot_info.BootIdentifier.Data4[1] = 'I' ^ ((boot_info.BootIdentifier.Data1 >> 4) & 0xFF);
boot_info.BootIdentifier.Data4[2] = 'N' ^ ((boot_info.BootIdentifier.Data1 >> 8) & 0xFF);
boot_info.BootIdentifier.Data4[3] = 'E' ^ ((boot_info.BootIdentifier.Data1 >> 12) & 0xFF);
boot_info.BootIdentifier.Data4[4] = 'B' ^ ((boot_info.BootIdentifier.Data1 >> 16) & 0xFF);
boot_info.BootIdentifier.Data4[5] = 'O' ^ ((boot_info.BootIdentifier.Data1 >> 20) & 0xFF);
boot_info.BootIdentifier.Data4[6] = 'O' ^ ((boot_info.BootIdentifier.Data1 >> 24) & 0xFF);
boot_info.BootIdentifier.Data4[7] = 'T' ^ ((boot_info.BootIdentifier.Data1 >> 28) & 0xFF);
}
#if defined(__linux__) || defined(__gnu_linux__)
}
#endif
boot_info.BootIdentifier.Data3 &= 0x0fff;
boot_info.BootIdentifier.Data3 |= (4 << 12);
/* Set the topmost bits of Data4 (clock_seq_hi_and_reserved) as
* specified in RFC 4122, section 4.4.
*/
boot_info.BootIdentifier.Data4[0] &= 0x3f;
boot_info.BootIdentifier.Data4[0] |= 0x80;
}
if (!info) ret = STATUS_ACCESS_VIOLATION;
else memcpy(info, &boot_info, len);
}
else ret = STATUS_INFO_LENGTH_MISMATCH;
if (ret_size) *ret_size = len;
break;
}
case SystemCpuInformation: /* 1 */ case SystemCpuInformation: /* 1 */
if (size >= (len = sizeof(cpu_info))) memcpy(info, &cpu_info, len); if (size >= (len = sizeof(cpu_info))) memcpy(info, &cpu_info, len);
else ret = STATUS_INFO_LENGTH_MISMATCH; else ret = STATUS_INFO_LENGTH_MISMATCH;
@ -3842,9 +3938,133 @@ NTSTATUS WINAPI NtQuerySystemEnvironmentValue( UNICODE_STRING *name, WCHAR *buff
NTSTATUS WINAPI NtQuerySystemEnvironmentValueEx( UNICODE_STRING *name, GUID *vendor, void *buffer, NTSTATUS WINAPI NtQuerySystemEnvironmentValueEx( UNICODE_STRING *name, GUID *vendor, void *buffer,
ULONG *retlen, ULONG *attrib ) ULONG *retlen, ULONG *attrib )
{ {
#if defined(__linux__) || defined(__gnu_linux__)
int fd, rc;
size_t bytes, pos = 0;
ssize_t ssz;
char buff[4];
char *cname;
char filename[PATH_MAX + 1];
NTSTATUS status;
struct stat stat_info = {0};
static SYSTEM_BOOT_ENVIRONMENT_INFORMATION boot_info = {0};
if(boot_info.FirmwareType == FirmwareTypeUnknown)
{
status = NtQuerySystemInformation(SystemBootEnvironmentInformation,
&boot_info, sizeof(boot_info), NULL);
if(status != STATUS_SUCCESS) return status;
}
if(boot_info.FirmwareType != FirmwareTypeUefi)
{
/*
* This behavior matches the behavior of Windows for non-UEFI boots,
* and older versions of Windows.
*/
return STATUS_NOT_IMPLEMENTED;
}
if(!name || !vendor || (name && vendor && !retlen && !attrib))
{
return STATUS_INVALID_PARAMETER;
}
cname = (char *) malloc(wcslen(name->Buffer) * 3 + 1);
if(!cname)
return STATUS_MEMORY_NOT_ALLOCATED;
rc = ntdll_wcstoumbs(name->Buffer, wcslen(name->Buffer) + 1, cname, wcslen(name->Buffer) * 3 + 1, TRUE);
if(rc <= 0) {
free(cname);
return STATUS_SOME_NOT_MAPPED;
}
snprintf(filename, sizeof(filename),
"/sys/firmware/efi/efivars/%s-%08lx-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
cname, (unsigned long)vendor->Data1, vendor->Data2, vendor->Data3,
vendor->Data4[0], vendor->Data4[1], vendor->Data4[2], vendor->Data4[3],
vendor->Data4[4], vendor->Data4[5], vendor->Data4[6], vendor->Data4[7]);
fd = open(filename, O_RDONLY);
if (fd == -1)
{
free(cname);
return STATUS_VARIABLE_NOT_FOUND;
}
rc = fstat(fd, &stat_info);
if (rc < 0 || stat_info.st_size == 0)
goto done;
if(attrib) ssz = read(fd, attrib, 4);
else ssz = read(fd, buff, 4); // lseek not work in efifs.
if (ssz < 0) goto done;
if(buffer && retlen)
{
if (stat_info.st_size - 4 < *retlen)
bytes = stat_info.st_size - 4;
else
bytes = *retlen;
while (pos < bytes)
{
ssz = read(fd, (char *) buffer + pos, bytes - pos);
if (ssz < 0) goto done;
pos += ssz;
}
*retlen = ssz & 0xFFFFFFFF;
}
else if(retlen) *retlen = (stat_info.st_size - 4) & 0xFFFFFFFF;
close(fd);
return STATUS_SUCCESS;
done:
free(cname);
if (fd >= 0)
close(fd);
return STATUS_UNSUCCESSFUL;
#elif defined(__APPLE__)
int rc;
char *cname;
GUID secureboot_guid = {0x8be4df61, 0x93ca, 0x11d2, {0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c}};
if(!name || !vendor || (name && vendor && !retlen && !attrib))
{
return STATUS_INVALID_PARAMETER;
}
cname = (char *) malloc(wcslen(name->Buffer) * 3 + 1);
if(!cname)
return STATUS_MEMORY_NOT_ALLOCATED;
rc = ntdll_wcstoumbs(name->Buffer, wcslen(name->Buffer) + 1, cname, wcslen(name->Buffer) * 3 + 1, TRUE);
if(rc <= 0) {
free(cname);
return STATUS_SOME_NOT_MAPPED;
}
/*
* Since 2006, Mac computers use Extensible Firmware Interface (EFI).
* Apple requires a developer account and mandatory code signing,
* and the entire system boot process is verified, we can return SecureBoot enabled.
* Reference: https://support.apple.com/guide/security/uefi-firmware-security-in-an-intel-based-mac-seced055bcf6/web
*/
if(!memcmp(vendor, &secureboot_guid, sizeof(secureboot_guid)) && !strcmp(cname, "SecureBoot"))
{
if(attrib) *attrib = 0x06;
if(buffer && retlen && *retlen == sizeof(BOOLEAN)) *((BOOLEAN *)buffer) = 1;
else if(retlen) *retlen = sizeof(BOOLEAN) & 0xFFFFFFFF;
free(cname);
return STATUS_SUCCESS;
}
free(cname);
return STATUS_VARIABLE_NOT_FOUND;
#else
FIXME( "(%s, %s, %p, %p, %p), stub\n", debugstr_us(name), FIXME( "(%s, %s, %p, %p, %p), stub\n", debugstr_us(name),
debugstr_guid(vendor), buffer, retlen, attrib ); debugstr_guid(vendor), buffer, retlen, attrib );
return STATUS_NOT_IMPLEMENTED; return STATUS_NOT_IMPLEMENTED;
#endif
} }

View file

@ -356,6 +356,9 @@ NTSTATUS WINAPI wow64_NtQuerySystemInformation( UINT *args )
if (retlen) *retlen = sizeof(SYSTEM_BASIC_INFORMATION32); if (retlen) *retlen = sizeof(SYSTEM_BASIC_INFORMATION32);
return status; return status;
case SystemBootEnvironmentInformation: /* SYSTEM_BOOT_ENVIRONMENT_INFORMATION */
return NtQuerySystemInformation(class, ptr, len, retlen);
case SystemProcessInformation: /* SYSTEM_PROCESS_INFORMATION */ case SystemProcessInformation: /* SYSTEM_PROCESS_INFORMATION */
case SystemExtendedProcessInformation: /* SYSTEM_PROCESS_INFORMATION */ case SystemExtendedProcessInformation: /* SYSTEM_PROCESS_INFORMATION */
{ {

View file

@ -2219,6 +2219,10 @@ WINBASEAPI DWORD WINAPI GetFileSize(HANDLE,LPDWORD);
WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE,PLARGE_INTEGER); WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE,PLARGE_INTEGER);
WINBASEAPI BOOL WINAPI GetFileTime(HANDLE,LPFILETIME,LPFILETIME,LPFILETIME); WINBASEAPI BOOL WINAPI GetFileTime(HANDLE,LPFILETIME,LPFILETIME,LPFILETIME);
WINBASEAPI DWORD WINAPI GetFileType(HANDLE); WINBASEAPI DWORD WINAPI GetFileType(HANDLE);
WINBASEAPI DWORD WINAPI GetFirmwareEnvironmentVariableA(LPCSTR,LPCSTR,PVOID,DWORD);
WINBASEAPI DWORD WINAPI GetFirmwareEnvironmentVariableExA(LPCSTR,LPCSTR,PVOID,DWORD,PDWORD);
WINBASEAPI DWORD WINAPI GetFirmwareEnvironmentVariableW(LPCWSTR,LPCWSTR,PVOID,DWORD);
WINBASEAPI DWORD WINAPI GetFirmwareEnvironmentVariableExW(LPCWSTR,LPCWSTR,PVOID,DWORD,PDWORD);
WINBASEAPI BOOL WINAPI GetFirmwareType(PFIRMWARE_TYPE); WINBASEAPI BOOL WINAPI GetFirmwareType(PFIRMWARE_TYPE);
#define GetFreeSpace(w) (__MSABI_LONG(0x100000)) #define GetFreeSpace(w) (__MSABI_LONG(0x100000))
WINBASEAPI DWORD WINAPI GetFullPathNameA(LPCSTR,DWORD,LPSTR,LPSTR*); WINBASEAPI DWORD WINAPI GetFullPathNameA(LPCSTR,DWORD,LPSTR,LPSTR*);

View file

@ -2739,6 +2739,28 @@ typedef struct _SYSTEM_BASIC_INFORMATION {
#endif #endif
} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
/* System Information Class 0x90 */
typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
{
GUID BootIdentifier;
FIRMWARE_TYPE FirmwareType;
union
{
ULONGLONG BootFlags;
struct
{
ULONGLONG DbgMenuOsSelection : 1;
ULONGLONG DbgHiberBoot : 1;
ULONGLONG DbgSoftBoot : 1;
ULONGLONG DbgMeasuredLaunch : 1;
ULONGLONG DbgMeasuredLaunchCapable : 1;
ULONGLONG DbgSystemHiveReplace : 1;
ULONGLONG DbgMeasuredLaunchSmmProtections : 1;
ULONGLONG DbgMeasuredLaunchSmmLevel : 7;
};
};
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION, *PSYSTEM_BOOT_ENVIRONMENT_INFORMATION;
/* System Information Class 0x01 */ /* System Information Class 0x01 */
typedef struct _SYSTEM_CPU_INFORMATION { typedef struct _SYSTEM_CPU_INFORMATION {