From: Grigory Vasilyev h0tc0d3@gmail.com
--- dlls/kernel32/kernel32.spec | 2 + dlls/kernel32/process.c | 96 +++++++++++++- dlls/kernel32/tests/firmware.c | 233 +++++++++++++++++++++++++++++++++ include/winbase.h | 4 + 4 files changed, 329 insertions(+), 6 deletions(-)
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 7ed8048f5d0..5d3556a2078 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -695,7 +695,9 @@ @ stdcall -import GetFileType(long) @ stdcall -import GetFinalPathNameByHandleA(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 GetFirmwareEnvironmentVariableExW(wstr wstr ptr long ptr) @ stdcall GetFirmwareEnvironmentVariableW(wstr wstr ptr long) @ stdcall GetFirmwareType(ptr) @ stdcall -import GetFullPathNameA(str long ptr ptr) diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 88a0ce2bc33..3358ae4b2fb 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -718,14 +718,99 @@ WORD WINAPI GetMaximumProcessorGroupCount(void) return groups; }
+/*********************************************************************** + * GetFirmwareEnvironmentVariableExA (KERNEL32.@) + */ +DWORD WINAPI GetFirmwareEnvironmentVariableExA(LPCSTR name, LPCSTR guid, PVOID buffer, DWORD size, PDWORD attributes) +{ + int nsize; + GUID vendor = {0}; + LPWSTR wname; + LPWSTR wguid; + UNICODE_STRING uname; + UNICODE_STRING uguid; + DWORD ret_size = 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); + + RtlInitUnicodeString(&uguid, wguid); + + if (!set_ntstatus(RtlGUIDFromString(&uguid, &vendor))) + return 0; + + 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); + + RtlInitUnicodeString(&uname, wname); + + if (!set_ntstatus(NtQuerySystemEnvironmentValueEx(&uname, &vendor, buffer, + &ret_size, attributes))) + ret_size = 0; + + HeapFree(GetProcessHeap(), 0, wname); + HeapFree(GetProcessHeap(), 0, wguid); + + return ret_size; +} + /*********************************************************************** * GetFirmwareEnvironmentVariableA (KERNEL32.@) */ DWORD WINAPI GetFirmwareEnvironmentVariableA(LPCSTR name, LPCSTR guid, PVOID buffer, DWORD size) { - FIXME("stub: %s %s %p %lu\n", debugstr_a(name), debugstr_a(guid), buffer, size); - SetLastError(ERROR_INVALID_FUNCTION); - return 0; + DWORD attributes; + return GetFirmwareEnvironmentVariableExA(name, guid, buffer, size, &attributes); +} + +/*********************************************************************** + * GetFirmwareEnvironmentVariableExW (KERNEL32.@) + */ +DWORD WINAPI GetFirmwareEnvironmentVariableExW(LPCWSTR name, LPCWSTR guid, PVOID buffer, DWORD size, PDWORD attributes) +{ + GUID vendor = {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); + + if (!set_ntstatus(NtQuerySystemEnvironmentValueEx(&uname, &vendor, buffer, + &ret_size, attributes))) + return 0; + + return ret_size; }
/*********************************************************************** @@ -733,9 +818,8 @@ DWORD WINAPI GetFirmwareEnvironmentVariableA(LPCSTR name, LPCSTR guid, PVOID buf */ 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); - SetLastError(ERROR_INVALID_FUNCTION); - return 0; + DWORD attributes; + return GetFirmwareEnvironmentVariableExW(name, guid, buffer, size, &attributes); }
/*********************************************************************** diff --git a/dlls/kernel32/tests/firmware.c b/dlls/kernel32/tests/firmware.c index 74cc87a33c9..78168f04bfc 100644 --- a/dlls/kernel32/tests/firmware.c +++ b/dlls/kernel32/tests/firmware.c @@ -49,7 +49,240 @@ static void test_get_firmware_type(void) "Expected FALSE and GetLastError() == ERROR_INVALID_PARAMETER\n"); }
+static BOOL EnableTokenPrivilege(HANDLE hToken, LPCTSTR pszPrivilegesName, BOOL bEnabled) +{ + LUID luid; + TOKEN_PRIVILEGES tp; + + if (!LookupPrivilegeValue(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() == STATUS_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() == STATUS_VARIABLE_NOT_FOUND, + "Expected status > 0 or GetLastError() == STATUS_VARIABLE_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() == STATUS_VARIABLE_NOT_FOUND, + "Expected status > 0 or GetLastError() == STATUS_VARIABLE_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() == STATUS_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() == STATUS_VARIABLE_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() == STATUS_VARIABLE_NOT_FOUND, + "Expected status > 0 or GetLastError() == STATUS_VARIABLE_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() == STATUS_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() == STATUS_VARIABLE_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() == STATUS_VARIABLE_NOT_FOUND, + "Expected status > 0 or GetLastError() == STATUS_VARIABLE_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() == STATUS_VARIABLE_NOT_FOUND, + "Expected status > 0 or GetLastError() == STATUS_VARIABLE_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() == STATUS_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() == STATUS_VARIABLE_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() == STATUS_VARIABLE_NOT_FOUND, + "Expected status > 0 or GetLastError() == STATUS_VARIABLE_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() == STATUS_VARIABLE_NOT_FOUND, + "Expected status > 0 or GetLastError() == STATUS_VARIABLE_NOT_FOUND, got error %ld.\n", GetLastError()); +} + START_TEST(firmware) { test_get_firmware_type(); + test_get_firmware_environment(); } diff --git a/include/winbase.h b/include/winbase.h index fe143cc7a61..2517417b170 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -2216,6 +2216,10 @@ WINBASEAPI DWORD WINAPI GetFileSize(HANDLE,LPDWORD); WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE,PLARGE_INTEGER); WINBASEAPI BOOL WINAPI GetFileTime(HANDLE,LPFILETIME,LPFILETIME,LPFILETIME); 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); #define GetFreeSpace(w) (__MSABI_LONG(0x100000)) WINBASEAPI DWORD WINAPI GetFullPathNameA(LPCSTR,DWORD,LPSTR,LPSTR*);