This commit is contained in:
Mario Fetka
2026-05-23 14:06:36 +02:00
parent 24ccc1257d
commit 1f74c940d8
3 changed files with 112 additions and 62 deletions

68
kern.c
View File

@@ -123,6 +123,74 @@ int KERN_C_CALL Net_Call_CX(unsigned int ax, unsigned int bx,
return Net_Call_C_Last.rc;
}
/*
* Experimental Client32/VLM-style AH=F2 raw request wrapper.
*
* This mirrors the official Novell FLAG.EXE wrapper shape seen in disassembly:
* DX = connection / connection reference
* ES:DI = reply buffer
* CX = caller supplied size/count
* DS:SI = request buffer
* AH = F2h
* AL = NCP function, e.g. 57h for NCP 87
* int 21h
*
* Return convention mirrors Novell wrapper and old kern.asm Net_Call:
* if AL != 0, AH is set to 89h in Net_Call_F2_C_Last.out_ax
* return AL only
*/
int KERN_C_CALL Net_Call_F2_C(UI conn, UI function, UI cx, void *req, void *repl)
{
union REGS inregs;
union REGS outregs;
struct SREGS segregs;
UI ret_ax;
memset(&inregs, 0, sizeof(inregs));
memset(&outregs, 0, sizeof(outregs));
memset(&segregs, 0, sizeof(segregs));
memset(&Net_Call_C_Last, 0, sizeof(Net_Call_C_Last));
inregs.h.ah = 0xF2;
inregs.h.al = (uint8)(function & 0xff);
inregs.x.dx = conn;
inregs.x.cx = cx;
inregs.x.si = FP_OFF(req);
inregs.x.di = FP_OFF(repl);
segregs.ds = FP_SEG(req);
segregs.es = FP_SEG(repl);
Net_Call_C_Last.in_ax = inregs.x.ax;
Net_Call_C_Last.in_bx = inregs.x.bx;
Net_Call_C_Last.in_cx = inregs.x.cx;
Net_Call_C_Last.in_dx = inregs.x.dx;
Net_Call_C_Last.in_si = inregs.x.si;
Net_Call_C_Last.in_di = inregs.x.di;
Net_Call_C_Last.in_ds = segregs.ds;
Net_Call_C_Last.in_es = segregs.es;
Net_Call_C_Last.req_ptr = req;
Net_Call_C_Last.repl_ptr = repl;
int86x(0x21, &inregs, &outregs, &segregs);
ret_ax = outregs.x.ax;
ret_ax &= 0x00ff;
if (ret_ax)
ret_ax |= 0x8900;
Net_Call_C_Last.out_ax = ret_ax;
Net_Call_C_Last.out_bx = outregs.x.bx;
Net_Call_C_Last.out_cx = outregs.x.cx;
Net_Call_C_Last.out_dx = outregs.x.dx;
Net_Call_C_Last.out_si = outregs.x.si;
Net_Call_C_Last.out_di = outregs.x.di;
Net_Call_C_Last.out_flags = outregs.x.cflag;
Net_Call_C_Last.rc = ret_ax & 0x00ff;
return Net_Call_C_Last.rc;
}
/*
* Text dump for quick testing. Later we can expose this through DEBUG.EXE
* as "debug netcall" or similar.

7
kern.h
View File

@@ -14,6 +14,13 @@ 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_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);
extern int KERN_CALL Net_Call_F2_C(UI conn, UI function, UI cx,
void *req, void *repl);
extern void KERN_CALL Net_Call_C_Dump(void);
extern UI KERN_CALL Net_Call_C_GetDebug(UI idx);
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);
extern void KERN_CALL Net_Call_C_Dump(void);

View File

@@ -21,7 +21,7 @@ static int tests_same_arg(char *a, char *b)
static void tests_usage(void)
{
fprintf(stdout, "Usage: TESTS [OLD|NETCALL|E300|NCP87 [file]|NCP87F2 [file]]\n");
fprintf(stdout, "Usage: TESTS [OLD|NETCALL|E300|NCPF2 [file] [REPLY]]\n");
}
static int tests_netcall(void)
@@ -188,24 +188,23 @@ static int tests_get_current_drive(void)
return((int)regs.h.al);
}
static int tests_current_dhandle(uint8 *dhandle)
static int tests_current_conn_dhandle(uint8 *connid, uint8 *dhandle)
{
uint8 connid = 0;
uint8 flags = 0;
int drive;
drive = tests_get_current_drive();
if (get_drive_info((uint8)drive, &connid, dhandle, &flags)) {
fprintf(stdout, "NCP87DBG get_drive_info failed drive=%c:\n", 'A' + drive);
if (get_drive_info((uint8)drive, connid, dhandle, &flags)) {
fprintf(stdout, "NCPF2DBG get_drive_info failed drive=%c:\n", 'A' + drive);
return(-1);
}
fprintf(stdout, "NCP87DBG drive=%c: connid=%u dhandle=%u flags=%02X\n",
'A' + drive, connid, *dhandle, flags);
fprintf(stdout, "NCPF2DBG drive=%c: connid=%u dhandle=%u flags=%02X\n",
'A' + drive, *connid, *dhandle, flags);
if (!connid || (flags & 0x80)) {
fprintf(stdout, "NCP87DBG current drive is not a network drive\n");
if (!*connid || (flags & 0x80)) {
fprintf(stdout, "NCPF2DBG current drive is not a network drive\n");
return(-1);
}
@@ -219,16 +218,9 @@ static int tests_add_handle_path(uint8 *p, uint8 dhandle, char *name)
nlen = strlen(name);
if (nlen > 255) nlen = 255;
/*
* ncpfs ncp_add_handle_path2() form for dirstyle 0:
* vol/handle byte
* dirbase dword
* dirstyle byte
* NW path: component-count, len, bytes
*/
*p++ = dhandle;
tests_put_dword_lh(p, 0L); p += 4;
*p++ = 0; /* NCP_DIRSTYLE_HANDLE */
*p++ = 0; /* dirstyle = short dir handle */
*p++ = 1; /* one component */
*p++ = (uint8)nlen;
memcpy(p, name, nlen);
@@ -237,85 +229,74 @@ static int tests_add_handle_path(uint8 *p, uint8 dhandle, char *name)
return(1 + 4 + 1 + 1 + 1 + nlen);
}
static int tests_ncp87_read_one(char *name, unsigned int ax)
static int tests_ncpf2_read_one(char *name, UI cx_mode)
{
struct {
uint16 len;
uint8 data[320];
} req;
struct {
uint16 len;
uint8 data[256];
} repl;
uint8 *p;
uint8 connid = 0;
uint8 dhandle = 0;
UI cx;
int hlen;
int rc;
uint32 attr;
if (tests_current_dhandle(&dhandle))
if (tests_current_conn_dhandle(&connid, &dhandle))
return(1);
memset(&req, 0, sizeof(req));
memset(&repl, 0, sizeof(repl));
p = req.data;
*p++ = 6; /* NCP87 subfunction 6: obtain file/subdir info */
*p++ = 0; /* source namespace DOS */
*p++ = 0; /* target namespace DOS */
tests_put_word_lh(p, 0x0006); p += 2; /* SA_ALL: hidden+system */
tests_put_dword_lh(p, 0x00000004UL); p += 4;/* RIM_ATTRIBUTES */
*p++ = 6; /* NCP87 subfunction 6: obtain file/subdir info */
*p++ = 0; /* source namespace DOS */
*p++ = 0; /* target namespace DOS */
tests_put_word_lh(p, 0x0006); p += 2; /* SA_ALL */
tests_put_dword_lh(p, 0x00000004UL); p += 4; /* RIM_ATTRIBUTES */
hlen = tests_add_handle_path(p, dhandle, name);
p += hlen;
req.len = (uint16)(p - req.data);
repl.len = sizeof(repl.data);
if (cx_mode == 0)
cx = (UI)(p - req.data); /* most likely: request length */
else
cx = sizeof(repl.data); /* alternate: reply buffer size */
fprintf(stdout, "NCP87DBG TRY AX=%04X name=%s req.len=%u repl.len=%u\n",
ax, name, req.len, repl.len);
tests_dump_bytes("NCP87DBG req:", req.data, req.len > 48 ? 48 : req.len);
fprintf(stdout, "NCPF2DBG name=%s func=57 conn=%u cx=%u mode=%u req.len=%u repl.max=%u\n",
name, connid, cx, cx_mode, (UI)(p - req.data), (UI)sizeof(repl.data));
tests_dump_bytes("NCPF2DBG req:", req.data, (p - req.data) > 64 ? 64 : (int)(p - req.data));
rc = Net_Call_C(ax, &req, &repl);
rc = Net_Call_F2_C((UI)connid, 0x57, cx, req.data, repl.data);
fprintf(stdout, "NCP87DBG rc=%04X repl.len=%u\n", rc, repl.len);
tests_dump_bytes("NCP87DBG repl:", repl.data, repl.len > 64 ? 64 : repl.len);
fprintf(stdout, "NCPF2DBG rc=%04X\n", rc);
tests_dump_bytes("NCPF2DBG repl:", repl.data, 64);
Net_Call_C_Dump();
attr = tests_get_dword_lh(repl.data);
fprintf(stdout, "NCP87DBG attr[0]=%08lX\n", attr);
fprintf(stdout, "NCPF2DBG attr[0]=%08lX\n", attr);
return(0);
}
static int tests_ncp87(int argc, char *argv[])
static int tests_ncpf2(int argc, char *argv[])
{
char *name = "LOGIN.EXE";
UI mode = 0;
if (argc > 2)
name = argv[2];
if (argc > 3 && tests_same_arg(argv[3], "REPLY"))
mode = 1;
fprintf(stdout, "TEST NCP87 obtain RIM_ATTRIBUTES for %s\n", name);
fprintf(stdout, "This is read-only. It does not modify the file.\n\n");
fprintf(stdout, "TEST NCPF2 AH=F2/AL=57 NCP87 obtain RIM_ATTRIBUTES\n");
fprintf(stdout, "Default CX is request length. Add REPLY to use reply size.\n");
fprintf(stdout, "This is read-only, but still experimental.\n\n");
/*
* Try only the old-shell-style AX first. 0xF257 previously hung when used
* inside FLAG, so do not try it here automatically.
*/
return tests_ncp87_read_one(name, 0xE200);
}
static int tests_ncp87f2(int argc, char *argv[])
{
char *name = "LOGIN.EXE";
if (argc > 2)
name = argv[2];
fprintf(stdout, "TEST NCP87 F257 obtain RIM_ATTRIBUTES for %s\n", name);
fprintf(stdout, "WARNING: this variant may hang on some clients.\n\n");
return tests_ncp87_read_one(name, 0xF257);
return tests_ncpf2_read_one(name, mode);
}
@@ -330,12 +311,6 @@ 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], "NCP87"))
return tests_ncp87(argc, argv);
if (tests_same_arg(argv[1], "NCP87F2"))
return tests_ncp87f2(argc, argv);
if (tests_same_arg(argv[1], "OLD"))
return tests_old(argc - 1, argv + 1, mode);