COUNT DosForceDup(COUNT OldHandle, COUNT NewHandle) { psp FAR *p = MK_FP(cu_psp, 0); sft FAR *Sftp; /* Get the SFT block that contains the SFT */ if ((Sftp = get_sft(OldHandle)) == (sft FAR *) - 1) return DE_INVLDHNDL; /* If not open - exit */ if (Sftp->sft_count <= 0) return DE_INVLDHNDL; /* now close the new handle if it's open */ if ((UBYTE) p->ps_filetab[NewHandle] != 0xff) { COUNT ret; if ((ret = DosClose(NewHandle)) != SUCCESS) return ret; } /* If everything looks ok, bump it up. */ if ((Sftp->sft_flags & SFT_FDEVICE) || (Sftp->sft_status >= 0)) { p->ps_filetab[NewHandle] = p->ps_filetab[OldHandle]; Sftp->sft_count += 1; return NewHandle; } else return DE_INVLDHNDL; }
COUNT DosSetFtime(COUNT hndl, date FAR * dp, time FAR * tp) { sft FAR *s; sfttbl FAR *sp; /* Test that the handle is valid */ if (hndl < 0) return DE_INVLDHNDL; /* Get the SFT block that contains the SFT */ if ((s = get_sft(hndl)) == (sft FAR *) - 1) return DE_INVLDHNDL; /* If this is not opened another error */ if (s->sft_count == 0) return DE_ACCESS; /* If SFT entry refers to a device, do nothing */ if (s->sft_flags & SFT_FDEVICE) return SUCCESS; if (s->sft_flags & SFT_FSHARED) { s->sft_date = *dp; s->sft_time = *tp; return SUCCESS; } /* call file system handler */ return dos_setftime(s->sft_status, dp, tp); }
COUNT DosDup(COUNT Handle) { psp FAR *p = MK_FP(cu_psp, 0); COUNT NewHandle; sft FAR *Sftp; /* Get the SFT block that contains the SFT */ if ((Sftp = get_sft(Handle)) == (sft FAR *) - 1) return DE_INVLDHNDL; /* If not open - exit */ if (Sftp->sft_count <= 0) return DE_INVLDHNDL; /* now get a free handle */ if ((NewHandle = get_free_hndl()) == 0xff) return DE_TOOMANY; /* If everything looks ok, bump it up. */ if ((Sftp->sft_flags & SFT_FDEVICE) || (Sftp->sft_status >= 0)) { p->ps_filetab[NewHandle] = p->ps_filetab[Handle]; Sftp->sft_count += 1; return NewHandle; } else return DE_INVLDHNDL; }
COUNT DosSeek(COUNT hndl, LONG new_pos, COUNT mode, ULONG * set_pos) { sft FAR *s; ULONG lrx; /* Test for invalid mode */ if (mode < 0 || mode > 2) return DE_INVLDFUNC; /* Test that the handle is valid */ if (hndl < 0) return DE_INVLDHNDL; /* Get the SFT block that contains the SFT */ if ((s = get_sft(hndl)) == (sft FAR *) - 1) return DE_INVLDHNDL; lpCurSft = (sfttbl FAR *) s; if (s->sft_flags & SFT_FSHARED) { if (mode == 2) { /* seek from end of file */ int2f_Remote_call(REM_LSEEK, 0, (UWORD) FP_SEG(new_pos), (UWORD) FP_OFF(new_pos), (VOID FAR *) s, 0, 0); *set_pos = s->sft_posit; return SUCCESS; } if (mode == 0) { s->sft_posit = new_pos; *set_pos = new_pos; return SUCCESS; } if (mode == 1) { s->sft_posit += new_pos; *set_pos = s->sft_posit; return SUCCESS; } return DE_INVLDFUNC; } /* Do special return for character devices */ if (s->sft_flags & SFT_FDEVICE) { *set_pos = 0l; return SUCCESS; } else { *set_pos = dos_lseek(s->sft_status, new_pos, mode); if ((LONG) * set_pos < 0) return (int)*set_pos; else return SUCCESS; } }
int StdinBusy(void) { sft FAR *s = get_sft(STDIN); struct dhdr FAR *dev = sft_to_dev(s); if (dev) return Busy(&dev); return s->sft_posit >= s->sft_size; }
COUNT CloneHandle(COUNT hndl) { sft FAR *sftp; /* now get the system file table entry */ if ((sftp = get_sft(hndl)) == (sft FAR *) - 1) return DE_INVLDHNDL; /* now that we have the system file table entry, get the fnode */ /* index, and increment the count, so that we've effectively */ /* cloned the file. */ sftp->sft_count += 1; return SUCCESS; }
COUNT DosClose(COUNT hndl) { psp FAR *p = MK_FP(cu_psp, 0); sft FAR *s; /* Test that the handle is valid */ if (hndl < 0) return DE_INVLDHNDL; /* Get the SFT block that contains the SFT */ if ((s = get_sft(hndl)) == (sft FAR *) - 1) return DE_INVLDHNDL; /* If this is not opened another error */ if (s->sft_count == 0) return DE_ACCESS; lpCurSft = (sfttbl FAR *) s; /* remote sub sft_count. */ if (s->sft_flags & SFT_FSHARED) { int2f_Remote_call(REM_CLOSE, 0, 0, 0, (VOID FAR *) s, 0, 0); p->ps_filetab[hndl] = 0xff; s->sft_flags = 0; return SUCCESS; } /* now just drop the count if a device, else */ /* call file system handler */ if (s->sft_flags & SFT_FDEVICE) { p->ps_filetab[hndl] = 0xff; s->sft_count -= 1; return SUCCESS; } else { p->ps_filetab[hndl] = 0xff; s->sft_count -= 1; if (s->sft_count > 0) return SUCCESS; else return dos_close(s->sft_status); } }
void write_char_stdout(int c) { unsigned char count = 1; unsigned flags = get_sft(STDOUT)->sft_flags; /* ah=2, ah=9 should expand tabs even for raw devices and disk files */ if ((flags & (SFT_FDEVICE|SFT_FBINARY)) != SFT_FDEVICE) { if (c == HT) { count = 8 - (scr_pos & 7); c = ' '; } /* for raw CONOUT devices already updated in dosfns.c */ if ((flags & (SFT_FDEVICE|SFT_FCONOUT)) != (SFT_FDEVICE|SFT_FCONOUT)) update_scr_pos(c, count); } do { write_char(c, get_sft_idx(STDOUT)); } while (--count != 0); }
LONG DosGetFsize(COUNT hndl) { sft FAR *s; /* sfttbl FAR *sp;*/ /* Get the SFT block that contains the SFT */ if ((s = get_sft(hndl)) == (sft FAR *) - 1) return DE_INVLDHNDL; /* If this is not opened another error */ if (s->sft_count == 0) return DE_ACCESS; /* If SFT entry refers to a device, return the date and time of opening */ if (s->sft_flags & (SFT_FDEVICE | SFT_FSHARED)) { return s->sft_size; } /* call file system handler */ return dos_getfsize(s->sft_status); }
UCOUNT DosWrite(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err) { sft FAR *s; WORD sys_idx; sfttbl FAR *sp; UCOUNT ReadCount; /* Test that the handle is valid */ if (hndl < 0) { *err = DE_INVLDHNDL; return 0; } /* Get the SFT block that contains the SFT */ if ((s = get_sft(hndl)) == (sft FAR *) - 1) { *err = DE_INVLDHNDL; return 0; } /* If this is not opened and it's not a write */ /* another error */ if (s->sft_count == 0 || (!(s->sft_mode & SFT_MWRITE) && !(s->sft_mode & SFT_MRDWR))) { *err = DE_ACCESS; return 0; } if (s->sft_flags & SFT_FSHARED) { ReadCount = Remote_RW(REM_WRITE, n, bp, s, err); if (err) { return ReadCount; } else return 0; } /* Do a device write if device */ if (s->sft_flags & SFT_FDEVICE) { request rq; /* set to no EOF */ s->sft_flags &= ~SFT_FEOF; /* if null just report full transfer */ if (s->sft_flags & SFT_FNUL) { *err = SUCCESS; return n; } /* Now handle raw and cooked modes */ if (s->sft_flags & SFT_FBINARY) { rq.r_length = sizeof(request); rq.r_command = C_OUTPUT; rq.r_count = n; rq.r_trans = (BYTE FAR *) bp; rq.r_status = 0; execrh((request FAR *) & rq, s->sft_dev); if (rq.r_status & S_ERROR) { char_error(&rq, s->sft_dev); } else { if (s->sft_flags & SFT_FCONOUT) { WORD cnt = rq.r_count; while (cnt--) { switch (*bp++) { case CR: scr_pos = 0; break; case LF: case BELL: break; case BS: --scr_pos; break; default: ++scr_pos; } } } *err = SUCCESS; return rq.r_count; } } else { REG WORD c, cnt = n, spaces_left = 0, next_pos, xfer = 0; static BYTE space = ' '; start: if (cnt-- == 0) goto end; if (*bp == CTL_Z) goto end; if (s->sft_flags & SFT_FCONOUT) { switch (*bp) { case CR: next_pos = 0; break; case LF: case BELL: next_pos = scr_pos; break; case BS: next_pos = scr_pos ? scr_pos - 1 : 0; break; case HT: spaces_left = 8 - (scr_pos & 7); next_pos = scr_pos + spaces_left; goto output_space; default: next_pos = scr_pos + 1; } } rq.r_length = sizeof(request); rq.r_command = C_OUTPUT; rq.r_count = 1; rq.r_trans = bp; rq.r_status = 0; execrh((request FAR *) & rq, s->sft_dev); if (rq.r_status & S_ERROR) char_error(&rq, s->sft_dev); goto post; output_space: rq.r_length = sizeof(request); rq.r_command = C_OUTPUT; rq.r_count = 1; rq.r_trans = &space; rq.r_status = 0; execrh((request FAR *) & rq, s->sft_dev); if (rq.r_status & S_ERROR) char_error(&rq, s->sft_dev); --spaces_left; post: if (spaces_left) goto output_space; ++bp; ++xfer; if (s->sft_flags & SFT_FCONOUT) scr_pos = next_pos; if (break_ena && control_break()) { handle_break(); goto end; } goto start; end: *err = SUCCESS; return xfer; } } else /* a block write */ { COUNT rc; ReadCount = writeblock(s->sft_status, bp, n, &rc); if (rc < SUCCESS) { *err = rc; return 0; } else { *err = SUCCESS; return ReadCount; } } *err = SUCCESS; return 0; }
/* * The `force_binary' parameter is a hack to allow functions 0x01, 0x06, 0x07, * and function 0x40 to use the same code for performing reads, even though the * two classes of functions behave quite differently: 0x01 etc. always do * binary reads, while for 0x40 the type of read (binary/text) depends on what * the SFT says. -- ror4 */ UCOUNT GenericRead(COUNT hndl, UCOUNT n, BYTE FAR * bp, COUNT FAR * err, BOOL force_binary) { sft FAR *s; WORD sys_idx; sfttbl FAR *sp; UCOUNT ReadCount; /* Test that the handle is valid */ if (hndl < 0) { *err = DE_INVLDHNDL; return 0; } /* Get the SFT block that contains the SFT */ if ((s = get_sft(hndl)) == (sft FAR *) - 1) { *err = DE_INVLDHNDL; return 0; } /* If not open or write permission - exit */ if (s->sft_count == 0 || (s->sft_mode & SFT_MWRITE)) { *err = DE_INVLDACC; return 0; } /* * Do remote first or return error. * must have been opened from remote. */ if (s->sft_flags & SFT_FSHARED) { ReadCount = Remote_RW(REM_READ, n, bp, s, err); if (err) { *err = SUCCESS; return ReadCount; } else return 0; } /* Do a device read if device */ if (s->sft_flags & SFT_FDEVICE) { request rq; /* First test for eof and exit */ /* immediately if it is */ if (!(s->sft_flags & SFT_FEOF) || (s->sft_flags & SFT_FNUL)) { s->sft_flags &= ~SFT_FEOF; *err = SUCCESS; return 0; } /* Now handle raw and cooked modes */ if (force_binary || (s->sft_flags & SFT_FBINARY)) { rq.r_length = sizeof(request); rq.r_command = C_INPUT; rq.r_count = n; rq.r_trans = (BYTE FAR *) bp; rq.r_status = 0; execrh((request FAR *) & rq, s->sft_dev); if (rq.r_status & S_ERROR) { char_error(&rq, s->sft_dev); } else { *err = SUCCESS; return rq.r_count; } } else if (s->sft_flags & SFT_FCONIN) { kb_buf.kb_size = LINESIZE - 1; kb_buf.kb_count = 0; sti((keyboard FAR *) & kb_buf); fbcopy((BYTE FAR *) kb_buf.kb_buf, bp, kb_buf.kb_count); *err = SUCCESS; return kb_buf.kb_count; } else { *bp = _sti(); *err = SUCCESS; return 1; } } else /* a block read */ { COUNT rc; ReadCount = readblock(s->sft_status, bp, n, &rc); if (rc != SUCCESS) { *err = rc; return 0; } else { *err = SUCCESS; return ReadCount; } } *err = SUCCESS; return 0; }
COUNT DosDevIOctl(iregs FAR * r, COUNT FAR * err) { sft FAR *s; struct dpb FAR *dpbp; BYTE FAR *pBuffer = MK_FP(r->DS, r->DX); COUNT nMode; /* Test that the handle is valid */ switch (r->AL) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0c: /* Get the SFT block that contains the SFT */ if ((s = get_sft(r->BX)) == (sft FAR *) - 1) { *err = DE_INVLDHNDL; return 0; } break; case 0x04: case 0x05: case 0x08: case 0x09: case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: if (r->BL > nblkdev) { *err = DE_INVLDDRV; return 0; } else { /* This line previously returned the deviceheader at r->bl. But, DOS numbers its drives starting at 1, not 0. A=1, B=2, and so on. Changed this line so it is now zero-based. -SRM */ /* JPP - changed to use default drive if drive=0 */ if (r->BL == 0) dpbp = &blk_devices[default_drive]; else dpbp = &blk_devices[r->BL - 1]; } break; case 0x0b: /* skip, it's a special case. */ NetDelay = r->CX; if (!r->DX) NetRetry = r->DX; break; default: *err = DE_INVLDFUNC; return 0; } switch (r->AL) { case 0x00: /* Get the flags from the SFT */ r->DX = r->AX = s->sft_flags; /* Test for file and network SFT. These return a 0 in */ /* the AH register. */ if ((s->sft_flags & SFT_FSHARED) || !(s->sft_flags & SFT_FDEVICE)) { r->AH = 0; } break; case 0x01: /* sft_flags is a file, return an error because you */ /* can't set the status of a file. */ if (!(s->sft_flags & SFT_FDEVICE)) { *err = DE_INVLDFUNC; return 0; } /* Set it to what we got in the DL register from the */ /* user. */ r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL; break; case 0x0c: nMode = C_GENIOCTL; goto IoCharCommon; case 0x02: nMode = C_IOCTLIN; goto IoCharCommon; case 0x10: nMode = C_IOCTLQRY; goto IoCharCommon; case 0x03: nMode = C_IOCTLOUT; IoCharCommon: if ((s->sft_flags & SFT_FDEVICE) || ((r->AL == 0x10) && !(s->sft_dev->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0c) && !(s->sft_dev->dh_attr & ATTR_GENIOCTL))) { if (s->sft_dev->dh_attr & SFT_FIOCTL) { CharReqHdr.r_unit = 0; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, s->sft_dev); if (CharReqHdr.r_status & S_ERROR) return char_error(&CharReqHdr, s->sft_dev); if (r->AL == 0x07) { r->AL = CharReqHdr.r_status & S_BUSY ? 00 : 0xff; } break; } } *err = DE_INVLDFUNC; return 0; case 0x0d: nMode = C_GENIOCTL; goto IoBlockCommon; case 0x04: nMode = C_IOCTLIN; goto IoBlockCommon; case 0x11: nMode = C_IOCTLQRY; goto IoBlockCommon; case 0x05: nMode = C_IOCTLOUT; IoBlockCommon: if ((dpbp->dpb_device->dh_attr & ATTR_IOCTL) || ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0d) && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))) { *err = DE_INVLDFUNC; return 0; } CharReqHdr.r_unit = r->BL; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (r->AL == 0x08) { if (CharReqHdr.r_status & S_ERROR) { *err = DE_DEVICE; return 0; } r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; } else { if (CharReqHdr.r_status & S_ERROR) { *err = DE_DEVICE; return 0; } } break; case 0x06: if (s->sft_flags & SFT_FDEVICE) { r->AL = s->sft_flags & SFT_FEOF ? 0 : 0xFF; } else r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0; break; case 0x07: if (s->sft_flags & SFT_FDEVICE) { goto IoCharCommon; } r->AL = 0; break; case 0x08: if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS) { nMode = C_REMMEDIA; goto IoBlockCommon; } *err = DE_INVLDFUNC; return 0; case 0x09: r->DX = dpbp->dpb_device->dh_attr; break; case 0x0a: r->DX = s->sft_dcb->dpb_device->dh_attr; break; case 0x0e: nMode = C_GETLDEV; goto IoLogCommon; case 0x0f: nMode = C_SETLDEV; IoLogCommon: if ((dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)) { if (r->BL == 0) r->BL = default_drive; CharReqHdr.r_unit = r->BL; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (CharReqHdr.r_status & S_ERROR) *err = DE_ACCESS; else *err = SUCCESS; return 0; } *err = DE_INVLDFUNC; return 0; default: *err = DE_INVLDFUNC; return 0; } *err = SUCCESS; return 0; }
COUNT DosDevIOctl(iregs FAR * r, COUNT FAR * err) { sft FAR *s; struct dpb FAR *dpbp; BYTE FAR *pBuffer = MK_FP(r->DS, r->DX); COUNT nMode; switch (r->AL) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0c: if ((s = get_sft(r->BX)) == (sft FAR *) - 1) { *err = DE_INVLDHNDL; return 0; } break; case 0x04: case 0x05: case 0x08: case 0x09: case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: if (r->BL > nblkdev) { *err = DE_INVLDDRV; return 0; } else { if (r->BL == 0) dpbp = &blk_devices[default_drive]; else dpbp = &blk_devices[r->BL - 1]; } break; case 0x0b: break; default: *err = DE_INVLDFUNC; return 0; } switch (r->AL) { case 0x00: r->DX = r->AX = s->sft_flags; if ((s->sft_flags & SFT_FSHARED) || !(s->sft_flags & SFT_FDEVICE)) { r->AH = 0; } break; case 0x01: if (!(s->sft_flags & SFT_FDEVICE)) { *err = DE_INVLDFUNC; return 0; } r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL; break; case 0x0c: nMode = C_GENIOCTL; goto IoCharCommon; case 0x02: nMode = C_IOCTLIN; goto IoCharCommon; case 0x10: nMode = C_IOCTLQRY; goto IoCharCommon; case 0x03: nMode = C_IOCTLOUT; IoCharCommon: if (!(s->sft_flags & SFT_FDEVICE) || ((r->AL == 0x10) && !(s->sft_dev->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0c) && !(s->sft_dev->dh_attr & ATTR_GENIOCTL))) { if (s->sft_dev->dh_attr & SFT_FIOCTL) { CharReqHdr.r_unit = 0; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, s->sft_dev); if (CharReqHdr.r_status & S_ERROR) return char_error(&CharReqHdr, s->sft_dev); if (r->AL == 0x07) { r->AL = CharReqHdr.r_status & S_BUSY ? 00 : 0xff; } break; } } *err = DE_INVLDFUNC; return 0; case 0x0d: nMode = C_GENIOCTL; goto IoBlockCommon; case 0x04: nMode = C_IOCTLIN; goto IoBlockCommon; case 0x11: nMode = C_IOCTLQRY; goto IoBlockCommon; case 0x05: nMode = C_IOCTLOUT; IoBlockCommon: if (!(dpbp->dpb_device->dh_attr & ATTR_IOCTL) || ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0d) && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))) { *err = DE_INVLDFUNC; return 0; } CharReqHdr.r_unit = r->BL; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (r->AL == 0x08) { if (CharReqHdr.r_status & S_ERROR) { *err = DE_DEVICE; return 0; } r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; } else { if (CharReqHdr.r_status & S_ERROR) { *err = DE_DEVICE; return 0; } } break; case 0x06: if (s->sft_flags & SFT_FDEVICE) { r->AL = s->sft_flags & SFT_FEOF ? 0 : 0xFF; } else r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0; break; case 0x07: if (s->sft_flags & SFT_FDEVICE) { goto IoCharCommon; } r->AL = 0; break; case 0x08: if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS) { nMode = C_REMMEDIA; goto IoBlockCommon; } *err = DE_INVLDFUNC; return 0; case 0x09: r->DX = dpbp->dpb_device->dh_attr; break; case 0x0a: r->DX = s->sft_dcb->dpb_device->dh_attr; break; case 0x0e: nMode = C_GETLDEV; goto IoLogCommon; case 0x0f: nMode = C_SETLDEV; IoLogCommon: if (!(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)) { if (r->BL == 0) r->BL = default_drive; CharReqHdr.r_unit = r->BL; CharReqHdr.r_length = sizeof(request); CharReqHdr.r_command = nMode; CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = pBuffer; CharReqHdr.r_status = 0; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (CharReqHdr.r_status & S_ERROR) *err = DE_ACCESS; else *err = SUCCESS; return 0; } *err = DE_INVLDFUNC; return 0; default: *err = DE_INVLDFUNC; return 0; } *err = SUCCESS; return 0; }
COUNT DosDevIOctl(iregs FAR * r) { sft FAR *s; struct dpb FAR *dpbp; COUNT nMode; /* commonly used, shouldn't harm to do front up */ CharReqHdr.r_length = sizeof(request); CharReqHdr.r_trans = MK_FP(r->DS, r->DX); CharReqHdr.r_status = 0; CharReqHdr.r_count = r->CX; /* Test that the handle is valid */ switch (r->AL) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0c: /* Get the SFT block that contains the SFT */ if ((s = get_sft(r->BX)) == (sft FAR *) - 1) return DE_INVLDHNDL; break; case 0x04: case 0x05: case 0x08: case 0x09: case 0x0d: case 0x0e: case 0x0f: case 0x10: case 0x11: /* This line previously returned the deviceheader at r->bl. But, DOS numbers its drives starting at 1, not 0. A=1, B=2, and so on. Changed this line so it is now zero-based. -SRM */ /* JPP - changed to use default drive if drive=0 */ /* JT Fixed it */ CharReqHdr.r_unit = ( r->BL == 0 ? default_drive : r->BL - 1); if (CharReqHdr.r_unit >= lastdrive) return DE_INVLDDRV; else { /* cdsp = &CDSp->cds_table[CharReqHdr.r_unit]; */ dpbp = CDSp->cds_table[CharReqHdr.r_unit].cdsDpb; } break; case 0x0b: /* skip, it's a special case. */ NetDelay = r->CX; if (!r->DX) NetRetry = r->DX; break; default: return DE_INVLDFUNC; } switch (r->AL) { case 0x00: /* Get the flags from the SFT */ if (s->sft_flags & SFT_FDEVICE) r->AX = (s->sft_dev->dh_attr & 0xff00) | s->sft_flags_lo; else r->AX = s->sft_flags; /* Undocumented result, Ax = Dx seen using Pcwatch */ r->DX = r->AX; break; case 0x01: /* sft_flags is a file, return an error because you */ /* can't set the status of a file. */ if (!(s->sft_flags & SFT_FDEVICE)) return DE_INVLDFUNC; /* Set it to what we got in the DL register from the */ /* user. */ r->AL = s->sft_flags_lo = SFT_FDEVICE | r->DL; break; case 0x0c: nMode = C_GENIOCTL; goto IoCharCommon; case 0x02: nMode = C_IOCTLIN; goto IoCharCommon; case 0x10: nMode = C_IOCTLQRY; goto IoCharCommon; case 0x03: nMode = C_IOCTLOUT; IoCharCommon: if ((s->sft_flags & SFT_FDEVICE) || ((r->AL == 0x02 ) && (s->sft_dev->dh_attr & SFT_FIOCTL)) || ((r->AL == 0x03 ) && (s->sft_dev->dh_attr & SFT_FIOCTL)) || ((r->AL == 0x10) && (s->sft_dev->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0c) && (s->sft_dev->dh_attr & ATTR_GENIOCTL))) { CharReqHdr.r_unit = 0; CharReqHdr.r_command = nMode; execrh((request FAR *) & CharReqHdr, s->sft_dev); if (CharReqHdr.r_status & S_ERROR) { CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; return DE_DEVICE; } if (r->AL == 0x07) { r->AL = CharReqHdr.r_status & S_BUSY ? 00 : 0xff; } else if (r->AL == 0x02 || r->AL == 0x03) { r->AX = CharReqHdr.r_count; } else if (r->AL == 0x0c || r->AL == 0x10) { r->AX = CharReqHdr.r_status; } break; } return DE_INVLDFUNC; case 0x0d: nMode = C_GENIOCTL; goto IoBlockCommon; case 0x04: nMode = C_IOCTLIN; goto IoBlockCommon; case 0x11: nMode = C_IOCTLQRY; goto IoBlockCommon; case 0x05: nMode = C_IOCTLOUT; IoBlockCommon: if(!dpbp) { return DE_INVLDDRV; } if ( ((r->AL == 0x04 ) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL)) || ((r->AL == 0x05 ) && !(dpbp->dpb_device->dh_attr & ATTR_IOCTL)) || ((r->AL == 0x11) && !(dpbp->dpb_device->dh_attr & ATTR_QRYIOCTL)) || ((r->AL == 0x0d) && !(dpbp->dpb_device->dh_attr & ATTR_GENIOCTL))) { return DE_INVLDFUNC; } CharReqHdr.r_command = nMode; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (CharReqHdr.r_status & S_ERROR) { CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; return DE_DEVICE; } if (r->AL == 0x08) { r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; } else if (r->AL == 0x04 || r->AL == 0x05) { r->AX = CharReqHdr.r_count; } else if (r->AL == 0x0d || r->AL == 0x11) { r->AX = CharReqHdr.r_status; } break; case 0x06: if (s->sft_flags & SFT_FDEVICE) { r->AL = s->sft_flags & SFT_FEOF ? 0xFF : 0; } else r->AL = s->sft_posit >= s->sft_size ? 0xFF : 0; break; case 0x07: if (s->sft_flags & SFT_FDEVICE) { nMode = C_OSTAT; goto IoCharCommon; } r->AL = 0; break; case 0x08: if(!dpbp) { return DE_INVLDDRV; } if (dpbp->dpb_device->dh_attr & ATTR_EXCALLS) { nMode = C_REMMEDIA; goto IoBlockCommon; } return DE_INVLDFUNC; case 0x09: if(CDSp->cds_table[CharReqHdr.r_unit].cdsFlags & CDSNETWDRV) { r->DX = ATTR_REMOTE ; r->AX = S_DONE|S_BUSY; } else { if(!dpbp) { return DE_INVLDDRV; } /* Need to add subst bit 15 */ r->DX = dpbp->dpb_device->dh_attr; r->AX = S_DONE|S_BUSY; } break; case 0x0a: r->DX = s->sft_flags; r->AX = 0; break; case 0x0e: nMode = C_GETLDEV; goto IoLogCommon; case 0x0f: nMode = C_SETLDEV; IoLogCommon: if(!dpbp) { return DE_INVLDDRV; } if ((dpbp->dpb_device->dh_attr & ATTR_GENIOCTL)) { CharReqHdr.r_command = nMode; execrh((request FAR *) & CharReqHdr, dpbp->dpb_device); if (CharReqHdr.r_status & S_ERROR) { CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; return DE_ACCESS; } else { r->AL = CharReqHdr.r_unit; return SUCCESS; } } return DE_INVLDFUNC; default: return DE_INVLDFUNC; } return SUCCESS; }
int DosDevIOctl(lregs * r) { struct dhdr FAR *dev; if (r->AL > 0x11) return DE_INVLDFUNC; switch (r->AL) { case 0x0b: /* skip, it's a special case. */ NetDelay = r->CX; if (r->DX) NetRetry = r->DX; return SUCCESS; case 0x00: case 0x01: case 0x02: case 0x03: case 0x06: case 0x07: case 0x0a: case 0x0c: case 0x10: { sft FAR *s; unsigned flags; /* Test that the handle is valid and */ /* get the SFT block that contains the SFT */ if ((s = get_sft(r->BX)) == (sft FAR *) - 1) return DE_INVLDHNDL; flags = s->sft_flags; switch (r->AL) { case 0x00: /* Get the flags from the SFT */ if (flags & SFT_FDEVICE) r->AX = (flags & 0xff) | (s->sft_dev->dh_attr & 0xff00); else r->AX = flags; /* Undocumented result, Ax = Dx seen using Pcwatch */ r->DX = r->AX; return SUCCESS; case 0x01: /* sft_flags is a file, return an error because you */ /* can't set the status of a file. */ if (!(flags & SFT_FDEVICE)) return DE_INVLDFUNC; /* RBIL says this is only for DOS < 6, but MSDOS 7.10 */ /* returns this as well... and some buggy program relies*/ /* on it :( */ if (r->DH != 0) return DE_INVLDDATA; /* Undocumented: AL should get the old value */ r->AL = s->sft_flags_lo; /* Set it to what we got in the DL register from the */ /* user. */ s->sft_flags_lo = SFT_FDEVICE | r->DL; return SUCCESS; case 0x0a: r->DX = flags; r->AX = 0; return SUCCESS; } if (!(flags & SFT_FDEVICE)) { if (r->AL == 0x06) r->AL = s->sft_posit >= s->sft_size ? 0 : 0xFF; else if (r->AL == 0x07) r->AL = 0; else return DE_INVLDFUNC; return SUCCESS; } dev = s->sft_dev; CharReqHdr.r_unit = 0; break; } default: /* block IOCTL: 4, 5, 8, 9, d, e, f, 11 */ { struct dpb FAR *dpbp; unsigned attr; /* This line previously returned the deviceheader at r->bl. But, DOS numbers its drives starting at 1, not 0. A=1, B=2, and so on. Changed this line so it is now zero-based. -SRM */ /* JPP - changed to use default drive if drive=0 */ /* JT Fixed it */ /* NDN feeds the actual ASCII drive letter to this function */ dpbp = get_dpb((r->BL & 0x1f) == 0 ? default_drive : (r->BL & 0x1f) - 1); if (dpbp) { CharReqHdr.r_unit = dpbp->dpb_subunit; dev = dpbp->dpb_device; attr = dev->dh_attr; } else { if (r->AL != 9) return DE_INVLDDRV; dev = NULL; attr = ATTR_REMOTE; } switch (r->AL) { case 0x09: { /* note from get_dpb() */ /* that if cdsp == NULL then dev must be NULL too */ struct cds FAR *cdsp = get_cds1(r->BL & 0x1f); if (cdsp == NULL) return DE_INVLDDRV; if (cdsp->cdsFlags & CDSSUBST) attr |= ATTR_SUBST; r->AX = S_DONE | S_BUSY; r->DX = attr; return SUCCESS; } case 0x0d: if ((r->CX & ~(0x486B-0x084A)) == 0x084A) { /* 084A/484A, 084B/484B, 086A/486A, 086B/486B */ r->AX = 0; /* (lock/unlock logical/physical volume) */ /* simulate success for MS-DOS 7+ SCANDISK etc. --LG */ return SUCCESS; } /* fall through */ default: /* 0x04, 0x05, 0x08, 0x0e, 0x0f, 0x11 */ break; } break; } } { unsigned testattr = ATTR_QRYIOCTL; if (r->AL<=0x0f) testattr = ATTR_GENIOCTL; if (r->AL<=0x08) testattr = ATTR_EXCALLS; if (r->AL<=0x07) testattr = 0xffff; if (r->AL<=0x05) testattr = ATTR_IOCTL; if (!(dev->dh_attr & testattr)) return DE_INVLDFUNC; } CharReqHdr.r_command = cmd[r->AL]; if (r->AL == 0x0C || r->AL == 0x0D || r->AL >= 0x10) /* generic or query */ { CharReqHdr.r_cat = r->CH; /* category (major) code */ CharReqHdr.r_fun = r->CL; /* function (minor) code */ CharReqHdr.r_si = r->SI; /* contents of SI and DI */ CharReqHdr.r_di = r->DI; CharReqHdr.r_io = MK_FP(r->DS, r->DX); /* parameter block */ } else { CharReqHdr.r_count = r->CX; CharReqHdr.r_trans = MK_FP(r->DS, r->DX); } CharReqHdr.r_length = sizeof(request); CharReqHdr.r_status = 0; execrh(&CharReqHdr, dev); if (CharReqHdr.r_status & S_ERROR) { CritErrCode = (CharReqHdr.r_status & S_MASK) + 0x13; return DE_ACCESS; } if (r->AL <= 0x05) /* 0x02, 0x03, 0x04, 0x05 */ r->AX = CharReqHdr.r_count; else if (r->AL <= 0x07) /* 0x06, 0x07 */ r->AX = (CharReqHdr.r_status & S_BUSY) ? 0000 : 0x00ff; else if (r->AL == 0x08) /* 0x08 */ r->AX = (CharReqHdr.r_status & S_BUSY) ? 1 : 0; else if (r->AL == 0x0e || r->AL == 0x0f) /* 0x0e, 0x0f */ r->AL = CharReqHdr.r_unit; else /* 0x0c, 0x0d, 0x10, 0x11 */ r->AX = CharReqHdr.r_status; return SUCCESS; }