FUCKYOU
This commit is contained in:
+1004
-30
@@ -1,22 +1,45 @@
|
||||
/* pe_shim.c — Windows API shim 实现。
|
||||
/* pe_shim.c — Windows API shim 实现.
|
||||
*
|
||||
* 所有 64位 shim 用 __attribute__((ms_abi)) 声明,匹配 PE32+ 调用约定。
|
||||
* 32位 shim 从模拟栈读参数,供 x86emu32 解释器调用。
|
||||
* 所有 64位 shim 用 __attribute__((ms_abi)) 声明,匹配 PE32+ 调用约定.
|
||||
* 32位 shim 从模拟栈读参数,供 x86emu32 解释器调用.
|
||||
*
|
||||
* 支持 API:kernel32.dll(GetStdHandle/WriteFile/ReadFile/ExitProcess/
|
||||
* HeapAlloc/HeapFree/VirtualAlloc/VirtualFree/GetCommandLineA/...)
|
||||
* msvcrt.dll(printf/puts/putchar/malloc/free/exit/memcpy/memset/
|
||||
* strlen/strcmp/strcpy/_initterm/_initterm_e)
|
||||
* 支持 API:
|
||||
* kernel32.dll 控制台、文件、堆、模块、编码转换、QPC、Sleep、同步、卸载桩
|
||||
* msvcrt.dll printf、puts、malloc、free、mem 系列、str 系列、_initterm
|
||||
* ntdll.dll NtWriteFile、RtlNtStatusToDosError
|
||||
* bcryptprimitives.dll ProcessPrng (rdtsc xorshift)
|
||||
* api-ms-win-core-synch-l1-2-0.dll WaitOnAddress、WakeByAddress (futex 桩)
|
||||
* user32.dll 窗口类、窗口、消息泵 (PS/2 键盘轮询)、DefWindowProc
|
||||
* gdi32.dll 内存 DC、DIBSection、BitBlt 到 Limine 帧缓冲
|
||||
*
|
||||
* 窗口模型:单顶层窗口 (固定伪句柄),GetDC 返回窗口 DC,
|
||||
* BitBlt(窗口 DC, ...) 把 DIB 后台缓冲按窗口原点拷入帧缓冲.
|
||||
* 消息泵:PeekMessageW 轮询 PS/2 键盘 (0x64/0x60),生成
|
||||
* WM_KEYDOWN、WM_KEYUP、WM_CHAR;Esc 额外合成 WM_CLOSE (无鼠标环境的
|
||||
* 唯一退出途径).鼠标字节 (状态位 0x20) 直接丢弃.
|
||||
*/
|
||||
|
||||
#include "pe_shim.h"
|
||||
#include <utsm/arena.h>
|
||||
#include <utsm/log.h>
|
||||
#include <utsm/types.h>
|
||||
#include "../arch/x86_64/limine.h"
|
||||
|
||||
/* arch/x86_64/io.c */
|
||||
extern void outb(u16 port, u8 value);
|
||||
extern u8 inb(u16 port);
|
||||
|
||||
/* dkm/boot_modules.c — Limine framebuffer 请求(GDI BitBlt 目标) */
|
||||
extern volatile struct limine_framebuffer_request g_fb_request;
|
||||
|
||||
/* 前向声明:shim 用户态堆(实现见下文"用户态堆"一节) */
|
||||
static void *shim_heap_alloc(u64 size);
|
||||
static void shim_heap_free(void *ptr);
|
||||
static void *shim_heap_realloc(void *ptr, u64 size);
|
||||
|
||||
/* setjmp/longjmp for ExitProcess — 使用 __builtin_setjmp/__builtin_longjmp
|
||||
* (clang/gcc 内置,freestanding 可用,无需 libc)。
|
||||
* __builtin_setjmp 接受 void** 缓冲区,至少需要 8 个指针槽。 */
|
||||
* (clang/gcc 内置,freestanding 可用,无需 libc).
|
||||
* __builtin_setjmp 接受 void** 缓冲区,至少需要 8 个指针槽. */
|
||||
static void *g_exit_jmp[24];
|
||||
static int g_exit_jmp_set;
|
||||
static u64 g_exit_code;
|
||||
@@ -28,7 +51,7 @@ void pe_shim_init(const char *cmdline) {
|
||||
g_exit_code = 0;
|
||||
}
|
||||
|
||||
/* pe_run 调用:保存上下文,返回 0 = 首次(继续执行),1 = ExitProcess 触发 */
|
||||
/* pe_run 调用:保存上下文,返回 0 = 首次(继续执行),1 = ExitProcess 触发 */
|
||||
int pe_shim_setup_exit(void) {
|
||||
g_exit_jmp_set = 1;
|
||||
return __builtin_setjmp(g_exit_jmp);
|
||||
@@ -39,7 +62,7 @@ void pe_shim_exit_process(u64 exit_code) {
|
||||
if (g_exit_jmp_set) {
|
||||
__builtin_longjmp(g_exit_jmp, 1);
|
||||
}
|
||||
/* 无 jmpbuf:直接返回 */
|
||||
/* 无 jmpbuf:直接返回 */
|
||||
}
|
||||
|
||||
int pe_shim_is_exit_call(u64 target) {
|
||||
@@ -57,7 +80,7 @@ u64 pe_shim_unimpl_stub(void) {
|
||||
return pe_shim_unimpl64_addr();
|
||||
}
|
||||
|
||||
/* ===== 串口/帧缓冲输出(shim 内部复用) ===== */
|
||||
/* ===== 串口/帧缓冲输出(shim 内部复用) ===== */
|
||||
static void shim_output(const char *s, u64 len) {
|
||||
for (u64 i = 0; i < len; i++) {
|
||||
serial_putc(s[i]);
|
||||
@@ -70,6 +93,9 @@ static void shim_output_str(const char *s) {
|
||||
|
||||
/* ===== kernel32.dll shims (64位, ms_abi) ===== */
|
||||
|
||||
/* 线程本地 last-error(简化全局) */
|
||||
static u64 g_last_error = 0;
|
||||
|
||||
/* 句柄定义 */
|
||||
#define STD_INPUT_HANDLE ((u64)0xFFFFFFF6)
|
||||
#define STD_OUTPUT_HANDLE ((u64)0xFFFFFFF5)
|
||||
@@ -91,7 +117,8 @@ static u64 __attribute__((ms_abi)) shim_WriteFile(u64 handle, u64 buffer, u64 le
|
||||
if (handle == SHIM_STDOUT_HANDLE || handle == SHIM_STDERR_HANDLE) {
|
||||
const char *buf = (const char *)buffer;
|
||||
shim_output(buf, length);
|
||||
if (bytes_written_ptr) *(u64 *)bytes_written_ptr = length;
|
||||
/* lpNumberOfBytesWritten 是 DWORD*(4 字节),不能按 u64 写 */
|
||||
if (bytes_written_ptr) *(u32 *)bytes_written_ptr = (u32)length;
|
||||
return 1; /* TRUE */
|
||||
}
|
||||
return 0;
|
||||
@@ -115,23 +142,36 @@ static u64 __attribute__((ms_abi)) shim_GetCommandLineA(void) {
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_GetCommandLineW(void) {
|
||||
return (u64)g_cmdline; /* 简化:返回 ASCII */
|
||||
return (u64)g_cmdline; /* 简化:返回 ASCII */
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_GetLastError(void) { return 0; }
|
||||
static u64 __attribute__((ms_abi)) shim_SetLastError(u64 code) { (void)code; return 0; }
|
||||
static u64 __attribute__((ms_abi)) shim_GetLastError(void) { return g_last_error; }
|
||||
static u64 __attribute__((ms_abi)) shim_SetLastError(u64 code) { g_last_error = code; return 0; }
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_HeapCreate(u64 fl, u64 init, u64 max) {
|
||||
(void)fl; (void)init; (void)max;
|
||||
return 0x10000010; /* 假堆句柄 */
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_HeapAlloc(u64 heap, u64 flags, u64 size) {
|
||||
(void)heap; (void)flags;
|
||||
return (u64)kmem_alloc(size);
|
||||
(void)heap;
|
||||
void *p = shim_heap_alloc(size);
|
||||
if (p && (flags & 8)) { /* HEAP_ZERO_MEMORY */
|
||||
u8 *z = (u8 *)p;
|
||||
for (u64 i = 0; i < size; i++) z[i] = 0;
|
||||
}
|
||||
return (u64)p;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_HeapFree(u64 heap, u64 flags, u64 ptr) {
|
||||
(void)heap; (void)flags; (void)ptr;
|
||||
return 1; /* arena 无 free,返回 TRUE */
|
||||
(void)heap; (void)flags;
|
||||
shim_heap_free((void *)ptr);
|
||||
return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_HeapReAlloc(u64 heap, u64 flags, u64 ptr, u64 size) {
|
||||
(void)heap; (void)flags;
|
||||
return (u64)shim_heap_realloc((void *)ptr, size);
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_GetProcessHeap(void) {
|
||||
return 0x10000010;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_VirtualAlloc(u64 addr, u64 size, u64 alloc_type, u64 protect) {
|
||||
(void)addr; (void)alloc_type; (void)protect;
|
||||
@@ -172,10 +212,10 @@ static void shim_msvcrt_output(const char *s) {
|
||||
shim_output_str(s);
|
||||
}
|
||||
|
||||
/* printf — 简化版,只支持 %s %d %c %x %u %% */
|
||||
/* printf — 简化版,只支持 %s %d %c %x %u %% */
|
||||
static u64 __attribute__((ms_abi)) shim_printf(u64 fmt, u64 a1, u64 a2, u64 a3) {
|
||||
/* 可变参数:MS x64 ABI 下 a1-a3 在 RDX/R8/R9,更多参数在栈上。
|
||||
* 简化处理:只处理前 3 个参数。 */
|
||||
/* 可变参数:MS x64 ABI 下 a1-a3 在 RDX/R8/R9,更多参数在栈上.
|
||||
* 简化处理:只处理前 3 个参数. */
|
||||
const char *f = (const char *)fmt;
|
||||
u64 args[3] = {a1, a2, a3};
|
||||
int argi = 0;
|
||||
@@ -244,17 +284,17 @@ static u64 __attribute__((ms_abi)) shim_putchar(u64 ch) {
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_malloc(u64 size) {
|
||||
return (u64)kmem_alloc(size);
|
||||
return (u64)shim_heap_alloc(size);
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_calloc(u64 count, u64 size) {
|
||||
u64 total = count * size;
|
||||
u8 *p = kmem_alloc(total);
|
||||
u8 *p = shim_heap_alloc(total);
|
||||
if (p) for (u64 i = 0; i < total; i++) p[i] = 0;
|
||||
return (u64)p;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_free(u64 ptr) { (void)ptr; return 0; }
|
||||
static u64 __attribute__((ms_abi)) shim_free(u64 ptr) { shim_heap_free((void *)ptr); return 0; }
|
||||
static u64 __attribute__((ms_abi)) shim_realloc(u64 ptr, u64 size) {
|
||||
(void)ptr; return (u64)kmem_alloc(size);
|
||||
return (u64)shim_heap_realloc((void *)ptr, size);
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_exit(u64 code) {
|
||||
pe_shim_exit_process(code);
|
||||
@@ -316,8 +356,8 @@ static u64 __attribute__((ms_abi)) shim_fputc(u64 ch, u64 stream) {
|
||||
serial_putc((char)(ch & 0xFF));
|
||||
return ch & 0xFF;
|
||||
}
|
||||
/* _initterm / _initterm_e — CRT 初始化,遍历函数指针表调用。
|
||||
* 简化:直接跳过(返回 0)。 */
|
||||
/* _initterm / _initterm_e — CRT 初始化,遍历函数指针表调用.
|
||||
* 简化:直接跳过(返回 0). */
|
||||
static u64 __attribute__((ms_abi)) shim_initterm(u64 start, u64 end) {
|
||||
(void)start; (void)end;
|
||||
return 0;
|
||||
@@ -327,10 +367,866 @@ static u64 __attribute__((ms_abi)) shim_initterm_e(u64 start, u64 end) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 未实现 stub(64位)— 日志告警并返回 0 */
|
||||
/* ============================================================
|
||||
* 用户态堆(free-list,支持真正 free/realloc)
|
||||
*
|
||||
* Rust std 的 GlobalAlloc 走 GetProcessHeap/HeapAlloc/HeapReAlloc/
|
||||
* HeapFree.arena 只增不减,GUI 主循环每帧的 Vec 分配会耗尽内存,
|
||||
* 因此 shim 从 arena carve 一块 8MB 区域自行管理:
|
||||
* 32B 块头 {size,used,next_free,pad},首次适应 + 分割 + 前向合并.
|
||||
* ========================================================== */
|
||||
|
||||
#define SHIM_HEAP_BYTES (8ULL * 1024ULL * 1024ULL)
|
||||
#define HEAP_HDR 32
|
||||
|
||||
typedef struct heap_blk {
|
||||
u64 size; /* 数据区字节数(不含头) */
|
||||
u64 used; /* 1=已分配 */
|
||||
u64 next_free; /* 空闲链表(heap_blk*,0=尾) */
|
||||
u64 pad;
|
||||
} heap_blk;
|
||||
|
||||
static u8 *g_heap_region;
|
||||
static heap_blk *g_heap_free_head;
|
||||
|
||||
static void shim_heap_init_once(void) {
|
||||
if (g_heap_region) return;
|
||||
g_heap_region = (u8 *)kmem_alloc_aligned(SHIM_HEAP_BYTES, 16);
|
||||
if (!g_heap_region) {
|
||||
log_error("[shim] heap region alloc failed");
|
||||
return;
|
||||
}
|
||||
heap_blk *b = (heap_blk *)g_heap_region;
|
||||
b->size = SHIM_HEAP_BYTES - HEAP_HDR;
|
||||
b->used = 0;
|
||||
b->next_free = 0;
|
||||
b->pad = 0;
|
||||
g_heap_free_head = b;
|
||||
}
|
||||
|
||||
static void *shim_heap_alloc(u64 size) {
|
||||
shim_heap_init_once();
|
||||
if (!g_heap_region) return 0;
|
||||
if (size == 0) size = 16;
|
||||
size = (size + 15) & ~15ULL;
|
||||
heap_blk *prev = 0, *b = g_heap_free_head;
|
||||
while (b) {
|
||||
if (b->size >= size) {
|
||||
if (prev) prev->next_free = b->next_free;
|
||||
else g_heap_free_head = (heap_blk *)b->next_free;
|
||||
/* 剩余足够再分一块则分割 */
|
||||
if (b->size >= size + HEAP_HDR + 16) {
|
||||
heap_blk *nb = (heap_blk *)((u8 *)b + HEAP_HDR + size);
|
||||
nb->size = b->size - size - HEAP_HDR;
|
||||
nb->used = 0;
|
||||
nb->pad = 0;
|
||||
nb->next_free = (u64)g_heap_free_head;
|
||||
g_heap_free_head = nb;
|
||||
b->size = size;
|
||||
}
|
||||
b->used = 1;
|
||||
b->next_free = 0;
|
||||
return (u8 *)b + HEAP_HDR;
|
||||
}
|
||||
prev = b;
|
||||
b = (heap_blk *)b->next_free;
|
||||
}
|
||||
log_error("[shim] heap OOM");
|
||||
log_hex64("[shim] heap req=", size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void shim_heap_free(void *ptr) {
|
||||
if (!ptr) return;
|
||||
heap_blk *b = (heap_blk *)((u8 *)ptr - HEAP_HDR);
|
||||
b->used = 0;
|
||||
/* 前向合并:物理下一块若空闲则吸收 */
|
||||
heap_blk *nb = (heap_blk *)((u8 *)b + HEAP_HDR + b->size);
|
||||
if ((u8 *)nb >= g_heap_region && (u8 *)nb < g_heap_region + SHIM_HEAP_BYTES
|
||||
&& !nb->used && nb->size) {
|
||||
/* 从空闲链摘除 nb */
|
||||
heap_blk *prev = 0, *x = g_heap_free_head;
|
||||
while (x && x != nb) { prev = x; x = (heap_blk *)x->next_free; }
|
||||
if (x == nb) {
|
||||
if (prev) prev->next_free = nb->next_free;
|
||||
else g_heap_free_head = (heap_blk *)nb->next_free;
|
||||
b->size += HEAP_HDR + nb->size;
|
||||
}
|
||||
}
|
||||
b->next_free = (u64)g_heap_free_head;
|
||||
g_heap_free_head = b;
|
||||
}
|
||||
|
||||
static void *shim_heap_realloc(void *ptr, u64 size) {
|
||||
if (!ptr) return shim_heap_alloc(size);
|
||||
heap_blk *b = (heap_blk *)((u8 *)ptr - HEAP_HDR);
|
||||
u64 old = b->size;
|
||||
if (size <= old) return ptr;
|
||||
u8 *np = (u8 *)shim_heap_alloc(size);
|
||||
if (!np) return 0;
|
||||
const u8 *s = (const u8 *)ptr;
|
||||
for (u64 i = 0; i < old; i++) np[i] = s[i];
|
||||
shim_heap_free(ptr);
|
||||
return np;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* TSC 计时(QueryPerformanceCounter/Frequency、GetTickCount、Sleep)
|
||||
* PIT channel 0 一次性校准(与 cmd.elf 同款手法).
|
||||
* ========================================================== */
|
||||
|
||||
static __inline__ u64 shim_rdtsc(void) {
|
||||
u32 lo, hi;
|
||||
__asm__ volatile("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
return ((u64)hi << 32) | lo;
|
||||
}
|
||||
|
||||
static u64 g_tsc_per_ms = 0;
|
||||
|
||||
static void shim_tsc_init(void) {
|
||||
if (g_tsc_per_ms) return;
|
||||
outb(0x43, 0x30);
|
||||
outb(0x40, 0x7c);
|
||||
outb(0x40, 0x2e);
|
||||
u64 t0 = shim_rdtsc();
|
||||
u16 prev = 0; u64 loops = 0;
|
||||
for (;;) {
|
||||
outb(0x43, 0x00);
|
||||
u16 cur = (u16)inb(0x40) | ((u16)inb(0x40) << 8);
|
||||
if (cur > prev && loops > 10) break;
|
||||
prev = cur; loops++;
|
||||
}
|
||||
u64 t1 = shim_rdtsc();
|
||||
g_tsc_per_ms = (t1 - t0) / 10;
|
||||
if (!g_tsc_per_ms) g_tsc_per_ms = 1000000; /* 兜底 1GHz */
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_QueryPerformanceFrequency(u64 freq_ptr) {
|
||||
shim_tsc_init();
|
||||
if (freq_ptr) *(u64 *)freq_ptr = g_tsc_per_ms * 1000;
|
||||
return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_QueryPerformanceCounter(u64 count_ptr) {
|
||||
shim_tsc_init();
|
||||
if (count_ptr) *(u64 *)count_ptr = shim_rdtsc();
|
||||
return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_GetTickCount(void) {
|
||||
shim_tsc_init();
|
||||
return shim_rdtsc() / g_tsc_per_ms;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_Sleep(u64 ms) {
|
||||
shim_tsc_init();
|
||||
u64 end = shim_rdtsc() + ms * g_tsc_per_ms;
|
||||
while (shim_rdtsc() < end) __asm__ volatile("pause");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* SYSTEM_INFO(x64,48 字节) */
|
||||
static u64 __attribute__((ms_abi)) shim_GetSystemInfo(u64 si_p) {
|
||||
if (!si_p) return 0;
|
||||
u8 *p = (u8 *)si_p;
|
||||
for (int i = 0; i < 48; i++) p[i] = 0;
|
||||
*(u32 *)(p + 0) = 9; /* PROCESSOR_ARCHITECTURE_AMD64 */
|
||||
*(u32 *)(p + 4) = 4096; /* dwPageSize */
|
||||
*(u32 *)(p + 20) = 1; /* dwNumberOfProcessors */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* kernel32 增量:控制台/目录/环境/进程/同步/Rtl/编码转换
|
||||
* ========================================================== */
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_GetConsoleMode(u64 handle, u64 mode_ptr) {
|
||||
(void)handle; (void)mode_ptr;
|
||||
g_last_error = 6; /* ERROR_INVALID_HANDLE -> std 回退 WriteFile */
|
||||
return 0;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_GetConsoleOutputCP(void) { return 65001; }
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_WriteConsoleW(u64 handle, u64 buf, u64 nchars,
|
||||
u64 written_ptr, u64 reserved) {
|
||||
(void)reserved;
|
||||
if (handle != SHIM_STDOUT_HANDLE && handle != SHIM_STDERR_HANDLE) return 0;
|
||||
const u16 *s = (const u16 *)buf;
|
||||
for (u64 i = 0; i < nchars; i++) {
|
||||
u32 c = s[i];
|
||||
if (c < 0x80) {
|
||||
serial_putc((char)c);
|
||||
} else if (c < 0x800) {
|
||||
serial_putc((char)(0xC0 | (c >> 6)));
|
||||
serial_putc((char)(0x80 | (c & 0x3F)));
|
||||
} else {
|
||||
serial_putc((char)(0xE0 | (c >> 12)));
|
||||
serial_putc((char)(0x80 | ((c >> 6) & 0x3F)));
|
||||
serial_putc((char)(0x80 | (c & 0x3F)));
|
||||
}
|
||||
}
|
||||
if (written_ptr) *(u32 *)written_ptr = (u32)nchars;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_GetCurrentDirectoryW(u64 buflen, u64 buf) {
|
||||
static const u16 cwd[] = { 'C', ':', '\\', 0 };
|
||||
if (!buf || buflen < 4) return 4; /* 需要 4 个字符(含 NUL) */
|
||||
u16 *out = (u16 *)buf;
|
||||
for (int i = 0; i < 4; i++) out[i] = cwd[i];
|
||||
return 3; /* 不含 NUL 的字符数 */
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_GetEnvironmentVariableW(u64 name, u64 buf, u64 size) {
|
||||
(void)name; (void)buf; (void)size;
|
||||
g_last_error = 203; /* ERROR_ENVVAR_NOT_FOUND */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_GetCurrentProcess(void) { return (u64)-1; }
|
||||
static u64 __attribute__((ms_abi)) shim_GetCurrentProcessId(void) { return 1; }
|
||||
static u64 __attribute__((ms_abi)) shim_GetCurrentThreadId(void) { return 1; }
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_CreateMutexA(u64 sa, u64 initial, u64 name) {
|
||||
(void)sa; (void)initial; (void)name;
|
||||
return 0x10000030;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_ReleaseMutex(u64 h) { (void)h; return 1; }
|
||||
static u64 __attribute__((ms_abi)) shim_WaitForSingleObject(u64 h, u64 ms) {
|
||||
(void)h; (void)ms; return 0; /* WAIT_OBJECT_0 */
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_WaitForSingleObjectEx(u64 h, u64 ms, u64 alert) {
|
||||
(void)h; (void)ms; (void)alert; return 0;
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_FormatMessageW(u64 flags, u64 src, u64 msgid,
|
||||
u64 lang, u64 buf, u64 size, u64 args) {
|
||||
(void)flags; (void)src; (void)msgid; (void)lang; (void)buf; (void)size; (void)args;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_LoadLibraryA(u64 name_p) {
|
||||
if (!name_p) return 0;
|
||||
const char *n = (const char *)name_p;
|
||||
/* 已知 DLL 返回伪句柄(大小写不敏感子串匹配) */
|
||||
static const char *known[] = { "kernel32", "ntdll", "user32", "gdi32", "msvcrt" };
|
||||
for (int k = 0; k < 5; k++) {
|
||||
const char *pat = known[k];
|
||||
for (const char *p = n; *p; p++) {
|
||||
int i = 0;
|
||||
while (pat[i] && p[i]) {
|
||||
char a = p[i], b = pat[i];
|
||||
if (a >= 'A' && a <= 'Z') a += 32;
|
||||
if (a != b) break;
|
||||
i++;
|
||||
}
|
||||
if (pat[i] == 0) return 0x10000020;
|
||||
}
|
||||
}
|
||||
g_last_error = 126; /* ERROR_MOD_NOT_FOUND */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_lstrlenW(u64 str_p) {
|
||||
const u16 *s = (const u16 *)str_p;
|
||||
u64 n = 0;
|
||||
if (s) while (s[n]) n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
/* GetProcAddress — 在 shim 表内按函数名全局查找(hModule 为伪句柄,不限定 DLL).
|
||||
* lpProcName 高 16 位为 0 时是 ordinal(不支持,返回 0)。
|
||||
* Rust std 用它动态探测 Rtl 系列/dbghelp API,命中返回真实 shim 地址,miss 返回 0。 */
|
||||
static u64 __attribute__((ms_abi)) shim_GetProcAddress(u64 module, u64 name_p) {
|
||||
(void)module;
|
||||
if (!name_p) return 0;
|
||||
if ((name_p >> 16) == 0) { /* ordinal 导入 */
|
||||
g_last_error = 127; /* ERROR_PROC_NOT_FOUND */
|
||||
return 0;
|
||||
}
|
||||
const char *name = (const char *)name_p;
|
||||
int n = pe_shim_count();
|
||||
for (int i = 0; i < n; i++) {
|
||||
const pe_shim_entry *e = pe_shim_get(i);
|
||||
if (!e || !e->func || !e->fn64) continue;
|
||||
const char *a = e->func, *b = name;
|
||||
while (*a && *b && *a == *b) { a++; b++; }
|
||||
if (*a == *b) return (u64)e->fn64;
|
||||
}
|
||||
log_info("[shim] GetProcAddress miss");
|
||||
serial_write(" -> ");
|
||||
serial_write(name);
|
||||
serial_write("\n");
|
||||
g_last_error = 127;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Rtl* — Rust panic/unwind 机制引用(panic=abort 下不会真正走到) */
|
||||
static u64 __attribute__((ms_abi)) shim_RtlCaptureContext(u64 ctx_p) {
|
||||
u8 *p = (u8 *)ctx_p;
|
||||
if (p) for (int i = 0; i < 1232; i++) p[i] = 0; /* x64 CONTEXT ≈ 1232B */
|
||||
return 0;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_RtlLookupFunctionEntry(u64 rip, u64 base_p, u64 table_p) {
|
||||
(void)rip;
|
||||
if (base_p) *(u64 *)base_p = 0;
|
||||
if (table_p) *(u64 *)table_p = 0;
|
||||
return 0;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_RtlVirtualUnwind(u64 a, u64 b, u64 c, u64 d,
|
||||
u64 e, u64 f, u64 g, u64 h, u64 i2) {
|
||||
(void)a; (void)b; (void)c; (void)d; (void)e; (void)f; (void)g; (void)h; (void)i2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---- MultiByteToWideChar / WideCharToMultiByte(CP_UTF8 + Latin-1)---- */
|
||||
static u64 __attribute__((ms_abi)) shim_MultiByteToWideChar(u64 cp, u64 flags, u64 mbs_p,
|
||||
u64 cbmb, u64 wbuf_p, u64 cchw) {
|
||||
(void)flags;
|
||||
const u8 *s = (const u8 *)mbs_p;
|
||||
u16 *out = (u16 *)wbuf_p;
|
||||
i64 remain = (i64)cbmb; /* -1 = NUL 结尾 */
|
||||
u64 need = 0;
|
||||
if (!s) return 0;
|
||||
for (;;) {
|
||||
if (remain == 0) break;
|
||||
u8 b0 = s[0];
|
||||
if (b0 == 0) {
|
||||
if (remain < 0) { /* -1 模式把 NUL 计入 */
|
||||
if (out && cchw > need) out[need] = 0;
|
||||
need++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
u32 cp32; u64 adv;
|
||||
if (cp == 65001 && b0 >= 0xC2 && b0 < 0xE0 && (remain < 0 || remain >= 2)
|
||||
&& (s[1] & 0xC0) == 0x80) {
|
||||
cp32 = ((u32)(b0 & 0x1F) << 6) | (s[1] & 0x3F); adv = 2;
|
||||
} else if (cp == 65001 && b0 >= 0xE0 && b0 < 0xF0 && (remain < 0 || remain >= 3)
|
||||
&& (s[1] & 0xC0) == 0x80 && (s[2] & 0xC0) == 0x80) {
|
||||
cp32 = ((u32)(b0 & 0x0F) << 12) | ((u32)(s[1] & 0x3F) << 6) | (s[2] & 0x3F); adv = 3;
|
||||
} else if (cp == 65001 && b0 >= 0xF0 && b0 < 0xF5 && (remain < 0 || remain >= 4)
|
||||
&& (s[1] & 0xC0) == 0x80 && (s[2] & 0xC0) == 0x80 && (s[3] & 0xC0) == 0x80) {
|
||||
cp32 = ((u32)(b0 & 0x07) << 18) | ((u32)(s[1] & 0x3F) << 12)
|
||||
| ((u32)(s[2] & 0x3F) << 6) | (s[3] & 0x3F); adv = 4;
|
||||
} else {
|
||||
cp32 = b0; adv = 1; /* Latin-1 / 非法序列按字节 */
|
||||
}
|
||||
if (cp32 > 0xFFFF) {
|
||||
if (out && cchw > need + 1) {
|
||||
cp32 -= 0x10000;
|
||||
out[need] = (u16)(0xD800 + (cp32 >> 10));
|
||||
out[need + 1] = (u16)(0xDC00 + (cp32 & 0x3FF));
|
||||
}
|
||||
need += 2;
|
||||
} else {
|
||||
if (out && cchw > need) out[need] = (u16)cp32;
|
||||
need++;
|
||||
}
|
||||
s += adv;
|
||||
if (remain > 0) remain -= (i64)adv;
|
||||
}
|
||||
return need;
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_WideCharToMultiByte(u64 cp, u64 flags, u64 ws_p,
|
||||
u64 cchw, u64 mbs_p, u64 cbmb,
|
||||
u64 defc, u64 used_p) {
|
||||
(void)flags; (void)defc;
|
||||
const u16 *s = (const u16 *)ws_p;
|
||||
u8 *out = (u8 *)mbs_p;
|
||||
i64 remain = (i64)cchw; /* -1 = NUL 结尾 */
|
||||
u64 need = 0;
|
||||
if (used_p) *(u32 *)used_p = 0;
|
||||
if (!s) return 0;
|
||||
for (;;) {
|
||||
if (remain == 0) break;
|
||||
u16 w = s[0];
|
||||
if (w == 0) {
|
||||
if (remain < 0) {
|
||||
if (out && cbmb > need) out[need] = 0;
|
||||
need++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
u32 cp32 = w; u64 adv = 1;
|
||||
if (w >= 0xD800 && w < 0xDC00 && (remain < 0 || remain >= 2)
|
||||
&& s[1] >= 0xDC00 && s[1] < 0xE000) {
|
||||
cp32 = 0x10000 + (((u32)(w - 0xD800) << 10) | (s[1] - 0xDC00));
|
||||
adv = 2;
|
||||
}
|
||||
u8 enc[4]; u64 elen;
|
||||
if (cp == 65001) {
|
||||
if (cp32 < 0x80) { enc[0] = (u8)cp32; elen = 1; }
|
||||
else if (cp32 < 0x800) {
|
||||
enc[0] = (u8)(0xC0 | (cp32 >> 6)); enc[1] = (u8)(0x80 | (cp32 & 0x3F)); elen = 2;
|
||||
} else if (cp32 < 0x10000) {
|
||||
enc[0] = (u8)(0xE0 | (cp32 >> 12)); enc[1] = (u8)(0x80 | ((cp32 >> 6) & 0x3F));
|
||||
enc[2] = (u8)(0x80 | (cp32 & 0x3F)); elen = 3;
|
||||
} else {
|
||||
enc[0] = (u8)(0xF0 | (cp32 >> 18)); enc[1] = (u8)(0x80 | ((cp32 >> 12) & 0x3F));
|
||||
enc[2] = (u8)(0x80 | ((cp32 >> 6) & 0x3F)); enc[3] = (u8)(0x80 | (cp32 & 0x3F));
|
||||
elen = 4;
|
||||
}
|
||||
} else {
|
||||
enc[0] = (u8)(cp32 < 256 ? cp32 : '?'); elen = 1;
|
||||
}
|
||||
if (out) for (u64 i = 0; i < elen; i++) { if (cbmb > need + i) out[need + i] = enc[i]; }
|
||||
need += elen;
|
||||
s += adv;
|
||||
if (remain > 0) remain -= (i64)adv;
|
||||
}
|
||||
return need;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* ntdll.dll / bcryptprimitives.dll / api-ms-win-core-synch
|
||||
* ========================================================== */
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_NtWriteFile(u64 fh, u64 ev, u64 apc_r, u64 apc_c,
|
||||
u64 iosb, u64 buf, u64 len,
|
||||
u64 off, u64 key) {
|
||||
(void)ev; (void)apc_r; (void)apc_c; (void)off; (void)key;
|
||||
if (fh == SHIM_STDOUT_HANDLE || fh == SHIM_STDERR_HANDLE) {
|
||||
shim_output((const char *)buf, len);
|
||||
}
|
||||
if (iosb) { /* IO_STATUS_BLOCK: {NTSTATUS Status; ULONG_PTR Information} */
|
||||
((u64 *)iosb)[0] = 0;
|
||||
((u64 *)iosb)[1] = len;
|
||||
}
|
||||
return 0; /* STATUS_SUCCESS */
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_RtlNtStatusToDosError(u64 status) {
|
||||
return status & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_ProcessPrng(u64 buf, u64 len) {
|
||||
u64 s = shim_rdtsc() ^ 0x9E3779B97F4A7C15ULL;
|
||||
u8 *p = (u8 *)buf;
|
||||
for (u64 i = 0; i < len; i++) {
|
||||
s ^= s << 13; s ^= s >> 7; s ^= s << 17; /* xorshift64 */
|
||||
p[i] = (u8)(s & 0xFF);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* WaitOnAddress 允许虚假唤醒(调用者自旋重检),立即返回 TRUE 合法 */
|
||||
static u64 __attribute__((ms_abi)) shim_WaitOnAddress(u64 addr, u64 expected, u64 size, u64 timeout) {
|
||||
(void)addr; (void)expected; (void)size; (void)timeout;
|
||||
return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_WakeByAddress(u64 addr) { (void)addr; return 0; }
|
||||
|
||||
/* ============================================================
|
||||
* user32.dll — 单窗口 + 消息泵(PS/2 键盘轮询)
|
||||
* ========================================================== */
|
||||
|
||||
#define SHIM_HWND 0x20000001ULL
|
||||
#define SHIM_HDC_WND 0x20000002ULL
|
||||
#define SHIM_HCURSOR 0x20000003ULL
|
||||
|
||||
#define SHIM_WM_CLOSE 0x0010u
|
||||
#define SHIM_WM_QUIT 0x0012u
|
||||
#define SHIM_WM_KEYDOWN 0x0100u
|
||||
#define SHIM_WM_KEYUP 0x0101u
|
||||
#define SHIM_WM_CHAR 0x0102u
|
||||
|
||||
static u64 g_wnd_proc = 0;
|
||||
static int g_wnd_created = 0;
|
||||
static i32 g_wnd_x = 0, g_wnd_y = 0, g_wnd_w = 0, g_wnd_h = 0;
|
||||
|
||||
/* MSG 布局与 PE 侧 #[repr(C)] MSG 一致(48 字节) */
|
||||
typedef struct {
|
||||
u64 hwnd;
|
||||
u32 message; u32 pad0;
|
||||
u64 wparam;
|
||||
u64 lparam;
|
||||
u32 time; u32 pad1;
|
||||
i32 ptx, pty;
|
||||
} shim_msg_t;
|
||||
|
||||
#define SHIM_MSGQ_CAP 64
|
||||
static shim_msg_t g_msgq[SHIM_MSGQ_CAP];
|
||||
static int g_mq_head = 0, g_mq_count = 0;
|
||||
|
||||
static void shim_msg_push(u32 msg, u64 w, u64 l) {
|
||||
if (g_mq_count >= SHIM_MSGQ_CAP) return; /* 满则丢弃 */
|
||||
int idx = (g_mq_head + g_mq_count) % SHIM_MSGQ_CAP;
|
||||
g_msgq[idx].hwnd = SHIM_HWND;
|
||||
g_msgq[idx].message = msg;
|
||||
g_msgq[idx].pad0 = 0;
|
||||
g_msgq[idx].wparam = w;
|
||||
g_msgq[idx].lparam = l;
|
||||
g_msgq[idx].time = 0;
|
||||
g_msgq[idx].pad1 = 0;
|
||||
g_msgq[idx].ptx = 0;
|
||||
g_msgq[idx].pty = 0;
|
||||
g_mq_count++;
|
||||
}
|
||||
|
||||
/* PS/2 键盘状态 */
|
||||
static int s_kbd_shift = 0, s_kbd_ctrl = 0, s_kbd_alt = 0, s_kbd_e0 = 0;
|
||||
|
||||
static char shim_scan_ascii(u8 sc, int shift) {
|
||||
static const char normal[58] = {
|
||||
0, 27, '1','2','3','4','5','6','7','8','9','0','-','=', 8, '\t',
|
||||
'q','w','e','r','t','y','u','i','o','p','[',']','\n',0,
|
||||
'a','s','d','f','g','h','j','k','l',';','\'', '`',0,'\\',
|
||||
'z','x','c','v','b','n','m',',','.','/',0,'*',0,' '
|
||||
};
|
||||
static const char shifted[58] = {
|
||||
0, 27, '!','@','#','$','%','^','&','*','(',')','_','+', 8, '\t',
|
||||
'Q','W','E','R','T','Y','U','I','O','P','{','}','\n',0,
|
||||
'A','S','D','F','G','H','J','K','L',':','"','~',0,'|',
|
||||
'Z','X','C','V','B','N','M','<','>','?',0,'*',0,' '
|
||||
};
|
||||
if (sc >= 58) return 0;
|
||||
return shift ? shifted[sc] : normal[sc];
|
||||
}
|
||||
|
||||
/* scan code set 1 -> Win32 VK */
|
||||
static u32 shim_scan_vk(u8 sc, int e0) {
|
||||
if (e0) {
|
||||
switch (sc) {
|
||||
case 0x4B: return 0x25; /* VK_LEFT */
|
||||
case 0x48: return 0x26; /* VK_UP */
|
||||
case 0x4D: return 0x27; /* VK_RIGHT */
|
||||
case 0x50: return 0x28; /* VK_DOWN */
|
||||
case 0x53: return 0x2E; /* VK_DELETE */
|
||||
case 0x1D: return 0x11; /* VK_CONTROL(右) */
|
||||
case 0x38: return 0x12; /* VK_MENU(右) */
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
if (sc >= 0x10 && sc <= 0x19) return 'Q' + (sc - 0x10);
|
||||
if (sc >= 0x1E && sc <= 0x26) return 'A' + (sc - 0x1E);
|
||||
if (sc >= 0x2C && sc <= 0x32) return 'Z' + (sc - 0x2C);
|
||||
if (sc >= 0x02 && sc <= 0x0A) return '1' + (sc - 0x02);
|
||||
if (sc == 0x0B) return '0';
|
||||
switch (sc) {
|
||||
case 0x1C: return 0x0D; /* VK_RETURN */
|
||||
case 0x0E: return 0x08; /* VK_BACK */
|
||||
case 0x39: return 0x20; /* VK_SPACE */
|
||||
case 0x01: return 0x1B; /* VK_ESCAPE */
|
||||
case 0x0F: return 0x09; /* VK_TAB */
|
||||
case 0x2A: case 0x36: return 0x10; /* VK_SHIFT */
|
||||
case 0x1D: return 0x11; /* VK_CONTROL */
|
||||
case 0x38: return 0x12; /* VK_MENU */
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 排空 PS/2 输出缓冲,转成 Win32 消息入队 */
|
||||
static void shim_kbd_poll(void) {
|
||||
for (;;) {
|
||||
u8 st = inb(0x64);
|
||||
if (!(st & 1)) break;
|
||||
u8 sc = inb(0x60);
|
||||
if (st & 0x20) continue; /* 鼠标字节丢弃 */
|
||||
if (sc == 0xE0) { s_kbd_e0 = 1; continue; }
|
||||
int e0 = s_kbd_e0;
|
||||
if (!e0) {
|
||||
if (sc == 0x2A || sc == 0x36) { s_kbd_shift = 1; shim_msg_push(SHIM_WM_KEYDOWN, 0x10, sc); continue; }
|
||||
if (sc == 0xAA || sc == 0xB6) { s_kbd_shift = 0; shim_msg_push(SHIM_WM_KEYUP, 0x10, sc); continue; }
|
||||
if (sc == 0x1D) { s_kbd_ctrl = 1; shim_msg_push(SHIM_WM_KEYDOWN, 0x11, sc); continue; }
|
||||
if (sc == 0x9D) { s_kbd_ctrl = 0; shim_msg_push(SHIM_WM_KEYUP, 0x11, sc); continue; }
|
||||
if (sc == 0x38) { s_kbd_alt = 1; shim_msg_push(SHIM_WM_KEYDOWN, 0x12, sc); continue; }
|
||||
if (sc == 0xB8) { s_kbd_alt = 0; shim_msg_push(SHIM_WM_KEYUP, 0x12, sc); continue; }
|
||||
}
|
||||
s_kbd_e0 = 0;
|
||||
if (sc & 0x80) {
|
||||
u32 vk = shim_scan_vk(sc & 0x7F, e0);
|
||||
if (vk) shim_msg_push(SHIM_WM_KEYUP, vk, sc);
|
||||
continue;
|
||||
}
|
||||
u32 vk = shim_scan_vk(sc, e0);
|
||||
if (vk) {
|
||||
shim_msg_push(SHIM_WM_KEYDOWN, vk, sc);
|
||||
/* Esc -> 额外合成 WM_CLOSE:无鼠标环境下关闭窗口的唯一途径 */
|
||||
if (vk == 0x1B && !e0) shim_msg_push(SHIM_WM_CLOSE, 0, 0);
|
||||
}
|
||||
if (!e0) {
|
||||
char c = shim_scan_ascii(sc, s_kbd_shift);
|
||||
if (c >= ' ' && c < 0x7F) shim_msg_push(SHIM_WM_CHAR, (u64)(u8)c, sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_RegisterClassExW(u64 wc_p) {
|
||||
if (!wc_p) return 0;
|
||||
g_wnd_proc = *(u64 *)(wc_p + 8); /* cbSize(4)+style(4) -> lpfnWndProc */
|
||||
log_info("[shim] RegisterClassExW ok");
|
||||
return 0xC000;
|
||||
}
|
||||
|
||||
static const struct limine_framebuffer *shim_fb(void) {
|
||||
if (!g_fb_request.response || g_fb_request.response->framebuffer_count == 0) return 0;
|
||||
return g_fb_request.response->framebuffers[0];
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_CreateWindowExW(
|
||||
u64 exstyle, u64 class_name, u64 wnd_name, u64 style,
|
||||
u64 x, u64 y, u64 w, u64 h,
|
||||
u64 parent, u64 menu, u64 hinst, u64 param) {
|
||||
(void)exstyle; (void)class_name; (void)wnd_name; (void)style;
|
||||
(void)parent; (void)menu; (void)hinst; (void)param;
|
||||
i32 ix = (i32)(u32)x, iy = (i32)(u32)y;
|
||||
i32 iw = (i32)(u32)w, ih = (i32)(u32)h;
|
||||
if (iw <= 0) iw = 800;
|
||||
if (ih <= 0) ih = 600;
|
||||
const struct limine_framebuffer *fb = shim_fb();
|
||||
i32 fw = fb ? (i32)fb->width : 0;
|
||||
i32 fh = fb ? (i32)fb->height : 0;
|
||||
if (fw && iw > fw) iw = fw;
|
||||
if (fh && ih > fh) ih = fh;
|
||||
/* CW_USEDEFAULT(0x80000000) -> 居中 */
|
||||
if (ix == (i32)0x80000000 || ix < 0) ix = fw ? (fw - iw) / 2 : 0;
|
||||
if (iy == (i32)0x80000000 || iy < 0) iy = fh ? (fh - ih) / 2 : 0;
|
||||
g_wnd_x = ix; g_wnd_y = iy; g_wnd_w = iw; g_wnd_h = ih;
|
||||
g_wnd_created = 1;
|
||||
log_info("[shim] CreateWindowExW ok");
|
||||
log_hex64("[shim] wnd x=", (u64)(i64)ix);
|
||||
log_hex64("[shim] wnd y=", (u64)(i64)iy);
|
||||
log_hex64("[shim] wnd w=", (u64)(i64)iw);
|
||||
log_hex64("[shim] wnd h=", (u64)(i64)ih);
|
||||
return SHIM_HWND;
|
||||
}
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_ShowWindow(u64 hwnd, u64 cmd) {
|
||||
(void)hwnd; (void)cmd; return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_UpdateWindow(u64 hwnd) {
|
||||
(void)hwnd; return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_DestroyWindow(u64 hwnd) {
|
||||
(void)hwnd; g_wnd_created = 0; return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_LoadCursorW(u64 hinst, u64 name) {
|
||||
(void)hinst; (void)name; return SHIM_HCURSOR;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_SetCursor(u64 cur) {
|
||||
(void)cur; return SHIM_HCURSOR;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_GetCursorPos(u64 pt_p) {
|
||||
if (pt_p) { ((i32 *)pt_p)[0] = g_wnd_w / 2; ((i32 *)pt_p)[1] = g_wnd_h / 2; }
|
||||
return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_ScreenToClient(u64 hwnd, u64 pt_p) {
|
||||
(void)hwnd; (void)pt_p; return 1; /* 窗口即全屏坐标系,无需转换 */
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_GetAsyncKeyState(u64 vk) {
|
||||
(void)vk; return 0; /* 修饰键状态已由消息流维护 */
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_SetTimer(u64 hwnd, u64 id, u64 elapse, u64 cb) {
|
||||
(void)hwnd; (void)elapse; (void)cb; return id ? id : 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_KillTimer(u64 hwnd, u64 id) {
|
||||
(void)hwnd; (void)id; return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_MessageBeep(u64 t) { (void)t; return 1; }
|
||||
static u64 __attribute__((ms_abi)) shim_GetClientRect(u64 hwnd, u64 rect_p) {
|
||||
(void)hwnd;
|
||||
if (!rect_p) return 0;
|
||||
i32 *r = (i32 *)rect_p;
|
||||
r[0] = 0; r[1] = 0; r[2] = g_wnd_w; r[3] = g_wnd_h;
|
||||
return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_InvalidateRect(u64 hwnd, u64 rect_p, u64 erase) {
|
||||
(void)hwnd; (void)rect_p; (void)erase; return 1; /* 主循环每帧全量重绘 */
|
||||
}
|
||||
/* PAINTSTRUCT: {hdc(8), fErase(4), rcPaint(16), fRestore(4), fIncUpdate(4), rgb(32)} */
|
||||
static u64 __attribute__((ms_abi)) shim_BeginPaint(u64 hwnd, u64 ps_p) {
|
||||
(void)hwnd;
|
||||
if (!ps_p) return 0;
|
||||
u8 *p = (u8 *)ps_p;
|
||||
for (int i = 0; i < 72; i++) p[i] = 0;
|
||||
*(u64 *)p = SHIM_HDC_WND;
|
||||
return SHIM_HDC_WND;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_EndPaint(u64 hwnd, u64 ps_p) {
|
||||
(void)hwnd; (void)ps_p; return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_ReleaseDC(u64 hwnd, u64 hdc) {
|
||||
(void)hwnd; (void)hdc; return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_GetSystemMetrics(u64 idx) {
|
||||
const struct limine_framebuffer *fb = shim_fb();
|
||||
if (!fb) return 0;
|
||||
if (idx == 0) return fb->width; /* SM_CXSCREEN */
|
||||
if (idx == 1) return fb->height; /* SM_CYSCREEN */
|
||||
return 0;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_DefWindowProcW(u64 hwnd, u64 msg, u64 w, u64 l) {
|
||||
(void)hwnd; (void)msg; (void)w; (void)l; return 0;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_TranslateMessage(u64 msg_p) {
|
||||
(void)msg_p; return 0; /* WM_CHAR 已在键盘轮询时合成 */
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_PeekMessageW(u64 msg_p, u64 hwnd,
|
||||
u64 fmin, u64 fmax, u64 remove) {
|
||||
(void)hwnd; (void)fmin; (void)fmax;
|
||||
shim_kbd_poll();
|
||||
if (g_mq_count == 0) return 0;
|
||||
shim_msg_t *m = &g_msgq[g_mq_head];
|
||||
if (msg_p) *(shim_msg_t *)msg_p = *m;
|
||||
if (remove & 1) { /* PM_REMOVE */
|
||||
g_mq_head = (g_mq_head + 1) % SHIM_MSGQ_CAP;
|
||||
g_mq_count--;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_GetMessageW(u64 msg_p, u64 hwnd,
|
||||
u64 fmin, u64 fmax) {
|
||||
(void)hwnd; (void)fmin; (void)fmax;
|
||||
for (;;) { /* 阻塞语义:轮询键盘直到有消息 */
|
||||
shim_kbd_poll();
|
||||
if (g_mq_count > 0) break;
|
||||
__asm__ volatile("pause");
|
||||
}
|
||||
shim_msg_t *m = &g_msgq[g_mq_head];
|
||||
if (msg_p) *(shim_msg_t *)msg_p = *m;
|
||||
g_mq_head = (g_mq_head + 1) % SHIM_MSGQ_CAP;
|
||||
g_mq_count--;
|
||||
return (m->message == SHIM_WM_QUIT) ? 0 : 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_PostQuitMessage(u64 exit_code) {
|
||||
shim_msg_push(SHIM_WM_QUIT, exit_code, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef u64 (__attribute__((ms_abi)) *shim_wndproc_t)(u64, u64, u64, u64);
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_DispatchMessageW(u64 msg_p) {
|
||||
if (!msg_p || !g_wnd_proc) return 0;
|
||||
const shim_msg_t *m = (const shim_msg_t *)msg_p;
|
||||
return ((shim_wndproc_t)g_wnd_proc)(m->hwnd, m->message, m->wparam, m->lparam);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* gdi32.dll — 内存 DC / DIBSection / BitBlt -> 帧缓冲
|
||||
* ========================================================== */
|
||||
|
||||
typedef struct { u64 bmp; } shim_dc_t; /* 当前选中位图(0=无) */
|
||||
typedef struct { i32 w, h; u32 *bits; } shim_bmp_t; /* 32bpp 0xAARRGGBB 位图 */
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_GetDC(u64 hwnd) {
|
||||
(void)hwnd; return SHIM_HDC_WND;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_CreateCompatibleDC(u64 hdc) {
|
||||
(void)hdc;
|
||||
shim_dc_t *dc = (shim_dc_t *)kmem_alloc(sizeof(shim_dc_t));
|
||||
if (dc) dc->bmp = 0;
|
||||
return (u64)dc;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_CreateDIBSection(u64 hdc, u64 bmi_p, u64 usage,
|
||||
u64 ppv, u64 hsec, u64 off) {
|
||||
(void)hdc; (void)usage; (void)hsec; (void)off;
|
||||
if (!bmi_p || !ppv) return 0;
|
||||
const u8 *bmi = (const u8 *)bmi_p;
|
||||
i32 w = *(const i32 *)(bmi + 4); /* biWidth */
|
||||
i32 h = *(const i32 *)(bmi + 8); /* biHeight(负=top-down) */
|
||||
u16 bpp = *(const u16 *)(bmi + 14); /* biBitCount */
|
||||
if (h < 0) h = -h;
|
||||
if (w <= 0 || h <= 0 || bpp != 32) return 0;
|
||||
u64 npix = (u64)w * (u64)h;
|
||||
u32 *bits = (u32 *)kmem_alloc(npix * 4);
|
||||
if (!bits) return 0;
|
||||
for (u64 i = 0; i < npix; i++) bits[i] = 0;
|
||||
shim_bmp_t *b = (shim_bmp_t *)kmem_alloc(sizeof(shim_bmp_t));
|
||||
if (!b) return 0;
|
||||
b->w = w; b->h = h; b->bits = bits;
|
||||
*(u64 *)ppv = (u64)bits;
|
||||
log_info("[shim] CreateDIBSection ok");
|
||||
log_hex64("[shim] dib w=", (u64)(i64)w);
|
||||
log_hex64("[shim] dib h=", (u64)(i64)h);
|
||||
log_hex64("[shim] dib bits=", (u64)bits);
|
||||
return (u64)b;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_SelectObject(u64 hdc, u64 obj) {
|
||||
shim_dc_t *dc = (shim_dc_t *)hdc;
|
||||
if (!dc) return 0;
|
||||
u64 prev = dc->bmp;
|
||||
dc->bmp = obj;
|
||||
return prev;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_DeleteDC(u64 hdc) {
|
||||
if (hdc == SHIM_HDC_WND) return 1; /* 窗口 DC 不释放 */
|
||||
shim_dc_t *dc = (shim_dc_t *)hdc;
|
||||
/* kmem arena 不支持 free,小对象泄漏可接受 */
|
||||
(void)dc;
|
||||
return 1;
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_DeleteObject(u64 obj) {
|
||||
(void)obj; return 1; /* 同上:arena 无 free,位图随进程退出回收 */
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_GetStockObject(u64 i) {
|
||||
(void)i; return 0x20000010; /* 伪 GDI 对象句柄 */
|
||||
}
|
||||
static u64 __attribute__((ms_abi)) shim_GdiFlush(void) { return 1; }
|
||||
|
||||
static u64 g_blit_count = 0;
|
||||
|
||||
static u64 __attribute__((ms_abi)) shim_BitBlt(u64 dstdc, u64 x, u64 y, u64 cx, u64 cy,
|
||||
u64 srcdc, u64 x1, u64 y1, u64 rop) {
|
||||
(void)rop;
|
||||
if (dstdc != SHIM_HDC_WND) return 1; /* 仅支持窗口 DC 目标 */
|
||||
const struct limine_framebuffer *fb = shim_fb();
|
||||
if (!fb || !fb->address) return 0;
|
||||
if (fb->bpp != 32 && fb->bpp != 24) return 0;
|
||||
shim_dc_t *sdc = (shim_dc_t *)srcdc;
|
||||
if (!sdc || !sdc->bmp) return 0;
|
||||
shim_bmp_t *bmp = (shim_bmp_t *)sdc->bmp;
|
||||
|
||||
i32 dx = (i32)(u32)x + g_wnd_x;
|
||||
i32 dy = (i32)(u32)y + g_wnd_y;
|
||||
i32 sx0 = (i32)(u32)x1, sy0 = (i32)(u32)y1;
|
||||
i32 w = (i32)(u32)cx, h = (i32)(u32)cy;
|
||||
|
||||
u8 *fbb = (u8 *)fb->address;
|
||||
u32 rsh = fb->red_mask_shift, gsh = fb->green_mask_shift, bsh = fb->blue_mask_shift;
|
||||
u32 rsz = fb->red_mask_size ? fb->red_mask_size : 8;
|
||||
u32 gsz = fb->green_mask_size ? fb->green_mask_size : 8;
|
||||
u32 bsz = fb->blue_mask_size ? fb->blue_mask_size : 8;
|
||||
int fast = (fb->bpp == 32 && rsh == 16 && gsh == 8 && bsh == 0
|
||||
&& rsz == 8 && gsz == 8 && bsz == 8);
|
||||
|
||||
for (i32 row = 0; row < h; row++) {
|
||||
i32 fy = dy + row, sy = sy0 + row;
|
||||
if (fy < 0 || fy >= (i32)fb->height) continue;
|
||||
if (sy < 0 || sy >= bmp->h) continue;
|
||||
u8 *dst_row = fbb + (u64)fy * fb->pitch;
|
||||
const u32 *src = bmp->bits + (u64)sy * (u64)bmp->w;
|
||||
for (i32 col = 0; col < w; col++) {
|
||||
i32 fx = dx + col, sx = sx0 + col;
|
||||
if (fx < 0 || fx >= (i32)fb->width) continue;
|
||||
if (sx < 0 || sx >= bmp->w) continue;
|
||||
u32 px = src[sx];
|
||||
if (fast) {
|
||||
((u32 *)dst_row)[fx] = px;
|
||||
} else {
|
||||
u32 r = (px >> 16) & 0xFF, g = (px >> 8) & 0xFF, bl = px & 0xFF;
|
||||
u32 v = ((r >> (8 - rsz)) << rsh)
|
||||
| ((g >> (8 - gsz)) << gsh)
|
||||
| ((bl >> (8 - bsz)) << bsh);
|
||||
if (fb->bpp == 32) {
|
||||
((u32 *)dst_row)[fx] = v;
|
||||
} else {
|
||||
u8 *p = dst_row + (u64)fx * 3;
|
||||
p[0] = (u8)(v & 0xFF);
|
||||
p[1] = (u8)((v >> 8) & 0xFF);
|
||||
p[2] = (u8)((v >> 16) & 0xFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g_blit_count++;
|
||||
if (g_blit_count == 1) log_info("[shim] BitBlt first frame on screen");
|
||||
if ((g_blit_count % 600) == 0) log_hex64("[shim] BitBlt frames=", g_blit_count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 未实现 stub(64位)— 日志告警(含调用点返回地址)并返回 0 */
|
||||
static u64 __attribute__((ms_abi)) shim_unimpl64(u64 a0, u64 a1, u64 a2, u64 a3) {
|
||||
(void)a0; (void)a1; (void)a2; (void)a3;
|
||||
log_warn("[PE] unimplemented API called");
|
||||
log_hex64("[PE] caller rip=", (u64)__builtin_return_address(0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -364,6 +1260,84 @@ static const pe_shim_entry g_shim_table[] = {
|
||||
{"kernel32.dll", "CloseHandle", (void*)shim_CloseHandle, 0},
|
||||
{"kernel32.dll", "GetFileSize", (void*)shim_GetFileSize, 0},
|
||||
{"kernel32.dll", "SetFilePointer", (void*)shim_SetFilePointer, 0},
|
||||
/* kernel32.dll — Deaicup GUI 增量 */
|
||||
{"kernel32.dll", "HeapReAlloc", (void*)shim_HeapReAlloc, 0},
|
||||
{"kernel32.dll", "GetProcessHeap", (void*)shim_GetProcessHeap, 0},
|
||||
{"kernel32.dll", "QueryPerformanceFrequency", (void*)shim_QueryPerformanceFrequency, 0},
|
||||
{"kernel32.dll", "QueryPerformanceCounter", (void*)shim_QueryPerformanceCounter, 0},
|
||||
{"kernel32.dll", "GetTickCount", (void*)shim_GetTickCount, 0},
|
||||
{"kernel32.dll", "Sleep", (void*)shim_Sleep, 0},
|
||||
{"kernel32.dll", "GetSystemInfo", (void*)shim_GetSystemInfo, 0},
|
||||
{"kernel32.dll", "GetConsoleMode", (void*)shim_GetConsoleMode, 0},
|
||||
{"kernel32.dll", "GetConsoleOutputCP", (void*)shim_GetConsoleOutputCP, 0},
|
||||
{"kernel32.dll", "WriteConsoleW", (void*)shim_WriteConsoleW, 0},
|
||||
{"kernel32.dll", "GetCurrentDirectoryW", (void*)shim_GetCurrentDirectoryW, 0},
|
||||
{"kernel32.dll", "GetEnvironmentVariableW", (void*)shim_GetEnvironmentVariableW, 0},
|
||||
{"kernel32.dll", "GetCurrentProcess", (void*)shim_GetCurrentProcess, 0},
|
||||
{"kernel32.dll", "GetCurrentProcessId", (void*)shim_GetCurrentProcessId, 0},
|
||||
{"kernel32.dll", "GetCurrentThreadId", (void*)shim_GetCurrentThreadId, 0},
|
||||
{"kernel32.dll", "CreateMutexA", (void*)shim_CreateMutexA, 0},
|
||||
{"kernel32.dll", "ReleaseMutex", (void*)shim_ReleaseMutex, 0},
|
||||
{"kernel32.dll", "WaitForSingleObject", (void*)shim_WaitForSingleObject, 0},
|
||||
{"kernel32.dll", "WaitForSingleObjectEx", (void*)shim_WaitForSingleObjectEx, 0},
|
||||
{"kernel32.dll", "FormatMessageW", (void*)shim_FormatMessageW, 0},
|
||||
{"kernel32.dll", "LoadLibraryA", (void*)shim_LoadLibraryA, 0},
|
||||
{"kernel32.dll", "GetProcAddress", (void*)shim_GetProcAddress, 0},
|
||||
{"kernel32.dll", "lstrlenW", (void*)shim_lstrlenW, 0},
|
||||
{"kernel32.dll", "MultiByteToWideChar", (void*)shim_MultiByteToWideChar, 0},
|
||||
{"kernel32.dll", "WideCharToMultiByte", (void*)shim_WideCharToMultiByte, 0},
|
||||
/* kernel32.dll 也转发导出这三个 Rtl*(Rust std 从 kernel32 静态导入) */
|
||||
{"kernel32.dll", "RtlCaptureContext", (void*)shim_RtlCaptureContext, 0},
|
||||
{"kernel32.dll", "RtlLookupFunctionEntry",(void*)shim_RtlLookupFunctionEntry, 0},
|
||||
{"kernel32.dll", "RtlVirtualUnwind", (void*)shim_RtlVirtualUnwind, 0},
|
||||
/* ntdll.dll */
|
||||
{"ntdll.dll", "RtlCaptureContext", (void*)shim_RtlCaptureContext, 0},
|
||||
{"ntdll.dll", "RtlLookupFunctionEntry",(void*)shim_RtlLookupFunctionEntry, 0},
|
||||
{"ntdll.dll", "RtlVirtualUnwind", (void*)shim_RtlVirtualUnwind, 0},
|
||||
{"ntdll.dll", "NtWriteFile", (void*)shim_NtWriteFile, 0},
|
||||
{"ntdll.dll", "RtlNtStatusToDosError", (void*)shim_RtlNtStatusToDosError, 0},
|
||||
/* bcryptprimitives.dll */
|
||||
{"bcryptprimitives.dll", "ProcessPrng", (void*)shim_ProcessPrng, 0},
|
||||
/* api-ms-win-core-synch-l1-2-0.dll */
|
||||
{"api-ms-win-core-synch-l1-2-0.dll", "WaitOnAddress", (void*)shim_WaitOnAddress, 0},
|
||||
{"api-ms-win-core-synch-l1-2-0.dll", "WakeByAddressSingle",(void*)shim_WakeByAddress, 0},
|
||||
{"api-ms-win-core-synch-l1-2-0.dll", "WakeByAddressAll", (void*)shim_WakeByAddress, 0},
|
||||
/* user32.dll */
|
||||
{"user32.dll", "RegisterClassExW", (void*)shim_RegisterClassExW, 0},
|
||||
{"user32.dll", "CreateWindowExW", (void*)shim_CreateWindowExW, 0},
|
||||
{"user32.dll", "DestroyWindow", (void*)shim_DestroyWindow, 0},
|
||||
{"user32.dll", "ShowWindow", (void*)shim_ShowWindow, 0},
|
||||
{"user32.dll", "UpdateWindow", (void*)shim_UpdateWindow, 0},
|
||||
{"user32.dll", "GetMessageW", (void*)shim_GetMessageW, 0},
|
||||
{"user32.dll", "PeekMessageW", (void*)shim_PeekMessageW, 0},
|
||||
{"user32.dll", "TranslateMessage", (void*)shim_TranslateMessage, 0},
|
||||
{"user32.dll", "DispatchMessageW", (void*)shim_DispatchMessageW, 0},
|
||||
{"user32.dll", "PostQuitMessage", (void*)shim_PostQuitMessage, 0},
|
||||
{"user32.dll", "DefWindowProcW", (void*)shim_DefWindowProcW, 0},
|
||||
{"user32.dll", "GetClientRect", (void*)shim_GetClientRect, 0},
|
||||
{"user32.dll", "InvalidateRect", (void*)shim_InvalidateRect, 0},
|
||||
{"user32.dll", "BeginPaint", (void*)shim_BeginPaint, 0},
|
||||
{"user32.dll", "EndPaint", (void*)shim_EndPaint, 0},
|
||||
{"user32.dll", "GetDC", (void*)shim_GetDC, 0},
|
||||
{"user32.dll", "ReleaseDC", (void*)shim_ReleaseDC, 0},
|
||||
{"user32.dll", "LoadCursorW", (void*)shim_LoadCursorW, 0},
|
||||
{"user32.dll", "SetCursor", (void*)shim_SetCursor, 0},
|
||||
{"user32.dll", "GetCursorPos", (void*)shim_GetCursorPos, 0},
|
||||
{"user32.dll", "ScreenToClient", (void*)shim_ScreenToClient, 0},
|
||||
{"user32.dll", "GetAsyncKeyState", (void*)shim_GetAsyncKeyState, 0},
|
||||
{"user32.dll", "SetTimer", (void*)shim_SetTimer, 0},
|
||||
{"user32.dll", "KillTimer", (void*)shim_KillTimer, 0},
|
||||
{"user32.dll", "MessageBeep", (void*)shim_MessageBeep, 0},
|
||||
{"user32.dll", "GetSystemMetrics", (void*)shim_GetSystemMetrics, 0},
|
||||
/* gdi32.dll */
|
||||
{"gdi32.dll", "CreateCompatibleDC", (void*)shim_CreateCompatibleDC, 0},
|
||||
{"gdi32.dll", "CreateDIBSection", (void*)shim_CreateDIBSection, 0},
|
||||
{"gdi32.dll", "SelectObject", (void*)shim_SelectObject, 0},
|
||||
{"gdi32.dll", "DeleteObject", (void*)shim_DeleteObject, 0},
|
||||
{"gdi32.dll", "DeleteDC", (void*)shim_DeleteDC, 0},
|
||||
{"gdi32.dll", "BitBlt", (void*)shim_BitBlt, 0},
|
||||
{"gdi32.dll", "GetStockObject", (void*)shim_GetStockObject, 0},
|
||||
{"gdi32.dll", "GdiFlush", (void*)shim_GdiFlush, 0},
|
||||
/* msvcrt.dll */
|
||||
{"msvcrt.dll", "printf", (void*)shim_printf, 0},
|
||||
{"msvcrt.dll", "puts", (void*)shim_puts, 0},
|
||||
|
||||
Reference in New Issue
Block a user