// Win32 type aliases, constants, and struct definitions.
const std = @import("std");

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

pub const CHAR = i8;
pub const UCHAR = u8;
pub const BYTE = u8;
pub const WORD = u16;
pub const WCHAR = u16;
pub const SHORT = i16;
pub const INT = i32;
pub const UINT = u32;
pub const LONG = i32;
pub const DWORD = u32;
pub const DWORD64 = u64;
pub const ULONG = u32;
pub const LONGLONG = i64;
pub const ULONGLONG = u64;
pub const BOOL = i32;
pub const BOOLEAN = u8;
pub const NTSTATUS = i32;
pub const HRESULT = i32;
pub const SIZE_T = usize;
pub const DWORD_PTR = usize;
pub const UINT_PTR = usize;
pub const ULONG_PTR = usize;
pub const LONG_PTR = isize;
pub const LARGE_INTEGER = i64;
pub const INTERNET_PORT = u16;

pub const LPVOID = *anyopaque;
pub const LPCVOID = *const anyopaque;
pub const HANDLE = *anyopaque;
pub const PHANDLE = *HANDLE;
pub const HMODULE = *anyopaque;
pub const HINSTANCE = *anyopaque;
pub const HINTERNET = *anyopaque;

pub const LPSTR = [*:0]u8;
pub const LPCSTR = [*:0]const u8;
pub const LPWSTR = [*:0]u16;
pub const LPCWSTR = [*:0]const u16;

pub const PDWORD = *DWORD;
pub const PULONG = *ULONG;
pub const PSIZE_T = *SIZE_T;
pub const PBOOL = *BOOL;

pub const FARPROC = *const fn () callconv(WINAPI) isize;

pub inline fn NT_SUCCESS(status: NTSTATUS) bool {
    return status >= 0;
}

pub const MEM_COMMIT: ULONG = 0x00001000;
pub const MEM_RESERVE: ULONG = 0x00002000;
pub const MEM_RELEASE: ULONG = 0x00008000;

pub const PAGE_NOACCESS: ULONG = 0x01;
pub const PAGE_READONLY: ULONG = 0x02;
pub const PAGE_READWRITE: ULONG = 0x04;
pub const DLL_PROCESS_ATTACH: ULONG = 1;
pub const PAGE_EXECUTE: ULONG = 0x10;
pub const PAGE_EXECUTE_READ: ULONG = 0x20;
pub const PAGE_EXECUTE_READWRITE: ULONG = 0x40;

pub const CONTEXT_AMD64: DWORD = 0x00100000;
pub const CONTEXT_DEBUG_REGISTERS: DWORD = CONTEXT_AMD64 | 0x00000010; // 0x00100010

pub const EXCEPTION_SINGLE_STEP: DWORD = 0x80000004;
pub const EXCEPTION_CONTINUE_EXECUTION: LONG = -1;
pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;

// process/startup constants + structures
pub const STARTF_USESTDHANDLES: DWORD = 0x00000100;

pub const EXTENDED_STARTUPINFO_PRESENT: DWORD = 0x00080000;
pub const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS: DWORD_PTR = 0x00020000;

pub const STARTUPINFOEXA = extern struct {
    StartupInfo: STARTUPINFOA,
    lpAttributeList: ?*anyopaque,
};

pub const CREATE_NO_WINDOW: DWORD = 0x08000000;

// Section access rights for NtOpenSection / NtMapViewOfSection
pub const SECTION_MAP_READ: DWORD = 0x0004;
pub const SECTION_MAP_WRITE: DWORD = 0x0002;
pub const SECTION_MAP_EXECUTE: DWORD = 0x0008;

pub const PROCESS_QUERY_INFORMATION: DWORD = 0x0400;
pub const PROCESS_QUERY_LIMITED_INFORMATION: DWORD = 0x1000;
pub const PROCESS_CREATE_PROCESS: DWORD = 0x0080;
pub const MAXIMUM_ALLOWED: DWORD = 0x02000000;

// Object attribute flags
pub const OBJ_CASE_INSENSITIVE: ULONG = 0x00000040;

pub const MAX_PATH: usize = 260;

pub const WINHTTP_FLAG_SECURE: ULONG = 0x00800000;
pub const WINHTTP_ACCESS_TYPE_DEFAULT_PROXY: ULONG = 0;
pub const WINHTTP_ACCESS_TYPE_NAMED_PROXY: ULONG = 3;
pub const WINHTTP_ADDREQ_FLAG_ADD_IF_NEW: ULONG = 0x10000000;
pub const WINHTTP_OPTION_ENABLE_HTTP2_PROTOCOL: ULONG = 133;
pub const WINHTTP_PROTOCOL_FLAG_HTTP2: ULONG = 0x1;

pub const WINHTTP_WEB_SOCKET_BUFFER_TYPE = enum(u32) {
    BINARY_MESSAGE = 0,
    BINARY_FRAGMENT = 1,
    UTF8_MESSAGE = 2,
    UTF8_FRAGMENT = 3,
    CLOSE = 4,
};

pub const IMAGE_DIRECTORY_ENTRY_EXPORT: usize = 0;
pub const IMAGE_SYM_CLASS_EXTERNAL: u8 = 2;
pub const IMAGE_FILE_MACHINE_AMD64: u16 = 0x8664;

pub const IMAGE_REL_AMD64_ABSOLUTE: u16 = 0x0000;
pub const IMAGE_REL_AMD64_ADDR64: u16 = 0x0001;
pub const IMAGE_REL_AMD64_ADDR32: u16 = 0x0002;
pub const IMAGE_REL_AMD64_ADDR32NB: u16 = 0x0003;
pub const IMAGE_REL_AMD64_REL32: u16 = 0x0004;
pub const IMAGE_REL_AMD64_REL32_1: u16 = 0x0005;
pub const IMAGE_REL_AMD64_REL32_2: u16 = 0x0006;
pub const IMAGE_REL_AMD64_REL32_3: u16 = 0x0007;
pub const IMAGE_REL_AMD64_REL32_4: u16 = 0x0008;
pub const IMAGE_REL_AMD64_REL32_5: u16 = 0x0009;

pub const COFF_SECT_EXEC: u32 = 0x20000000;
pub const COFF_SECT_WRITE: u32 = 0x80000000;
pub const COFF_SECT_DATA: u32 = 0x40000000;

pub const BCRYPT_AES_ALGORITHM: LPCWSTR = &[_:0]u16{ 'a', 'e', 's' };
pub const BCRYPT_CHAINING_MODE: LPCWSTR = &[_:0]u16{ 'C', 'h', 'a', 'i', 'n', 'i', 'n', 'g', 'M', 'o', 'd', 'e' };
pub const BCRYPT_CHAIN_MODE_GCM: LPCWSTR = &[_:0]u16{ 'C', 'h', 'a', 'i', 'n', 'i', 'n', 'g', 'M', 'o', 'd', 'e', 'G', 'C', 'M' };
pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: ULONG = 0x00000002;

pub const BCRYPT_ECDH_P256_ALGORITHM: LPCWSTR = &[_:0]u16{ 'E', 'C', 'D', 'H', '_', 'P', '2', '5', '6' };
pub const BCRYPT_ECCPUBLIC_BLOB: LPCWSTR = &[_:0]u16{ 'E', 'C', 'C', 'P', 'U', 'B', 'L', 'I', 'C', 'B', 'L', 'O', 'B' };
pub const BCRYPT_KDF_RAW_SECRET: ?*const anyopaque = @as(?*const anyopaque, @ptrFromInt(3));

pub const AES_KEY_SIZE: usize = 32;
pub const GCM_NONCE_SIZE: usize = 12;
pub const GCM_TAG_SIZE: usize = 16;

pub fn BCRYPT_INIT_AUTH_MODE_INFO(info: *BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO) void {
    info.cbSize = @sizeOf(BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO);
    info.dwInfoVersion = 1;
    info.pbNonce = null;
    info.cbNonce = 0;
    info.pbAuthData = null;
    info.cbAuthData = 0;
    info.pbTag = null;
    info.cbTag = 0;
    info.pbMacContext = null;
    info.cbMacContext = 0;
    info.dwFlags = 0;
    info.pbIV = null;
    info.cbIV = 0;
}

pub const UNICODE_STRING = extern struct {
    Length: u16,
    MaximumLength: u16,
    Buffer: [*]u16,
};

pub const SYSTEM_INFO = extern struct {
    u: extern union {
        dwOemId: DWORD,
        s: extern struct {
            wProcessorArchitecture: WORD,
            wReserved: WORD,
        },
    },
    dwPageSize: DWORD,
    lpMinimumApplicationAddress: LPVOID,
    lpMaximumApplicationAddress: LPVOID,
    dwActiveProcessorMask: DWORD_PTR,
    dwNumberOfProcessors: DWORD,
    dwProcessorType: DWORD,
    dwAllocationGranularity: DWORD,
    wProcessorLevel: WORD,
    wProcessorRevision: WORD,
};

pub const COORD = extern struct {
    X: SHORT,
    Y: SHORT,
};

pub const MEMORY_BASIC_INFORMATION = extern struct {
    BaseAddress: LPVOID,
    AllocationBase: LPVOID,
    AllocationProtect: DWORD,
    RegionSize: SIZE_T,
    State: DWORD,
    Protect: DWORD,
    Type: DWORD,
};

pub const SECURITY_ATTRIBUTES = extern struct {
    nLength: DWORD,
    lpSecurityDescriptor: ?LPVOID,
    bInheritHandle: BOOL,
};

pub const PROCESS_INFORMATION = extern struct {
    hProcess: HANDLE,
    hThread: HANDLE,
    dwProcessId: DWORD,
    dwThreadId: DWORD,
};

pub const STARTUPINFOA = extern struct {
    cb: DWORD,
    lpReserved: LPSTR,
    lpDesktop: LPSTR,
    lpTitle: LPSTR,
    dwX: DWORD,
    dwY: DWORD,
    dwXSize: DWORD,
    dwYSize: DWORD,
    dwXCountChars: DWORD,
    dwYCountChars: DWORD,
    dwFillAttribute: DWORD,
    dwFlags: DWORD,
    wShowWindow: WORD,
    cbReserved2: WORD,
    lpReserved2: *BYTE,
    hStdInput: HANDLE,
    hStdOutput: HANDLE,
    hStdError: HANDLE,
};

pub const SYSTEMTIME = extern struct {
    wYear: WORD,
    wMonth: WORD,
    wDayOfWeek: WORD,
    wDay: WORD,
    wHour: WORD,
    wMinute: WORD,
    wSecond: WORD,
    wMilliseconds: WORD,
};

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

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

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

pub const RTL_OSVERSIONINFOW = extern struct {
    dwOSVersionInfoSize: DWORD,
    dwMajorVersion: DWORD,
    dwMinorVersion: DWORD,
    dwBuildNumber: DWORD,
    dwPlatformId: DWORD,
    szCSDVersion: [128]WCHAR,
};

pub const BCRYPT_ALG_HANDLE = *opaque {};
pub const BCRYPT_KEY_HANDLE = *opaque {};
pub const BCRYPT_SECRET_HANDLE = *opaque {};

pub const BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO = extern struct {
    cbSize: ULONG,
    dwInfoVersion: ULONG,
    pbNonce: ?*u8,
    cbNonce: ULONG,
    pbAuthData: ?*u8,
    cbAuthData: ULONG,
    pbTag: ?*u8,
    cbTag: ULONG,
    pbMacContext: ?*u8,
    cbMacContext: ULONG,
    dwFlags: ULONG,
    pbIV: ?*u8,
    cbIV: ULONG,
};

pub const coff_file_header_t = extern struct {
    Machine: u16,
    NumberOfSections: u16,
    TimeDateStamp: u32,
    PointerToSymbolTable: u32,
    NumberOfSymbols: u32,
    SizeOfOptionalHeader: u16,
    Characteristics: u16,
};

pub const coff_section_header_t = extern struct {
    Name: [8]u8,
    VirtualSize: u32,
    VirtualAddress: u32,
    SizeOfRawData: u32,
    PointerToRawData: u32,
    PointerToRelocations: u32,
    PointerToLinenumbers: u32,
    NumberOfRelocations: u16,
    NumberOfLinenumbers: u16,
    Characteristics: u32,
};

pub const coff_symbol_t = extern struct {
    Name: extern union {
        ShortName: [8]u8,
        LongName: extern struct {
            Zeroes: u32,
            Offset: u32,
        },
    },
    Value: u32,
    SectionNumber: i16,
    Type: u16,
    StorageClass: u8,
    NumberOfAuxSymbols: u8,
};

pub const coff_reloc_t = extern struct {
    VirtualAddress: u32,
    SymbolTableIndex: u32,
    Type: u16,
};

pub const coff_mapped_section_t = struct {
    data: []u8,
    characteristics: u32,
    name: [8]u8,
};

pub const bof_data_parser_t = struct {
    data: []const u8,
    offset: usize,
};

pub const OBJECT_ATTRIBUTES = extern struct {
    Length: ULONG,
    RootDirectory: ?HANDLE,
    ObjectName: ?*anyopaque,
    Attributes: ULONG,
    SecurityDescriptor: ?*anyopaque,
    SecurityQualityOfService: ?*anyopaque,
};

pub const CLIENT_ID = extern struct {
    UniqueProcess: HANDLE,
    UniqueThread: ?HANDLE,
};

pub const PROCESS_INSTRUMENTATION_CALLBACK = extern struct {
    Version: ULONG,
    Reserved: ULONG,
    Callback: ?*anyopaque,
};

pub const PROCESS_CREATE_INFO = extern struct {
    Size: SIZE_T,
    ProcessHandle: HANDLE,
    ParentProcess: HANDLE,
};

pub const SECURITY_IMPERSONATION_LEVEL = enum(u32) {
    SecurityAnonymous = 0,
    SecurityIdentification = 1,
    SecurityImpersonation = 2,
    SecurityDelegation = 3,
};

pub const TOKEN_TYPE = enum(u32) {
    TokenPrimary = 1,
    TokenImpersonation = 2,
};

pub const TOKEN_DUPLICATE: DWORD = 0x0002;
pub const TOKEN_QUERY: DWORD = 0x0008;
pub const TOKEN_ADJUST_PRIVILEGES: DWORD = 0x0020;
pub const TOKEN_ASSIGN_PRIMARY: DWORD = 0x0001;
pub const TOKEN_IMPERSONATE: DWORD = 0x0004;

pub const LUID = extern struct {
    LowPart: DWORD,
    HighPart: LONG,
};

pub const LUID_AND_ATTRIBUTES = extern struct {
    Luid: LUID,
    Attributes: DWORD,
};

pub const TOKEN_PRIVILEGES = extern struct {
    PrivilegeCount: DWORD,
    Privileges: [1]LUID_AND_ATTRIBUTES,
};

pub const SE_PRIVILEGE_ENABLED: DWORD = 0x00000002;
pub const GENERIC_READ: DWORD = 0x80000000;
pub const GENERIC_WRITE: DWORD = 0x40000000;
pub const OPEN_EXISTING: DWORD = 3;
pub const OPEN_ALWAYS: DWORD = 4;
pub const CREATE_ALWAYS: DWORD = 2;
pub const FILE_SHARE_READ: DWORD = 0x00000001;
pub const FILE_SHARE_WRITE: DWORD = 0x00000002;
pub const FILE_ATTRIBUTE_NORMAL: DWORD = 0x00000080;
pub const INVALID_HANDLE_VALUE: HANDLE = @ptrFromInt(~@as(usize, 0));

pub const CRITICAL_SECTION = extern struct {
    DebugInfo: ?*anyopaque,
    LockCount: LONG,
    RecursionCount: LONG,
    OwningThread: HANDLE,
    LockSemaphore: HANDLE,
    SpinCount: ULONG_PTR,
};

pub const PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: DWORD_PTR = 0x00020016;
