This commit is contained in:
Mario Fetka
2026-05-23 15:33:07 +02:00
parent 3562cd1301
commit a5ce0d2f63
3 changed files with 168 additions and 57 deletions

3
kern.h
View File

@@ -13,6 +13,9 @@ extern void asm_esr_routine(void);
extern void esr_routine(ECB *ecb);
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 Net_Call_VLM_Raw(UI ax, UI bx, UI cx, UI dx,
void *req, void *repl,
UI p1, UI p2, UI p3);
extern int KERN_CALL Net_Call_C(UI func, void *req, void *repl);
extern int KERN_CALL Net_Call_CX(UI func, UI bx, UI cx, UI dx,
void *req, void *repl);

View File

@@ -14,14 +14,15 @@ enterIPX dd 0
.code
public _IPXinit
public _IPXopen_socket
public _IPXclose_socket
public _IPXlisten
public _xmemmove
public _Net_Call
public IPXinit_
public IPXopen_socket_
public IPXclose_socket_
public IPXlisten_
public xmemmove_
public Net_Call_
public Net_Call_VLM_Raw_
_IPXinit proc far
IPXinit_ proc far
push bp
mov bp, sp
push ds
@@ -48,9 +49,9 @@ ipxinit_done:
pop ds
pop bp
ret
_IPXinit endp
IPXinit_ endp
_xmemmove proc far
xmemmove_ proc far
push bp
mov bp, sp
@@ -101,9 +102,9 @@ xmem_done:
pop bp
sti
ret
_xmemmove endp
xmemmove_ endp
_IPXopen_socket proc far
IPXopen_socket_ proc far
push bp
mov bp, sp
push ds
@@ -138,9 +139,9 @@ ipxopen_done:
pop ds
pop bp
ret
_IPXopen_socket endp
IPXopen_socket_ endp
_IPXclose_socket proc far
IPXclose_socket_ proc far
push bp
mov bp, sp
push ds
@@ -159,9 +160,9 @@ _IPXclose_socket proc far
pop ds
pop bp
ret
_IPXclose_socket endp
IPXclose_socket_ endp
_IPXlisten proc far
IPXlisten_ proc far
push bp
mov bp, sp
push ds
@@ -181,9 +182,9 @@ _IPXlisten proc far
pop bp
mov ah, 0
ret
_IPXlisten endp
IPXlisten_ endp
_Net_Call proc far
Net_Call_ proc far
push bp
mov bp, sp
@@ -211,6 +212,82 @@ _Net_Call proc far
pop bp
mov ah, 0
ret
_Net_Call endp
Net_Call_ endp
; int Net_Call_VLM_Raw(UI ax, UI bx, UI cx, UI dx,
; void *req, void *repl,
; UI p1, UI p2, UI p3)
;
; Experimental VLM entry caller.
; INT 2F AX=7A20 returns ES:BX = VLM entry if AX == 0000.
;
; Registers loaded for VLM entry:
; AX, BX, CX, DX from function args
; DS:SI = req
; ES:DI = repl
;
; Stack args pushed before call, matching DeveloperNet clndos16 NWCVLMREQ:
; push p3
; push p2
; push p1
; call VLM_entry
;
; For NWCREQUEST/VLM:
; AX=function
; BX=numReqFrags
; CX=conn
; DX=numReplyFrags
; DS:SI=reqFragList
; ES:DI=replyFragList
; p1=6, p2=20h, p3=0
Net_Call_VLM_Raw_ proc far
push bp
mov bp, sp
sub sp, 4
push ds
push si
push di
push es
mov ax, 7A20h
xor bx, bx
int 2Fh
or ax, ax
jz vlm_raw_found
mov ax, 88FFh
jmp short vlm_raw_done
vlm_raw_found:
; save VLM entry ES:BX in stack locals [bp-4]=off [bp-2]=seg
mov [bp-4], bx
mov ax, es
mov [bp-2], ax
; load caller-requested registers
mov ax, [bp+6]
mov bx, [bp+8]
mov cx, [bp+10]
mov dx, [bp+12]
lds si, dword ptr [bp+14]
les di, dword ptr [bp+18]
push word ptr [bp+26]
push word ptr [bp+24]
push word ptr [bp+22]
call dword ptr [bp-4]
vlm_raw_done:
pop es
pop di
pop si
pop ds
mov sp, bp
pop bp
ret
Net_Call_VLM_Raw_ endp
end

109
nwtests.c
View File

@@ -426,54 +426,85 @@ static int tests_nwreq87(int argc, char *argv[])
}
static int tests_reqtype(void)
typedef struct {
uint16 off;
uint16 seg;
uint16 len;
} TEST_NWFRAG16;
static void tests_set_frag(TEST_NWFRAG16 *f, void *ptr, UI len)
{
union REGS r;
struct SREGS s;
f->off = FP_OFF(ptr);
f->seg = FP_SEG(ptr);
f->len = (uint16)len;
}
memset(&r, 0, sizeof(r));
memset(&s, 0, sizeof(s));
static int tests_nwreq87vlm(int argc, char *argv[])
{
char *name = "LOGIN.EXE";
uint8 connid = 0;
uint8 dhandle = 0;
uint8 path[300];
uint8 hdr[16];
uint8 repl[0x180];
TEST_NWFRAG16 reqfrags[2];
TEST_NWFRAG16 replfrags[2];
UI path_len;
int rc;
uint32 a0;
uint32 a4d;
fprintf(stdout, "TEST requester type probes\n\n");
if (argc > 2)
name = argv[2];
if (tests_current_conn_dhandle(&connid, &dhandle))
return(1);
tests_build_nwreq87_path(path, dhandle, name, &path_len);
memset(hdr, 0, sizeof(hdr));
memset(repl, 0, sizeof(repl));
memset(reqfrags, 0, sizeof(reqfrags));
memset(replfrags, 0, sizeof(replfrags));
/*
* DeveloperNet 1997 dvlmreq.c:
* AX=7A20h, BX=0, INT 2Fh
* if AX==0 then ES:BX is VLM entry and client type is VLM.
* ncpdos16 87s6.c request frag #1, length 9.
*/
r.x.ax = 0x7A20;
r.x.bx = 0;
int86x(0x2F, &r, &r, &s);
hdr[0] = 6; /* subfunction */
hdr[1] = 0; /* src namespace DOS */
hdr[2] = 0; /* dst namespace DOS */
tests_put_word_lh(hdr + 3, 0x0006); /* SA_ALL */
tests_put_dword_lh(hdr + 5, 0x00000004UL); /* RIM_ATTRIBUTES */
fprintf(stdout, "INT 2F AX=7A20 -> AX=%04X BX=%04X ES=%04X\n",
r.x.ax, r.x.bx, s.es);
if (r.x.ax == 0)
fprintf(stdout, "VLM entry likely present at %04X:%04X\n", s.es, r.x.bx);
else
fprintf(stdout, "VLM entry not reported by INT 2F/7A20\n");
tests_set_frag(&reqfrags[0], hdr, 9);
tests_set_frag(&reqfrags[1], path, path_len);
/*
* DeveloperNet 1997 dvlmreq.c:
* AH=DCh, CX=0, INT 21h
* if CX != 0 then NETX/Shell API is present.
* ncpdos16 87s6.c reply frags:
* local entry-info block 0x4d
* caller output extension 0x100
*/
memset(&r, 0, sizeof(r));
memset(&s, 0, sizeof(s));
r.h.ah = 0xDC;
r.x.cx = 0;
int86x(0x21, &r, &r, &s);
tests_set_frag(&replfrags[0], repl, 0x4d);
tests_set_frag(&replfrags[1], repl + 0x4d, 0x100);
fprintf(stdout, "INT 21 AH=DC CX=0 -> AX=%04X BX=%04X CX=%04X DX=%04X ES=%04X\n",
r.x.ax, r.x.bx, r.x.cx, r.x.dx, s.es);
if (r.x.cx != 0)
fprintf(stdout, "NETX/Shell API likely present\n");
else
fprintf(stdout, "NETX/Shell API not reported by AH=DC\n");
fprintf(stdout, "TEST NWREQ87VLM NCP87/S6 for %s\n", name);
fprintf(stdout, "connid=%u dhandle=%u path.len=%u\n", connid, dhandle, path_len);
tests_dump_bytes("VLM hdr :", hdr, 9);
tests_dump_bytes("VLM path:", path, path_len > 48 ? 48 : path_len);
fprintf(stdout, "\nInterpretation like DeveloperNet dvlmreq.c:\n");
if (r.x.cx != 0)
fprintf(stdout, " Shell bit present\n");
fprintf(stdout, " If INT2F AX=7A20 returned AX=0000, VLM path should be used for NWCREQUEST.\n");
fprintf(stdout, "VLM call: AX=0057 BX=0002 CX=conn DX=0002 p1=6 p2=20 p3=0\n");
rc = Net_Call_VLM_Raw(0x0057, 2, (UI)connid, 2,
reqfrags, replfrags,
6, 0x20, 0);
fprintf(stdout, "NWREQ87VLM rc=%04X\n", rc);
tests_dump_bytes("VLM repl[0..63]:", repl, 64);
tests_dump_bytes("VLM repl[4d..8c]:", repl + 0x4d, 64);
a0 = tests_get_dword_lh(repl);
a4d = tests_get_dword_lh(repl + 0x4d);
fprintf(stdout, "NWREQ87VLM dword[0]=%08lX dword[4d]=%08lX\n", a0, a4d);
return(0);
}
@@ -488,12 +519,12 @@ int func_tests(int argc, char *argv[], int mode)
if (tests_same_arg(argv[1], "E300") || tests_same_arg(argv[1], "NETCALLE300"))
return tests_netcall_e300();
if (tests_same_arg(argv[1], "REQTYPE"))
return tests_reqtype();
if (tests_same_arg(argv[1], "NWREQ87"))
return tests_nwreq87(argc, argv);
if (tests_same_arg(argv[1], "NWREQ87VLM"))
return tests_nwreq87vlm(argc, argv);
if (tests_same_arg(argv[1], "NCPF2"))
return tests_ncpf2(argc, argv);