#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); }