@@ -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 } ,