/*
 * ci_probe.h
 *
 * Types and declarations for ci_probe.c.
 * See https://dkom.dev/posts/dse-ci-patch/ for the technique write-up.
 */

#pragma once

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdint.h>

typedef unsigned char      u8;
typedef unsigned long long u64;

/* WinIO64.sys IOCTLs */
#define IOCTL_WINIO_MAP_PHYSMEM   0x80102040
#define IOCTL_WINIO_UNMAP_PHYSMEM 0x80102044

#pragma pack(push, 1)
struct winio_packet {
    u64 size;
    u64 phys_address;
    u64 phys_handle;
    u64 phys_linear;
    u64 phys_section;
};
#pragma pack(pop)

/* WinIO device handle (set by winio_open) */
extern HANDLE g_winio;

/* physical memory read/write via WinIO */
int  winio_open(void);
void winio_close(void);
int  read_phys(u64 pa, void *buf, u64 len);
int  write_phys(u64 pa, const void *buf, u64 len);  /* not called by the probe */

/* kernel module VA from NtQuerySystemInformation class 11 */
u64  get_kernel_module_va(const char *module_name);

/* map a file as a section image (SEC_IMAGE layout) */
void *map_file_image(const char *path);

/* byte pattern scan */
const u8 *scan_sig(const u8 *buf, size_t buf_len,
                   const u8 *sig, size_t sig_len);

/* physical memory scan for ntoskrnl MZ header */
u64  find_ntoskrnl_pa(void);

/* extract PTE_BASE from MiGetPteAddress in physical ntoskrnl pages */
u64  find_pte_base(u64 ntos_pa);

/*
 * Compute PTE virtual address for an arbitrary kernel VA.
 * This is the same arithmetic MiGetPteAddress uses at runtime.
 * Returns a kernel VA in the self-map region -- not a physical address.
 *
 * To read or write the PTE via a physical primitive (WinIO), you need
 * to translate this VA to its physical address first. That requires a
 * page-table walk using the physical pages found from the scan.
 * The walk is described in the post; it is not implemented here.
 */
u64  pte_va_for(u64 pte_base, u64 kernel_va);
