diff --git a/nwtests.c b/nwtests.c index c2b967d..78818e3 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]\n"); + fprintf(stdout, "Usage: TESTS [OLD|NETCALL|E300|NCP87 [file]|NCP87F2 [file]]\n"); } static int tests_netcall(void) @@ -157,6 +157,168 @@ static int tests_netcall_e300(void) } +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_dhandle(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); + return(-1); + } + + fprintf(stdout, "NCP87DBG 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"); + 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; + + /* + * 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++ = 1; /* one component */ + *p++ = (uint8)nlen; + memcpy(p, name, nlen); + p += nlen; + + return(1 + 4 + 1 + 1 + 1 + nlen); +} + +static int tests_ncp87_read_one(char *name, unsigned int ax) +{ + struct { + uint16 len; + uint8 data[320]; + } req; + struct { + uint16 len; + uint8 data[256]; + } repl; + + uint8 *p; + uint8 dhandle = 0; + int hlen; + int rc; + uint32 attr; + + if (tests_current_dhandle(&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 */ + hlen = tests_add_handle_path(p, dhandle, name); + p += hlen; + + req.len = (uint16)(p - req.data); + repl.len = sizeof(repl.data); + + 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); + + rc = Net_Call_C(ax, &req, &repl); + + 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); + Net_Call_C_Dump(); + + attr = tests_get_dword_lh(repl.data); + fprintf(stdout, "NCP87DBG attr[0]=%08lX\n", attr); + + return(0); +} + +static int tests_ncp87(int argc, char *argv[]) +{ + char *name = "LOGIN.EXE"; + + if (argc > 2) + name = argv[2]; + + 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"); + + /* + * 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); +} + + int func_tests(int argc, char *argv[], int mode) { if (argc < 2) @@ -168,6 +330,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], "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);