310 lines
8.1 KiB
C
310 lines
8.1 KiB
C
#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);
|
|
}
|
|
|
|
|