diff --git a/CMakeLists.txt b/CMakeLists.txt index 18f965d..b769940 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,6 @@ if(MARS_NWE_BUILD_DOSUTILS) find_package(OpenWatcom REQUIRED) set(DOSUTILS_C_SOURCES - kern.c net.c tools.c netcall.c @@ -45,6 +44,7 @@ if(MARS_NWE_BUILD_DOSUTILS) map.c slist.c flag.c + c32ncp.c nwcrypt.c nwdebug.c nwtests.c diff --git a/c32ncp.c b/c32ncp.c new file mode 100644 index 0000000..475e3f3 --- /dev/null +++ b/c32ncp.c @@ -0,0 +1,309 @@ +#include "net.h" +#include "c32ncp.h" + +/* c32ncp.c - Client32 NCP helpers for mars-dosutils */ +static void c32_put_word_lh(uint8 *p, uint16 v) +{ + p[0] = (uint8)(v & 0xff); + p[1] = (uint8)((v >> 8) & 0xff); +} + +static void c32_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 uint16 c32_get_word_lh(uint8 *p) +{ + return((uint16)(p[0] | ((uint16)p[1] << 8))); +} + +static uint32 c32_get_dword_lh(uint8 *p) +{ + return((uint32)p[0] | + ((uint32)p[1] << 8) | + ((uint32)p[2] << 16) | + ((uint32)p[3] << 24)); +} + +static UI c32_build_handle_path(uint8 *buf, uint8 dhandle, + uint16 dirbase, uint8 style, + int count, + const char *c1, const char *c2, const char *c3) +{ + uint8 *p; + int l; + UI used; + + /* + * DeveloperNet/ncpdos16 path structure used by NCP87/S6 through + * Client32 COMPATNcpRequestReply. + * + * This is the exact shape verified by TESTS NCP87C32AUTO: + * 00 02 00 00 00 00 01 09 4C 4F 47 49 4E 2E 45 58 45 + * + * Meaning: + * word[1] = short dir handle + * word[3] = dir base + * byte[5] = dirstyle + * byte[6] = component count + * then len/name components + * + * The old/simple struct used by the INT 21h F257 fallback is not accepted + * by this Client32 path. + */ + memset(buf, 0, 0x140); + + if (dhandle) { + c32_put_word_lh(buf + 1, (uint16)dhandle); + c32_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); + c32_put_word_lh(buf + 0x13c, used); + return(used); +} + +/* + * Current verified Client32 path for mars-nwe DOS utilities: + * + * C32_MapVar_Probe(4,0) -> connRefLocal FFFF:FFFE + * C32_OpenRef_Probe(connRefLocal) -> Client32 handle, e.g. 0101:0001 + * + * C32_MapVar_Probe currently contains the confirmed Mars server-name scan + * shape. It is intentionally kept small and isolated here so FLAG and later + * tools do not carry the old exploratory tests. + */ +int c32_get_ncp_handle(uint16 *handle_lo, uint16 *handle_hi) +{ + uint8 mapout[32]; + uint8 openout[32]; + uint16 map_ret_ax, map_ret_dx; + uint16 cref_lo, cref_hi; + uint16 open_ret_ax, open_ret_dx; + + if (!handle_lo || !handle_hi) + return(1); + + *handle_lo = 0; + *handle_hi = 0; + + memset(mapout, 0, sizeof(mapout)); + C32_MapVar_Probe(4, 0, mapout); + + map_ret_ax = c32_get_word_lh(mapout + 14); + map_ret_dx = c32_get_word_lh(mapout + 16); + cref_lo = c32_get_word_lh(mapout + 22); + cref_hi = c32_get_word_lh(mapout + 24); + + if (map_ret_ax != 0 || map_ret_dx != 0 || (cref_lo == 0 && cref_hi == 0)) + return(2); + + memset(openout, 0, sizeof(openout)); + C32_OpenRef_Probe(cref_lo, cref_hi, openout); + + open_ret_ax = c32_get_word_lh(openout + 14); + open_ret_dx = c32_get_word_lh(openout + 16); + *handle_lo = c32_get_word_lh(openout + 18); + *handle_hi = c32_get_word_lh(openout + 20); + + if (open_ret_ax != 0 || open_ret_dx != 0 || (*handle_lo == 0 && *handle_hi == 0)) + return(3); + + return(0); +} + +int c32_ncp87_obtain_rim_attributes(const char *name, + uint16 dir_handle, + uint32 *attr_out, + uint16 *actual_out, + uint16 *handle_lo_out, + uint16 *handle_hi_out) +{ + uint16 handle_lo, handle_hi; + uint8 hdr[16]; + uint8 path[0x140]; + uint8 rep0[0x60]; + uint8 rep1[0x110]; + uint8 rawout[32]; + uint16 raw_ret_ax, raw_ret_dx; + uint16 actual_lo; + int path_len; + int rc; + + if (!name || !attr_out) + return(1); + + *attr_out = 0; + if (actual_out) *actual_out = 0; + if (handle_lo_out) *handle_lo_out = 0; + if (handle_hi_out) *handle_hi_out = 0; + + rc = c32_get_ncp_handle(&handle_lo, &handle_hi); + if (rc) + return(10 + rc); + + memset(hdr, 0, sizeof(hdr)); + hdr[0] = 6; /* NCP87 subfunction 6 */ + hdr[1] = 0; /* source namespace DOS */ + hdr[2] = 0; /* target namespace DOS */ + c32_put_word_lh(hdr + 3, 0x0006); /* SA_ALL */ + c32_put_dword_lh(hdr + 5, 0x00000004UL); /* RIM_ATTRIBUTES */ + + path_len = c32_build_handle_path(path, (uint8)dir_handle, 0, 0, 1, + name, NULL, NULL); + + memset(rep0, 0, sizeof(rep0)); + memset(rep1, 0, sizeof(rep1)); + memset(rawout, 0, sizeof(rawout)); + + C32_NCP87_Raw5_Probe(handle_lo, handle_hi, + hdr, 9, + path, (UI)path_len, + rep0, 0x4d, + rep1, 0x100, + rawout); + + raw_ret_ax = c32_get_word_lh(rawout + 14); + raw_ret_dx = c32_get_word_lh(rawout + 16); + actual_lo = c32_get_word_lh(rawout + 18); + + if (raw_ret_ax != 0 || raw_ret_dx != 0) + return(20); + + /* + * Verified reply layout for RIM_ATTRIBUTES: + * REP0+4 little-endian dword = DOS attributes + * Example LOGIN.EXE: 20h archive. + */ + *attr_out = c32_get_dword_lh(rep0 + 4); + + if (actual_out) *actual_out = actual_lo; + if (handle_lo_out) *handle_lo_out = handle_lo; + if (handle_hi_out) *handle_hi_out = handle_hi; + + return(0); +} + + +int c32_ncp87_modify_dos_attributes(char *name, + uint16 dir_handle, + uint32 attrs, + uint16 *actual_out, + uint16 *handle_lo_out, + uint16 *handle_hi_out) +{ + uint16 handle_lo, handle_hi; + uint8 modbuf[64]; + uint8 path[0x140]; + uint8 rep0[0x20]; + uint8 rep1[0x20]; + uint8 rawout[32]; + uint8 *p; + UI mod_len; + UI path_len; + uint16 raw_ret_ax, raw_ret_dx; + uint16 actual_lo; + int rc; + + if (!name) + return(1); + + if (actual_out) + *actual_out = 0; + if (handle_lo_out) + *handle_lo_out = 0; + if (handle_hi_out) + *handle_hi_out = 0; + + rc = c32_get_ncp_handle(&handle_lo, &handle_hi); + if (rc) + return(10 + rc); + + /* + * NCP 87 subfunction 7: Modify DOS information. + * + * First request fragment contains the fixed header and DOS info structure. + * Second request fragment contains the verified SDK-style path structure. + * + * This avoids the old INT 21h F257 modify path, which can hang under DOS + * Client32 for high FLAG bits such as Transactional. + */ + memset(modbuf, 0, sizeof(modbuf)); + p = modbuf; + + *p++ = 7; /* subfunction: modify DOS info */ + *p++ = 0; /* namespace DOS */ + *p++ = 0; /* reserved */ + c32_put_word_lh(p, 0x0006); p += 2; /* SA_ALL */ + c32_put_dword_lh(p, 0x00000002UL); p += 4; /* DM_ATTRIBUTES: attributes */ + + c32_put_dword_lh(p, attrs); p += 4; /* Attributes */ + memset(p, 0, 34); p += 34; /* rest of DOS info */ + mod_len = (UI)(p - modbuf); + + path_len = c32_build_handle_path(path, (uint8)dir_handle, 0, 0, 1, + name, NULL, NULL); + + memset(rep0, 0, sizeof(rep0)); + memset(rep1, 0, sizeof(rep1)); + memset(rawout, 0, sizeof(rawout)); + + C32_NCP87_Raw5_Probe(handle_lo, handle_hi, + modbuf, mod_len, + path, path_len, + rep0, sizeof(rep0), + rep1, sizeof(rep1), + rawout); + + raw_ret_ax = c32_get_word_lh(rawout + 14); + raw_ret_dx = c32_get_word_lh(rawout + 16); + actual_lo = c32_get_word_lh(rawout + 18); + + if (actual_out) + *actual_out = actual_lo; + if (handle_lo_out) + *handle_lo_out = handle_lo; + if (handle_hi_out) + *handle_hi_out = handle_hi; + + if (raw_ret_ax != 0 || raw_ret_dx != 0) + return(20); + + return(0); +} + + diff --git a/c32ncp.h b/c32ncp.h new file mode 100644 index 0000000..471a655 --- /dev/null +++ b/c32ncp.h @@ -0,0 +1,22 @@ +/* c32ncp.h - minimal Client32 NCP helpers for mars-dosutils */ + +#ifndef C32NCP_H +#define C32NCP_H +int c32_get_ncp_handle(uint16 *handle_lo, uint16 *handle_hi); + +int c32_ncp87_obtain_rim_attributes(const char *name, + uint16 dir_handle, + uint32 *attr_out, + uint16 *actual_out, + uint16 *handle_lo_out, + uint16 *handle_hi_out); + + +int c32_ncp87_modify_dos_attributes(char *name, + uint16 dir_handle, + uint32 attrs, + uint16 *actual_out, + uint16 *handle_lo_out, + uint16 *handle_hi_out); + +#endif diff --git a/flag.c b/flag.c index db41cff..c5e6834 100644 --- a/flag.c +++ b/flag.c @@ -1,6 +1,7 @@ /* flag.c - Novell FLAG-like DOS utility, stage 1 */ #include "net.h" +#include "c32ncp.h" #include /* @@ -121,6 +122,14 @@ static int flag_ncp87_obtain_attrs(char *name, uint32 *attrs) if (flag_current_dhandle(&dhandle)) return(-1); + /* + * Prefer the verified Client32 NCP87 path. If it is not available, + * fall back to the historical INT 21h/Net_Call path below. + */ + if (c32_ncp87_obtain_rim_attributes(name, (uint16)dhandle, + attrs, NULL, NULL, NULL) == 0) + return(0); + memset(&req, 0, sizeof(req)); memset(&repl, 0, sizeof(repl)); @@ -167,6 +176,19 @@ static int flag_ncp87_modify_attrs(char *name, uint32 attrs) if (flag_current_dhandle(&dhandle)) return(-1); + /* + * Prefer verified Client32 modify path. The old INT 21h/F257 modify path + * can hang under DOS Client32 for high FLAG bits such as T/P/DI/RI. + */ + { + uint16 actual = 0; + uint16 hlo = 0; + uint16 hhi = 0; + if (!c32_ncp87_modify_dos_attributes(name, (uint16)dhandle, attrs, + &actual, &hlo, &hhi)) + return(0); + } + memset(&req, 0, sizeof(req)); memset(&repl, 0, sizeof(repl)); @@ -257,7 +279,7 @@ static void flag_help(void) fprintf(stdout, "SUB\n"); } -static int flag_attr_mask(char *s, unsigned *setbits, unsigned *clearbits) +static int flag_attr_mask(char *s, uint32 *setbits, uint32 *clearbits) { int set = 1; char *p = s; @@ -274,51 +296,51 @@ static int flag_attr_mask(char *s, unsigned *setbits, unsigned *clearbits) if (flag_same(p, "RO")) { if (set) { - *setbits |= (unsigned)(NWFA_RO | NWFA_DI | NWFA_RI); + *setbits |= (NWFA_RO | NWFA_DI | NWFA_RI); } else { - *clearbits |= (unsigned)(NWFA_RO | NWFA_DI | NWFA_RI); + *clearbits |= (NWFA_RO | NWFA_DI | NWFA_RI); } } else if (flag_same(p, "RW")) { - *clearbits |= (unsigned)(NWFA_RO | NWFA_DI | NWFA_RI); + *clearbits |= (NWFA_RO | NWFA_DI | NWFA_RI); } else if (flag_same(p, "S")) { - if (set) *setbits |= (unsigned)NWFA_S; - else *clearbits |= (unsigned)NWFA_S; + if (set) *setbits |= NWFA_S; + else *clearbits |= NWFA_S; } else if (flag_same(p, "H")) { - if (set) *setbits |= (unsigned)NWFA_H; - else *clearbits |= (unsigned)NWFA_H; + if (set) *setbits |= NWFA_H; + else *clearbits |= NWFA_H; } else if (flag_same(p, "SY") || flag_same(p, "SYS") || flag_same(p, "SYSTEM")) { - if (set) *setbits |= (unsigned)NWFA_SY; - else *clearbits |= (unsigned)NWFA_SY; + if (set) *setbits |= NWFA_SY; + else *clearbits |= NWFA_SY; } else if (flag_same(p, "T")) { - if (set) *setbits |= (unsigned)NWFA_T; - else *clearbits |= (unsigned)NWFA_T; + if (set) *setbits |= NWFA_T; + else *clearbits |= NWFA_T; } else if (flag_same(p, "P")) { - if (set) *setbits |= (unsigned)NWFA_P; - else *clearbits |= (unsigned)NWFA_P; + if (set) *setbits |= NWFA_P; + else *clearbits |= NWFA_P; } else if (flag_same(p, "A")) { - if (set) *setbits |= (unsigned)NWFA_A; - else *clearbits |= (unsigned)NWFA_A; + if (set) *setbits |= NWFA_A; + else *clearbits |= NWFA_A; } else if (flag_same(p, "RA")) { - if (set) *setbits |= (unsigned)NWFA_RA; - else *clearbits |= (unsigned)NWFA_RA; + if (set) *setbits |= NWFA_RA; + else *clearbits |= NWFA_RA; } else if (flag_same(p, "WA")) { - if (set) *setbits |= (unsigned)NWFA_WA; - else *clearbits |= (unsigned)NWFA_WA; + if (set) *setbits |= NWFA_WA; + else *clearbits |= NWFA_WA; } else if (flag_same(p, "CI")) { - if (set) *setbits |= (unsigned)NWFA_CI; - else *clearbits |= (unsigned)NWFA_CI; + if (set) *setbits |= NWFA_CI; + else *clearbits |= NWFA_CI; } else if (flag_same(p, "DI")) { - if (set) *setbits |= (unsigned)NWFA_DI; - else *clearbits |= (unsigned)NWFA_DI; + if (set) *setbits |= NWFA_DI; + else *clearbits |= NWFA_DI; } else if (flag_same(p, "RI")) { - if (set) *setbits |= (unsigned)NWFA_RI; - else *clearbits |= (unsigned)NWFA_RI; + if (set) *setbits |= NWFA_RI; + else *clearbits |= NWFA_RI; } else if (flag_same(p, "N") || flag_same(p, "NORMAL")) { - *clearbits |= (unsigned)(NWFA_RO | NWFA_H | NWFA_SY | NWFA_A | + *clearbits |= (NWFA_RO | NWFA_H | NWFA_SY | NWFA_A | NWFA_S | NWFA_T | NWFA_P | NWFA_RA | NWFA_WA | NWFA_CI | NWFA_DI | NWFA_RI); } else if (flag_same(p, "ALL")) { - *setbits |= (unsigned)(NWFA_RO | NWFA_H | NWFA_SY | NWFA_A | + *setbits |= (NWFA_RO | NWFA_H | NWFA_SY | NWFA_A | NWFA_S | NWFA_T | NWFA_P | NWFA_RA | NWFA_WA | NWFA_CI | NWFA_DI | NWFA_RI); } else { @@ -329,18 +351,19 @@ static int flag_attr_mask(char *s, unsigned *setbits, unsigned *clearbits) return(0); } -static void flag_print_attrs(unsigned attr) +static void flag_print_attrs(uint32 attr) { /* * Novell order: - * RO/RW S A H Sy T P RA WA CI DI RI + * Ro/Rw S A - H Sy T P Ra Wa CI DI RI */ fprintf(stdout, "[ "); - fprintf(stdout, "%s ", (attr & NWFA_RO) ? "RO" : "Rw"); + fprintf(stdout, "%s ", (attr & NWFA_RO) ? "Ro" : "Rw"); fprintf(stdout, "%c ", (attr & NWFA_S) ? 'S' : '-'); fprintf(stdout, "%c ", (attr & NWFA_A) ? 'A' : '-'); + fprintf(stdout, "- "); fprintf(stdout, "%c ", (attr & NWFA_H) ? 'H' : '-'); - fprintf(stdout, "%s ", (attr & NWFA_SY) ? "Sy" : "-"); + fprintf(stdout, "%s ", (attr & NWFA_SY) ? "Sy" : "--"); fprintf(stdout, "%c ", (attr & NWFA_T) ? 'T' : '-'); fprintf(stdout, "%c ", (attr & NWFA_P) ? 'P' : '-'); fprintf(stdout, "%s ", (attr & NWFA_RA) ? "Ra" : "--"); @@ -351,7 +374,7 @@ static void flag_print_attrs(unsigned attr) fprintf(stdout, "]"); } -static void flag_display_one(char *name, unsigned attr) +static void flag_display_one(char *name, uint32 attr) { fprintf(stdout, " %-23s ", name); flag_print_attrs(attr); @@ -383,7 +406,7 @@ static int flag_list(char *pattern) if (flag_ncp87_obtain_attrs(ff.name, &nwattrs)) nwattrs = (uint32)ff.attrib; - flag_display_one(ff.name, (unsigned)nwattrs); + flag_display_one(ff.name, nwattrs); found++; } } while (!_dos_findnext(&ff)); @@ -391,7 +414,7 @@ static int flag_list(char *pattern) return(found); } -static int flag_apply(char *pattern, unsigned setbits, unsigned clearbits) +static int flag_apply(char *pattern, uint32 setbits, uint32 clearbits) { struct find_t ff; unsigned findattr = _A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_ARCH; @@ -416,7 +439,7 @@ static int flag_apply(char *pattern, unsigned setbits, unsigned clearbits) if (newattrs != attrs) { if (flag_ncp87_modify_attrs(fname, newattrs)) { - unsigned dosattr = (unsigned)(newattrs & (_A_RDONLY|_A_HIDDEN|_A_SYSTEM|_A_ARCH)); + unsigned dosattr = (newattrs & (_A_RDONLY|_A_HIDDEN|_A_SYSTEM|_A_ARCH)); if (_dos_setfileattr(fname, dosattr)) { fprintf(stderr, "You don't have rights to change : %s\n", fname); continue; @@ -427,7 +450,7 @@ static int flag_apply(char *pattern, unsigned setbits, unsigned clearbits) if (flag_ncp87_obtain_attrs(fname, &attrs)) attrs = newattrs; - flag_display_one(fname, (unsigned)attrs); + flag_display_one(fname, newattrs); shown++; } while (!_dos_findnext(&ff)); @@ -439,8 +462,8 @@ int func_flag(int argc, char *argv[], int mode) { char *path = "*.*"; int i; - unsigned setbits = 0; - unsigned clearbits = 0; + uint32 setbits = 0; + uint32 clearbits = 0; int have_change = 0; int rc; diff --git a/kern.c b/kern.c deleted file mode 100644 index 31ab335..0000000 --- a/kern.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * kern.c - C-side experimental NetWare/DOS request wrappers - * - * kern_wasm.asm remains the production/reference implementation. - * These C functions are test wrappers so we can inspect register setup and - * slowly port proven pieces from ASM to C. - */ - -#include -#include -#include - -#include "net.h" - -#if defined(__WATCOMC__) -#define KERN_C_CALL _Cdecl -#else -#define KERN_C_CALL -#endif - -typedef struct { - unsigned int in_ax; - unsigned int in_bx; - unsigned int in_cx; - unsigned int in_dx; - unsigned int in_si; - unsigned int in_di; - unsigned int in_ds; - unsigned int in_es; - - unsigned int out_ax; - unsigned int out_bx; - unsigned int out_cx; - unsigned int out_dx; - unsigned int out_si; - unsigned int out_di; - unsigned int out_flags; - - void far *req_ptr; - void far *repl_ptr; - - int rc; -} NET_CALL_C_DEBUG; - -NET_CALL_C_DEBUG Net_Call_C_Last; - -static void net_call_c_clear(void) -{ - memset(&Net_Call_C_Last, 0, sizeof(Net_Call_C_Last)); -} - -static void net_call_c_save_in(union REGS *r, struct SREGS *s, - void *req, void *repl) -{ - Net_Call_C_Last.in_ax = r->x.ax; - Net_Call_C_Last.in_bx = r->x.bx; - Net_Call_C_Last.in_cx = r->x.cx; - Net_Call_C_Last.in_dx = r->x.dx; - Net_Call_C_Last.in_si = r->x.si; - Net_Call_C_Last.in_di = r->x.di; - Net_Call_C_Last.in_ds = s->ds; - Net_Call_C_Last.in_es = s->es; - Net_Call_C_Last.req_ptr = req; - Net_Call_C_Last.repl_ptr = repl; -} - -static void net_call_c_save_out(union REGS *r, unsigned int returned_ax) -{ - Net_Call_C_Last.out_ax = returned_ax; - Net_Call_C_Last.out_bx = r->x.bx; - Net_Call_C_Last.out_cx = r->x.cx; - Net_Call_C_Last.out_dx = r->x.dx; - Net_Call_C_Last.out_si = r->x.si; - Net_Call_C_Last.out_di = r->x.di; - Net_Call_C_Last.out_flags = r->x.cflag; - Net_Call_C_Last.rc = returned_ax & 0x00ff; -} - -/* - * C equivalent of kern_wasm.asm Net_Call: - * AX = func - * DS:SI = request - * ES:DI = reply - * int 21h - * return AL only, because kern_wasm.asm clears AH before return. - */ -int KERN_C_CALL Net_Call_C(unsigned int ax, void *req, void *repl) -{ - return Net_Call_CX(ax, 0, 0, 0, req, repl); -} - -int KERN_C_CALL Net_Call_CX(unsigned int ax, unsigned int bx, - unsigned int cx, unsigned int dx, - void *req, void *repl) -{ - union REGS inregs; - union REGS outregs; - struct SREGS segregs; - unsigned int ret_ax; - - memset(&inregs, 0, sizeof(inregs)); - memset(&outregs, 0, sizeof(outregs)); - memset(&segregs, 0, sizeof(segregs)); - net_call_c_clear(); - - inregs.x.ax = ax; - inregs.x.bx = bx; - inregs.x.cx = cx; - inregs.x.dx = dx; - - 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_save_in(&inregs, &segregs, req, repl); - - int86x(0x21, &inregs, &outregs, &segregs); - - ret_ax = outregs.x.ax & 0x00ff; /* match ASM Net_Call return */ - - net_call_c_save_out(&outregs, ret_ax); - - return (int)ret_ax; -} - -/* - * Experimental Novell Client/VLM AH=F2 wrapper derived from official FLAG.EXE - * disassembly: - * AH = F2h - * AL = NCP function, e.g. 57h for NCP 87 - * CX = request length - * DX = reply buffer length - * DS:SI = request buffer - * ES:DI = reply buffer - */ -int KERN_C_CALL Net_Call_F2_C(unsigned int function, - unsigned int req_len, - unsigned int repl_len, - void *req, - void *repl) -{ - union REGS inregs; - union REGS outregs; - struct SREGS segregs; - unsigned int ret_ax; - - memset(&inregs, 0, sizeof(inregs)); - memset(&outregs, 0, sizeof(outregs)); - memset(&segregs, 0, sizeof(segregs)); - net_call_c_clear(); - - inregs.h.ah = 0xF2; - inregs.h.al = (unsigned char)(function & 0xff); - inregs.x.cx = req_len; - inregs.x.dx = repl_len; - 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_save_in(&inregs, &segregs, req, repl); - - int86x(0x21, &inregs, &outregs, &segregs); - - /* - * Novell wrapper behavior: - * xor ah,ah - * or al,al - * if al != 0: ah=89h - * Return AL only for C caller, but keep 89xx in debug out_ax. - */ - ret_ax = outregs.x.ax & 0x00ff; - if (ret_ax) - ret_ax |= 0x8900; - - net_call_c_save_out(&outregs, ret_ax); - - return (int)(ret_ax & 0x00ff); -} - -/* - * Fully generic INT 21h register test wrapper. - * Used for reproducing the NWCREQUEST/NWCSHELLREQ register calls seen in - * DeveloperNet 1997 clndos16.lib. - */ -int KERN_C_CALL Net_Call_F2X_C(unsigned int ax, - unsigned int bx, - unsigned int cx, - unsigned int dx, - void *req, - void *repl) -{ - union REGS inregs; - union REGS outregs; - struct SREGS segregs; - unsigned int ret_ax; - - memset(&inregs, 0, sizeof(inregs)); - memset(&outregs, 0, sizeof(outregs)); - memset(&segregs, 0, sizeof(segregs)); - net_call_c_clear(); - - inregs.x.ax = ax; - inregs.x.bx = bx; - inregs.x.cx = cx; - inregs.x.dx = dx; - 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_save_in(&inregs, &segregs, req, repl); - - int86x(0x21, &inregs, &outregs, &segregs); - - ret_ax = outregs.x.ax & 0x00ff; - if (ret_ax) - ret_ax |= 0x8900; - - net_call_c_save_out(&outregs, ret_ax); - - return (int)(ret_ax & 0x00ff); -} - - -void KERN_C_CALL Net_Call_C_Dump(void) -{ - fprintf(stdout, "NETCALLC in : AX=%04X BX=%04X CX=%04X DX=%04X DS:SI=%04X:%04X ES:DI=%04X:%04X\n", - Net_Call_C_Last.in_ax, - Net_Call_C_Last.in_bx, - Net_Call_C_Last.in_cx, - Net_Call_C_Last.in_dx, - Net_Call_C_Last.in_ds, - Net_Call_C_Last.in_si, - Net_Call_C_Last.in_es, - Net_Call_C_Last.in_di); - - fprintf(stdout, "NETCALLC out: AX=%04X BX=%04X CX=%04X DX=%04X SI=%04X DI=%04X CF=%04X RC=%d\n", - Net_Call_C_Last.out_ax, - Net_Call_C_Last.out_bx, - Net_Call_C_Last.out_cx, - Net_Call_C_Last.out_dx, - Net_Call_C_Last.out_si, - Net_Call_C_Last.out_di, - Net_Call_C_Last.out_flags, - Net_Call_C_Last.rc); -} - -unsigned int KERN_C_CALL Net_Call_C_GetDebug(unsigned int idx) -{ - switch (idx) { - case 0: return Net_Call_C_Last.in_ax; - case 1: return Net_Call_C_Last.in_bx; - case 2: return Net_Call_C_Last.in_cx; - case 3: return Net_Call_C_Last.in_dx; - case 4: return Net_Call_C_Last.in_ds; - case 5: return Net_Call_C_Last.in_si; - case 6: return Net_Call_C_Last.in_es; - case 7: return Net_Call_C_Last.in_di; - case 8: return Net_Call_C_Last.out_ax; - case 9: return Net_Call_C_Last.out_bx; - case 10: return Net_Call_C_Last.out_cx; - case 11: return Net_Call_C_Last.out_dx; - case 12: return Net_Call_C_Last.out_si; - case 13: return Net_Call_C_Last.out_di; - case 14: return Net_Call_C_Last.out_flags; - case 15: return (unsigned int)Net_Call_C_Last.rc; - } - return 0xffff; -} diff --git a/kern.h b/kern.h index 8e2c5a4..ca7d337 100644 --- a/kern.h +++ b/kern.h @@ -15,10 +15,6 @@ 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 C32_LoadNios_Probe(UI axfunc, void *outbuf); -extern int KERN_CALL C32_GetFunc_Probe(char *name, void *outbuf); -extern int KERN_CALL C32_CallVersion_Nios_Probe(void *outbuf); -extern int KERN_CALL C32_MapLock_Probe(void *ptr, UI len, void *outbuf); extern int KERN_CALL C32_MapVar_Probe(UI specLen, UI flag, void *outbuf); extern int KERN_CALL C32_OpenRef_Probe(UI refLo, UI refHi, void *outbuf); extern int KERN_CALL C32_NCP87_Raw5_Probe(UI connLo, UI connHi, @@ -27,22 +23,6 @@ extern int KERN_CALL C32_NCP87_Raw5_Probe(UI connLo, UI connHi, void *rep0, UI rep0Len, void *rep1, UI rep1Len, void *outbuf); -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); -extern int KERN_CALL Net_Call_F2_C(UI function, UI req_len, UI repl_len, - void *req, void *repl); -extern int KERN_CALL Net_Call_F2X_C(UI ax, UI bx, UI cx, UI dx, - void *req, void *repl); -extern void KERN_CALL Net_Call_C_Dump(void); -extern UI KERN_CALL Net_Call_C_GetDebug(UI idx); - - - - #undef KERN_CALL diff --git a/kern_wasm.asm b/kern_wasm.asm index 2b7be2b..750d092 100644 --- a/kern_wasm.asm +++ b/kern_wasm.asm @@ -20,14 +20,9 @@ public _IPXclose_socket public _IPXlisten public _xmemmove public _Net_Call -public _C32_LoadNios_Probe -public _C32_GetFunc_Probe -public _C32_CallVersion_Nios_Probe -public _C32_MapLock_Probe public _C32_NCP87_Raw5_Probe public _C32_OpenRef_Probe public _C32_MapVar_Probe -public _Net_Call_VLM_Raw _IPXinit proc far push bp mov bp, sp @@ -220,495 +215,6 @@ _Net_Call proc far ret _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. -; -; Register setup for VLM entry: -; AX, BX, CX, DX from function args -; DS:SI = req -; ES:DI = repl -; -; Extra stack args pushed before calling VLM entry: -; p3, p2, p1 -; -; For NWCREQUEST/VLM test: -; AX=function -; BX=numReqFrags -; CX=connid -; 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 - 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 - - -; int C32_LoadNios_Probe(UI axfunc, void *outbuf) -; -; 16-bit object, but captures 32-bit ESI and ECX using manual 386 opcodes. -; This keeps the OMF/linker in 16-bit mode while still reading Client32/NIOS -; values returned by: -; INT 2F AX=D8C1 -; -; outbuf: -; +00 word AX after INT 2F -; +02 dword ESI after INT 2F -; +06 dword ECX after INT 2F -; +0A word BX -; +0C word CX low -; +0E word DX -; +10 word SI low -; +12 word DS -; +14 word ES -_C32_LoadNios_Probe proc far - push bp - mov bp, sp - - push ds - push es - push si - push di - - ; xor ecx, ecx - db 66h, 33h, 0C9h - ; xor esi, esi - db 66h, 33h, 0F6h - - mov ax, [bp+6] - int 2Fh - - push ds - push es - push si - push cx - push bx - push dx - push ax - - les di, dword ptr [bp+8] - - ; restore AX result into AX and store word at out+0 - pop ax - mov es:[di+0], ax - - ; Store ESI dword at es:[di+2]. - ; Encoding: ES override + operand-size prefix + MOV r/m32,r32 - ; mov es:[di+02], esi = 26 66 89 75 02 - db 26h, 66h, 89h, 75h, 02h - - ; Store ECX dword at es:[di+6]. - ; mov es:[di+06], ecx = 26 66 89 4Dh 06 - db 26h, 66h, 89h, 4Dh, 06h - - pop dx - pop bx - pop cx - - mov es:[di+10], bx - mov es:[di+12], cx - mov es:[di+14], dx - - pop ax ; saved SI - mov es:[di+16], ax - - pop ax ; saved ES - pop bx ; saved DS - mov es:[di+18], bx - mov es:[di+20], ax - - pop di - pop si - pop es - pop ds - pop bp - xor ah, ah - ret -_C32_LoadNios_Probe endp - - -; int C32_GetFunc_Probe(char *name, void *outbuf) -; -; 16-bit OMF Client32 function resolver probe. -; This mimics C32BEGINUSE for one function name: -; INT 2F AX=D8C1 -; save ESI as far pointer to __Nios+8 function resolver -; push name segment -; push name offset -; push 0 -; push 0 -; call far [ESI] -; add sp,8 -; -; outbuf: -; +00 word load AX from INT2F -; +02 dword ESI from INT2F -; +06 dword ECX from INT2F -; +0A word resolver return AX -; +0C word resolver return DX -; +0E word BX -; +10 word CX -_C32_GetFunc_Probe proc far - push bp - mov bp, sp - sub sp, 4 - - push ds - push es - push si - push di - - ; clear ECX/ESI - db 66h, 33h, 0C9h - db 66h, 33h, 0F6h - - mov ax, 0D8C1h - int 2Fh - - ; save ESI dword to [bp-4] - db 66h, 89h, 76h, 0FCh - - push ax ; save load AX - - ; call resolver only if AX == 0 - or ax, ax - jne c32get_store_fail - - push word ptr [bp+8] ; name segment - push word ptr [bp+6] ; name offset - push 0 - push 0 - call dword ptr [bp-4] - add sp, 8 - - jmp short c32get_store - -c32get_store_fail: - xor dx, dx - xor ax, ax - -c32get_store: - push dx - push ax - - les di, dword ptr [bp+10] - - pop ax ; resolver AX - pop dx ; resolver DX - pop bx ; load AX saved in BX temporarily - - mov es:[di+0], bx - - ; Store ESI dword at out+2: ES override + operand prefix - db 26h, 66h, 89h, 75h, 02h - - ; Store ECX dword at out+6 - db 26h, 66h, 89h, 4Dh, 06h - - mov es:[di+10], ax - mov es:[di+12], dx - mov es:[di+14], bx - mov es:[di+16], cx - - pop di - pop si - pop es - pop ds - mov sp, bp - pop bp - xor ah, ah - ret -_C32_GetFunc_Probe endp - - -; int C32_CallVersion_Nios_Probe(void *outbuf) -; -; Safe Client32 version call using the exact d32wrap convention: -; 1) INT 2F AX=D8C1 -; 2) use ESI resolver to resolve "CLIENT32GetVersion" -; 3) call ECX trampoline, not the function pointer directly: -; push 0 -; push 0 -; push fn_seg -; push fn_off -; call ECX -; add sp,8 -; -; outbuf: -; +00 load AX -; +02 resolver off -; +04 resolver seg -; +06 trampoline off -; +08 trampoline seg -; +0A fn off -; +0C fn seg -; +0E call AX -; +10 call DX -; +12 flags -_C32_CallVersion_Nios_Probe proc far - push bp - mov bp, sp - sub sp, 12 - - push ds - push es - push si - push di - pushf - - ; clear ECX/ESI - db 66h, 33h, 0C9h - db 66h, 33h, 0F6h - - mov ax, 0D8C1h - int 2Fh - - ; save ESI resolver at [bp-4] - db 66h, 89h, 76h, 0FCh - ; save ECX trampoline at [bp-8] - db 66h, 89h, 4Eh, 0F8h - - push ax ; load AX for output - or ax, ax - jne c32ver_fail - - push cs - push offset c32ver_name - push 0 - push 0 - call dword ptr [bp-4] - add sp, 8 - - ; resolver returns DX:AX function pointer - mov [bp-12], ax - mov [bp-10], dx - - or ax, dx - je c32ver_fail - - ; d32wrap _CLIENT32GetVersion convention: - push 0 - push 0 - push word ptr [bp-10] - push word ptr [bp-12] - call dword ptr [bp-8] - add sp, 8 - - pushf - push dx - push ax - jmp short c32ver_store - -c32ver_fail: - xor dx, dx - xor ax, ax - pushf - push dx - push ax - -c32ver_store: - les di, dword ptr [bp+6] - - pop ax ; call AX - pop dx ; call DX - pop bx ; flags - pop cx ; load AX - - mov es:[di+0], cx - mov cx, word ptr [bp-4] - mov es:[di+2], cx - mov cx, word ptr [bp-2] - mov es:[di+4], cx - mov cx, word ptr [bp-8] - mov es:[di+6], cx - mov cx, word ptr [bp-6] - mov es:[di+8], cx - mov cx, word ptr [bp-12] - mov es:[di+10], cx - mov cx, word ptr [bp-10] - mov es:[di+12], cx - mov es:[di+14], ax - mov es:[di+16], dx - mov es:[di+18], bx - - popf - pop di - pop si - pop es - pop ds - mov sp, bp - pop bp - xor ah, ah - ret - -c32ver_name db 'CLIENT32GetVersion',0 - -_C32_CallVersion_Nios_Probe endp - - -; int C32_MapLock_Probe(void *ptr, UI len, void *outbuf) -; -; Probe d32wrap.o __MapLockFlat / __UnlockFlat: -; INT 2F AX=D8C1 -; ESI resolver returned by D8C1 is used with command 2 and 3: -; push len_hi -; push len_lo -; push seg -; push off -; push 0 -; push 2 -; call ESI ; returns flat DX:AX -; -; push len_hi -; push len_lo -; push flat_hi -; push flat_lo -; push 0 -; push 3 -; call ESI ; unlock -; -; outbuf: -; +00 load AX -; +02 ESI off -; +04 ESI seg -; +06 map AX low -; +08 map DX high -; +0A unlock AX -; +0C unlock DX -_C32_MapLock_Probe proc far - push bp - mov bp, sp - sub sp, 8 - - push ds - push es - push si - push di - - ; clear ECX/ESI - db 66h, 33h, 0C9h - db 66h, 33h, 0F6h - - mov ax, 0D8C1h - int 2Fh - - ; save ESI resolver at [bp-4] - db 66h, 89h, 76h, 0FCh - push ax ; load AX - - or ax, ax - jne mapflat_fail - - ; MapLockFlat(ptr, len) - push 0 - push word ptr [bp+10] ; len - push word ptr [bp+8] ; ptr seg - push word ptr [bp+6] ; ptr off - push 0 - push 2 - call dword ptr [bp-4] - add sp, 0cH - - ; save mapped flat DX:AX at [bp-8] - mov word ptr [bp-8], ax - mov word ptr [bp-6], dx - - ; UnlockFlat(flat, len) - push 0 - push word ptr [bp+10] ; len - push dx - push ax - push 0 - push 3 - call dword ptr [bp-4] - add sp, 0cH - - jmp short mapflat_store - -mapflat_fail: - xor dx, dx - xor ax, ax - mov word ptr [bp-8], ax - mov word ptr [bp-6], dx - -mapflat_store: - les di, dword ptr [bp+12] - - mov bx, ax ; unlock AX - mov cx, dx ; unlock DX - pop ax ; load AX - - mov es:[di+0], ax - mov ax, word ptr [bp-4] - mov es:[di+2], ax - mov ax, word ptr [bp-2] - mov es:[di+4], ax - mov ax, word ptr [bp-8] - mov es:[di+6], ax - mov ax, word ptr [bp-6] - mov es:[di+8], ax - mov es:[di+10], bx - mov es:[di+12], cx - - pop di - pop si - pop es - pop ds - mov sp, bp - pop bp - xor ah, ah - ret -_C32_MapLock_Probe endp - ; int C32_OpenRef_Probe(UI refLo, UI refHi, void *outbuf) diff --git a/nwtests.c b/nwtests.c index 1895418..ceeba2d 100644 --- a/nwtests.c +++ b/nwtests.c @@ -1,12 +1,7 @@ -/* nwtests.c 20-May-96 */ - -/**************************************************************** - * (C)opyright (C) 1993,1996 Martin Stover, Marburg, Germany * - ****************************************************************/ +/* nwtests.c - small DOS utility tests */ #include "net.h" - - +#include "c32ncp.h" static int tests_same_arg(char *a, char *b) { while (*a || *b) { @@ -21,162 +16,7 @@ static int tests_same_arg(char *a, char *b) 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)); + fprintf(stdout, "Usage: TESTS [NCP87C32ATTR|NCP87C32AUTO]\n"); } static int tests_get_current_drive(void) @@ -188,1431 +28,35 @@ static int tests_get_current_drive(void) return((int)regs.h.al); } -static int tests_current_conn_dhandle(uint8 *connid, uint8 *dhandle) +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, "NCPF2DBG get_drive_info failed drive=%c:\n", 'A' + drive); + if (get_drive_info((uint8)drive, &connid, dhandle, &flags)) 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"); + if (!connid || (flags & 0x80)) 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); -} - - -static int tests_c32callver2(void) -{ - uint8 out[32]; - uint16 load_ax; - uint16 res_off, res_seg; - uint16 tramp_off, tramp_seg; - uint16 fn_off, fn_seg; - uint16 call_ax, call_dx, flags; - - memset(out, 0, sizeof(out)); - - fprintf(stdout, "TEST C32CALLVER2\n"); - fprintf(stdout, "Call CLIENT32GetVersion through ECX NIOS trampoline\n\n"); - - C32_CallVersion_Nios_Probe(out); - - load_ax = tests_get_word_lh(out + 0); - res_off = tests_get_word_lh(out + 2); - res_seg = tests_get_word_lh(out + 4); - tramp_off = tests_get_word_lh(out + 6); - tramp_seg = tests_get_word_lh(out + 8); - fn_off = tests_get_word_lh(out + 10); - fn_seg = tests_get_word_lh(out + 12); - call_ax = tests_get_word_lh(out + 14); - call_dx = tests_get_word_lh(out + 16); - flags = tests_get_word_lh(out + 18); - - fprintf(stdout, "Load AX=%04X\n", load_ax); - fprintf(stdout, "Resolver=%04X:%04X Trampoline=%04X:%04X\n", - res_seg, res_off, tramp_seg, tramp_off); - fprintf(stdout, "Function=%04X:%04X\n", fn_seg, fn_off); - fprintf(stdout, "Call returned DX:AX=%04X:%04X FLAGS=%04X\n", - call_dx, call_ax, flags); - tests_dump_bytes("RAW:", out, 20); - - if (load_ax == 0 && (fn_off || fn_seg)) - fprintf(stdout, "\nNIOS trampoline path resolved successfully.\n"); - return(0); -} - - -static int tests_c32mapflat(void) -{ - uint8 out[32]; - char sample[32]; - uint16 load_ax, esi_off, esi_seg; - uint16 map_lo, map_hi; - uint16 unl_ax, unl_dx; - - strcpy(sample, "C32MAPFLAT"); - memset(out, 0, sizeof(out)); - - fprintf(stdout, "TEST C32MAPFLAT\n"); - fprintf(stdout, "Probe d32wrap __MapLockFlat/__UnlockFlat via NIOS resolver\n"); - fprintf(stdout, "sample ptr=%04X:%04X len=%u text=%s\n", - FP_SEG(sample), FP_OFF(sample), (UI)strlen(sample) + 1, sample); - - C32_MapLock_Probe(sample, (UI)strlen(sample) + 1, out); - - load_ax = tests_get_word_lh(out + 0); - esi_off = tests_get_word_lh(out + 2); - esi_seg = tests_get_word_lh(out + 4); - map_lo = tests_get_word_lh(out + 6); - map_hi = tests_get_word_lh(out + 8); - unl_ax = tests_get_word_lh(out + 10); - unl_dx = tests_get_word_lh(out + 12); - - fprintf(stdout, "Load AX=%04X Resolver=%04X:%04X\n", - load_ax, esi_seg, esi_off); - fprintf(stdout, "MapLock returned flat=%04X:%04X\n", map_hi, map_lo); - fprintf(stdout, "Unlock returned DX:AX=%04X:%04X\n", unl_dx, unl_ax); - tests_dump_bytes("RAW:", out, 14); - - if (load_ax == 0 && (map_lo || map_hi)) - fprintf(stdout, "\nMapLockFlat appears to work.\n"); - else - fprintf(stdout, "\nMapLockFlat did not return a flat pointer.\n"); - - return(0); -} - - - - - -static void tests_set_reg_word(uint8 *r, int off, UI val) -{ - tests_put_word_lh(r + off, (uint16)val); -} - -static UI tests_get_reg_word(uint8 *r, int off) -{ - return (UI)(r[off] | ((UI)r[off + 1] << 8)); -} - -static void tests_dump_vlm_regs(char *title, uint8 *r) -{ - fprintf(stdout, "%s SI=%04X DS=%04X DI=%04X ES=%04X AX=%04X BX=%04X CX=%04X DX=%04X\n", - title, - tests_get_reg_word(r, 0), - tests_get_reg_word(r, 2), - tests_get_reg_word(r, 4), - tests_get_reg_word(r, 6), - tests_get_reg_word(r, 8), - tests_get_reg_word(r, 10), - tests_get_reg_word(r, 12), - tests_get_reg_word(r, 14)); -} - - - - - - - - - - - - - -static unsigned long tests_get_dword_be_local(uint8 *p) -{ - return (((unsigned long)p[0]) << 24) | - (((unsigned long)p[1]) << 16) | - (((unsigned long)p[2]) << 8) | - ((unsigned long)p[3]); -} - -static unsigned long tests_get_dword_le_local(uint8 *p) -{ - return ((unsigned long)p[0]) | - (((unsigned long)p[1]) << 8) | - (((unsigned long)p[2]) << 16) | - (((unsigned long)p[3]) << 24); -} - -static int tests_ncp87c32auto(void) -{ - uint8 connid = 0; - uint8 dhandle = 0; - uint8 flags = 0; - int drive; - - uint8 mapout[32]; - uint8 openout[32]; - uint8 rawout[32]; - - uint16 map_ret_ax, map_ret_dx; - uint16 cref_lo, cref_hi; - uint16 open_ret_ax, open_ret_dx; - uint16 handle_lo, handle_hi; - uint16 raw_ret_ax, raw_ret_dx; - uint16 actual_lo, actual_hi; - - uint8 hdr[16]; - uint8 path[0x140]; - uint8 rep0[0x60]; - uint8 rep1[0x110]; - UI path_len; - - drive = tests_get_current_drive(); - get_drive_info((uint8)drive, &connid, &dhandle, &flags); - - fprintf(stdout, "TEST NCP87C32AUTO\n"); - fprintf(stdout, "Auto Client32 path: MAPVAR len=4 flag=0 -> OPENREF -> NCP87/S6\n"); - fprintf(stdout, "drive=%c: connid=%u dhandle=%u flags=%02X\n", - 'A' + drive, connid, dhandle, flags); - - memset(mapout, 0, sizeof(mapout)); - C32_MapVar_Probe(4, 0, mapout); - - map_ret_ax = tests_get_word_lh(mapout + 14); - map_ret_dx = tests_get_word_lh(mapout + 16); - cref_lo = tests_get_word_lh(mapout + 22); /* connRefLocal */ - cref_hi = tests_get_word_lh(mapout + 24); - - fprintf(stdout, "\nSTEP1 C32MAPVAR 4 0\n"); - fprintf(stdout, "Return DX:AX=%04X:%04X connRefLocal=%04X:%04X\n", - map_ret_dx, map_ret_ax, cref_hi, cref_lo); - tests_dump_bytes("MAP OUT:", mapout, 26); - - if (map_ret_ax != 0 || map_ret_dx != 0 || (cref_lo == 0 && cref_hi == 0)) { - fprintf(stdout, "MAP step failed or returned empty connRef.\n"); - return(1); - } - - memset(openout, 0, sizeof(openout)); - C32_OpenRef_Probe(cref_lo, cref_hi, openout); - - open_ret_ax = tests_get_word_lh(openout + 14); - open_ret_dx = tests_get_word_lh(openout + 16); - handle_lo = tests_get_word_lh(openout + 18); - handle_hi = tests_get_word_lh(openout + 20); - - fprintf(stdout, "\nSTEP2 C32OPENREF %u %u\n", cref_lo, cref_hi); - fprintf(stdout, "Return DX:AX=%04X:%04X handle=%04X:%04X\n", - open_ret_dx, open_ret_ax, handle_hi, handle_lo); - tests_dump_bytes("OPEN OUT:", openout, 22); - - if (open_ret_ax != 0 || open_ret_dx != 0 || (handle_lo == 0 && handle_hi == 0)) { - fprintf(stdout, "OPENREF failed or returned empty handle.\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); /* RIM_ATTRIBUTES */ - - path_len = tests_build_novell_handle_path(path, dhandle, 0, 0, 1, - "LOGIN.EXE", 0, 0); - - memset(rep0, 0, sizeof(rep0)); - memset(rep1, 0, sizeof(rep1)); - memset(rawout, 0, sizeof(rawout)); - - C32_NCP87_Raw5_Probe(handle_lo, handle_hi, - hdr, 9, - path, path_len, - rep0, 0x4d, - rep1, 0x100, - rawout); - - raw_ret_ax = tests_get_word_lh(rawout + 14); - raw_ret_dx = tests_get_word_lh(rawout + 16); - actual_lo = tests_get_word_lh(rawout + 18); - actual_hi = tests_get_word_lh(rawout + 20); - - fprintf(stdout, "\nSTEP3 NWREQ87C32RAW5 handle=%04X:%04X\n", - handle_hi, handle_lo); - fprintf(stdout, "Return DX:AX=%04X:%04X actual=%04X:%04X\n", - raw_ret_dx, raw_ret_ax, actual_hi, actual_lo); - tests_dump_bytes("RAW OUT:", rawout, 22); - tests_dump_bytes("REP0:", rep0, 80); - tests_dump_bytes("REP1:", rep1, 64); - - if (raw_ret_ax == 0 && raw_ret_dx == 0) { - fprintf(stdout, "\nNCP87C32AUTO OK\n"); - fprintf(stdout, "attr guess BE dword[0]=%08lX LE dword[0]=%08lX\n", - tests_get_dword_be_local(rep0 + 0), - tests_get_dword_le_local(rep0 + 0)); - fprintf(stdout, "dword[4] BE=%08lX LE=%08lX\n", - tests_get_dword_be_local(rep0 + 4), - tests_get_dword_le_local(rep0 + 4)); - } - - return(0); -} - - - -/* - * Reusable Client32 helpers for FLAG and future DOS tools. - * - * These are intentionally not test/probe commands. They wrap the verified - * Client32 sequence: - * - * C32_MapVar_Probe(4,0) -> connRefLocal FFFF:FFFE - * C32_OpenRef_Probe(connRefLocal) -> Client32 handle, e.g. 0101:0001 - * C32_NCP87_Raw5_Probe(handle) -> NCP87/S6 - */ -static int c32_get_ncp_handle(uint16 *handle_lo, uint16 *handle_hi) -{ - uint8 mapout[32]; - uint8 openout[32]; - uint16 map_ret_ax, map_ret_dx; - uint16 cref_lo, cref_hi; - uint16 open_ret_ax, open_ret_dx; - - if (!handle_lo || !handle_hi) - return(1); - - *handle_lo = 0; - *handle_hi = 0; - - memset(mapout, 0, sizeof(mapout)); - C32_MapVar_Probe(4, 0, mapout); - - map_ret_ax = tests_get_word_lh(mapout + 14); - map_ret_dx = tests_get_word_lh(mapout + 16); - cref_lo = tests_get_word_lh(mapout + 22); - cref_hi = tests_get_word_lh(mapout + 24); - - if (map_ret_ax != 0 || map_ret_dx != 0 || (cref_lo == 0 && cref_hi == 0)) - return(2); - - memset(openout, 0, sizeof(openout)); - C32_OpenRef_Probe(cref_lo, cref_hi, openout); - - open_ret_ax = tests_get_word_lh(openout + 14); - open_ret_dx = tests_get_word_lh(openout + 16); - *handle_lo = tests_get_word_lh(openout + 18); - *handle_hi = tests_get_word_lh(openout + 20); - - if (open_ret_ax != 0 || open_ret_dx != 0 || (*handle_lo == 0 && *handle_hi == 0)) - return(3); - - return(0); -} - -static int c32_ncp87_obtain_rim_attributes(const char *name, - uint16 dir_handle, - unsigned long *attr_out, - uint16 *actual_out, - uint16 *handle_lo_out, - uint16 *handle_hi_out) -{ - uint16 handle_lo, handle_hi; - uint8 hdr[16]; - uint8 path[0x140]; - uint8 rep0[0x60]; - uint8 rep1[0x110]; - uint8 rawout[32]; - UI path_len; - uint16 raw_ret_ax, raw_ret_dx; - uint16 actual_lo; - int rc; - - if (!name || !attr_out) - return(1); - - *attr_out = 0; - if (actual_out) - *actual_out = 0; - if (handle_lo_out) - *handle_lo_out = 0; - if (handle_hi_out) - *handle_hi_out = 0; - - rc = c32_get_ncp_handle(&handle_lo, &handle_hi); - if (rc) - return(10 + rc); - - memset(hdr, 0, sizeof(hdr)); - hdr[0] = 6; - hdr[1] = 0; - hdr[2] = 0; - tests_put_word_lh(hdr + 3, 0x0006); /* NCP87 subfunction 6 */ - tests_put_dword_lh(hdr + 5, 0x00000004UL); /* RIM_ATTRIBUTES */ - - path_len = tests_build_novell_handle_path(path, dir_handle, 0, 0, 1, - (char *)name, 0, 0); - - memset(rep0, 0, sizeof(rep0)); - memset(rep1, 0, sizeof(rep1)); - memset(rawout, 0, sizeof(rawout)); - - C32_NCP87_Raw5_Probe(handle_lo, handle_hi, - hdr, 9, - path, path_len, - rep0, 0x4d, - rep1, 0x100, - rawout); - - raw_ret_ax = tests_get_word_lh(rawout + 14); - raw_ret_dx = tests_get_word_lh(rawout + 16); - actual_lo = tests_get_word_lh(rawout + 18); - - if (raw_ret_ax != 0 || raw_ret_dx != 0) - return(20); - - /* - * Verified reply layout for RIM_ATTRIBUTES: - * REP0+4 little-endian dword = DOS attributes - * Example LOGIN.EXE: 20h archive. - */ - *attr_out = tests_get_dword_le_local(rep0 + 4); - - if (actual_out) - *actual_out = actual_lo; - if (handle_lo_out) - *handle_lo_out = handle_lo; - if (handle_hi_out) - *handle_hi_out = handle_hi; return(0); } static int tests_ncp87c32attr(void) { - uint8 connid = 0; uint8 dhandle = 0; - uint8 flags = 0; - int drive; - unsigned long attr; - uint16 actual; - uint16 handle_lo; - uint16 handle_hi; + uint32 attr = 0; + uint16 actual = 0; + uint16 handle_lo = 0; + uint16 handle_hi = 0; int rc; - drive = tests_get_current_drive(); - get_drive_info((uint8)drive, &connid, &dhandle, &flags); + if (tests_current_dhandle(&dhandle)) { + fprintf(stdout, "NCP87C32ATTR failed: current drive is not a network drive\n"); + return(1); + } rc = c32_ncp87_obtain_rim_attributes("LOGIN.EXE", (uint16)dhandle, @@ -1631,72 +75,30 @@ static int tests_ncp87c32attr(void) return(0); } -int func_tests(int argc, char *argv[], int mode) +static int tests_ncp87c32auto(void) { - 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], "C32CALLVER2")) - return tests_c32callver2(); - - if (tests_same_arg(argv[1], "C32MAPFLAT")) - return tests_c32mapflat(); - - if (tests_same_arg(argv[1], "NCP87C32ATTR")) - return tests_ncp87c32attr(); - - if (tests_same_arg(argv[1], "NCP87C32AUTO")) - return tests_ncp87c32auto(); - 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. + * Kept as a compatibility alias for the former verbose test command. + * The production helper path is exercised by NCP87C32ATTR. */ - return tests_old(argc, argv, mode); + return tests_ncp87c32attr(); } +int func_tests(int argc, char *argv[], int mode) +{ + (void)mode; + + if (argc < 2) { + tests_usage(); + return(1); + } + + if (tests_same_arg(argv[1], "NCP87C32ATTR")) + return tests_ncp87c32attr(); + + if (tests_same_arg(argv[1], "NCP87C32AUTO")) + return tests_ncp87c32auto(); + + tests_usage(); + return(1); +} diff --git a/tools.c b/tools.c index ff30402..e4b44a4 100644 --- a/tools.c +++ b/tools.c @@ -328,7 +328,7 @@ int putglobenv(char *option) } search=nextp; } - /* nicht gefunden , nun eintragen, falls m”glich */ + /* nicht gefunden , nun eintragen, falls m�glich */ if (*(equal+1) && optionlen < maxenvsize - aktenvsize) { strcpy(search, option); *(search+optionlen+1) = '\0'; /* letzter Eintrag '\0' nicht vergessen */