const std = @import("std");
const windows = std.os.windows;

pub const WINAPI: std.builtin.CallingConvention = .winapi;

// Page protection constants for NtProtectVirtualMemory.
// https://ntdoc.m417z.com/ntprotectvirtualmemory
pub const PAGE_NOACCESS: windows.ULONG = 0x01;
pub const PAGE_READONLY: windows.ULONG = 0x02;
pub const PAGE_READWRITE: windows.ULONG = 0x04;
pub const PAGE_EXECUTE_READ: windows.ULONG = 0x20;
pub const PAGE_EXECUTE_READWRITE: windows.ULONG = 0x40;

pub const CONTEXT_DEBUG_REGISTERS: windows.DWORD = 0x00100010;
pub const EXCEPTION_SINGLE_STEP: windows.DWORD = 0x80000004;
pub const EXCEPTION_CONTINUE_EXECUTION: windows.LONG = -1;
pub const EXCEPTION_CONTINUE_SEARCH: windows.LONG = 0;

// https://ntdoc.m417z.com/object_attributes
pub const OBJ_CASE_INSENSITIVE: windows.ULONG = 0x00000040;

// https://ntdoc.m417z.com/unicode_string
pub const UNICODE_STRING = extern struct {
    Length: u16,
    MaximumLength: u16,
    Buffer: [*]u16,
};

// https://ntdoc.m417z.com/object_attributes
pub const OBJECT_ATTRIBUTES = extern struct {
    Length: windows.ULONG,
    RootDirectory: ?windows.HANDLE,
    ObjectName: ?*UNICODE_STRING,
    Attributes: windows.ULONG,
    SecurityDescriptor: ?*anyopaque,
    SecurityQualityOfService: ?*anyopaque,
};

// https://ntdoc.m417z.com/client_id
pub const CLIENT_ID = extern struct {
    UniqueProcess: windows.HANDLE,
    UniqueThread: ?windows.HANDLE,
};

// https://ntdoc.m417z.com/token_type
pub const TOKEN_TYPE = enum(u32) {
    TokenPrimary = 1,
    TokenImpersonation = 2,
};

pub const PROCESS_QUERY_LIMITED_INFORMATION: windows.DWORD = 0x1000;
pub const MAXIMUM_ALLOWED: windows.DWORD = 0x02000000;

// Access rights for NtOpenProcessToken.
// https://ntdoc.m417z.com/ntopenprocesstoken
pub const TOKEN_DUPLICATE: windows.DWORD = 0x0002;
pub const TOKEN_QUERY: windows.DWORD = 0x0008;
pub const TOKEN_IMPERSONATE: windows.DWORD = 0x0004;

// https://ntdoc.m417z.com/ntopensection
pub const SECTION_MAP_READ: windows.DWORD = 0x0004;

pub const CONTEXT = extern struct {
    P1Home: windows.DWORD64,
    P2Home: windows.DWORD64,
    P3Home: windows.DWORD64,
    P4Home: windows.DWORD64,
    P5Home: windows.DWORD64,
    P6Home: windows.DWORD64,
    ContextFlags: windows.DWORD,
    MxCsr: windows.DWORD,
    SegCs: windows.WORD,
    SegDs: windows.WORD,
    SegEs: windows.WORD,
    SegFs: windows.WORD,
    SegGs: windows.WORD,
    SegSs: windows.WORD,
    EFlags: windows.DWORD,
    Dr0: windows.DWORD64,
    Dr1: windows.DWORD64,
    Dr2: windows.DWORD64,
    Dr3: windows.DWORD64,
    Dr6: windows.DWORD64,
    Dr7: windows.DWORD64,
    Rax: windows.DWORD64,
    Rcx: windows.DWORD64,
    Rdx: windows.DWORD64,
    Rbx: windows.DWORD64,
    Rsp: windows.DWORD64,
    Rbp: windows.DWORD64,
    Rsi: windows.DWORD64,
    Rdi: windows.DWORD64,
    R8: windows.DWORD64,
    R9: windows.DWORD64,
    R10: windows.DWORD64,
    R11: windows.DWORD64,
    R12: windows.DWORD64,
    R13: windows.DWORD64,
    R14: windows.DWORD64,
    R15: windows.DWORD64,
    Rip: windows.DWORD64,
};

pub const EXCEPTION_RECORD = extern struct {
    ExceptionCode: windows.DWORD,
    ExceptionFlags: windows.DWORD,
    ExceptionRecord: *EXCEPTION_RECORD,
    ExceptionAddress: *anyopaque,
    NumberParameters: windows.DWORD,
    ExceptionInformation: [15]windows.ULONG_PTR,
};

pub const EXCEPTION_POINTERS = extern struct {
    ExceptionRecord: *EXCEPTION_RECORD,
    ContextRecord: *CONTEXT,
};

pub inline fn NT_SUCCESS(status: windows.NTSTATUS) bool {
    return @as(i32, @bitCast(@intFromEnum(status))) >= 0;
}

pub fn FALSE_BOOL() windows.BOOLEAN {
    return @enumFromInt(@as(u8, 0));
}

