diff --git a/kern.c b/kern.c index 44bbac2..b2d2da3 100644 --- a/kern.c +++ b/kern.c @@ -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. diff --git a/kern.h b/kern.h index cda095e..ed6ca1d 100644 --- a/kern.h +++ b/kern.h @@ -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); diff --git a/nwtests.c b/nwtests.c index 78818e3..7ae8398 100644 --- a/nwtests.c +++ b/nwtests.c @@ -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);