/* nwtests.c 20-May-96 */ /**************************************************************** * (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * ****************************************************************/ #include "net.h" static int tests_same_arg(char *a, char *b) { while (*a || *b) { int ca = *a++; int cb = *b++; if (ca >= 'a' && ca <= 'z') ca -= 32; if (cb >= 'a' && cb <= 'z') cb -= 32; if (ca != cb) return(0); } return(1); } static void tests_usage(void) { fprintf(stdout, "Usage: TESTS [OLD|NETCALL|E300|NCPF2 [file]|NWREQ87 [file]]\n"); } static int tests_netcall(void) { unsigned char req[4]; unsigned char repl[4]; int asm_rc; int c_rc; memset(req, 0, sizeof(req)); memset(repl, 0, sizeof(repl)); fprintf(stdout, "TEST Net_Call ASM vs C\n"); fprintf(stdout, "Call: INT 21h AH=19h get current drive\n"); fprintf(stdout, "Expected: AL=0 for A:, 1 for B:, 2 for C:, ...\n\n"); asm_rc = Net_Call(0x1900, req, repl); fprintf(stdout, "ASM Net_Call(1900h) rc=%04X drive=%c:\n", asm_rc, 'A' + (asm_rc & 0xff)); c_rc = Net_Call_C(0x1900, req, repl); fprintf(stdout, "C Net_Call_C(1900h) rc=%04X drive=%c:\n", c_rc, 'A' + (c_rc & 0xff)); Net_Call_C_Dump(); if ((asm_rc & 0xff) == (c_rc & 0xff)) fprintf(stdout, "\nNETCALL C basic register test OK\n"); else fprintf(stdout, "\nNETCALL C basic register test FAILED\n"); return(0); } static int tests_old(int argc, char *argv[], int mode) { int level = ncp_17_02(NWCONN, 6); int dirhandle = alloc_temp_dir_handle(0, "SYS:", 'd', NULL); int result = -1; uint8 *path = (argc < 2) ? "SYS:\\TMP" : argv[1]; if (dirhandle > -1) { result = ncp_16_02(dirhandle, "SYSTEM/", NULL, NULL, NULL, NULL); result = ncp_16_02(dirhandle, "SYSTEM", NULL, NULL, NULL, NULL); } fprintf(stdout, "dirhandle=%d, result=%d\n", dirhandle, result); result = redir_device_drive(0x4, "u:", path); fprintf(stdout, "redir path=%s, result=%d\n", path, result); path="Q1"; result = redir_device_drive(0x3, "LPT1", path); fprintf(stdout, "redir path=%s, result=%d\n", path, result); { int k =-1; uint8 devname[20]; uint8 remotename[130]; int devicetyp; while ((result = list_redir(++k, &devicetyp, devname, remotename)) > -1){ fprintf(stdout, "index=%d, dev=%s(%d), %s result=%d\n", k, devname, devicetyp, remotename, result); } } if (level > -1) (void) ncp_17_02(NWCONN, level); return(0); } static void tests_dump_bytes(char *title, unsigned char *p, int len) { int i; fprintf(stdout, "%s", title); for (i = 0; i < len; i++) fprintf(stdout, " %02X", p[i]); fprintf(stdout, "\n"); } static int tests_netcall_e300(void) { struct { uint16 len; uint8 func; } req_asm, req_c; struct { uint16 len; uint8 data[16]; } repl_asm, repl_c; int asm_rc; int c_rc; memset(&req_asm, 0, sizeof(req_asm)); memset(&req_c, 0, sizeof(req_c)); memset(&repl_asm, 0, sizeof(repl_asm)); memset(&repl_c, 0, sizeof(repl_c)); /* * NCP 17/17 Get Login Encryption Key. * This is a known safe bindery/login helper call used by LOGIN/PASSWD code. * Request via old DOS NetWare API AX=E300. */ req_asm.len = 1; req_asm.func = 0x17; repl_asm.len = 8; req_c.len = 1; req_c.func = 0x17; repl_c.len = 8; fprintf(stdout, "TEST Net_Call ASM vs C E300/NCP17/17\n"); fprintf(stdout, "Call: Get Login Encryption Key\n\n"); asm_rc = Net_Call(0xE300, &req_asm, &repl_asm); fprintf(stdout, "ASM Net_Call(E300h) rc=%04X\n", asm_rc); tests_dump_bytes("ASM key:", repl_asm.data, 8); c_rc = Net_Call_C(0xE300, &req_c, &repl_c); fprintf(stdout, "C Net_Call_C(E300h) rc=%04X\n", c_rc); tests_dump_bytes("C key:", repl_c.data, 8); Net_Call_C_Dump(); if ((asm_rc & 0xff) == (c_rc & 0xff)) fprintf(stdout, "\nNETCALL C E300 return test OK\n"); else fprintf(stdout, "\nNETCALL C E300 return test FAILED\n"); /* * Keys can differ per request, so do not require byte-identical keys. * We only compare return status and check that both calls returned 8 bytes. */ return(0); } static void tests_put_word_lh(uint8 *p, uint16 v) { p[0] = (uint8)(v & 0xff); p[1] = (uint8)((v >> 8) & 0xff); } static void tests_put_dword_lh(uint8 *p, uint32 v) { p[0] = (uint8)(v & 0xff); p[1] = (uint8)((v >> 8) & 0xff); p[2] = (uint8)((v >> 16) & 0xff); p[3] = (uint8)((v >> 24) & 0xff); } static uint32 tests_get_dword_lh(uint8 *p) { return((uint32)p[0] | ((uint32)p[1] << 8) | ((uint32)p[2] << 16) | ((uint32)p[3] << 24)); } static int tests_get_current_drive(void) { REGS regs; regs.h.ah = 0x19; int86(0x21, ®s, ®s); return((int)regs.h.al); } static int tests_current_conn_dhandle(uint8 *connid, uint8 *dhandle) { uint8 flags = 0; int drive; drive = tests_get_current_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, "NCPF2DBG drive=%c: connid=%u dhandle=%u flags=%02X\n", 'A' + drive, *connid, *dhandle, flags); if (!*connid || (flags & 0x80)) { fprintf(stdout, "NCPF2DBG current drive is not a network drive\n"); return(-1); } return(0); } static int tests_add_handle_path(uint8 *p, uint8 dhandle, char *name) { int nlen; nlen = strlen(name); if (nlen > 255) nlen = 255; *p++ = dhandle; tests_put_dword_lh(p, 0L); p += 4; *p++ = 0; /* dirstyle = short dir handle */ *p++ = 1; /* one component */ *p++ = (uint8)nlen; memcpy(p, name, nlen); p += nlen; return(1 + 4 + 1 + 1 + 1 + nlen); } static int tests_ncpf2_read_one(char *name, UI cx_mode) { struct { uint8 data[320]; } req; struct { uint8 data[256]; } repl; uint8 *p; uint8 connid = 0; uint8 dhandle = 0; UI cx; int hlen; int rc; uint32 attr; 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 */ tests_put_dword_lh(p, 0x00000004UL); p += 4; /* RIM_ATTRIBUTES */ hlen = tests_add_handle_path(p, dhandle, name); p += hlen; if (cx_mode == 0) cx = (UI)(p - req.data); /* most likely: request length */ else cx = sizeof(repl.data); /* alternate: reply buffer size */ fprintf(stdout, "NCPF2DBG name=%s func=57 conn=%u cx=%u dx=%u mode=%u req.len=%u repl.max=%u\n", name, connid, cx, (UI)sizeof(repl.data), 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_F2_C(0x57, cx, (UI)sizeof(repl.data), req.data, repl.data); 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, "NCPF2DBG attr[0]=%08lX\n", attr); return(0); } 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 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"); return tests_ncpf2_read_one(name, mode); } static void tests_build_nwreq87_path(uint8 *buf, uint8 dhandle, char *name, UI *out_len) { uint8 *p; int nlen; memset(buf, 0, 300); p = buf; nlen = strlen(name); if (nlen > 255) nlen = 255; /* * Same compact handle/path payload we used before: * handle, dirbase, dirstyle, component-count, len, name * The new part in this test is not the path itself; it is that we now * reproduce NWCREQUEST's fragmented request and full reply size. */ *p++ = dhandle; tests_put_dword_lh(p, 0L); p += 4; *p++ = 0; /* dirstyle = short directory handle */ *p++ = 1; /* one path component */ *p++ = (uint8)nlen; memcpy(p, name, nlen); p += nlen; *out_len = (UI)(p - buf); } static UI tests_build_nwreq87s6_flat(uint8 *req, uint8 *path, UI path_len) { uint8 *p; memset(req, 0, 400); p = req; /* * DeveloperNet ncpdos16 87s6.c builds two request fragments: * frag 1 length 9: * subfn=6, srcNS, dstNS, searchAttrs, returnInfoMask * frag 2: * packed handle/path structure * * NWCREQUEST for NETX/Shell concatenates those request fragments before * calling NWCSHELLREQ. */ *p++ = 6; /* NCP87 subfunction 6 */ *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 */ memcpy(p, path, path_len); p += path_len; return (UI)(p - req); } static int tests_nwreq87(int argc, char *argv[]) { char *name = "LOGIN.EXE"; uint8 connid = 0; uint8 dhandle = 0; uint8 path[300]; uint8 req[400]; uint8 repl[0x180]; uint8 dummy[8]; UI path_len; UI req_len; int rc; uint32 a0; uint32 a4; uint32 a4d; if (argc > 2) name = argv[2]; if (tests_current_conn_dhandle(&connid, &dhandle)) return(1); tests_build_nwreq87_path(path, dhandle, name, &path_len); req_len = tests_build_nwreq87s6_flat(req, path, path_len); memset(repl, 0, sizeof(repl)); memset(dummy, 0, sizeof(dummy)); fprintf(stdout, "TEST NWREQ87 shell-style NCP87/S6 for %s\n", name); fprintf(stdout, "connid=%u dhandle=%u path.len=%u req.len=%u repl.len=%u\n", connid, dhandle, path_len, req_len, (UI)0x014d); tests_dump_bytes("NWREQ87 path:", path, path_len > 48 ? 48 : path_len); tests_dump_bytes("NWREQ87 req :", req, req_len > 64 ? 64 : req_len); /* * Reproduce the NETX/Shell path in clndos16 dreq.c: * first AH=F0/DX=conn via NWCSHELLREQ * then AH=F2/AL=function with DS:SI=request, CX=requestLen, * ES:DI=reply, DX=sum(replyFragLengths). * * For 87s6.c reply fragments are 0x4d + 0x100 = 0x014d. */ fprintf(stdout, "NWREQ87 init F000 DX=conn\n"); rc = Net_Call_F2X_C(0xF000, 0, 0, (UI)connid, dummy, repl); fprintf(stdout, "NWREQ87 init rc=%04X\n", rc); Net_Call_C_Dump(); fprintf(stdout, "NWREQ87 call F257 CX=req.len DX=014D\n"); rc = Net_Call_F2X_C(0xF257, 0, req_len, 0x014d, req, repl); fprintf(stdout, "NWREQ87 rc=%04X\n", rc); Net_Call_C_Dump(); tests_dump_bytes("NWREQ87 repl[0..63]:", repl, 64); tests_dump_bytes("NWREQ87 repl[4d..8c]:", repl + 0x4d, 64); a0 = tests_get_dword_lh(repl); a4 = tests_get_dword_lh(repl + 4); a4d = tests_get_dword_lh(repl + 0x4d); fprintf(stdout, "NWREQ87 dword[0]=%08lX dword[4]=%08lX dword[4d]=%08lX\n", a0, a4, a4d); return(0); } typedef struct { uint16 off; uint16 seg; uint16 len; } TEST_NWFRAG16; static void tests_set_frag(TEST_NWFRAG16 *f, void *ptr, UI len) { f->off = FP_OFF(ptr); f->seg = FP_SEG(ptr); f->len = (uint16)len; } 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; 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)); /* * ncpdos16 87s6.c request frag #1, length 9. */ 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 */ tests_set_frag(&reqfrags[0], hdr, 9); tests_set_frag(&reqfrags[1], path, path_len); /* * ncpdos16 87s6.c reply frags: * local entry-info block 0x4d * caller output extension 0x100 */ tests_set_frag(&replfrags[0], repl, 0x4d); tests_set_frag(&replfrags[1], repl + 0x4d, 0x100); 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, "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); } static UI tests_build_nwreq87_path_multi(uint8 *buf, uint8 dhandle, UI dirbase, uint8 style, int count, char *c1, char *c2, char *c3) { uint8 *p; int l; memset(buf, 0, 300); p = buf; *p++ = dhandle; tests_put_dword_lh(p, (uint32)dirbase); p += 4; *p++ = style; *p++ = (uint8)count; if (count > 0 && c1) { l = strlen(c1); if (l > 255) l = 255; *p++ = (uint8)l; memcpy(p, c1, l); p += l; } if (count > 1 && c2) { l = strlen(c2); if (l > 255) l = 255; *p++ = (uint8)l; memcpy(p, c2, l); p += l; } if (count > 2 && c3) { l = strlen(c3); if (l > 255) l = 255; *p++ = (uint8)l; memcpy(p, c3, l); p += l; } return (UI)(p - buf); } static void tests_wait_key(void) { fprintf(stdout, "\nStrike any key when ready . . . "); fflush(stdout); getch(); fprintf(stdout, "\n"); fflush(stdout); } static int tests_nwreq87vlm_one(char *label, uint8 connid, uint8 *hdr, uint8 *path, UI path_len) { uint8 repl[0x180]; TEST_NWFRAG16 reqfrags[2]; TEST_NWFRAG16 replfrags[2]; int rc; uint32 a0; uint32 a4d; memset(repl, 0, sizeof(repl)); memset(reqfrags, 0, sizeof(reqfrags)); memset(replfrags, 0, sizeof(replfrags)); tests_set_frag(&reqfrags[0], hdr, 9); tests_set_frag(&reqfrags[1], path, path_len); tests_set_frag(&replfrags[0], repl, 0x4d); tests_set_frag(&replfrags[1], repl + 0x4d, 0x100); fprintf(stdout, "\nCASE %s\n", label); tests_dump_bytes("PATH:", path, path_len > 64 ? 64 : path_len); rc = Net_Call_VLM_Raw(0x0057, 2, (UI)connid, 2, reqfrags, replfrags, 6, 0x20, 0); fprintf(stdout, "RC=%04X\n", rc); tests_dump_bytes("REPL0:", repl, 32); tests_dump_bytes("REPL4D:", repl + 0x4d, 32); a0 = tests_get_dword_lh(repl); a4d = tests_get_dword_lh(repl + 0x4d); fprintf(stdout, "DW0=%08lX DW4D=%08lX\n", a0, a4d); tests_wait_key(); return rc; } static int tests_nwreq87vlmmatrix(int argc, char *argv[]) { char *name = "LOGIN.EXE"; uint8 connid = 0; uint8 dhandle = 0; uint8 hdr[16]; uint8 path[300]; UI len; (void)argc; (void)argv; if (tests_current_conn_dhandle(&connid, &dhandle)) return(1); memset(hdr, 0, sizeof(hdr)); hdr[0] = 6; hdr[1] = 0; hdr[2] = 0; tests_put_word_lh(hdr + 3, 0x0006); tests_put_dword_lh(hdr + 5, 0x00000004UL); fprintf(stdout, "TEST NWREQ87VLMMATRIX NCP87/S6\n"); fprintf(stdout, "connid=%u dhandle=%u file=%s\n", connid, dhandle, name); tests_dump_bytes("HDR:", hdr, 9); /* * We know the VLM transport is reached. RC=81 now likely means our * packed handle/path is wrong for NCP87. Try the common handle/path * variants: * * current mapped handle + file * current mapped handle + PUBLIC/file * root handle 0 + PUBLIC/file * style 1 variants in case dirstyle differs */ len = tests_build_nwreq87_path_multi(path, dhandle, 0, 0, 1, "LOGIN.EXE", 0, 0); tests_nwreq87vlm_one("h=dhandle style=0 LOGIN.EXE", connid, hdr, path, len); len = tests_build_nwreq87_path_multi(path, dhandle, 0, 0, 2, "PUBLIC", "LOGIN.EXE", 0); tests_nwreq87vlm_one("h=dhandle style=0 PUBLIC/LOGIN.EXE", connid, hdr, path, len); len = tests_build_nwreq87_path_multi(path, 0, 0, 0, 2, "PUBLIC", "LOGIN.EXE", 0); tests_nwreq87vlm_one("h=0 style=0 PUBLIC/LOGIN.EXE", connid, hdr, path, len); len = tests_build_nwreq87_path_multi(path, dhandle, 0, 1, 1, "LOGIN.EXE", 0, 0); tests_nwreq87vlm_one("h=dhandle style=1 LOGIN.EXE", connid, hdr, path, len); len = tests_build_nwreq87_path_multi(path, 0, 0, 1, 2, "PUBLIC", "LOGIN.EXE", 0); tests_nwreq87vlm_one("h=0 style=1 PUBLIC/LOGIN.EXE", connid, hdr, path, len); return(0); } static int tests_nwreq87vlmcase(int argc, char *argv[]) { int which = 1; uint8 connid = 0; uint8 dhandle = 0; uint8 hdr[16]; uint8 path[300]; UI len; if (argc > 2) which = atoi(argv[2]); if (tests_current_conn_dhandle(&connid, &dhandle)) return(1); memset(hdr, 0, sizeof(hdr)); hdr[0] = 6; hdr[1] = 0; hdr[2] = 0; tests_put_word_lh(hdr + 3, 0x0006); tests_put_dword_lh(hdr + 5, 0x00000004UL); fprintf(stdout, "TEST NWREQ87VLMCASE %d\n", which); fprintf(stdout, "connid=%u dhandle=%u\n", connid, dhandle); tests_dump_bytes("HDR:", hdr, 9); switch (which) { case 1: len = tests_build_nwreq87_path_multi(path, dhandle, 0, 0, 1, "LOGIN.EXE", 0, 0); return tests_nwreq87vlm_one("1 h=dhandle style=0 LOGIN.EXE", connid, hdr, path, len); case 2: len = tests_build_nwreq87_path_multi(path, dhandle, 0, 0, 2, "PUBLIC", "LOGIN.EXE", 0); return tests_nwreq87vlm_one("2 h=dhandle style=0 PUBLIC/LOGIN.EXE", connid, hdr, path, len); case 3: len = tests_build_nwreq87_path_multi(path, 0, 0, 0, 2, "PUBLIC", "LOGIN.EXE", 0); return tests_nwreq87vlm_one("3 h=0 style=0 PUBLIC/LOGIN.EXE", connid, hdr, path, len); case 4: len = tests_build_nwreq87_path_multi(path, dhandle, 0, 1, 1, "LOGIN.EXE", 0, 0); return tests_nwreq87vlm_one("4 h=dhandle style=1 LOGIN.EXE", connid, hdr, path, len); case 5: len = tests_build_nwreq87_path_multi(path, 0, 0, 1, 2, "PUBLIC", "LOGIN.EXE", 0); return tests_nwreq87vlm_one("5 h=0 style=1 PUBLIC/LOGIN.EXE", connid, hdr, path, len); } fprintf(stdout, "Valid cases: 1..5\n"); return(1); } static void tests_set_frag_alt_len_off_seg(uint8 *buf, void *ptr, UI len) { tests_put_word_lh(buf + 0, (uint16)len); tests_put_word_lh(buf + 2, (uint16)FP_OFF(ptr)); tests_put_word_lh(buf + 4, (uint16)FP_SEG(ptr)); } static void tests_nwreq87vlmreg_help(void) { fprintf(stdout, "Usage: TESTS NWREQ87VLMREG n\n"); fprintf(stdout, "n=1..20, one VLM register/fragment-layout case\n"); fprintf(stdout, "1-10 frag layout off,seg,len\n"); fprintf(stdout, "11-20 frag layout len,off,seg\n"); fprintf(stdout, "odd=stack 6,20,0 even=stack 0,20,6\n"); fprintf(stdout, "reg maps repeat every 2 cases:\n"); fprintf(stdout, " A AX=57 BX=reqs CX=conn DX=reps\n"); fprintf(stdout, " B AX=57 BX=conn CX=reqs DX=reps\n"); fprintf(stdout, " C AX=57 BX=reqs CX=reps DX=conn\n"); fprintf(stdout, " D AX=57 BX=conn CX=reps DX=reqs\n"); fprintf(stdout, " E AX=57 BX=reps CX=conn DX=reqs\n"); } static int tests_nwreq87vlmreg(int argc, char *argv[]) { int which = 1; int layout_alt; int local_case; int stack_rev; int regmap; uint8 connid = 0; uint8 dhandle = 0; uint8 hdr[16]; uint8 path[300]; uint8 repl[0x180]; UI path_len; TEST_NWFRAG16 frags_req_std[2]; TEST_NWFRAG16 frags_rep_std[2]; uint8 frags_req_alt[12]; uint8 frags_rep_alt[12]; void *reqfragp; void *repfragp; UI ax = 0x0057; UI bx = 0; UI cx = 0; UI dx = 0; UI p1 = 6; UI p2 = 0x20; UI p3 = 0; int rc; uint32 dw0; uint32 dw4d; if (argc < 3) { tests_nwreq87vlmreg_help(); return(1); } which = atoi(argv[2]); if (which < 1 || which > 20) { tests_nwreq87vlmreg_help(); return(1); } if (tests_current_conn_dhandle(&connid, &dhandle)) return(1); memset(hdr, 0, sizeof(hdr)); hdr[0] = 6; hdr[1] = 0; hdr[2] = 0; tests_put_word_lh(hdr + 3, 0x0006); tests_put_dword_lh(hdr + 5, 0x00000004UL); path_len = tests_build_nwreq87_path_multi(path, dhandle, 0, 0, 1, "LOGIN.EXE", 0, 0); memset(repl, 0, sizeof(repl)); memset(frags_req_std, 0, sizeof(frags_req_std)); memset(frags_rep_std, 0, sizeof(frags_rep_std)); memset(frags_req_alt, 0, sizeof(frags_req_alt)); memset(frags_rep_alt, 0, sizeof(frags_rep_alt)); tests_set_frag(&frags_req_std[0], hdr, 9); tests_set_frag(&frags_req_std[1], path, path_len); tests_set_frag(&frags_rep_std[0], repl, 0x4d); tests_set_frag(&frags_rep_std[1], repl + 0x4d, 0x100); tests_set_frag_alt_len_off_seg(frags_req_alt + 0, hdr, 9); tests_set_frag_alt_len_off_seg(frags_req_alt + 6, path, path_len); tests_set_frag_alt_len_off_seg(frags_rep_alt + 0, repl, 0x4d); tests_set_frag_alt_len_off_seg(frags_rep_alt + 6, repl + 0x4d, 0x100); layout_alt = (which > 10); local_case = layout_alt ? which - 10 : which; stack_rev = ((local_case & 1) == 0); regmap = (local_case + 1) / 2; /* 1..5 */ if (layout_alt) { reqfragp = frags_req_alt; repfragp = frags_rep_alt; } else { reqfragp = frags_req_std; repfragp = frags_rep_std; } if (stack_rev) { p1 = 0; p2 = 0x20; p3 = 6; } switch (regmap) { case 1: bx = 2; cx = connid; dx = 2; break; case 2: bx = connid; cx = 2; dx = 2; break; case 3: bx = 2; cx = 2; dx = connid; break; case 4: bx = connid; cx = 2; dx = 2; break; case 5: bx = 2; cx = connid; dx = 2; break; } /* * Cases 2 and 4 share registers but differ stack order. * Cases 1 and 9 share registers but let us repeat with same stack/table * for sanity. Keep explicit output so we know exactly what was run. */ fprintf(stdout, "TEST NWREQ87VLMREG case=%d\n", which); fprintf(stdout, "layout=%s stack=%s regmap=%d\n", layout_alt ? "len,off,seg" : "off,seg,len", stack_rev ? "0,20,6" : "6,20,0", regmap); fprintf(stdout, "connid=%u dhandle=%u path_len=%u\n", connid, dhandle, path_len); fprintf(stdout, "AX=%04X BX=%04X CX=%04X DX=%04X p1=%04X p2=%04X p3=%04X\n", ax, bx, cx, dx, p1, p2, p3); tests_dump_bytes("HDR :", hdr, 9); tests_dump_bytes("PATH:", path, path_len > 48 ? 48 : path_len); rc = Net_Call_VLM_Raw(ax, bx, cx, dx, reqfragp, repfragp, p1, p2, p3); fprintf(stdout, "RC=%04X\n", rc); tests_dump_bytes("REPL0 :", repl, 32); tests_dump_bytes("REPL4D:", repl + 0x4d, 32); dw0 = tests_get_dword_lh(repl); dw4d = tests_get_dword_lh(repl + 0x4d); fprintf(stdout, "DW0=%08lX DW4D=%08lX\n", dw0, dw4d); return(0); } static int tests_nwreq87vlmconn_one(UI conn_value, UI label_value) { uint8 connid = 0; uint8 dhandle = 0; uint8 hdr[16]; uint8 path[300]; uint8 repl[0x180]; TEST_NWFRAG16 reqfrags[2]; TEST_NWFRAG16 replfrags[2]; UI path_len; int rc; uint32 dw0; uint32 dw4d; if (tests_current_conn_dhandle(&connid, &dhandle)) return(1); memset(hdr, 0, sizeof(hdr)); hdr[0] = 6; hdr[1] = 0; hdr[2] = 0; tests_put_word_lh(hdr + 3, 0x0006); tests_put_dword_lh(hdr + 5, 0x00000004UL); path_len = tests_build_nwreq87_path_multi(path, dhandle, 0, 0, 1, "LOGIN.EXE", 0, 0); memset(repl, 0, sizeof(repl)); memset(reqfrags, 0, sizeof(reqfrags)); memset(replfrags, 0, sizeof(replfrags)); tests_set_frag(&reqfrags[0], hdr, 9); tests_set_frag(&reqfrags[1], path, path_len); tests_set_frag(&replfrags[0], repl, 0x4d); tests_set_frag(&replfrags[1], repl + 0x4d, 0x100); fprintf(stdout, "TEST NWREQ87VLMCONN value=%u label=%u\n", conn_value, label_value); fprintf(stdout, "drive connid=%u dhandle=%u path_len=%u\n", connid, dhandle, path_len); fprintf(stdout, "VLM call: AX=0057 BX=0002 CX=%04X DX=0002 p1=0006 p2=0020 p3=0000\n", conn_value); tests_dump_bytes("HDR :", hdr, 9); tests_dump_bytes("PATH:", path, path_len > 48 ? 48 : path_len); rc = Net_Call_VLM_Raw(0x0057, 2, conn_value, 2, reqfrags, replfrags, 6, 0x20, 0); fprintf(stdout, "RC=%04X\n", rc); tests_dump_bytes("REPL0 :", repl, 32); tests_dump_bytes("REPL4D:", repl + 0x4d, 32); dw0 = tests_get_dword_lh(repl); dw4d = tests_get_dword_lh(repl + 0x4d); fprintf(stdout, "DW0=%08lX DW4D=%08lX\n", dw0, dw4d); return(rc); } static int tests_nwreq87vlmconn(int argc, char *argv[]) { UI value; if (argc < 3) { fprintf(stdout, "Usage: TESTS NWREQ87VLMCONN value\n"); fprintf(stdout, "Examples:\n"); fprintf(stdout, " TESTS NWREQ87VLMCONN 0\n"); fprintf(stdout, " TESTS NWREQ87VLMCONN 1\n"); fprintf(stdout, " TESTS NWREQ87VLMCONN 2\n"); fprintf(stdout, "Hex is not parsed; use decimal values.\n"); return(1); } value = (UI)atoi(argv[2]); return tests_nwreq87vlmconn_one(value, value); } static int tests_nwreq87vlmconnmatrix(void) { UI values[10]; int i; uint8 connid = 0; uint8 dhandle = 0; uint8 flags = 0; int drive; drive = tests_get_current_drive(); get_drive_info((uint8)drive, &connid, &dhandle, &flags); /* * Paged matrix: one screen per value. * Start with likely connection-reference candidates. */ values[0] = 0; values[1] = 1; values[2] = 2; values[3] = 3; values[4] = (UI)connid; values[5] = (UI)dhandle; values[6] = (UI)drive; values[7] = (UI)(drive + 1); values[8] = 0x31; /* low byte observed in AH=DC CX=3130 */ values[9] = 0x3130; /* AH=DC returned CX */ fprintf(stdout, "TEST NWREQ87VLMCONNMATRIX paged\n"); fprintf(stdout, "current drive=%c: connid=%u dhandle=%u flags=%02X\n", 'A' + drive, connid, dhandle, flags); tests_wait_key(); for (i = 0; i < 10; i++) { tests_nwreq87vlmconn_one(values[i], (UI)i); if (i != 9) tests_wait_key(); } return(0); } static UI tests_build_novell_handle_path(uint8 *buf, uint8 dhandle, uint16 dirbase, uint8 style, int count, char *c1, char *c2, char *c3) { uint8 *p; int l; UI used; /* * DeveloperNet fillhan.o: * memset(pathStruct, 0, 0x133) * if handle != 0: * byte[5] = 0 * word[1] = handle * word[3] = 0 * else: * byte[5] = 0xff * * _NWGETCOMPATHSTRUCTLENGTH reads component count at offset 6 and returns * 7 + sum(1 + componentLen) * * ncpdos16 87s6.c sends frag2 from struct start with length stored at +13c. */ memset(buf, 0, 0x140); if (dhandle) { tests_put_word_lh(buf + 1, (uint16)dhandle); tests_put_word_lh(buf + 3, dirbase); buf[5] = style; } else { buf[5] = 0xff; } p = buf + 6; *p++ = (uint8)count; if (count > 0 && c1) { l = strlen(c1); if (l > 255) l = 255; *p++ = (uint8)l; memcpy(p, c1, l); p += l; } if (count > 1 && c2) { l = strlen(c2); if (l > 255) l = 255; *p++ = (uint8)l; memcpy(p, c2, l); p += l; } if (count > 2 && c3) { l = strlen(c3); if (l > 255) l = 255; *p++ = (uint8)l; memcpy(p, c3, l); p += l; } used = (UI)(p - buf); tests_put_word_lh(buf + 0x13c, used); return used; } static int tests_nwreq87vlmfull_one(char *label, uint8 connid, uint8 *hdr, uint8 *path_struct) { uint8 repl[0x180]; TEST_NWFRAG16 reqfrags[2]; TEST_NWFRAG16 replfrags[2]; UI path_len; int rc; uint32 dw0; uint32 dw4d; path_len = (UI)(path_struct[0x13c] | ((UI)path_struct[0x13d] << 8)); memset(repl, 0, sizeof(repl)); memset(reqfrags, 0, sizeof(reqfrags)); memset(replfrags, 0, sizeof(replfrags)); tests_set_frag(&reqfrags[0], hdr, 9); tests_set_frag(&reqfrags[1], path_struct, path_len); tests_set_frag(&replfrags[0], repl, 0x4d); tests_set_frag(&replfrags[1], repl + 0x4d, 0x100); fprintf(stdout, "\nCASE %s\n", label); fprintf(stdout, "path_len=%u\n", path_len); tests_dump_bytes("PATH:", path_struct, path_len > 64 ? 64 : path_len); rc = Net_Call_VLM_Raw(0x0057, 2, (UI)connid, 2, reqfrags, replfrags, 6, 0x20, 0); fprintf(stdout, "RC=%04X\n", rc); tests_dump_bytes("REPL0 :", repl, 32); tests_dump_bytes("REPL4D:", repl + 0x4d, 32); dw0 = tests_get_dword_lh(repl); dw4d = tests_get_dword_lh(repl + 0x4d); fprintf(stdout, "DW0=%08lX DW4D=%08lX\n", dw0, dw4d); tests_wait_key(); return rc; } static int tests_nwreq87vlmfull(void) { uint8 connid = 0; uint8 dhandle = 0; uint8 flags = 0; int drive; uint8 hdr[16]; uint8 path[0x140]; drive = tests_get_current_drive(); if (get_drive_info((uint8)drive, &connid, &dhandle, &flags)) { fprintf(stdout, "get_drive_info failed\n"); return(1); } memset(hdr, 0, sizeof(hdr)); hdr[0] = 6; hdr[1] = 0; hdr[2] = 0; tests_put_word_lh(hdr + 3, 0x0006); tests_put_dword_lh(hdr + 5, 0x00000004UL); fprintf(stdout, "TEST NWREQ87VLMFULL Novell handle/path struct\n"); fprintf(stdout, "drive=%c: connid=%u dhandle=%u flags=%02X\n", 'A' + drive, connid, dhandle, flags); tests_dump_bytes("HDR:", hdr, 9); tests_build_novell_handle_path(path, dhandle, 0, 0, 1, "LOGIN.EXE", 0, 0); tests_nwreq87vlmfull_one("1 dhandle LOGIN.EXE", connid, hdr, path); tests_build_novell_handle_path(path, dhandle, 0, 0, 2, "PUBLIC", "LOGIN.EXE", 0); tests_nwreq87vlmfull_one("2 dhandle PUBLIC/LOGIN.EXE", connid, hdr, path); tests_build_novell_handle_path(path, 0, 0, 0, 2, "PUBLIC", "LOGIN.EXE", 0); tests_nwreq87vlmfull_one("3 handle0 PUBLIC/LOGIN.EXE", connid, hdr, path); return(0); } static uint16 tests_get_word_lh(uint8 *p) { return (uint16)(p[0] | ((uint16)p[1] << 8)); } static uint32 tests_get_dword_lh2(uint8 *p) { return ((uint32)p[0] | ((uint32)p[1] << 8) | ((uint32)p[2] << 16) | ((uint32)p[3] << 24)); } static int tests_c32type(void) { uint8 out[32]; int rc; uint16 ax, bx, cx, dx, si, dsreg, esreg; uint32 esi, ecx; memset(out, 0, sizeof(out)); fprintf(stdout, "TEST Client32/NIOS probe ESI/ECX\n"); fprintf(stdout, "16-bit OMF, manual 386 stores after INT 2F AX=D8C1\n\n"); rc = C32_LoadNios_Probe(0xD8C1, out); ax = tests_get_word_lh(out + 0); esi = tests_get_dword_lh2(out + 2); ecx = tests_get_dword_lh2(out + 6); bx = tests_get_word_lh(out + 10); cx = tests_get_word_lh(out + 12); dx = tests_get_word_lh(out + 14); si = tests_get_word_lh(out + 16); dsreg = tests_get_word_lh(out + 18); esreg = tests_get_word_lh(out + 20); fprintf(stdout, "C32 probe rc=%04X\n", rc); fprintf(stdout, "INT2F D8C1 result AX=%04X\n", ax); fprintf(stdout, "ESI=%08lX ECX=%08lX\n", esi, ecx); fprintf(stdout, "BX=%04X CX=%04X DX=%04X SI=%04X\n", bx, cx, dx, si); fprintf(stdout, "DS=%04X ES=%04X\n", dsreg, esreg); tests_dump_bytes("RAW:", out, 22); if (ax == 0) fprintf(stdout, "\nClient32/NIOS D8C1 reports success.\n"); else fprintf(stdout, "\nClient32/NIOS D8C1 did not report success.\n"); return(0); } static void tests_c32get_one(char *name) { uint8 out[32]; uint16 load_ax; uint32 esi, ecx; uint16 ret_ax, ret_dx; memset(out, 0, sizeof(out)); C32_GetFunc_Probe(name, out); load_ax = tests_get_word_lh(out + 0); esi = tests_get_dword_lh2(out + 2); ecx = tests_get_dword_lh2(out + 6); ret_ax = tests_get_word_lh(out + 10); ret_dx = tests_get_word_lh(out + 12); fprintf(stdout, "\nFUNC %s\n", name); fprintf(stdout, "Load AX=%04X ESI=%08lX ECX=%08lX\n", load_ax, esi, ecx); fprintf(stdout, "Resolver returned DX:AX=%04X:%04X\n", ret_dx, ret_ax); tests_dump_bytes("RAW:", out, 18); } static int tests_c32getfunc(void) { fprintf(stdout, "TEST C32GETFUNC\n"); fprintf(stdout, "Resolve Client32 function addresses via NIOS resolver\n"); tests_c32get_one("CLIENT32GetVersion"); tests_c32get_one("COMPATNcpRequestReply"); tests_c32get_one("CONNOpenByReference"); tests_c32get_one("CONNClose"); return(0); } int func_tests(int argc, char *argv[], int mode) { if (argc >= 2) { if (tests_same_arg(argv[1], "NETCALL")) return tests_netcall(); if (tests_same_arg(argv[1], "E300") || tests_same_arg(argv[1], "NETCALLE300")) return tests_netcall_e300(); if (tests_same_arg(argv[1], "C32TYPE")) return tests_c32type(); if (tests_same_arg(argv[1], "C32GETFUNC")) return tests_c32getfunc(); 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], "NWREQ87VLMMATRIX")) return tests_nwreq87vlmmatrix(argc, argv); if (tests_same_arg(argv[1], "NWREQ87VLMCASE")) return tests_nwreq87vlmcase(argc, argv); if (tests_same_arg(argv[1], "NWREQ87VLMCONN")) return tests_nwreq87vlmconn(argc, argv); if (tests_same_arg(argv[1], "NWREQ87VLMCONNMATRIX")) return tests_nwreq87vlmconnmatrix(); if (tests_same_arg(argv[1], "NWREQ87VLMFULL")) return tests_nwreq87vlmfull(); if (tests_same_arg(argv[1], "NWREQ87VLMREG")) return tests_nwreq87vlmreg(argc, argv); if (tests_same_arg(argv[1], "NCPF2")) return tests_ncpf2(argc, argv); if (tests_same_arg(argv[1], "OLD")) return tests_old(argc - 1, argv + 1, mode); if (tests_same_arg(argv[1], "/?") || tests_same_arg(argv[1], "-?") || tests_same_arg(argv[1], "?")) { tests_usage(); return(0); } } /* * Default and unknown arguments keep the historical nwtests.c behavior. */ return tests_old(argc, argv, mode); }