https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4c8a2a8815c5ac1e92d0c8cf3c2893a05b567dc9

commit 4c8a2a8815c5ac1e92d0c8cf3c2893a05b567dc9
Author:     Ratin Gao <[email protected]>
AuthorDate: Fri Sep 15 03:14:07 2023 +0800
Commit:     GitHub <[email protected]>
CommitDate: Thu Sep 14 22:14:07 2023 +0300

    [KERNEL32][KERNEL32_APITEST] Implement user-mode UEFI / Firmware API (#5149)
    
    - Implement firmware environment variable read/write APIs
    - Add, fix and improve related definitions and declarations
    - Add kernel32:UEFIFirmware apitest
    
    CORE-11954
---
 dll/win32/kernel32/client/sysinfo.c               | 299 ++++++++++++++++++----
 modules/rostests/apitests/kernel32/CMakeLists.txt |   1 +
 modules/rostests/apitests/kernel32/UEFIFirmware.c | 253 ++++++++++++++++++
 modules/rostests/apitests/kernel32/testlist.c     |   2 +
 ntoskrnl/ex/sysinfo.c                             |  22 +-
 sdk/include/ndk/exfuncs.h                         |  10 +-
 sdk/include/ndk/extypes.h                         |  35 ++-
 sdk/include/psdk/winbase.h                        |  78 ++++--
 sdk/include/xdk/extypes.h                         |  11 +
 sdk/include/xdk/winnt.template.h                  |   1 +
 10 files changed, 614 insertions(+), 98 deletions(-)

diff --git a/dll/win32/kernel32/client/sysinfo.c 
b/dll/win32/kernel32/client/sysinfo.c
index 3b25a19a1e4..7dbb320c118 100644
--- a/dll/win32/kernel32/client/sysinfo.c
+++ b/dll/win32/kernel32/client/sysinfo.c
@@ -1,14 +1,14 @@
 /*
  * PROJECT:         ReactOS Win32 Base API
- * LICENSE:         See COPYING in the top level directory
- * FILE:            dll/win32/kernel32/client/sysinfo.c
+ * LICENSE:         GPL-2.0-or-later 
(https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:         System Information Functions
- * PROGRAMMERS:     Emanuele Aliberti
+ * COPYRIGHT:       Emanuele Aliberti
  *                  Christoph von Wittich
  *                  Thomas Weidenmueller
  *                  Gunnar Andre Dalsnes
  *                  Stanislav Motylkov ([email protected])
  *                  Mark Jansen ([email protected])
+ *                  Copyright 2023 Ratin Gao <[email protected]>
  */
 
 /* INCLUDES 
*******************************************************************/
@@ -78,11 +78,12 @@ GetSystemInfoInternal(IN PSYSTEM_BASIC_INFORMATION 
BasicInfo,
 
 static
 UINT
-BaseQuerySystemFirmware(IN DWORD FirmwareTableProviderSignature,
-                        IN DWORD FirmwareTableID,
-                        OUT PVOID pFirmwareTableBuffer,
-                        IN DWORD BufferSize,
-                        IN SYSTEM_FIRMWARE_TABLE_ACTION Action)
+BaseQuerySystemFirmware(
+    _In_ DWORD FirmwareTableProviderSignature,
+    _In_ DWORD FirmwareTableID,
+    _Out_writes_bytes_to_opt_(BufferSize, return) PVOID pFirmwareTableBuffer,
+    _In_ DWORD BufferSize,
+    _In_ SYSTEM_FIRMWARE_TABLE_ACTION Action)
 {
     SYSTEM_FIRMWARE_TABLE_INFORMATION* SysFirmwareInfo;
     ULONG Result = 0, ReturnedSize;
@@ -413,60 +414,246 @@ GetNumaAvailableMemoryNode(IN UCHAR Node,
     return TRUE;
 }
 
-/*
- * @unimplemented
- */
+_Success_(return > 0)
 DWORD
 WINAPI
-GetFirmwareEnvironmentVariableW(IN LPCWSTR lpName,
-                                IN LPCWSTR lpGuid,
-                                IN PVOID pValue,
-                                IN DWORD nSize)
+GetFirmwareEnvironmentVariableExW(
+    _In_ LPCWSTR lpName,
+    _In_ LPCWSTR lpGuid,
+    _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer,
+    _In_ DWORD nSize,
+    _Out_opt_ PDWORD pdwAttribubutes)
 {
-    STUB;
-    return 0;
+    NTSTATUS Status;
+    UNICODE_STRING VariableName, Namespace;
+    GUID VendorGuid;
+    ULONG Length;
+
+    /* Check input parameters and build NT strings */
+    if (!lpName || !lpGuid)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+    RtlInitUnicodeString(&VariableName, lpName);
+    RtlInitUnicodeString(&Namespace, lpGuid);
+    Status = RtlGUIDFromString(&Namespace, &VendorGuid);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return 0;
+    }
+
+    /* Query firmware system environment variable value */
+    Length = nSize;
+    Status = NtQuerySystemEnvironmentValueEx(&VariableName,
+                                             &VendorGuid,
+                                             pBuffer,
+                                             &Length,
+                                             pdwAttribubutes);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return 0;
+    }
+
+    return Length;
 }
 
-/*
- * @unimplemented
- */
-BOOL
+_Success_(return > 0)
+DWORD
 WINAPI
-SetFirmwareEnvironmentVariableW(IN LPCWSTR lpName,
-                                IN LPCWSTR lpGuid,
-                                IN PVOID pValue,
-                                IN DWORD nSize)
+GetFirmwareEnvironmentVariableExA(
+    _In_ LPCSTR lpName,
+    _In_ LPCSTR lpGuid,
+    _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer,
+    _In_ DWORD nSize,
+    _Out_opt_ PDWORD pdwAttribubutes)
 {
-    STUB;
-    return 0;
+    NTSTATUS Status;
+    DWORD Length;
+    UNICODE_STRING VariableName, Namespace;
+    ANSI_STRING AnsiVariableName, AnsiNamespace;
+
+    /* Check input parameters and build NT strings */
+    if (!lpName || !lpGuid)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
+    RtlInitString(&AnsiVariableName, lpName);
+    Status = RtlAnsiStringToUnicodeString(&VariableName, &AnsiVariableName, 
TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return 0;
+    }
+    RtlInitString(&AnsiNamespace, lpGuid);
+    Status = RtlAnsiStringToUnicodeString(&Namespace, &AnsiNamespace, TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        RtlFreeUnicodeString(&VariableName);
+        BaseSetLastNTError(Status);
+        return 0;
+    }
+
+    /* Call unicode version interface */
+    Length = GetFirmwareEnvironmentVariableExW(VariableName.Buffer,
+                                               Namespace.Buffer,
+                                               pBuffer,
+                                               nSize,
+                                               pdwAttribubutes);
+
+    /* Cleanup and return */
+    RtlFreeUnicodeString(&Namespace);
+    RtlFreeUnicodeString(&VariableName);
+    return Length;
 }
 
-/*
- * @unimplemented
- */
+_Success_(return > 0)
 DWORD
 WINAPI
-GetFirmwareEnvironmentVariableA(IN LPCSTR lpName,
-                                IN LPCSTR lpGuid,
-                                IN PVOID pValue,
-                                IN DWORD nSize)
+GetFirmwareEnvironmentVariableW(
+    _In_ LPCWSTR lpName,
+    _In_ LPCWSTR lpGuid,
+    _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer,
+    _In_ DWORD nSize)
 {
-    STUB;
-    return 0;
+    return GetFirmwareEnvironmentVariableExW(lpName, lpGuid, pBuffer, nSize, 
NULL);
+}
+
+_Success_(return > 0)
+DWORD
+WINAPI
+GetFirmwareEnvironmentVariableA(
+    _In_ LPCSTR lpName,
+    _In_ LPCSTR lpGuid,
+    _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer,
+    _In_ DWORD nSize)
+{
+    return GetFirmwareEnvironmentVariableExA(lpName, lpGuid, pBuffer, nSize, 
NULL);
 }
 
-/*
- * @unimplemented
- */
 BOOL
 WINAPI
-SetFirmwareEnvironmentVariableA(IN LPCSTR lpName,
-                                IN LPCSTR lpGuid,
-                                IN PVOID pValue,
-                                IN DWORD nSize)
+SetFirmwareEnvironmentVariableExW(
+    _In_ LPCWSTR lpName,
+    _In_ LPCWSTR lpGuid,
+    _In_reads_bytes_opt_(nSize) PVOID pValue,
+    _In_ DWORD nSize,
+    _In_ DWORD dwAttributes)
 {
-    STUB;
-    return 0;
+    NTSTATUS Status;
+    UNICODE_STRING VariableName, Namespace;
+    GUID VendorGuid;
+
+    /* Check input parameters and build NT strings */
+    if (!lpName || !lpGuid)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    RtlInitUnicodeString(&VariableName, lpName);
+    RtlInitUnicodeString(&Namespace, lpGuid);
+    Status = RtlGUIDFromString(&Namespace, &VendorGuid);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    /* Set firmware system environment variable value */
+    Status = NtSetSystemEnvironmentValueEx(&VariableName,
+                                           &VendorGuid,
+                                           pValue,
+                                           nSize,
+                                           dwAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+BOOL
+WINAPI
+SetFirmwareEnvironmentVariableExA(
+    _In_ LPCSTR lpName,
+    _In_ LPCSTR lpGuid,
+    _In_reads_bytes_opt_(nSize) PVOID pValue,
+    _In_ DWORD nSize,
+    _In_ DWORD dwAttributes)
+{
+    NTSTATUS Status;
+    BOOL Result;
+    UNICODE_STRING VariableName, Namespace;
+    ANSI_STRING AnsiVariableName, AnsiNamespace;
+
+    /* Check input parameters and build NT strings */
+    if (!lpName || !lpGuid)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    RtlInitString(&AnsiVariableName, lpName);
+    Status = RtlAnsiStringToUnicodeString(&VariableName, &AnsiVariableName, 
TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+    RtlInitString(&AnsiNamespace, lpGuid);
+    Status = RtlAnsiStringToUnicodeString(&Namespace, &AnsiNamespace, TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        RtlFreeUnicodeString(&VariableName);
+        BaseSetLastNTError(Status);
+        return FALSE;
+    }
+
+    /* Call unicode version interface */
+    Result = SetFirmwareEnvironmentVariableExW(VariableName.Buffer,
+                                               Namespace.Buffer,
+                                               pValue,
+                                               nSize,
+                                               dwAttributes);
+
+    /* Cleanup and return */
+    RtlFreeUnicodeString(&Namespace);
+    RtlFreeUnicodeString(&VariableName);
+    return Result;
+}
+
+BOOL
+WINAPI
+SetFirmwareEnvironmentVariableW(
+    _In_ LPCWSTR lpName,
+    _In_ LPCWSTR lpGuid,
+    _In_reads_bytes_opt_(nSize) PVOID pValue,
+    _In_ DWORD nSize)
+{
+    return SetFirmwareEnvironmentVariableExW(lpName,
+                                             lpGuid,
+                                             pValue,
+                                             nSize,
+                                             VARIABLE_ATTRIBUTE_NON_VOLATILE);
+}
+
+BOOL
+WINAPI
+SetFirmwareEnvironmentVariableA(
+    _In_ LPCSTR lpName,
+    _In_ LPCSTR lpGuid,
+    _In_reads_bytes_opt_(nSize) PVOID pValue,
+    _In_ DWORD nSize)
+{
+    return SetFirmwareEnvironmentVariableExA(lpName,
+                                             lpGuid,
+                                             pValue,
+                                             nSize,
+                                             VARIABLE_ATTRIBUTE_NON_VOLATILE);
 }
 
 /**
@@ -474,7 +661,7 @@ SetFirmwareEnvironmentVariableA(IN LPCSTR lpName,
  * @implemented
  *
  * Obtains firmware table identifiers.
- * 
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724259(v=vs.85).aspx
+ * 
https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-enumsystemfirmwaretables
  *
  * @param FirmwareTableProviderSignature
  * Can be either ACPI, FIRM, or RSMB.
@@ -498,13 +685,14 @@ SetFirmwareEnvironmentVariableA(IN LPCSTR lpName,
  */
 UINT
 WINAPI
-EnumSystemFirmwareTables(IN DWORD FirmwareTableProviderSignature,
-                         OUT PVOID pFirmwareTableBuffer,
-                         IN DWORD BufferSize)
+EnumSystemFirmwareTables(
+    _In_ DWORD FirmwareTableProviderSignature,
+    _Out_writes_bytes_to_opt_(BufferSize, return) PVOID 
pFirmwareTableEnumBuffer,
+    _In_ DWORD BufferSize)
 {
     return BaseQuerySystemFirmware(FirmwareTableProviderSignature,
                                    0,
-                                   pFirmwareTableBuffer,
+                                   pFirmwareTableEnumBuffer,
                                    BufferSize,
                                    SystemFirmwareTable_Enumerate);
 }
@@ -514,7 +702,7 @@ EnumSystemFirmwareTables(IN DWORD 
FirmwareTableProviderSignature,
  * @implemented
  *
  * Obtains the firmware table data.
- * 
https://msdn.microsoft.com/en-us/library/windows/desktop/ms724379(v=vs.85).aspx
+ * 
https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemfirmwaretable
  *
  * @param FirmwareTableProviderSignature
  * Can be either ACPI, FIRM, or RSMB.
@@ -545,10 +733,11 @@ EnumSystemFirmwareTables(IN DWORD 
FirmwareTableProviderSignature,
  */
 UINT
 WINAPI
-GetSystemFirmwareTable(IN DWORD FirmwareTableProviderSignature,
-                       IN DWORD FirmwareTableID,
-                       OUT PVOID pFirmwareTableBuffer,
-                       IN DWORD BufferSize)
+GetSystemFirmwareTable(
+    _In_ DWORD FirmwareTableProviderSignature,
+    _In_ DWORD FirmwareTableID,
+    _Out_writes_bytes_to_opt_(BufferSize, return) PVOID pFirmwareTableBuffer,
+    _In_ DWORD BufferSize)
 {
     return BaseQuerySystemFirmware(FirmwareTableProviderSignature,
                                    FirmwareTableID,
diff --git a/modules/rostests/apitests/kernel32/CMakeLists.txt 
b/modules/rostests/apitests/kernel32/CMakeLists.txt
index 8c26b340edc..582d3f5627f 100644
--- a/modules/rostests/apitests/kernel32/CMakeLists.txt
+++ b/modules/rostests/apitests/kernel32/CMakeLists.txt
@@ -36,6 +36,7 @@ list(APPEND SOURCE
     SystemFirmware.c
     TerminateProcess.c
     TunnelCache.c
+    UEFIFirmware.c
     WideCharToMultiByte.c)
 
 list(APPEND PCH_SKIP_SOURCE
diff --git a/modules/rostests/apitests/kernel32/UEFIFirmware.c 
b/modules/rostests/apitests/kernel32/UEFIFirmware.c
new file mode 100644
index 00000000000..4ab0ea6ea73
--- /dev/null
+++ b/modules/rostests/apitests/kernel32/UEFIFirmware.c
@@ -0,0 +1,253 @@
+/*
+ * PROJECT:     ReactOS API Tests
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Tests for UEFI Firmware functions
+ * COPYRIGHT:   Copyright 2023 Ratin Gao <[email protected]>
+ */
+
+#include "precomp.h"
+
+#include <ndk/psfuncs.h>
+#include <ndk/setypes.h>
+#include <ndk/sefuncs.h>
+#include <ndk/obfuncs.h>
+
+#define _A2W(quote) __A2W(quote)
+#define __A2W(quote) L##quote
+
+#define EFI_TEST_GUID_STRING "{8768B7AC-F82F-4120-B093-30DFA27DA3B5}"
+#define EFI_TEST_VARIABLE_NAME "RosUefiVarTest"
+
+#define EFI_DUMMY_NAMESPACE_GUID_STRING 
"{00000000-0000-0000-0000-000000000000}"
+#define EFI_DUMMY_VARIABLE_NAME ""
+
+static ULONG RandomSeed;
+static DWORD EfiVariableValue;
+
+static VOID test_GetFirmwareType(BOOL bIsUEFI)
+{
+#if (_WIN32_WINNT >= 0x0602)
+    BOOL bResult;
+    FIRMWARE_TYPE FirmwareType = FirmwareTypeUnknown, FirmwareExpect;
+
+    /* Test GetFirmwareType, should return FirmwareTypeBios or 
FirmwareTypeUefi */
+    bResult = GetFirmwareType(&FirmwareType);
+
+    ok(bResult,
+       "GetFirmwareType failed with error: 0x%08lX\n",
+       GetLastError());
+
+    if (!bResult)
+        return;
+
+    FirmwareExpect = (bIsUEFI ? FirmwareTypeUefi : FirmwareTypeBios);
+    ok(FirmwareType == FirmwareExpect,
+       "FirmwareType is %d, but %d is expected.\n",
+       FirmwareType, FirmwareExpect);
+#else
+    skip("This test can be run only when compiled for NT >= 6.2.\n");
+#endif
+}
+
+START_TEST(UEFIFirmware)
+{
+    BOOL bResult, bResultTemp, bIsUEFI;
+    DWORD dwError, dwErrorTemp, dwLength, dwLengthTemp, dwValue;
+    HANDLE hToken;
+    TOKEN_PRIVILEGES Privilege;
+    NTSTATUS Status;
+    ULONG ReturnLength;
+
+    /*
+     * Check whether this test runs on legacy BIOS-based or UEFI system
+     * by calling GetFirmwareEnvironmentVariable with dummy name and GUID.
+     * It should fail with ERROR_INVALID_FUNCTION on the former and
+     * fail with another error on the latter.
+     */
+    dwLength = GetFirmwareEnvironmentVariableW(_A2W(EFI_DUMMY_VARIABLE_NAME),
+                                               
_A2W(EFI_DUMMY_NAMESPACE_GUID_STRING),
+                                               NULL,
+                                               0);
+    dwError = GetLastError();
+    ok(dwLength == 0, "dwLength = %lu, expected 0\n", dwLength);
+
+    bIsUEFI = (dwLength == 0 && dwError != ERROR_INVALID_FUNCTION);
+    test_GetFirmwareType(bIsUEFI);
+    if (!bIsUEFI)
+    {
+        skip("Skipping tests that require UEFI environment.\n");
+        return;
+    }
+
+    /* Test ANSI function too */
+    dwLengthTemp = GetFirmwareEnvironmentVariableA(EFI_DUMMY_VARIABLE_NAME,
+                                                   
EFI_DUMMY_NAMESPACE_GUID_STRING,
+                                                   NULL,
+                                                   0);
+    dwErrorTemp = GetLastError();
+    ok(dwLengthTemp == dwLength && dwErrorTemp == dwError,
+       "dwLength = %lu, LastError = %lu, expected bResult = %lu, LastError = 
%lu\n",
+       dwLengthTemp,
+       dwErrorTemp,
+       dwLength,
+       dwError);
+
+    /* Generate a random variable value to be used in this test */
+    RandomSeed = GetTickCount();
+    EfiVariableValue = RtlRandom(&RandomSeed);
+
+    /* Try to set firmware variable, should fail with ERROR_PRIVILEGE_NOT_HELD,
+     * because no SE_SYSTEM_ENVIRONMENT_NAME privilege enabled by default. */
+    bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME),
+                                              _A2W(EFI_TEST_GUID_STRING),
+                                              &EfiVariableValue,
+                                              sizeof(EfiVariableValue));
+    dwError = GetLastError();
+    ok(!bResult && dwError == ERROR_PRIVILEGE_NOT_HELD,
+       "bResult = %d, LastError = %lu, expected bResult = 0, LastError = 
ERROR_PRIVILEGE_NOT_HELD\n",
+       bResult,
+       dwError);
+
+    /* Test ANSI function too */
+    bResultTemp = SetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME,
+                                                  EFI_TEST_GUID_STRING,
+                                                  &EfiVariableValue,
+                                                  sizeof(EfiVariableValue));
+    dwErrorTemp = GetLastError();
+    ok(bResultTemp == bResult && dwErrorTemp == dwError,
+       "bResult = %d, LastError = %lu, expected bResult = %d, LastError = 
%lu\n",
+       bResultTemp,
+       dwErrorTemp,
+       bResult,
+       dwError);
+
+    /* Enable SE_SYSTEM_ENVIRONMENT_NAME privilege required by the following 
tests */
+    bResult = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, 
&hToken);
+    if (!bResult)
+    {
+        skip("OpenProcessToken failed with error: 0x%08lX, aborting.\n", 
GetLastError());
+        return;
+    }
+    Privilege.PrivilegeCount = 1;
+    Privilege.Privileges[0].Luid = 
RtlConvertUlongToLuid(SE_SYSTEM_ENVIRONMENT_PRIVILEGE);
+    Privilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+    Status = NtAdjustPrivilegesToken(hToken, FALSE, &Privilege, 
sizeof(Privilege), NULL, &ReturnLength);
+    if (Status != STATUS_SUCCESS)
+    {
+        skip("NtAdjustPrivilegesToken failed with status: 0x%08lX, 
aborting.\n", Status);
+        NtClose(hToken);
+        return;
+    }
+
+    /* Set our test variable to UEFI firmware */
+    bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME),
+                                              _A2W(EFI_TEST_GUID_STRING),
+                                              &EfiVariableValue,
+                                              sizeof(EfiVariableValue));
+    ok(bResult,
+       "SetFirmwareEnvironmentVariableW failed with error: 0x%08lX\n",
+       GetLastError());
+    if (bResult)
+    {
+        /* Get the variable back and verify */
+        dwLength = 
GetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME),
+                                                   _A2W(EFI_TEST_GUID_STRING),
+                                                   &dwValue,
+                                                   sizeof(dwValue));
+        ok(dwLength,
+           "GetFirmwareEnvironmentVariableW failed with error: 0x%08lX\n",
+           GetLastError());
+        if (dwLength)
+        {
+            ok(dwLength == sizeof(EfiVariableValue) && dwValue == 
EfiVariableValue,
+               "Retrieved variable different from what we set, "
+               "dwLength = %lu, dwValue = %lu, expected dwLength = %u, dwValue 
= %lu",
+               dwLength,
+               dwValue,
+               sizeof(EfiVariableValue),
+               EfiVariableValue);
+        }
+    }
+
+    /* Change variable value and test ANSI function */
+    EfiVariableValue = RtlRandom(&RandomSeed);
+    bResult = SetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME,
+                                              EFI_TEST_GUID_STRING,
+                                              &EfiVariableValue,
+                                              sizeof(EfiVariableValue));
+    ok(bResult,
+       "SetFirmwareEnvironmentVariableA failed with error: 0x%08lX\n",
+       GetLastError());
+    if (bResult)
+    {
+        /* Get the variable back and verify */
+        dwLength = GetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME,
+                                                   EFI_TEST_GUID_STRING,
+                                                   &dwValue,
+                                                   sizeof(dwValue));
+        ok(dwLength,
+           "GetFirmwareEnvironmentVariableA failed with error: 0x%08lX\n",
+           GetLastError());
+        if (dwLength)
+        {
+            ok(dwLength == sizeof(EfiVariableValue) && dwValue == 
EfiVariableValue,
+               "Retrieved variable different from what we set, "
+               "dwLength = %lu, dwValue = %lu, expected dwLength = %u, dwValue 
= %lu",
+               dwLength,
+               dwValue,
+               sizeof(EfiVariableValue),
+               EfiVariableValue);
+        }
+    }
+
+    /* Delete the variable */
+    bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME),
+                                              _A2W(EFI_TEST_GUID_STRING),
+                                              NULL,
+                                              0);
+    ok(bResult,
+       "SetFirmwareEnvironmentVariableW failed with error: 0x%08lX\n",
+       GetLastError());
+    if (bResult)
+    {
+        dwLength = 
GetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME),
+                                                   _A2W(EFI_TEST_GUID_STRING),
+                                                   &dwValue,
+                                                   sizeof(dwValue));
+        ok(dwLength == 0, "SetFirmwareEnvironmentVariableW didn't delete the 
variable!\n");
+    }
+
+    /* Restore variable and test ANSI function */
+    bResult = SetFirmwareEnvironmentVariableW(_A2W(EFI_TEST_VARIABLE_NAME),
+                                              _A2W(EFI_TEST_GUID_STRING),
+                                              &EfiVariableValue,
+                                              sizeof(EfiVariableValue));
+    if (!bResult)
+    {
+        skip("SetFirmwareEnvironmentVariableW failed to restore variable with 
error: 0x%08lX\n",
+             GetLastError());
+        goto _exit;
+    }
+    bResult = SetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME,
+                                              EFI_TEST_GUID_STRING,
+                                              NULL,
+                                              0);
+    ok(bResult,
+       "SetFirmwareEnvironmentVariableA failed with error: 0x%08lX\n",
+       GetLastError());
+    if (bResult)
+    {
+        dwLength = GetFirmwareEnvironmentVariableA(EFI_TEST_VARIABLE_NAME,
+                                                   EFI_TEST_GUID_STRING,
+                                                   &dwValue,
+                                                   sizeof(dwValue));
+        ok(dwLength == 0, "SetFirmwareEnvironmentVariableA didn't delete the 
variable!\n");
+    }
+
+_exit:
+    /* Restore the privilege */
+    Privilege.Privileges[0].Attributes = 0;
+    Status = NtAdjustPrivilegesToken(hToken, FALSE, &Privilege, 
sizeof(Privilege), NULL, &ReturnLength);
+    ok(Status == STATUS_SUCCESS, "NtAdjustPrivilegesToken failed with status: 
0x%08lX\n", Status);
+    NtClose(hToken);
+}
diff --git a/modules/rostests/apitests/kernel32/testlist.c 
b/modules/rostests/apitests/kernel32/testlist.c
index 4802d88079c..a0a11a88d1a 100644
--- a/modules/rostests/apitests/kernel32/testlist.c
+++ b/modules/rostests/apitests/kernel32/testlist.c
@@ -36,6 +36,7 @@ extern void func_SetUnhandledExceptionFilter(void);
 extern void func_SystemFirmware(void);
 extern void func_TerminateProcess(void);
 extern void func_TunnelCache(void);
+extern void func_UEFIFirmware(void);
 extern void func_WideCharToMultiByte(void);
 
 const struct test winetest_testlist[] =
@@ -72,6 +73,7 @@ const struct test winetest_testlist[] =
     { "SystemFirmware",              func_SystemFirmware },
     { "TerminateProcess",            func_TerminateProcess },
     { "TunnelCache",                 func_TunnelCache },
+    { "UEFIFirmware",                func_UEFIFirmware },
     { "WideCharToMultiByte",         func_WideCharToMultiByte },
     { "ActCtxWithXmlNamespaces",     func_ActCtxWithXmlNamespaces },
     { 0, 0 }
diff --git a/ntoskrnl/ex/sysinfo.c b/ntoskrnl/ex/sysinfo.c
index d6692bc83f6..58b023466a1 100644
--- a/ntoskrnl/ex/sysinfo.c
+++ b/ntoskrnl/ex/sysinfo.c
@@ -564,11 +564,12 @@ NtEnumerateSystemEnvironmentValuesEx(IN ULONG 
InformationClass,
 
 NTSTATUS
 NTAPI
-NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
-                                IN LPGUID VendorGuid,
-                                IN PVOID Value,
-                                IN OUT PULONG ReturnLength,
-                                IN OUT PULONG Attributes)
+NtQuerySystemEnvironmentValueEx(
+    _In_ PUNICODE_STRING VariableName,
+    _In_ LPGUID VendorGuid,
+    _Out_opt_ PVOID Value,
+    _Inout_ PULONG ReturnLength,
+    _Out_opt_ PULONG Attributes)
 {
     UNIMPLEMENTED;
     return STATUS_NOT_IMPLEMENTED;
@@ -576,11 +577,12 @@ NtQuerySystemEnvironmentValueEx(IN PUNICODE_STRING 
VariableName,
 
 NTSTATUS
 NTAPI
-NtSetSystemEnvironmentValueEx(IN PUNICODE_STRING VariableName,
-                              IN LPGUID VendorGuid,
-                              IN PVOID Value,
-                              IN OUT PULONG ReturnLength,
-                              IN OUT PULONG Attributes)
+NtSetSystemEnvironmentValueEx(
+    _In_ PUNICODE_STRING VariableName,
+    _In_ LPGUID VendorGuid,
+    _In_reads_bytes_opt_(ValueLength) PVOID Value,
+    _In_ ULONG ValueLength,
+    _In_ ULONG Attributes)
 {
     UNIMPLEMENTED;
     return STATUS_NOT_IMPLEMENTED;
diff --git a/sdk/include/ndk/exfuncs.h b/sdk/include/ndk/exfuncs.h
index bca4e87010c..d3dd33bb1d7 100644
--- a/sdk/include/ndk/exfuncs.h
+++ b/sdk/include/ndk/exfuncs.h
@@ -396,9 +396,9 @@ NTAPI
 NtQuerySystemEnvironmentValueEx(
     _In_ PUNICODE_STRING VariableName,
     _In_ LPGUID VendorGuid,
-    _In_ PVOID Value,
+    _Out_opt_ PVOID Value,
     _Inout_ PULONG ReturnLength,
-    _Inout_ PULONG Attributes
+    _Out_opt_ PULONG Attributes
 );
 
 __kernel_entry
@@ -550,9 +550,9 @@ NTAPI
 NtSetSystemEnvironmentValueEx(
     _In_ PUNICODE_STRING VariableName,
     _In_ LPGUID VendorGuid,
-    _In_ PVOID Value,
-    _Inout_ PULONG ReturnLength,
-    _Inout_ PULONG Attributes
+    _In_reads_bytes_opt_(ValueLength) PVOID Value,
+    _In_ ULONG ValueLength,
+    _In_ ULONG Attributes
 );
 
 __kernel_entry
diff --git a/sdk/include/ndk/extypes.h b/sdk/include/ndk/extypes.h
index 6cc77cb1d7c..2b190f1ca30 100644
--- a/sdk/include/ndk/extypes.h
+++ b/sdk/include/ndk/extypes.h
@@ -1432,7 +1432,29 @@ typedef struct _SYSTEM_HANDLE_INFORMATION_EX
     SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handle[1];
 } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX;
 
-// FIXME: Class 65-97
+// FIXME: Class 65-89
+
+// Class 90
+#if (NTDDI_VERSION >= NTDDI_LONGHORN)
+typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
+{
+    GUID BootIdentifier;
+    FIRMWARE_TYPE FirmwareType;
+#if (NTDDI_VERSION >= NTDDI_WIN8)
+    ULONGLONG BootFlags;
+#endif
+} SYSTEM_BOOT_ENVIRONMENT_INFORMATION, *PSYSTEM_BOOT_ENVIRONMENT_INFORMATION;
+#endif
+
+#if (NTDDI_VERSION >= NTDDI_WIN8)
+typedef struct _SYSTEM_BOOT_ENVIRONMENT_V1
+{
+    GUID BootIdentifier;
+    FIRMWARE_TYPE FirmwareType;
+} SYSTEM_BOOT_ENVIRONMENT_V1, *PSYSTEM_BOOT_ENVIRONMENT_V1;
+#endif
+
+// FIXME: Class 91-97
 
 //
 // Hotpatch flags
@@ -1540,6 +1562,17 @@ typedef struct _SYSTEM_MEMORY_LIST_INFORMATION
     SIZE_T ModifiedPageCountPageFile;
 } SYSTEM_MEMORY_LIST_INFORMATION, *PSYSTEM_MEMORY_LIST_INFORMATION;
 
+//
+// Firmware variable attributes
+//
+#define VARIABLE_ATTRIBUTE_NON_VOLATILE                             0x00000001
+#define VARIABLE_ATTRIBUTE_BOOTSERVICE_ACCESS                       0x00000002
+#define VARIABLE_ATTRIBUTE_RUNTIME_ACCESS                           0x00000004
+#define VARIABLE_ATTRIBUTE_HARDWARE_ERROR_RECORD                    0x00000008
+#define VARIABLE_ATTRIBUTE_AUTHENTICATED_WRITE_ACCESS               0x00000010
+#define VARIABLE_ATTRIBUTE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS    0x00000020
+#define VARIABLE_ATTRIBUTE_APPEND_WRITE                             0x00000040
+
 #ifdef __cplusplus
 }; // extern "C"
 #endif
diff --git a/sdk/include/psdk/winbase.h b/sdk/include/psdk/winbase.h
index 6b616b07b39..397ad4d92cc 100644
--- a/sdk/include/psdk/winbase.h
+++ b/sdk/include/psdk/winbase.h
@@ -2004,25 +2004,7 @@ _Ret_maybenull_ HRSRC WINAPI FindResourceA(_In_opt_ 
HMODULE,_In_ LPCSTR, _In_ LP
 _Ret_maybenull_ HRSRC WINAPI FindResourceW(_In_opt_ HMODULE,_In_ LPCWSTR, _In_ 
LPCWSTR);
 _Ret_maybenull_ HRSRC WINAPI FindResourceExA(_In_opt_ HMODULE, _In_ LPCSTR, 
_In_ LPCSTR, _In_ WORD);
 HRSRC WINAPI FindResourceExW(HINSTANCE,LPCWSTR,LPCWSTR,WORD);
-#if (_WIN32_WINNT >= 0x0502)
-
-DWORD
-WINAPI
-GetFirmwareEnvironmentVariableA(
-  _In_ LPCSTR lpName,
-  _In_ LPCSTR lpGuid,
-  _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer,
-  _In_ DWORD nSize);
-
-DWORD
-WINAPI
-GetFirmwareEnvironmentVariableW(
-  _In_ LPCWSTR lpName,
-  _In_ LPCWSTR lpGuid,
-  _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer,
-  _In_ DWORD nSize);
 
-#endif
 BOOL WINAPI FlushFileBuffers(HANDLE);
 BOOL WINAPI FlushInstructionCache(HANDLE,LPCVOID,SIZE_T);
 BOOL WINAPI FlushViewOfFile(LPCVOID,SIZE_T);
@@ -2430,15 +2412,6 @@ HANDLE WINAPI GetStdHandle(_In_ DWORD);
 UINT WINAPI GetSystemDirectoryA(LPSTR,UINT);
 UINT WINAPI GetSystemDirectoryW(LPWSTR,UINT);
 
-WINBASEAPI
-UINT
-WINAPI
-GetSystemFirmwareTable(
-  _In_ DWORD FirmwareTableProviderSignature,
-  _In_ DWORD FirmwareTableID,
-  _Out_writes_bytes_to_opt_(BufferSize,return) PVOID pFirmwareTableBuffer,
-  _In_ DWORD BufferSize);
-
 VOID WINAPI GetSystemInfo(LPSYSTEM_INFO);
 BOOL WINAPI GetSystemPowerStatus(_Out_ LPSYSTEM_POWER_STATUS);
 #if (_WIN32_WINNT >= 0x0502)
@@ -3170,6 +3143,50 @@ BOOL WINAPI SetFileValidData(HANDLE,LONGLONG);
 
 #if (_WIN32_WINNT >= 0x0502)
 
+WINBASEAPI
+UINT
+WINAPI
+EnumSystemFirmwareTables(
+    _In_ DWORD FirmwareTableProviderSignature,
+    _Out_writes_bytes_to_opt_(BufferSize, return) PVOID 
pFirmwareTableEnumBuffer,
+    _In_ DWORD BufferSize);
+
+WINBASEAPI
+UINT
+WINAPI
+GetSystemFirmwareTable(
+    _In_ DWORD FirmwareTableProviderSignature,
+    _In_ DWORD FirmwareTableID,
+    _Out_writes_bytes_to_opt_(BufferSize, return) PVOID pFirmwareTableBuffer,
+    _In_ DWORD BufferSize);
+
+_Success_(return > 0)
+WINBASEAPI
+DWORD
+WINAPI
+GetFirmwareEnvironmentVariableA(
+    _In_ LPCSTR lpName,
+    _In_ LPCSTR lpGuid,
+    _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer,
+    _In_ DWORD nSize);
+
+_Success_(return > 0)
+WINBASEAPI
+DWORD
+WINAPI
+GetFirmwareEnvironmentVariableW(
+    _In_ LPCWSTR lpName,
+    _In_ LPCWSTR lpGuid,
+    _Out_writes_bytes_to_opt_(nSize, return) PVOID pBuffer,
+    _In_ DWORD nSize);
+
+#ifdef UNICODE
+#define GetFirmwareEnvironmentVariable GetFirmwareEnvironmentVariableW
+#else
+#define GetFirmwareEnvironmentVariable GetFirmwareEnvironmentVariableA
+#endif
+
+WINBASEAPI
 BOOL
 WINAPI
 SetFirmwareEnvironmentVariableA(
@@ -3178,6 +3195,7 @@ SetFirmwareEnvironmentVariableA(
   _In_reads_bytes_opt_(nSize) PVOID pValue,
   _In_ DWORD nSize);
 
+WINBASEAPI
 BOOL
 WINAPI
 SetFirmwareEnvironmentVariableW(
@@ -3186,8 +3204,14 @@ SetFirmwareEnvironmentVariableW(
   _In_reads_bytes_opt_(nSize) PVOID pValue,
   _In_ DWORD nSize);
 
+#ifdef UNICODE
+#define SetFirmwareEnvironmentVariable SetFirmwareEnvironmentVariableW
+#else
+#define SetFirmwareEnvironmentVariable SetFirmwareEnvironmentVariableA
 #endif
 
+#endif /* _WIN32_WINNT >= 0x0502 */
+
 UINT WINAPI SetHandleCount(UINT);
 BOOL WINAPI SetHandleInformation(HANDLE,DWORD,DWORD);
 
diff --git a/sdk/include/xdk/extypes.h b/sdk/include/xdk/extypes.h
index a8c5fa87dc2..a5311330872 100644
--- a/sdk/include/xdk/extypes.h
+++ b/sdk/include/xdk/extypes.h
@@ -346,3 +346,14 @@ $if (_NTIFS_)
 #define EX_PUSH_LOCK ULONG_PTR
 #define PEX_PUSH_LOCK PULONG_PTR
 $endif (_NTIFS_)
+
+$if (_WINNT_ || _WDMDDK_)
+#if (NTDDI_VERSION >= NTDDI_VISTA)
+typedef enum _FIRMWARE_TYPE {
+    FirmwareTypeUnknown,
+    FirmwareTypeBios,
+    FirmwareTypeUefi,
+    FirmwareTypeMax
+} FIRMWARE_TYPE, *PFIRMWARE_TYPE;
+#endif /* (NTDDI_VERSION >= NTDDI_VISTA) */
+$endif (_WINNT_ || _WDMDDK_)
diff --git a/sdk/include/xdk/winnt.template.h b/sdk/include/xdk/winnt.template.h
index dd28aee4238..75a85102e08 100644
--- a/sdk/include/xdk/winnt.template.h
+++ b/sdk/include/xdk/winnt.template.h
@@ -73,6 +73,7 @@ $define(UCHAR=BYTE)
 $include(ntbasedef.h)
 $include(interlocked.h)
 $include(ketypes.h)
+$include(extypes.h)
 $include(winnt_old.h)
 
 #ifdef __cplusplus

Reply via email to