diff --git a/c32ncp.c b/c32ncp.c index 128e3ea..eb3d172 100644 --- a/c32ncp.c +++ b/c32ncp.c @@ -217,3 +217,93 @@ int c32_ncp87_obtain_rim_attributes(const char *name, 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, 0x00000004UL); p += 4; /* modify mask: 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 index aed90bb..471a655 100644 --- a/c32ncp.h +++ b/c32ncp.h @@ -11,4 +11,12 @@ int c32_ncp87_obtain_rim_attributes(const char *name, 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 4c90242..533a792 100644 --- a/flag.c +++ b/flag.c @@ -176,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));