From 0dc6a02450ff170101ce911cf9f628187d17fe2f Mon Sep 17 00:00:00 2001 From: Andrew Bird Date: Sun, 10 Dec 2017 10:39:47 +0000 Subject: [PATCH] int2f: Allow 1217h function to return new CDS entry DOS provides the interrupt 2f/12xx functions for use by filesystem redirectors in order that they do not need to access structures and variables using undocumented methods. Interrupt 2f/1217 is a function used by a redirector to get the CDS entry corresponding to a drive without iterating the CDS array found via SYSVARS LOL. FreeDOS currently validates the flags in CDS entry before deciding whether to return the entry to the caller. This behaviour prevents a redirector receiving the CDS entry corresponding to an as yet unassigned drive so preventing any new drive mapping. I've tested the following flavours of DOS and only FreeDOS does this. # DOS variants returning new CDS entries okay DR-DOS 6.00-930319 7.00 7.01 7.02-971119 7.02-980123 7.03 8.00 MS-DOS 3.10 3.20 3.21 3.30-Nec 3.30 3.31 4.01 5.00 6.00 6.20 6.21 6.22 7.00 7.10 PC-DOS 3.00-Compaq 3.00 3.10-850307 3.10-850422 3.10-Compaq 3.20-851230 3.20-860221 3.30 3.31-Compaq 4.00 4.01 5.00 5.02 6.10 6.30 7.00 7.10 7.2K # DOS variants that return error rather than new CDS entry FR-DOS 1.00 1.10 1.20 This patch introduces an unvalidated version of get_cds() and calls it only for the int2f/1217h call, other uses remain as before. --- kernel/dosfns.c | 7 +++++++ kernel/inthndlr.c | 2 +- kernel/proto.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/dosfns.c b/kernel/dosfns.c index 06d7700..23d9974 100644 --- a/kernel/dosfns.c +++ b/kernel/dosfns.c @@ -93,6 +93,13 @@ STATIC int remote_lock_unlock(sft FAR *sftp, /* SFT for file */ unsigned long len, /* length (in bytes) of region to lock or unlock */ int unlock); /* one to unlock; zero to lock */ +struct cds FAR *get_cds_unvalidated(unsigned drive) +{ + if (drive >= lastdrive) + return NULL; + return &CDSp[drive]; +} + /* get current directory structure for drive return NULL if the CDS is not valid or the drive is not within range */ diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index cd5d0e3..2e7308c 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -1917,7 +1917,7 @@ VOID ASMCFUNC int2F_12_handler(struct int2f12regs r) ; probable use: get sizeof(CDSentry) */ { - struct cds FAR *cdsp = get_cds(r.callerARG1 & 0xff); + struct cds FAR *cdsp = get_cds_unvalidated(r.callerARG1 & 0xff); if (cdsp == NULL) { diff --git a/kernel/proto.h b/kernel/proto.h index b45a9fb..301d0ff 100644 --- a/kernel/proto.h +++ b/kernel/proto.h @@ -118,6 +118,7 @@ COUNT DosLockUnlock(COUNT hndl, LONG pos, LONG len, COUNT unlock); int idx_to_sft_(int SftIndex); sft FAR *idx_to_sft(int SftIndex); int get_sft_idx(UCOUNT hndl); +struct cds FAR *get_cds_unvalidated(unsigned dsk); struct cds FAR *get_cds(unsigned dsk); struct cds FAR *get_cds1(unsigned dsk); COUNT DosTruename(const char FAR * src, char FAR * dest);