ohmu
·
2026-10-15
1#include "bootmgr.h"
2#include "common/debug.h"
3#include "efi_helper.h"
4#include "common/io.h"
5#include "common/windows/nt.h"
6
7#include <ntstatus.h>
8#include <windows.h>
9
10const char* enablePrivilege(const wchar_t* privilege) {
11 FF_AUTO_CLOSE_FD HANDLE token = nullptr;
12 NTSTATUS status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token);
13 if (!NT_SUCCESS(status)) {
14 FF_DEBUG("NtOpenProcessToken() failed: %s", ffDebugNtStatus(status));
15 return "NtOpenProcessToken() failed";
16 }
17
18 TOKEN_PRIVILEGES tp = {
19 .PrivilegeCount = 1,
20 .Privileges = {
21 (LUID_AND_ATTRIBUTES) { .Attributes = SE_PRIVILEGE_ENABLED } },
22 };
23 if (!LookupPrivilegeValueW(nullptr, privilege, &tp.Privileges[0].Luid)) {
24 FF_DEBUG("LookupPrivilegeValue() failed: %s", ffDebugWin32Error(GetLastError()));
25 return "LookupPrivilegeValue() failed";
26 }
27
28 status = NtAdjustPrivilegesToken(token, false, &tp, sizeof(tp), nullptr, nullptr);
29 if (!NT_SUCCESS(status)) {
30 FF_DEBUG("NtAdjustPrivilegesToken() failed: %s", ffDebugNtStatus(status));
31 return "NtAdjustPrivilegesToken() failed";
32 }
33
34 if (status == STATUS_NOT_ALL_ASSIGNED) {
35 FF_DEBUG("NtAdjustPrivilegesToken() did not assign the privilege: %s", ffDebugNtStatus(status));
36 return "The token does not have the specified privilege; try sudo please";
37 }
38
39 return nullptr;
40}
41
42const char* ffDetectBootmgr(FFBootmgrResult* result) {
43 const char* err = enablePrivilege(L"SeSystemEnvironmentPrivilege");
44 if (err != nullptr) {
45 return err;
46 }
47
48 GUID efiGlobalGuid = {
49 .Data1 = 0x8be4df61,
50 .Data2 = 0x93ca,
51 .Data3 = 0x11d2,
52 .Data4 = { 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c },
53 };
54
55 ULONG size = sizeof(result->order);
56 NTSTATUS status = NtQuerySystemEnvironmentValueEx(&(UNICODE_STRING) RTL_CONSTANT_STRING(L"BootCurrent"), &efiGlobalGuid, &result->order, &size, nullptr);
57 if (!NT_SUCCESS(status)) {
58 FF_DEBUG("NtQuerySystemEnvironmentValueEx(BootCurrent) failed: %s", ffDebugNtStatus(status));
59 return "NtQuerySystemEnvironmentValueEx(BootCurrent) failed";
60 }
61 if (size != sizeof(result->order)) {
62 FF_DEBUG("NtQuerySystemEnvironmentValueEx(BootCurrent) returned unexpected size");
63 return "NtQuerySystemEnvironmentValueEx(BootCurrent) returned unexpected size";
64 }
65
66 uint8_t buffer[2048];
67 wchar_t key[9];
68 swprintf(key, ARRAY_SIZE(key), L"Boot%04X", result->order);
69 size = sizeof(buffer);
70 status = NtQuerySystemEnvironmentValueEx(&(UNICODE_STRING) RTL_CONSTANT_STRING(key), &efiGlobalGuid, buffer, &size, nullptr);
71 if (!NT_SUCCESS(status)) {
72 FF_DEBUG("NtQuerySystemEnvironmentValueEx(Boot####) failed: %s", ffDebugNtStatus(status));
73 return "NtQuerySystemEnvironmentValueEx(Boot####) failed";
74 }
75 if (size < sizeof(FFEfiLoadOption) || size == ARRAY_SIZE(buffer)) {
76 FF_DEBUG("NtQuerySystemEnvironmentValueEx(Boot####) returned unexpected size");
77 return "NtQuerySystemEnvironmentValueEx(Boot####) returned unexpected size";
78 }
79
80 ffEfiFillLoadOption((FFEfiLoadOption*) buffer, result);
81
82 SYSTEM_SECUREBOOT_INFORMATION ssi;
83 if (NT_SUCCESS(NtQuerySystemInformation(SystemSecureBootInformation, &ssi, sizeof(ssi), nullptr))) {
84 result->secureBoot = ssi.SecureBootEnabled;
85 }
86
87 return nullptr;
88}