tests
This commit is contained in:
2
kern.h
2
kern.h
@@ -15,7 +15,7 @@ extern void KERN_CALL xmemmove(void *ziel, void *quelle, UI anz);
|
||||
extern int KERN_CALL Net_Call(UI func, void *req, void *repl);
|
||||
extern int KERN_CALL C32_LoadNios_Probe(UI axfunc, void *outbuf);
|
||||
extern int KERN_CALL C32_GetFunc_Probe(char *name, void *outbuf);
|
||||
extern int KERN_CALL C32_CallName0_Probe(char *name, void *outbuf);
|
||||
extern int KERN_CALL C32_CallVersion_Nios_Probe(void *outbuf);
|
||||
extern int KERN_CALL Net_Call_VLM_Raw(UI ax, UI bx, UI cx, UI dx,
|
||||
void *req, void *repl,
|
||||
UI p1, UI p2, UI p3);
|
||||
|
||||
@@ -22,7 +22,7 @@ public _xmemmove
|
||||
public _Net_Call
|
||||
public _C32_LoadNios_Probe
|
||||
public _C32_GetFunc_Probe
|
||||
public _C32_CallName0_Probe
|
||||
public _C32_CallVersion_Nios_Probe
|
||||
public _Net_Call_VLM_Raw
|
||||
|
||||
_IPXinit proc far
|
||||
@@ -467,26 +467,34 @@ c32get_store:
|
||||
_C32_GetFunc_Probe endp
|
||||
|
||||
|
||||
; int C32_CallName0_Probe(char *name, void *outbuf)
|
||||
; int C32_CallVersion_Nios_Probe(void *outbuf)
|
||||
;
|
||||
; Resolve Client32 function by name via NIOS resolver returned by D8C1,
|
||||
; then call resolved function with zero arguments.
|
||||
;
|
||||
; This is safe for CLIENT32GetVersion. Do not use for functions needing args.
|
||||
; Safe Client32 version call using the exact d32wrap convention:
|
||||
; 1) INT 2F AX=D8C1
|
||||
; 2) use ESI resolver to resolve "CLIENT32GetVersion"
|
||||
; 3) call ECX trampoline, not the function pointer directly:
|
||||
; push 0
|
||||
; push 0
|
||||
; push fn_seg
|
||||
; push fn_off
|
||||
; call ECX
|
||||
; add sp,8
|
||||
;
|
||||
; outbuf:
|
||||
; +00 load AX
|
||||
; +02 resolver ptr off
|
||||
; +04 resolver ptr seg
|
||||
; +06 resolved fn off
|
||||
; +08 resolved fn seg
|
||||
; +0A call return AX
|
||||
; +0C call return DX
|
||||
; +0E call return FLAGS
|
||||
_C32_CallName0_Probe proc far
|
||||
; +02 resolver off
|
||||
; +04 resolver seg
|
||||
; +06 trampoline off
|
||||
; +08 trampoline seg
|
||||
; +0A fn off
|
||||
; +0C fn seg
|
||||
; +0E call AX
|
||||
; +10 call DX
|
||||
; +12 flags
|
||||
_C32_CallVersion_Nios_Probe proc far
|
||||
push bp
|
||||
mov bp, sp
|
||||
sub sp, 8
|
||||
sub sp, 12
|
||||
|
||||
push ds
|
||||
push es
|
||||
@@ -501,47 +509,51 @@ _C32_CallName0_Probe proc far
|
||||
mov ax, 0D8C1h
|
||||
int 2Fh
|
||||
|
||||
; save resolver ESI at [bp-4]
|
||||
; save ESI resolver at [bp-4]
|
||||
db 66h, 89h, 76h, 0FCh
|
||||
; save ECX trampoline at [bp-8]
|
||||
db 66h, 89h, 4Eh, 0F8h
|
||||
|
||||
push ax ; load AX
|
||||
|
||||
push ax ; load AX for output
|
||||
or ax, ax
|
||||
jne c32call_store_fail
|
||||
jne c32ver_fail
|
||||
|
||||
; resolve function name:
|
||||
; push name segment, name offset, 0, 0; call resolver; add sp,8
|
||||
push word ptr [bp+8]
|
||||
push word ptr [bp+6]
|
||||
push cs
|
||||
push offset c32ver_name
|
||||
push 0
|
||||
push 0
|
||||
call dword ptr [bp-4]
|
||||
add sp, 8
|
||||
|
||||
; save resolved function pointer DX:AX at [bp-8]
|
||||
mov word ptr [bp-8], ax
|
||||
mov word ptr [bp-6], dx
|
||||
; resolver returns DX:AX function pointer
|
||||
mov [bp-12], ax
|
||||
mov [bp-10], dx
|
||||
|
||||
or ax, dx
|
||||
je c32call_store_fail2
|
||||
je c32ver_fail
|
||||
|
||||
; call resolved function with zero args
|
||||
; d32wrap _CLIENT32GetVersion convention:
|
||||
push 0
|
||||
push 0
|
||||
push word ptr [bp-10]
|
||||
push word ptr [bp-12]
|
||||
call dword ptr [bp-8]
|
||||
add sp, 8
|
||||
|
||||
pushf
|
||||
push dx
|
||||
push ax
|
||||
jmp short c32call_store
|
||||
jmp short c32ver_store
|
||||
|
||||
c32call_store_fail2:
|
||||
c32ver_fail:
|
||||
xor dx, dx
|
||||
xor ax, ax
|
||||
c32call_store_fail:
|
||||
pushf
|
||||
push dx
|
||||
push ax
|
||||
|
||||
c32call_store:
|
||||
les di, dword ptr [bp+10]
|
||||
c32ver_store:
|
||||
les di, dword ptr [bp+6]
|
||||
|
||||
pop ax ; call AX
|
||||
pop dx ; call DX
|
||||
@@ -557,9 +569,13 @@ c32call_store:
|
||||
mov es:[di+6], cx
|
||||
mov cx, word ptr [bp-6]
|
||||
mov es:[di+8], cx
|
||||
mov es:[di+10], ax
|
||||
mov es:[di+12], dx
|
||||
mov es:[di+14], bx
|
||||
mov cx, word ptr [bp-12]
|
||||
mov es:[di+10], cx
|
||||
mov cx, word ptr [bp-10]
|
||||
mov es:[di+12], cx
|
||||
mov es:[di+14], ax
|
||||
mov es:[di+16], dx
|
||||
mov es:[di+18], bx
|
||||
|
||||
popf
|
||||
pop di
|
||||
@@ -570,7 +586,10 @@ c32call_store:
|
||||
pop bp
|
||||
xor ah, ah
|
||||
ret
|
||||
_C32_CallName0_Probe endp
|
||||
|
||||
c32ver_name db 'CLIENT32GetVersion',0
|
||||
|
||||
_C32_CallVersion_Nios_Probe endp
|
||||
|
||||
|
||||
end
|
||||
|
||||
43
nwtests.c
43
nwtests.c
@@ -1218,42 +1218,43 @@ static int tests_c32getfunc(void)
|
||||
}
|
||||
|
||||
|
||||
static int tests_c32callver(void)
|
||||
static int tests_c32callver2(void)
|
||||
{
|
||||
uint8 out[32];
|
||||
uint16 load_ax;
|
||||
uint16 res_off, res_seg;
|
||||
uint16 tramp_off, tramp_seg;
|
||||
uint16 fn_off, fn_seg;
|
||||
uint16 call_ax, call_dx, flags;
|
||||
|
||||
memset(out, 0, sizeof(out));
|
||||
|
||||
fprintf(stdout, "TEST C32CALLVER\n");
|
||||
fprintf(stdout, "Resolve and call CLIENT32GetVersion with zero args\n\n");
|
||||
fprintf(stdout, "TEST C32CALLVER2\n");
|
||||
fprintf(stdout, "Call CLIENT32GetVersion through ECX NIOS trampoline\n\n");
|
||||
|
||||
C32_CallName0_Probe("CLIENT32GetVersion", out);
|
||||
C32_CallVersion_Nios_Probe(out);
|
||||
|
||||
load_ax = tests_get_word_lh(out + 0);
|
||||
res_off = tests_get_word_lh(out + 2);
|
||||
res_seg = tests_get_word_lh(out + 4);
|
||||
fn_off = tests_get_word_lh(out + 6);
|
||||
fn_seg = tests_get_word_lh(out + 8);
|
||||
call_ax = tests_get_word_lh(out + 10);
|
||||
call_dx = tests_get_word_lh(out + 12);
|
||||
flags = tests_get_word_lh(out + 14);
|
||||
load_ax = tests_get_word_lh(out + 0);
|
||||
res_off = tests_get_word_lh(out + 2);
|
||||
res_seg = tests_get_word_lh(out + 4);
|
||||
tramp_off = tests_get_word_lh(out + 6);
|
||||
tramp_seg = tests_get_word_lh(out + 8);
|
||||
fn_off = tests_get_word_lh(out + 10);
|
||||
fn_seg = tests_get_word_lh(out + 12);
|
||||
call_ax = tests_get_word_lh(out + 14);
|
||||
call_dx = tests_get_word_lh(out + 16);
|
||||
flags = tests_get_word_lh(out + 18);
|
||||
|
||||
fprintf(stdout, "Load AX=%04X\n", load_ax);
|
||||
fprintf(stdout, "Resolver=%04X:%04X\n", res_seg, res_off);
|
||||
fprintf(stdout, "Resolver=%04X:%04X Trampoline=%04X:%04X\n",
|
||||
res_seg, res_off, tramp_seg, tramp_off);
|
||||
fprintf(stdout, "Function=%04X:%04X\n", fn_seg, fn_off);
|
||||
fprintf(stdout, "Call returned DX:AX=%04X:%04X FLAGS=%04X\n",
|
||||
call_dx, call_ax, flags);
|
||||
tests_dump_bytes("RAW:", out, 16);
|
||||
|
||||
if (fn_off || fn_seg)
|
||||
fprintf(stdout, "\nFunction pointer resolved.\n");
|
||||
if (call_ax || call_dx)
|
||||
fprintf(stdout, "Call returned non-zero version value.\n");
|
||||
tests_dump_bytes("RAW:", out, 20);
|
||||
|
||||
if (load_ax == 0 && (fn_off || fn_seg))
|
||||
fprintf(stdout, "\nNIOS trampoline path resolved successfully.\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1273,8 +1274,8 @@ int func_tests(int argc, char *argv[], int mode)
|
||||
if (tests_same_arg(argv[1], "C32GETFUNC"))
|
||||
return tests_c32getfunc();
|
||||
|
||||
if (tests_same_arg(argv[1], "C32CALLVER"))
|
||||
return tests_c32callver();
|
||||
if (tests_same_arg(argv[1], "C32CALLVER2"))
|
||||
return tests_c32callver2();
|
||||
|
||||
if (tests_same_arg(argv[1], "NWREQ87"))
|
||||
return tests_nwreq87(argc, argv);
|
||||
|
||||
Reference in New Issue
Block a user