;       SCCSID = @(#)d_read.asm	6.1 91/02/15
;       SCCSID = @(#)d_read.asm	6.2 90/01/22
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
;***  d_read.asm - API stub routine DosRead
;
;       Member of API library
;       Steve Salisbury & Bill Mershon
;       Copyright MicroSoft Corporation, 1986
;       18-Feb-1986
;
;       library routine for API simulator
;
;       Called from dos 2.x,3.x compatible dos 5.x applications
;
;       Special Information
;               none
;
;       Modification History
;
;       02-Oct-86 (billme): add code to redirect console reads
;       to 'kbdstringin' and make corresponding modifications
;       for compatibility with DOS 5.  See also d_open.asm.
;
;       14-Oct-86 (billme): add ctrl-z check in cooked mode to
;       be compatible with DOS 5.
;
;       30-Oct-86 (billme): add dbcs support (see #DBCS#)
;
;       18-Nov-86 (billme): change code to handle entry of strings
;       of length zero (i.e. just CR) as pointed out by PTM 4484 (391)
;
;       06-Jan-87 (billme): Replace initial pushes and final pops
;       with calls to __api_begin and __api_end resp.  This will
;       reduce the size of FAPI and allow support for signals.
;
;       15-Jan-87 (billme): Change reference to __api_dev_table to
;       call to __api_devtab_ptr ... to reduce code size.
;
;       17-Feb-87 (davidl): Fixed problem with 1 byte buffer on call
;       and rewrote using STRUC for readability.
;
;       04-May-87 (robertc): Install hooks for DOSErrorClass Support.
;       All int 21h errors are passed through api_get_extended to get the
;       extended errorcode and to provide the class, action, and locus for
;       the dynamic error FIFO queue.
;
;       17-June-87 (stevee): fix to insure that all FAPI file handles are
;       less than MAX_HANDLES (p5553)
;
;       19-June-87 (CWY): Check if it is CONIN_FLAG and keyboard input
;                         then read in from keyboard
;
;       19-Nov-87 (marieu): commented out code for Line Feed as it
;       is now provided by KBDSTRINGIN (p1250)
;
;       29-Feb-88 (Jimmyg): KBDSTRINGIN is now only called in case of
;       raw mode input from conin and handle 0 . (p1250 and P1823)
;
;       12-May-88 (Jimmyg): The use of the topcall variable around the
;       call to int 21 dosread has been removed as it was preventing someone
;       from ctrl-break from being recognized.  (cp111 p2643)



include dos2equ.inc
include error.inc
include api.inc
include kbdfapi.inc
include struc.inc
        EXTRN   DosErrAdd:far
        EXTRN   api_get_extended:far

        EXTRN   __api_devtab_ptr:near
        EXTRN   __api_incTopCall:near
        EXTRN   __api_decTopCall:near
        EXTRN   SignalCheck:near

CR      equ     0Dh
LF      equ     0Ah
CRLF    equ     0A0Dh ;Note this is byte reversed for WORD move use.
CTRLZ   equ     01Ah

;***    DOSREAD - stub to emulate DOSREAD function call
;
;       simulates DOS 5.0 call from DOS 2.x,3.x environment
;
;       errorcode = unsigned far pascal
;       DosRead (FileHandle,BufferArea,BufferLength,BytesRead)
;
;       ENTRY:
;               FileHandle - file handle
;               BufferArea - address of user buffer
;               BufferLength - length of byffer
;               BytesRead - bytes read
;
;       RETURN:
;               AX = 0 if no error, else error code (see DOS 5 spec)
;
;       EXIT:
;               number of bytes read stored at BytesRead
;
;       USES:
;               AX
;
;       Pseudo Code:
;               save registers
;               use BP as pointer to stack parameters
;               load registers for int 21 call
;               execute int 21 with function 3fh
;               restore registers
;               return
;
;       WARNING:
;               may return error code from Dos 2.x, 3.x (see dos manuals)
;
;       EFFECTS:
;               none
;

        title   DOSREAD - stub to emulate DOSREAD function call
;
;       EXTRN   DOSREAD:FAR
;
;       PUSH    WORD FileHandle
;       PUSH    @ OTHER BufferArea
;       PUSH    WORD BufferLength
;       PUSH    @ WORD ByteCount
;       CALL    DOSREAD
;

        extrn   KBDSTRINGIN : FAR
        extrn __api_dev_table : word

        EXTRN   StatusFlag:BYTE


        EXTRN   api_testdbcs:far
        EXTRN   api_testdbcs_b:far
        EXTRN   api_testdbcs_bst:far
        EXTRN   api_testdbcs_bdec:far
        EXTRN   api_dbcs_findchar:far


_TEXT   segment byte public 'CODE'


;;DPL NOTE: The KBDSTRINGIN support under 3xBox doesn't match the support
;;under protect mode. The following data supports the changes made that
;;correct the difference.

pNext       DW      inputbuf       ;Pointer to next avail char in buffer.
pEnd        DW      inputbuf       ;Pointer beyond last avail char.
inputbuf    DB      KBD_BUF_SIZE dup (?) ;Buffer.
tmplt_cnt   DW      0              ;Previous byte cnt received from STRINGIN.

LenTable        struc
input_Len       dw      ?       ; input buffer length
receive_In_Len  dw      ?       ; received input length
LenTable        ends

len LenTable <>

;;End of data added to make 3xBox support work like protect mode.


        assume  CS:_TEXT,DS:NOTHING

        public  DOSREAD

FileHandle      equ     [BP+16]
BufferArea      equ     [BP+12]
BufferLength    equ     [BP+10]
ByteCount       equ     [BP+6]

DOSREAD proc    far
        xor     ax,ax   ;THG            ; AX <- 0 (default locals size)
        push    bp      ;THG
        mov     bp,sp   ;THG
        sub     sp,ax   ;THG            ; setup local stack frame
        push    ds      ;THG            ; save all registers except AX
        push    es      ;THG
        push    bx      ;THG
        push    cx      ;THG
        push    dx      ;THG
        push    si      ;THG
        push    di      ;THG
                        ;THG
;THG
;THG call __api_begin           ;Init bp and save bp,ds,bx,cx,dx,si,di,es
;THG                            ;Required to save: bp,ds,bx,cx,dx,si,di,es
  LDS SI,[BufferArea]                   ;DS:SI <- pntr to buffer
  LES DI,[ByteCount]                    ;ES:DI <- pntr to count
  xor ax,ax                             ;init byte count in case of error
  mov es:[di],ax
  Mov DX,[FileHandle]                   ;DX <- file handle
  Mov AX,ERROR_INVALID_HANDLE           ;Set error code.
 .If <DX ae MAX_HANDLES>                ;Check if handle out of range.
    Jmp NormalExit                      ;If so, return error.
 .Endif
  Mov AX,DX                             ;AX <- file handle
  Call __api_devtab_ptr                 ;BX <- address of entry
  Test cs:[bx].hi_attrdev,CONIN_FLAG    ;@@ Check if this is conin
  .If <nz>  AND  NEAR                   ;@@ yes it is con in
    or  dx,dx                           ;@@ is keyboard input
    .If <z> AND  NEAR                   ;yes, keyboard input
      Test CS:[StatusFlag],RAW_NOECHO   ;Check if raw mode.
       .If <nz>   NEAR



   ;Establish addressability to internal buffer and variables.

    Push CS
    Pop DS
    ASSUME DS:_TEXT

   ;See if there is buffered data.  If not, fill the internal buffer.

    Mov SI,[pNext]               ;Get pointer to next char.
   .If <SI e [pEnd]>             ;Check if any chars left in buffer.

     ;No chars left, so prepare to call kbdstringin.

      Mov AX,[BufferLength]       ;Fetch passed buffer length.
     .If <AX a KBD_MAX_IN>        ;Check if request too large.
        Mov AX,KBD_MAX_IN         ;If so, reduce to fit.
     .Endif
      Xor CX,CX                         ;Clear template length.
      Mov [len.input_Len],AX            ;Set count.
      Mov [len.receive_In_Len],CX       ;Set template length.

     ;Set parms for stringin call.

      Push DS                           ;Push segment of buffer.
      Mov AX,offset _TEXT:inputbuf      ;Get pointer to internal buffer.
      Push AX                           ;Push ptr as parm.
      Push DS                           ;Push segment of len struc.
      Mov AX,offset _TEXT:len           ;Get offset of len struc.
      Push AX                           ;Push it as parm.
      Xor AX,AX                         ;AX <- WAITIO (wait for chars).
      Push AX                           ;Push WAIT flag.
      Push AX                           ;Push dummy handle.
      Call KBDSTRINGIN                  ;Go get string.
      Or AX,AX                          ;Check for error.
     .If <nz>                           ;If so...
       Jmp NormalExit                   ;...quit now.
     .Endif

     ;Finished with stringin, now update structures.

      Mov DI,Offset _TEXT:inputbuf            ;Set "next char" as...
      Mov [pNext],DI                          ;  ...first in buffer.
      Add DI,[len.receive_In_Len]             ;DI points to end of buffer.
      Mov [pEnd],DI                           ;Set end (temporary) of string.


   .Endif   ;Endif for test for remaining data in internal buffer.

   ;Copy data from buffer into user's address space

    LES DI,[BufferArea]            ;Point to user's data area with ES:DI.
    Mov SI,[pNext]                 ;DS:SI point to next data
    Mov CX,[pEnd]                  ;Get pointer to end.
    Sub CX,SI                      ;Subtract beginning to get xfer count.
   .If <CX a [BufferLength]>       ;Check if more than asked for.
      Mov CX,[BufferLength]        ;It was, so reduce to requested cnt.
   .Endif
    Mov AX,CX                      ;Save transfer count.
    ClD
    Rep MovSB                      ;Move requested bytes.
    Mov [pNext],SI                 ;Point beyond transferred data.
    LDS SI,[ByteCount]             ;Point to callers transfer count spot.

    ASSUME DS:Nothing

    Mov [SI],AX                    ;Return count moved to user.
    Xor AX,AX                      ;Indicate success.


 .Else NEAR                  ;   ;If not, do Int 21 read now.

                                ;THG THG
;   call __api_incTopCall       ;THG THG
                                ;THG THG
    Mov BX,DX                             ;BX <- handle
    Mov CX,[BufferLength]                 ;CX <- number of bytes to read
    Mov DX,SI                             ;DS:DX <- pointer to buffer
    Mov AH,D2_ReadForD                    ;Set read function.
    Int 21h                               ;Go do it.
   .If <c>                                ;Check for error during Int 21.
      call __api_decTopCall               ; if there is an error
      jmp     ErrorExit                   ;@@ Added support for DOSErrorClass
   .Endif

      Mov ES:[DI],AX                        ;If not, return byte count.
      Xor AX,AX                             ;And indicate no error.
                                ;THG THG THG THG THG THG THG THG THG THG THG
;   call __api_decTopCall       ;THG THG THG THG THG THG THG THG THG THG THG
                                ;THG THG THG THG THG THG THG THG THG THG THG

 .Endif                ;Endif for choice between direct Int21 & STRINGIN call.


        jmp     short NormalExit        ;@@ Added support for DOSErrorClass
ErrorExit:                              ;@@
;       call    api_get_extended        ;@@
NormalExit:                             ;@@
        call    SignalCheck   ;THG
        pop     di            ;THG
        pop     si            ;THG
        pop     dx            ;THG
        pop     cx            ;THG
        pop     bx            ;THG
        pop     es            ;THG
        pop     ds            ;THG
        mov     sp,bp         ;THG
        pop     bp            ;THG
;THG
;THG  call __api_end       ; check sigs & restore es,di,si,dx,cx,bx,ds,bp
;THG
  ret  12              ; clear stack of entry parameters (bytes)

DOSREAD endp

_TEXT   ends

        end
