;       SCCSID = @(#)demmisc.asm        6.4 92/02/13
;       SCCSID = @(#)demmisc.asm        6.4 92/02/13
TITLE MISC - Miscellanious routines for MS-DOS
NAME  MISC
;
; Miscellaneous system calls most of which are CAVEAT
;
;   $SLEAZEFUNC
;   $SLEAZEFUNCDL
;   $GET_INDOS_FLAG
;   $GET_IN_VARS
;   $GET_DEFAULT_DPB
;   $GET_DPB
;   $DISK_RESET
;   $SETDPB
;   $Dup_PDB
;   $CREATE_PROCESS_DATA_BLOCK
;   SETMEM
;   FETCHI_CHECK
;
;   Revisions:
;
;Local  DCR/
;Tag    PTM(R)  Who     When
;               ARR     30 March 1983
;
;A000                   Jan. 1988
;                   version 4.00
;
;A001   D490
;                   Change IOCTL subfunctions from 63h, 43h to 66h , 46h
;
;               danno   07-Jan-1989
;                   Modified for MVDM
;
;***********************************************************************;BN001;
; BN001 - 27Feb91 G.L.Fulk                                              ;BN001;
; Change the code to support either the DOS 3.x or DOS 4+5 DPB          ;BN001;
; structure, based on DOS version number.  The default should be DOS 5  ;BN001;
; compatible.                                                           ;BN001;
;***********************************************************************;BN001;
; BN002 - 10/9/91  CP20 AA03991  Mark Rogalski                          ;BN002;
;         Add Dup_PDB function to increment the reference counts for    ;BN002;
;         OS/2 files when a PDB is duplicated.                          ;BN002;
;***********************************************************************;BN002;
; BN003 - 1/30/92  CP20 AA04471  Mark Rogalski                          ;BN003;
;         We no longer need to keep the CurrentPDB variable             ;BN003;
;***********************************************************************;BN003;
; BN004 - 2/10/92  CP20 B732823  Mark Rogalski                          ;BN004;
;         We need to set a flag in our PDBs so that the OS/2 filesystem ;BN004;
;         determine that it should not scan our JFTs.                   ;BN004;
;***********************************************************************;BN004;
; BN005 - 5/13/92  CP20 DEFECT 24729 Mark Rogalski                      ;BN005;
;         Remove unneeded code for handling RM devices.                 ;BN005;
;***********************************************************************;BN005;
; 63183 - 03/05/93 Lisa M. Primm                                        ;63183;
;         Added TXT_MSG_STAND_BY to this for WinOS2 "Loading Please     ;63183;
;         Wait" message.  This is where it is in the corresponding      ;63183;
;         V86CODE module.                                               ;63183;
;***********************************************************************;63183;
; 88962 - 07/12/94 ChangeTeam (Defect #80871-orginal)                   ;88962;
;         Added procedures GET_DATE, SET_DATE, GET_TIME, and SET_TIME,  ;88962;
;         so time/date changes in a VMB will not be overwritten.        ;88962;
;         This was merged from r206 to r207 by V. Taplin.               ;88962;
;***********************************************************************;88962;

.xlist
;
; get the appropriate segment definitions
;
include v86seg.inc

.xcref
include basemaca.inc
include osmaca.inc
include oldmaca.inc
include demmac.inc
include dossymc.inc
include devsym.inc
include error.inc
include pdb.inc
include dpb.inc
include sft.inc
include vector.inc
include mi.inc
include mvdmexp.inc
include demsvc.inc
include dos3dev.inc
include demver.inc
.cref
.list

        CpuMode 386

ENTRYPOINTSEG   EQU     0CH
MAXDIF          EQU     0FFFH
SAVEXIT         EQU     10

;m        i_need  BuffHead,DWORD
        i_need  INDOS,BYTE
;m        i_need  SYSINITVAR,BYTE
;BD003        i_need  CurrentPDB,WORD
;m        i_need  CreatePDB,BYTE
        i_need  THISSFT,DWORD
        i_need  FETCHI_TAG,WORD                  ; for TAG CHECK
        i_need  DOS34_FLAG,WORD                  ;AN000;
        i_need  FATBYTE,WORD

;BD005        ReferV86    RMDevHandleInfo,rmdi
        ReferV86    os2_handled,BYTE             ; mdr
        ReferV86    pOldInt21,DWORD              ;BN002
        ReferV86    handle_count,BYTE            ;BN002
if debug
        I_need  BugLev,WORD
        I_need  BugTyp,WORD
;       include bugtyp.asm
endif


V86CODE    SEGMENT
        ASSUME  CS:V86GROUP

        EXTRN   Get_User_Stack:NEAR
        EXTRN   pJFNFromHandle:NEAR
;        EXTRN   DOSInit:NEAR
        EXTRN   $IoCtl:NEAR
        EXTRN       ECritDisk:NEAR
        EXTRN       LCritDisk:NEAR
;BD005        EXTRN   SFFromSFN:NEAR
;BD005        EXTRN   RMDevCheck:NEAR                        ;BN002
        EXTRN   Sys_Return:NEAR
        EXTRN   Sys_Ret_OK:NEAR
        EXTRN   Sys_Ret_Err:NEAR
        EXTRN   FCB_RET_ERR:NEAR
;m        EXTRN   $GET_VERSION:NEAR                                       ;BN001;
        EXTRN   VMcheck_drive:NEAR                                      ;mdr
        EXTRN   VSFNFromHandle:NEAR                    ;BN002


BREAK <SleazeFunc -- get a pointer to media byte>

;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;                                                                          ;
; Inputs:
;       None
; Function:
;       Return Stuff sort of like old get fat call
; Outputs:
;       DS:BX = Points to FAT ID byte (IBM only)
;               GOD help anyone who tries to do ANYTHING except
;               READ this ONE byte.
;       DX = Total Number of allocation units on disk
;       CX = Sector size
;       AL = Sectors per allocation unit
;          = -1 if bad drive specified

        procedure   $SLEAZEFUNC,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

        XOR     DL,DL

entry   $SLEAZEFUNCDL           ; Same as above except that drive is
                                ; passed in DL (0=default, 1=A, 2=B, ...)
        call    vmcheck_drive   ; mdr return if dos drive
        context DS
        SVC     SVC_DEMGETDRIVEFREESPACE
        JC      short BADDRV
        MOV     BYTE PTR [FATBYTE],AL   ; FAT ID BYTE
        MOV     AX,SI                   ; (AL) = Sectors per allocation unit
; NOTE THAT A FIXED MEMORY CELL IS USED --> THIS CALL IS NOT
; RE-ENTRANT. USERS BETTER GET THE ID BYTE BEFORE THEY MAKE THE
; CALL AGAIN
        MOV     DI,OFFSET V86GROUP:FATBYTE
DOST:
        invoke  get_user_stack
ASSUME  DS:NOTHING
        MOV     [SI.user_DX],DX         ; Number of clusters on drive
        MOV     [SI.user_CX],CX         ; Bytes/sector
        MOV     [SI.user_BX],DI         ; Offset of FAT ID BYTE
        MOV     [SI.user_DS],CS         ; Segment of FAT ID BYTE ; stash correct pointer
        ret
BADDRV:
        MOV     AX,error_invalid_drive  ; Assume error
        jmp     FCB_RET_ERR

EndProc $SLEAZEFUNC
;                                                                          ;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;

IF NOT_FILTER

BREAK <$Get_INDOS_Flag -- Return location of DOS critical-section flag>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;                                                                          ;
; Inputs:
;       None
; Function:
;       Returns location of DOS status for interrupt routines
; Returns:
;       Flag location in ES:BX

        procedure   $GET_INDOS_FLAG,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

        invoke  get_user_stack
        MOV     [SI.user_BX],OFFSET V86GROUP:INDOS
        MOV     [SI.user_ES],SS
        ret
EndProc $GET_INDOS_FLAG
;                                                                          ;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;

BREAK <$Get_IN_VARS -- Return a pointer to DOS variables>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;                                                                          ;
; Return a pointer to interesting DOS variables This call is version
; dependent and is subject to change without notice in future versions.
; Use at risk.
        procedure   $GET_IN_VARS,NEAR
        invoke  get_user_stack
        MOV     [SI.user_BX],OFFSET V86GROUP:SYSINITVAR
        MOV     [SI.user_ES],SS
        ret
EndProc $GET_IN_VARS
;                                                                          ;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;

;filter
ENDIF

BREAK <$GET_DEFAULT_DPB - Get default DPB>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;                                                                          ;
;***    $Get_Default_DPB - Return pointer to DPB for default drive
;
;       Fill in a static buffer with disk information in the form of
;       a DOS 3.2 DPB.
;
;       ENTRY:  none
;
;       EXIT:   (AL) =  0, success
;                   (DS:BX) = ptr to static DPB buffer
;               (AL) = -1, bad drive (call 32h only)

V86DATA SEGMENT
Fake4xDPB   dpb4x     <>                                                ;BN001;
V86DATA ENDS

procedure   $GET_DEFAULT_DPB,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

        XOR     DL,DL

entry   $GET_DPB                        ; Same as above only drive passed
                                        ; in DL (0=default, 1=A, 2=B, ...)
        call    VMcheck_drive           ; mdr return if dos drive

        ; Fake DPB filled by worker                                     ;BN001;
        MOV     DI, OFFSET V86GROUP:FAKE4XDPB                           ;BN001;
        PUSH    CS
        POP     ES                      ; ES:DI fake DPB
        XOR     DH,DH
        SVC     SVC_DEMGETDPB
        CMP     AL, -1
        JE      GDD_ERR

;-------                                                                ;BN001;
        push    ax                                                      ;BN001;
        push    bx                                                      ;BN001;
        push    cx                                                      ;BN001;
;        call    $GET_VERSION                                            ;BN001;
        mov     ah,30h                 ;mdr
        int     21h                    ;mdr
        xchg    ah,al                                                   ;BN001;
        cmp     ax,100h* 4                                              ;BN001;
        jb      glf_x3                                                  ;BN001;
        cmp     ax,100h* 10                                             ;BN001;
        jb      glf_x4                                                  ;BN001;
        cmp     ax,100h* 20                                             ;BN001;
        jae     glf_x4                                                  ;BN001;
glf_x3:                                                                 ;BN001;
        MOV     bx,offset V86GROUP:FAKE4XDPB  ; Offset of fake DPB      ;BN001;
                                                                        ;BN001;
        mov     ax,cs:[bx].dpb4x_dir_sector                             ;BN001;
        mov     cs:[bx].dpb3x_dir_sector,ax                             ;BN001;
                                                                        ;BN001;
        mov     ax,word ptr cs:[bx].dpb4x_driver_addr                   ;BN001;
        mov     word ptr cs:[bx].dpb3x_driver_addr,ax                   ;BN001;
        mov     ax,word ptr cs:[bx].dpb4x_driver_addr+2                 ;BN001;
        mov     word ptr cs:[bx].dpb3x_driver_addr+2,ax                 ;BN001;
                                                                        ;BN001;
        mov     al,cs:[bx].dpb4x_media                                  ;BN001;
        mov     cs:[bx].dpb3x_media,al                                  ;BN001;
                                                                        ;BN001;
        mov     al,cs:[bx].dpb4x_first_access                           ;BN001;
        mov     cs:[bx].dpb3x_first_access,al                           ;BN001;
                                                                        ;BN001;
        mov     ax,word ptr cs:[bx].dpb4x_next_dpb                      ;BN001;
        mov     word ptr cs:[bx].dpb3x_next_dpb,ax                      ;BN001;
        mov     ax,word ptr cs:[bx].dpb4x_next_dpb+2                    ;BN001;
        mov     word ptr cs:[bx].dpb3x_next_dpb+2,ax                    ;BN001;
                                                                        ;BN001;
        mov     ax,cs:[bx].dpb4x_next_free                              ;BN001;
        mov     cs:[bx].dpb3x_next_free,ax                              ;BN001;
                                                                        ;BN001;
        mov     ax,cs:[bx].dpb4x_free_cnt                               ;BN001;
        mov     cs:[bx].dpb3x_free_cnt,ax                               ;BN001;
glf_x4:                                                                 ;BN001;
        pop     cx                                                      ;BN001;
        pop     bx                                                      ;BN001;
        pop     ax                                                      ;BN001;
;-------                                                                ;BN001;
                                                                        ;BN001;
        invoke  get_user_stack
        MOV     [SI.user_BX],OFFSET V86GROUP:FAKE4XDPB  ; Offset &      ;BN001;
        MOV     [SI.user_DS],CS                         ; Segment of fake DPB
        XOR     AL,AL
GDD_ERR:
        return
EndProc $GET_DEFAULT_DPB


;                                                                          ;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;


BREAK <$SetDPB - Create a valid DPB from a user-specified BPB>
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;                                                                          ;


;***    $SETDPB - set drive parameter block
;
;       NOTE    Not supported in OS/2.  The DPB is a global system data
;               object, so we cannot allow the 3xBox to fiddle with it.
;
;       ENTRY   ignored
;
;       EXIT    return error

        procedure   $SETDPB,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

        error   ERROR_INVALID_FUNCTION

EndProc $SetDPB
;                                                                          ;
;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;


BREAK <$Disk_Reset -- Flush out all dirty buffers>

        procedure   $DISK_RESET,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

; Inputs:
;       None
; Function:
;       Flush and invalidate all buffers
; Returns:
;       Nothing

        MOV     AL,-1
 entry $DISK_RESET2             ; who calls this entry point?
        EnterCrit   critDisk
        SVC     SVC_DEMDISKRESET            ; Let OS2 do everything
        LeaveCrit   critDisk
        mov     os2_handled,0               ; mdr let DOS do it too
        ret

EndProc $DISK_RESET




BREAK <$Dup_PDB -- increment OS/2 file reference counts>        ;BN002  start
;
; Inputs:   DX is new segment address of process
;           SI is end of new allocation block
;
procedure   $Dup_PDB,NEAR
ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING

        pushf                           ; call DOS to dup PDB
        call    cs:[pOldInt21]
        jc      bad_dup                 ; end if problem

;BD003        mov     CurrentPDB,dx           ; save segment of new PDB in our var
        mov     ds,dx                   ; use new PDB segment
        mov     ds:[4],04341h           ;BN004   set our flag in new PDB
        mov     ds:[6],04543h           ;BN004   set our flag in new PDB

        mov     cx,ds:[PDB_JFN_Length]  ; init cx with size of JFT
        dec     cx

begin:  mov     bx,cx                   ; get DOS handle
        call    VSFNFromHandle          ; get SFN from JFT slot
        jc      short dos_handle        ; if error do not DUP
        jz      short dos_handle        ; if DOS handle do not DUP

;BD005        call    RMDevCheck              ; see if OS/2 file or device
;BD005        jc      file                    ; Skip if OS2 file
;BD005        SVC     SVC_DEMDUP              ; Dup the OS/2 device handle
;BD005        jc      short dos_handle        ; Skip if error
;BD005        inc     es:[di].rmdi_refcnt     ; increment reference count
;BD005        jmp     short dos_handle

file:   SVC     SVC_DEMDUP              ; Dup the OS/2 file handle
        jc      short dos_handle        ; Skip if error
        mov     bx,cx                   ; get handle to dup from dx
        call    pJFNFromHandle          ; get pointer into JFT
        movzx   bx,byte ptr es:[di]     ; get SFN from JFT
        inc     cs:handle_count[bx]     ; increment ref count in our table

dos_handle:
        inc     si
        loop    begin
        jmp     Sys_Ret_Ok

bad_dup:
        jmp     Sys_Ret_Err

EndProc $Dup_PDB,NoCheck                                       ;BN002  end



Procedure FETCHI_CHECK,NEAR
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
        PUSHF
        CMP     CS:[FETCHI_TAG],22642
        JZ      TAG_OK
        InternalError   <DOSINIT>                 ; go to hell
TAG_OK:
        POPF
        ret
EndProc   FETCHI_CHECK

;begin:63183;
PUBLIC TXT_MSG_STAND_BY
include demmisc.inc
;end:63183;

;-----------------------------------------------------------------------
public  $GET_DATE                                                 ;88962
$GET_DATE proc near                                               ;88962
        ASSUME  ds:NOTHING,es:NOTHING                             ;88962
        ;entry: none                                              ;88962
        SVC     SVC_DEMQUERYDATE        ; Get the date            ;88962
        ;exit:  DH=month 1..12                                    ;88962
        ;       DL=day 1..31                                      ;88962
        ;       CX=year 1980..2099                                ;88962
        ;       AL=weekday 0..6                                   ;88962
                                                                  ;88962
        call    get_user_stack          ;Get pointer to user regs ;88962
        mov     [si].user_DX,dx         ;DH=month, DL=day         ;88962
        mov     [si].user_CX,cx         ;CX=year                  ;88962
        ret                                                       ;88962
$GET_DATE endp                                                    ;88962
;-----------------------------------------------------------------------




;-----------------------------------------------------------------------
public $SET_DATE                                                  ;88962
$SET_DATE proc NEAR                                               ;88962
        ASSUME  DS:NOTHING,ES:NOTHING                             ;88962
                                                                  ;88962
; Inputs:                                                         ;88962
;       CX:DX valid date                                          ;88962
; Function:                                                       ;88962
;       Set current date                                          ;88962
; Returns:                                                        ;88962
;       AL = -1 date bad, = 0 OK\                                 ;88962
                                                                  ;88962
        SVC     SVC_DEMSETDATE                                    ;88962
                                                                  ;88962
        ret                                                       ;88962
$SET_DATE endp                                                    ;88962
;-----------------------------------------------------------------------




;-----------------------------------------------------------------------
public $GET_TIME                                                  ;88962
$GET_TIME proc NEAR                                               ;88962
        ASSUME  DS:NOTHING,ES:NOTHING                             ;88962
                                                                  ;88962
; Inputs:                                                         ;88962
;       None                                                      ;88962
; Function:                                                       ;88962
;       Get current time                                          ;88962
; Returns:                                                        ;88962
;       Time in CX:DX                                             ;88962
                                                                  ;88962
        SVC     SVC_DEMQUERYTIME                                  ;88962
        call    get_user_stack          ;Get pointer to user regs ;88962
        mov     [SI.user_DX],DX                                   ;88962
        mov     [SI.user_CX],CX                                   ;88962
        xor     AL,AL                                             ;88962
        ret                                                       ;88962
$GET_TIME endp                                                    ;88962
;-----------------------------------------------------------------------



;-----------------------------------------------------------------------
public $SET_TIME                                                  ;88962
$SET_TIME proc NEAR                                               ;88962
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING      ;88962
                                                                  ;88962
; Inputs:                                                         ;88962
;       CX:DX = Time                                              ;88962
; Function:                                                       ;88962
;       Set time                                                  ;88962
; Returns:                                                        ;88962
;       AL = -1 time bad, = 0 OK                                  ;88962
                                                                  ;88962
        SVC     SVC_DEMSETTIME                                    ;88962
        ret                                                       ;88962
$SET_TIME endp                                                    ;88962
;-----------------------------------------------------------------------
V86CODE ENDS

        END
