;       SCCSID = @(#)api2.asm   6.9 92/03/11
;      SCCSID = @(#)api2.asm    6.9 92/03/11
;
;***    api2.asm
;
;       IBM/Microsoft Confidential
;
;       Copyright (c) IBM Corporation 1987, 1989
;       Copyright (c) Microsoft Corporation 1987, 1989
;
;       All Rights Reserved
;
;       Applications Program Interface, in particular, the protected mode,
;       dynamic link, PLM calling convention used in OS/2.
;
;       18:Nov-95    MLM   Defect 72417, moved find.inc after tkexport.inc
;

PAGE    ,132
TITLE   API2
NAME    API2

INCL_ERRORS     EQU     1
.xlist
include fnotask.inc
include basemaca.inc
include osmaca.inc
include dossymc.inc
include ostypes.inc
include dosseg.inc
include bseerr.inc
include mi.inc
include error.inc
include protmode.inc
include seldesc.inc
include proc.inc
include kmode.inc
include sysentry.inc
include ordinals.inc
include struc.inc
include osconst.inc
include sigdef.inc
include except.inc
include infoseg.inc
include pgexport.inc
include vmowner.inc
include vmexport.inc
include selxport.inc
include curdir.inc
include dirent.inc
include screen.inc
include sem.inc
include tkexport.inc
include find.inc
include tkptda.inc
include mmpha.inc
include devhlp.inc
.list

        CpuMode 286
        ModName api2,FNO_API2_ASM

        EXTRN           w_EnterCritSec:NEAR
        EXTRN           w_ExitCritSec:NEAR
        EXTRN           _SELSetDescInfo:near

if RAS
        EXTRNFAR        w_systrace
endif ;RAS

        EXTRNFAR        AllocateGDTSelector
        EXTRNFAR        FreeGDTSelector

        EXTRN32         _PGVerifyInfoSegs
        EXTRN32         KMSETCLIENTREGISTER

        EXTRNF32        KMEnterKmodeEvents

        ReferFlat       _flGlobalActions,DWORD
        ReferFlat       _pTCBCur,DWORD
        ReferFlat       _pPTDACur,DWORD

if RAS
        ReferGlobal     ras_stda_addr,WORD
endif

;
; The code in the first part of this module enables the ability to
; "dynamically" add an API callgate to the system. These dynamic APIs follow
; all normal API kernel entry and exit rules and use the same code as
; normal APIs
;
; There are DYNAM_MAX 'blank' API entry points that can be assigned to
; a worker routine by the DevHlp_DynamicAPi devhlp. Either a 16 or 32 bit
; callgate is created. The worker routine can be a 16:16 address or a 32
; bit address in the flat space. Callgates can be removed. Up to DYNAM_DWC
; double word parameters can be copied for 32 bit callgates, or DYNAM_WC
; parameters for 16 call gates.
;
; There are two data structures. The first, dynam_API_table, is used to
; remember API configuration and match an API to the 'blank' API entry
; point. The second, dynam_ret_table, is an array of SCIReturnX routine
; addresses. The SCIReturnX routine does the final stack clearing and does
; the RETFD X back to the calling application, where X defines how many
; parm words must be freed.
;
; Here's some tricky parts
; - The SysEntry macro expects parameters to be 'hard coded' at compile
;   time. This won't work for dynamic APIs, so the prolog code to calling
;   the SCI routine is coded without use of the macro. We also don't want to
;   define the callgate or mess with ordinal numbers.
; - One of the SysEntry pushes is for the address of the SCIReturnX
;   routine. This is initially pushed as 0, and fixed up later.
; - The return address must be converted for a retfd on a 32 bit worker call
; - The idea is to use the normal SCI code, inorder to do enter and exit kmode
;   right, with extenstions and hooks to fix up the dynamic stuff that can't
;   be coded at complie time.
;
; Heres the flow.
;
; Application                                     ; call the callgate
;  |
; callgate             <- allocated by Devhlp_DynamicAPI
;  |
; DYNAM_API_?                                     ; one of the 'blank' entry pts
;  |
; dynam_sci                                       ; common funnel entry point
;  |
; call SCI-------|
;                |
;               threadop mv_si_si                 ; get pointer to parms
;                |
;               farcall -------|
;                              |
;                         w_dynam_API             ; hook to call real worker
;                              |
;                |-------- <real worker>
;                |
;                return                           ; SCI exit threadop
;                |
;                SCIReturnX                       ; retfd routine
;                |
;                Application                      ; back to application

; structure for each entry in Dynamic API table

dynam_s struc
   dynam_EP_IP   dw  ?   ; API entry point IP
   dynam_EP_CS   dw  ?   ; API entry point CS
   dynam_GDTSel  dw  0   ; callgate selector
   dynam_flag    dw  0   ; flags from devhlp reg DH
   dynam_DWC     dw  0   ; double word parm count
   dynam_pad     dw  0   ;
   dynam_WK      dd  0   ; worker routine
dynam_s ends

; stack frame structure for entry to SCI

dynam_f struc
   dynam_parmCnt dd  0   ; double word parm count
   dynam_ret_ret dw  0   ; return address for  threadop RETURN
   dynam_ef      dd  0   ; pushfd
   dynam_IP_low  dw  0   ; callers IP
   dynam_IP_high dw  0   ;
   dynam_CS_low  dw  0   ; callers CS
   dynam_CS_high dw  0   ;
dynam_f ends
dynam_index   EQU dynam_CS_high ; overlay with index

; stack frame structure for entry to SCI from 16 bit callgate

dynam_g struc
   dynam_saveBP  dw  0   ;
   dynam_saveAX  dw  0   ;
   dynam_saveCX  dw  0   ;
   dynam_32IP_L  dw  0   ;
   dynam_32IP_H  dw  0   ;
   dynam_32CS    dw  0   ;
   dynam_Gindex  dw  0   ;
   dynam_16IP    dw  0   ;
   dynam_16CS    dw  0   ;
dynam_g ends
dynam_saveDS     EQU dynam_32CS
dynam_saveSI     EQU dynam_Gindex
dynam_save_size  EQU 4+6  ; room needed to extend stack
                          ; 4 to extend ss:esp
                          ; 6 for extra save registers that will be poped

; stack frame to convert 16 bit SS:SP to SS:ESP

dynam_h struc
   dynam_32SP_L  dw  0   ;
   dynam_32SP_H  dw  0   ;
   dynam_32SS_L  dw  0   ;
   dynam_32SS_H  dw  0   ;
dynam_h ends
dynam_16SS EQU dynam_32SS_H
dynam_16SP EQU dynam_32SS_L

; w_dynam stack frames

dynam_i struc
   dynai_saveDS     dw 0 ;
   dynai_saveSI     dw 0 ;
   dynai_gotoIP_L   dw 0 ;
   dynai_gotoIP_H   dw 0 ;
   dynai_gotoCS     dw 0 ;
   dynai_gotoCS_pad dw 0 ;
   dynai_retIP      dw 0 ;
   dynai_retCS      dw 0 ;
dynam_i ends

dynam_j struc
   dynaj_saveDS     dw 0 ;
   dynaj_saveSI     dw 0 ;
   dynaj_gotoIP     dd 0 ;
   dynaj_gotoCS     dw 0 ;
   dynaj_gotoCS_pad dw 0 ;
   dynaj_retIP_L    dw 0 ;
   dynaj_retIP_H    dw 0 ;
   dynaj_retCS      dw 0 ;
   dynaj_retCS_pad  dw 0 ;
dynam_j ends

DYNAM_S_SHIFT  EQU  4    ; shift to convert index to offset

; Define Dynamic API entry points

FARCODE HIGH3
HIGH3CODE  SEGMENT

; make extrns to SCIReturnX in SCI.ASM

CpuMode 386
IRP x,<0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36>          ;B729310
  extrn SCIReturn&x:near
ENDM

DYNAM_MAX=0              ; maximum number of dynamic APIs
IRPC x,0123456789ABCDEF

    Procedure DYNAM_API_&x,far
    movzx esp,sp
    push  si
    mov   si,  DYNAM_MAX
    jmp   dynam_sci
    EndProc   DYNAM_API_&x

   DYNAM_MAX=DYNAM_MAX+1

ENDM

CpuMode reset

; Finite Dynamic API table

CONSTANTS       SEGMENT

public dynam_API_table
dynam_API_table label byte   ; API table
IRPC x,0123456789ABCDEF
   dynam_s <DYNAM_API_&x,seg HIGH3CODE>
ENDM

public dynam_ret_table
dynam_ret_table label byte   ; return table
DYNAM_DWC  EQU 8             ; Max double word parm count
DYNAM_WC   EQU DYNAM_DWC*2   ; Max word parm count
IRP x,<0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32>
  dw    SCIReturn&x
ENDM

CONSTANTS       ENDS

HIGH3CODE  ENDS

        FARCODE LOW
CODE segment

;***EP  dh_DynamicAPI - Dynamically add an API
;
;       ENTRY:  (AX:BX) = address of entry point
;               (DH)    = bit 0 : 1 = 16 callgate, 0 = 32 bit callgate
;                         bit 1 : 1 = 16:16 rtn  , 1 = 32 bit linear
;                         FFh : free callgate
;               (CX)    = double word parm count
;               (DI)    = call gate to free
;       EXIT:   Carry Flag clear on success
;                       DI = valid call gate selector
;               Carry Flag set on error
;
;       USES:   Flags
;
;               FS and GS must be preserved (DevHelp requirement)

Procedure dh_DynamicAPI,near
        CALLFAR Dynam_API_DevHlp
        ret
EndProc dh_DynamicAPI
CODE ends

FARCODE HIGH3
HIGH3CODE  SEGMENT
Procedure Dynam_API_DevHlp,faronly
    assume ds:nothing, es:nothing, ss:nothing, fs:nothing, gs:nothing

.386p

LocalVar API_IP,WORD            ; real worker to call
LocalVar API_CS,WORD
LocalVar GDTArray,DWORD         ; receive callgate selector
LocalVar DWC,WORD
LocalVar CallType,WORD
LocalVar TableIndex,WORD        ; save index into dynam_API_Table
LocalVar EP_IP,DWORD            ; call gate entry point
LocalVar EP_CS,DWORD

        EnterProc

        SaveReg <ds,eax,ecx,edx,es,esi>

; save input parms & convert to DWORD for call to _SelSetDescInfo

        movzx   dx,dh
        mov     word ptr [CallType],dx
        mov     word ptr [API_IP], bx
        mov     word ptr [API_CS], ax
        mov     word ptr [DWC],cx
        mov     word ptr [GDTArray]+2,0   ; clear double word high order

        DosContext <ds>

; check out parm count

        test    dx,DHDYNAM_16B_CALLGATE
        jnz     dynam_dh11
        shl     cx,1        ; convert dword count to word count
dynam_dh11:
        cmp     cx,DYNAM_WC
        jle     dynam_dh12
        stc
        jmp     dyn_done
dynam_dh12:

; find an empty slot (else return error)
        mov   di, 0              ; request empty slot
        call  dyn_locateSlot
        jc    dyn_done
        mov   [TableIndex],si

; allocate a GDT selector

        push  ss
        pop   es
        lea   di, GDTArray            ; es:di = array to receive selector
        mov   cx, 1                   ; cx = count
        CALLFAR AllocateGDTSelector
        jc    dyn_done

; map the callgate
;  _SELSetDescInfo(scope, attr/access, callgate sel, offset, entry sel,
;      don't care, don't care, don't care)

        mov     si,[TableIndex]
        mov     ax,[si].dynam_API_table.dynam_EP_IP
        mov     word ptr [EP_IP],ax
        mov     word ptr [EP_IP]+2,0
        mov     ax,[si].dynam_API_table.dynam_EP_CS
        mov     word ptr [EP_CS],ax
        mov     word ptr [EP_CS]+2,0
        mov     ecx, SELSD_GATE
        mov     dh, byte ptr [DWC]
        test    [CallType],DHDYNAM_16B_CALLGATE
        jnz     dynam_dh21
        mov     dl, D_GATE332            ; 32 bit callgate
        jmp     short dynam_dh22
dynam_dh21:
        mov     dl, D_GATE3              ; 16 bit callgate
dynam_dh22:

        FlatContext <ds,es>

        CCALL32 _SELSetDescInfo <ecx, edx, [GDTArray], \
                [EP_IP],[EP_CS],ecx, ecx, ecx>
        .386p
        DosContext <ds>

; set up table entry

        mov     si,[TableIndex]
        mov     di, word ptr [GDTArray]
        mov     [si].dynam_API_table.dynam_GDTSel, di
        mov     ax, word ptr [DWC]
        mov     [si].dynam_API_table.dynam_DWC,ax
        mov     ax, word ptr [CallType]
        mov     [si].dynam_API_table.dynam_flag,ax
        mov     ax, word ptr [API_IP]
        mov     word ptr [si].dynam_API_table.dynam_WK,ax
        mov     ax, word ptr [API_CS]
        mov     word ptr [si].dynam_API_table.dynam_WK+2,ax
        clc

dyn_done:
        RestoreReg <esi,es,edx,ecx,eax,ds>
        LeaveProc
        ret
EndProc Dynam_API_DevHlp


;***    dh_locateSlot - find an entry in the dynamic_API table
;
;       ENTRY:  (DI)    = callgate GDT entry (or 0 to find free)
;       EXIT:   Carry Flag clear on success
;                       SI = dynamic_API table entry index
;               Carry Flag set on error
;
;       USES:   Flags


Procedure dyn_locateSlot
        mov  cx, DYNAM_MAX
        mov  si, 0
dyn_loc_loop:
        cmp  [si].dynam_API_table.dynam_GDTSel, di  ; match ?
        jne  dyn_loc_1
        clc                  ; found match return
        ret

dyn_loc_1:
        add  si,SIZE dynam_s
        loop dyn_loc_loop
        stc                  ; no match found, return
        ret
EndProc dyn_locateSlot

CpuMode reset

extrn sci:near

;***    dynam_sci - call SCI for dynamic APIs
;
;
public dynam_sci
dynam_sci:
    CpuMode 386           ; set up entry to SCI
    push    ds
    DosContext <ds>
    shl     si, DYNAM_S_SHIFT   ; convert to an offset
    test    [si].dynam_API_table.dynam_flag,DHDYNAM_16B_CALLGATE
    jz      dynam_sci10
                          ; fix up stack to look like 32 bit callgate
    sub     esp,dynam_save_size
    mov     [esp].dynam_saveCX,cx
    mov     [esp].dynam_saveBP,bp
    mov     [esp].dynam_saveAX,ax
    mov     cx, [si].dynam_API_table.dynam_DWC
    mov     ds, [esp].dynam_saveDS ; restore DS
    shr     si, DYNAM_S_SHIFT
    xchg    [esp].dynam_Gindex,si  ; restore si & put index
    mov     ax, [esp].dynam_16CS
    mov     [esp].dynam_32CS,ax    ; set up 32 bit CS
    mov     ax, [esp].dynam_16IP
    mov     [esp].dynam_32IP_L,ax  ; set up 32 bit EIP
    mov     [esp].dynam_32IP_H,0
    mov     bp, sp
    add     bp, SIZE dynam_g - 4
    jcxz    dynam_sci1
dynam_sci0:
    mov     ax, [bp+4]
    mov     [bp],ax
    add     bp,2
    loop    dynam_sci0
dynam_sci1:
    mov     ax, [bp].dynam_16SP
    mov     [bp].dynam_32SP_L,ax
    mov     ax, [bp].dynam_16SS
    mov     [bp].dynam_32SS_L,ax
    mov     [bp].dynam_32SS_H,0

    ; restore regiseters

    pop     bp
    pop     ax
    pop     cx
    jmp     short dynam_sci11

dynam_sci10:              ; its OK
    shr     si, DYNAM_S_SHIFT   ; convert to an index
    mov     [esp+10],si   ; save index in CS pad
    pop     ds
    pop     si
dynam_sci11:
    pushfd
    push    0             ; address of return routine
    PUSHD   0             ; number of parameters
    CpuMode reset
    call    sci
    sci_init
    mv_si_si
    farcall w_dynam_API,0
    return

;***    w_dynam_API - fix up stack and call API routine
;
;   SI = user parms on stack
;
Procedure w_dynam_API,faronly

CpuMode 386
        sub     sp, 8               ; reserve some stack to build a
                                    ; "goto" retfd
        push    si
        push    ds
        DosContext <ds>
        mov     bp, si              ; get the API index
        sub     bp, SIZE dynam_f
        mov     si, [bp].dynam_index
        shl     si, DYNAM_S_SHIFT   ; convert to an offset

; fix up stack for threadop return's ret to SCIReturnX

        movzx   eax, [si].dynam_API_table.dynam_DWC   ; fix up return
        shl     ax,1      ;convert (DWC to WC) or (WC to BC (Byte Count))
        test    [si].dynam_API_table.dynam_flag,DHDYNAM_16B_CALLGATE
        jz      dynam_w0                                             ;B729310
        or      eax,_16B_Gate                                        ;B729310
        jmp     dynam_w3                                             ;B729310
dynam_w0:                                                            ;B729310
        shl     ax,1      ;convert (WC to BC) for 32 bit call gates  ;B729310
dynam_w3:                                                            ;B729310
        mov     [bp].dynam_parmCnt,eax                               ;B729310
        and     eax, not _16B_Gate                                   ;B729310
        mov     ax, word ptr [eax].dynam_ret_table
        mov     [bp].dynam_ret_ret,ax

; make the retfd stack frame to jmp to the real worker routine

        test    [si].dynam_API_table.dynam_flag,DHDYNAM_16B_APIRTN
        jnz     dynam_w1
                          ;its a 32 bit call, make a retfd return
        sub     esp,4     ; make more room
        mov     ax,[esp+4].dynai_saveDS
        mov     [esp].dynaj_saveDS,ax
        mov     ax,[esp+4].dynai_saveSI
        mov     [esp].dynaj_saveSI,ax
        mov     ax,[esp+4].dynai_retIP
        mov     [esp].dynaj_retIP_L,ax
        mov     [esp].dynaj_retIP_H,0
        mov     ax,[esp+4].dynai_retCS
        mov     [esp].dynaj_retCS,ax

                          ;make retf frame
        mov     eax, [si].dynam_API_table.dynam_WK    ; get linear addr
        mov     [esp].dynaj_gotoIP,eax
        mov     ax, seg FLAT:DOSHIGH32CODE
        mov     word  ptr [esp].dynaj_gotoCS,ax
        jmp     dynam_w2

dynam_w1:                 ;its a 16 bit call
        mov     ax, word ptr [si].dynam_API_table.dynam_WK  ; get offset
        mov     word  ptr [esp].dynai_gotoIP_L,ax
        mov     word  ptr [esp].dynai_gotoIP_H,0
        mov     ax, word ptr [si].dynam_API_table.dynam_WK+2; get cs
        mov     word  ptr [esp].dynai_gotoCS,ax
dynam_w2:
        pop     ds
        pop     si
        RETFD           ; "goto" real worker routine

CpuMode reset

EndProc w_dynam_API





;***    DOSSETDATETIME - Set the time and day maintained by the system
;
;       INVOKE  push@   OTHER DateTime          (2 words)
;               call    DOSSETDATETIME
;
;       RETURN  (ax) = return code
;                       0 - success
;                       0FFFFh - error -- date is not valid
;
SysEntry DOSSETDATETIME, ORD_DOSSETDATETIME, 2

        ld_si                           ; offset of DateTime structure
        ld_bx                           ; segment of DateTime structure

if RAS
;***DT  preDOSSETDATETIME - DosSetDateTime pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSSETDATETIME>,
;          TP    = .preDOSSETDATETIME,
;          TYPE  = (PRE,API),
;          GROUP = TIM,
;          DESC  = "(OS) DosSetDateTime Pre-Invocation",
;          <LOG_BX>,
;          <LOG_SI>,
;          FMT   = "DateTime structure at <FMT_BX><FMT_SI>"

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall  w_SetDateTime, ORD_DOSSETDATETIME                        ;@SEC

if RAS
;***DT  postDOSSETDATETIME - DosSetDateTime post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSSETDATETIME>,
;          TP    = .postDOSSETDATETIME,
;          TYPE  = (POST,API),
;          GROUP = TIM,
;          DESC  = "(OS) DosSetDateTime Post-Invocation",
;          <LOG_RETVAL>,
;          FMT   = "Return code = <FMT_RETVAL>"

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry DOSSETDATETIME

;***    DOSGETDATETIME  Get the date and time
;
;       INVOKE  push    DWORD  address of date/time
;               call    DOSGETDATETIME
;
;       RETURN  (ax) = return code
;                      0 - success
;
SysEntry DOSGETDATETIME, ORD_DOSGETDATETIME, 2

        ld_di                           ; (bx:di) = address of date/time
        ld_bx

if RAS
;***DT  preDOSGETDATETIME - DosGetDateTime pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSGETDATETIME>,
;          TP    = .preDOSGETDATETIME,
;          TYPE  = (PRE,API),
;          GROUP = TIM,
;          DESC  = "(OS) DosGetDateTime Pre-Invocation",
;          <LOG_BX>,
;          <LOG_DI>,
;          FMT   = "DateTime structure at <FMT_BX><FMT_DI>"

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall  w_GetDateTime, ORD_DOSGETDATETIME   ; call the worker    ;@SEC

if RAS
;***DT  postDOSGETDATETIME - DosGetDateTime post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSGETDATETIME>,
;          TP    = .postDOSGETDATETIME,
;          TYPE  = (POST,API),
;          GROUP = TIM,
;          DESC  = "(OS) DosGetDateTime Post-Invocation",
;          <LOG_RETVAL>,
;          FMT   = "Return code = <FMT_RETVAL>"

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry DOSGETDATETIME


;***    DOSSETPRTY - Set Priority
;
;       INVOKE  push    scope:word
;               push    class:word
;               push    delta:word
;               push    id:word
;               call    DOSSETPRTY:far
;
;       RETURN  (ax) = return code
;
SysEntry DOSSETPRTY, ORD_DOSSETPRTY, 4, GDT_DOSSETPRTY
        ld_ax                           ; ax = id
        ld_bl                           ; bl = delta
        ld_bh                           ; bh = class
        ld_dx                           ; dx = scope

if RAS
;***DT  preDOSSETPRTY - DosSetPrty pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSSETPRTY>,
;          TP    = .preDOSSETPRTY,
;          TYPE  = (PRE,API),
;          GROUP = TK,
;          DESC  = "(OS) DosSetPrty Pre-Invocation",
;          <LOG_DX>,
;          <LOG_BX>,
;          <LOG_AX>,
;          FMT   = "Scope = <FMT_DX>  Priority Class, Delta = <FMT_BX>",
;          FMT   = "ID = <FMT_AX>"

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall  w_SetPrty, ORD_DOSSETPRTY   ; see SchedAPI.asm           ;@SEC

if RAS
;***DT  postDOSSETPRTY - DosSetPrty post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSSETPRTY>,
;          TP    = .postDOSSETPRTY,
;          TYPE  = (POST,API),
;          GROUP = TK,
;          DESC  = "(OS) DosSetPrty Post-Invocation",
;          <LOG_RETVAL>,
;          FMT   = "Return code = <FMT_RETVAL>"

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry        DOSSETPRTY


;***    DOSGETPRTY - Get Priority
;
;       INVOKE  push    scope:word
;               push    @priority:word
;               push    id:word
;               call    DOSGETPRTY:far
;
;       RETURN  (ax) = return code
;               (bx) = priority
;
SysEntry DOSGETPRTY, ORD_DOSGETPRTY, 4
        ld_ax                           ; ax = id
        skip_ptr                        ; ptr = @priority
        ld_dx                           ; dx = scope

if RAS
;***DT  preDOSGETPRTY - DosGetPrty pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSGETPRTY>,
;          TP    = .preDOSGETPRTY,
;          TYPE  = (PRE,API),
;          GROUP = TK,
;          DESC  = "(OS) DosGetPrty Pre-Invocation",
;          <LOG_AX>,
;          <LOG_DX>,
;          FMT   = "ID = <FMT_AX>  Scope = <FMT_DX>"

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall  w_GetPrty, ORD_DOSGETPRTY              ; see SchedAPI.asm  @SEC
        skip_word                       ; skip over id
        st_bx                           ; bx = priority

if RAS
;***DT  postDOSGETPRTY - DosGetPrty post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSGETPRTY>,
;          TP    = .postDOSGETPRTY,
;          TYPE  = (POST,API),
;          GROUP = TK,
;          DESC  = "(OS) DosGetPrty Post-Invocation",
;          <LOG_BX>,
;          <LOG_RETVAL>,
;          FMT   = "Priority = <FMT_BX>  Return code = <FMT_RETVAL>"

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry        DOSGETPRTY


;***    DOSSETFGND - Identify the Foreground Process
;
;       INVOKE  push    scope:word
;               push    id:word
;               call    DOSSETFGND:far
;
;       RETURN  (ax) = return code
;
;       NOTE    This is an undocumented system call intended only
;               for the session manager's use to establish which
;               process the user is interacting with. The scheduler
;               will boost the priority of this process so that the
;               user thinks the background process(es) are not degrading
;               the system's performance.
;
SysEntry DOSSETFGND, ORD_DOSSETFGND, 2
        ld_ax                           ; ax = id (PID or SGID)
        ld_dx                           ; dx = scope
        farcall  w_SetFgnd, ORD_DOSSETFGND              ; see SchedAPI.asm  @SEC
EndEntry        DOSSETFGND


;***    DOSSETFGNDONLY - Identify a Foreground Only Process
;
;       INVOKE  push    pid:word
;               call    DOSSETFGNDONLY:far
;
;       RETURN  (ax) = return code
;
;       NOTE    This is an undocumented system call which is intended
;               for the loader's use to establish that a process is running
;               in the 3.x box. Since the loader is in the kernel, this
;               call is provided soly for the purpose of testing of the
;               foreground only function.
;
;;SysEntry DOSSETFGNDONLY, ORD_DOSSETFGNDONLY, 1
;;        enterfscrit                     ; Entering kernel
;;        ld_ax                           ; ax = pid
;;        nearcall w_SetFgndOnly          ; see SchedAPI.asm
;;        exitfscrit                      ; Exiting Kernel
;;EndEntry        DOSSETFGNDONLY



BREAK   <DosBeep - Generate Sound From Speaker>

;/********************** START OF SPECIFICATIONS **********************/
;/*                                                                   */
;/* SUBROUTINE NAME: DosBeep                                          */
;/*                                                                   */
;/* DESCRIPTIVE NAME: Generate sound from speaker                     */
;/*                                                                   */
;/* FUNCTION:    To sound a tone from the speaker of a given          */
;/*                frequency and duration                             */
;/*                                                                   */
;/* NOTES:       DosBeep runs in protected mode under the caller's    */
;/*                thread, in User Mode, Ring 0.                      */
;/*                                                                   */
;/* ENTRY POINT: DosBeep                                              */
;/*    LINKAGE:  Call far                                             */
;/*                                                                   */
;/* INPUT:       The following variables are pushed onto the stack:   */
;/*                                                                   */
;/*                Frequency = WORD containing the frequency of the   */
;/*                            sound, in Hertz                        */
;/*                Duration  = WORD containing the length of the      */
;/*                            sound, in milliseconds                 */
;/*                                                                   */
;/* EXIT-NORMAL: AX = 0                                               */
;/*                                                                   */
;/* EXIT-ERROR:  AX = error code:                                     */
;/*                     ERROR_INVALID_FREQUENCY                       */
;/*                                                                   */
;/* EFFECTS:     All other registers are preserved                    */
;/*                                                                   */
;/* INTERNAL REFERENCES:                                              */
;/*    ROUTINES: None                                                 */
;/*                                                                   */
;/* EXTERNAL REFERENCES:                                              */
;/*    ROUTINES: SCI             - System call interpreter            */
;/*              W_Beep          - Worker routine                     */
;/*                                                                   */
;/*********************** END OF SPECIFICATIONS ***********************/

SysEntry DOSBEEP,ORD_DOSBEEP,2

        ld_cx                         ; CX = duration, in milliseconds
        ld_bx                         ; BX = frequency, in Hertz

if RAS
;***DT  preDOSBEEP - DosBeep pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSBEEP>,
;          TP    = .preDOSBEEP,
;          TYPE  = (PRE,API),
;          GROUP = IO,
;          DESC  = "(OS) DosBeep Pre-Invocation",

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall  w_Beep, ORD_DOSBEEP                                      ;@SEC

if RAS
;***DT  postDOSBEEP - DosBeep post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSBEEP>,
;          TP    = .postDOSBEEP,
;          TYPE  = (POST,API),
;          GROUP = IO,
;          DESC  = "(OS) DosBeep Post-Invocation",
;          <LOG_RETVAL>,
;          FMT   = "Return code = <FMT_RETVAL>"

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry DOSBEEP


;***    DosSGSwitch - Switch foreground screen group
;
;       INVOKE  push    word OldScrGroup         (1 word)
;               push    word NewScrGroup         (1 word)
;               push    word DebuggerSGID        (1 word)
;               push    word Reserved            (1 word)
;               call    DosSGSwitch
;
;       RETURN  (ax) = return code
;                       0 - success
;
SysEntry DOSSGSWITCH,ORD_DOSSGSWITCH,4

        skip_word                       ; reserved
        ld_dx                           ; Debugger SGID or ZERO
        ld_bx                           ; new SGID
        ld_ax                           ; old SGID
        farcall w_DosSGSwitch, ORD_DOSSGSWITCH                            ;@SEC

EndEntry DOSSGSWITCH


;***    DosSGSwitchMe - Put Process in Screen Group
;
;       INVOKE  push    word  ScrGroup        (1 word)
;               push    word  FGSwitch        (1 word)
;               call    DosSGSwitchMe
;
;       RETURN  (ax) = return code
;                       0 - success
;
;
SysEntry DOSSGSWITCHME,ORD_DOSSGSWITCHME,2

        ld_bx                           ; Option
        ld_ax                           ; SGID
        farcall w_DosSGSwitchMe, ORD_DOSSGSWITCHME                        ;@SEC

EndEntry DOSSGSWITCHME


;***    DosSGSwitchProc2 - Put Process in Screen Group
;
;       INVOKE  push    word  PID             (1 word)
;               push    word  SGID            (1 word)
;               push    word  ProcType        (1 word) CDB
;               call    DosSGSwitchProc2
;
;       RETURN  (ax) = return code
;                       0 - success
;
;

SysEntry DOSSGSWITCHPROC2,ORD_DOSSGSWITCHPROC2,3 ;

        ld_dx                           ; Process Type CDB
        ld_bx                           ; SGID
        ld_ax                           ; PID
        farcall w_DosSGSwitchProc2, ORD_DOSSGSWITCHPROC2                  ;@SEC

EndEntry DOSSGSWITCHPROC2

BREAK   <DosStruCheck - Determine Type of Static Tracing>

;********************* START OF SPECIFICATIONS *****************
;
; SUBROUTINE NAME:   DosStruCheck
;
; DESCRIPTIVE NAME:  System Trace Resident Update checking on
;                    tracing existence
;
; FUNCTION: An undocumented internal dynamic link call used by
;           the TRACE utility.
;
; NOTES:
;
; ENTRY POINT:  StruCheck
;    LINKAGE:   Dynamic link
;
; INPUT: None
;
;
; EXIT-NORMAL: AX  = 0 trace does not exist
;              AX  = 1 major code tracing enabled
;              AX  = 2 major/minor code tracing enabled
;
; EXIT-ERROR:  N/A
;
; EFFECTS:
;     Uses: AX, Flags
;
; INTERNAL REFERENCES:
;    ROUTINES:
;
;
; EXTERNAL REFERENCES:
;    ROUTINES:
;
;         w_strucheck          - worker routine under the
;                                dynamic link call entry point
;                                STRUCheck
;********************** END OF SPECIFICATIONS ******************

SysEntry DOSSTRUCHECK,ORD_STRUCHECK,0   ; the start of the DL entry

        enterfscrit                     ; do not reenter this from same process
        farcall  w_strucheck, ORD_STRUCHECK    ; call the worker routine  @SEC
        exitfscrit                      ; exit

EndEntry DOSSTRUCHECK                   ; the end of the DL entry

BREAK   <DosStruResUpdate - Update Major/Minor Code arrays>

;********************* START OF SPECIFICATIONS *****************
;
; SUBROUTINE NAME:   DosStruResUpdate
;
; DESCRIPTIVE NAME:  System Trace Resident Update to update
;                    the major event code array and the
;                    minor event code table
;
; FUNCTION: An undocumented internal dynamic link call used by
;           TRACE utility for updating the MEC array and
;           the minor code array.
;           The  first invocation of this with a request to
;           trace by minor code will result in an 8K minor
;           event code table being allocated in fixed high mem.
;
; NOTES:
;
; ENTRY POINT:  StruResUpdate
;    LINKAGE:   Dynamic link
;
; INPUT: (PARAMETERS)
;
;   PUSH@ other data - address of the Major code array
;   PUSH@ other data - address of the Minor code array
;   PUSH  WORD  request - Type of Tracing
;                      0 = Major Code,  1 = Major/Minor Code
;   PUSH  WORD  flag - on_off_flag indicating "ON/OFF" parm
;                      1 = ON; 0 = OFF
;
; EXIT-NORMAL: AX = 0 (normal dynamic link exit)
;
; EXIT-ERROR:  AX = ERROR_NO_MC_TRACE (No minor code trace)
;              AX = ERROR_MC_TRACE (Bad Major/Minor code table)
;
; EFFECTS:
;     Uses: AX, SP, Flags
;
; INTERNAL REFERENCES:
;
;    ROUTINES:
;
; EXTERNAL REFERENCES:
;
;    ROUTINES:
;
;         w_struresupdate      - worker routine
;********************** END OF SPECIFICATIONS ******************


SysEntry  DOSSTRURESUPDATE,ORD_STRURESUPDATE,6

        enterfscrit                     ; do not reenter this from same process
        ld_ax                           ; ax = on_off_flag
        ld_cx                           ; cx = major/minor flag
        rplstampptr                     ; RPL stamp buffer pointer
        ld_di                           ; dx:di = address of minor code
        ld_dx
        rplstampptr                     ; RPL stamp buffer pointer
        ld_si                           ; bx:si = address of mec array
        ld_bx
        farcall  w_struresupdate, ORD_STRURESUPDATE  ; call worker routine   @SEC
        exitfscrit                      ; exit

EndEntry  DOSSTRURESUPDATE              ; end of DL entry


BREAK   <DosGetSTDA - Copy STDA To User's Buffer>
;********************* START OF SPECIFICATIONS *********************
;
; SUBROUTINE NAME: DosGetSTDA
;
; DESCRIPTIVE NAME: Copy STDA to user's buffer
;
; FUNCTION:    To copy the System Trace Data Area segment to
;              caller's buffer.
;
; NOTES:       DosGetSTDA runs in protected mode under the caller's
;              thread, in User Mode, Ring 0.
;
;              Tracing is temporarily suspended until buffer is
;              copied to user area.
;
; ENTRY POINT: DosGetSTDA
;    LINKAGE:  Call far
;
; INPUT:       The following variables are pushed onto the stack:
;
;                buffer    = DWORD pointing to the user's buffer
;                length    = WORD containing the size of the
;                            user's buffer
;
; EXIT-NORMAL: AX = 0
;
; EXIT-ERROR:  AX = error code:
;                     error_system_trace
;
; EFFECTS:
;     Uses:  AX, SP, Flags
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES:
;              w_GetSTDA       - Worker routine
;********************** END OF SPECIFICATIONS **********************


SysEntry DOSGETSTDA,ORD_DOSGETSTDA,3

        ld_cx                         ; CX = size of buffer
        rplstampptr                   ; RPL stamp buffer pointer
        ld_di                         ; bx:di -> User buffer
        ld_bx
        farcall w_GetSTDA, ORD_DOSGETSTDA                                 ;@SEC

EndEntry DOSGETSTDA


BREAK   <DosSetTraceInfo - Set System Trace Options>
;********************* START OF SPECIFICATIONS *********************
;
; SUBROUTINE NAME: DosSetTraceInfo
;
; DESCRIPTIVE NAME: Set System Trace Information/Options
;
; FUNCTION:    To set the desired options for system tracing
;
; NOTES:       DosSetTraceInfo runs in protected mode under the
;              caller's  thread, in User Mode, Ring 0.
;
;              Tracing is temporarily suspended until all request
;              are complete.
;
; ENTRY POINT: DosSetTraceInfo
;    LINKAGE:  Call far
;
; INPUT:       The following variables are pushed onto the stack:
;
;                push  word  Request Code
;
;                      0 - Suspend Trace logging
;                      1 - Resume Trace logging
;                      2 - Clear system trace buffer
;                      3 - Trace until error count
;                      4 - Trace Off until error
;                      5 - Increment error count
;                      6 - Trace ON Specific PID
;                      7 - Trace ON all PIDs
;                      8 - Trace OFF Specific PID
;                      9 - Trace OFF all PIDs
;
;                push  word  MaxErrorCount
;                push  word  Pid
;
;
; EXIT-NORMAL: AX = 0
;
; EXIT-ERROR:  AX = error code:
;                     error_pid_non_existent
;                     error_trc_count_active
;                     error_trc_count_inactive
;                     error_trc_count_reached
;                     error_trc_suspended_by_count
;                     error_trc_count_zero
;
; EFFECTS:
;     Uses: AX, SP, Flags
;
; INTERNAL REFERENCES:
;    ROUTINES: None
;
; EXTERNAL REFERENCES:
;    ROUTINES:
;              w_SetTraceInfo  - Worker routine
;********************** END OF SPECIFICATIONS **********************


SysEntry DOSSETTRACEINFO,ORD_DOSSETTRACEINFO,3

        enterfscrit                   ; do not reenter this from same process
        ld_cx                         ; PID to enable/disable
        ld_dx                         ; Max Error Count
        ld_bx                         ; Request Code

if RAS
;***DT  preDOSSETTRACEINFO - DosSetTraceInfo pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSSETTRACEINFO>,
;          TP    = .preDOSSETTRACEINFO,
;          TYPE  = (PRE,API),
;          GROUP = TK,
;          DESC  = "(OS) DosSetTraceInfo Pre-Invocation",
;          <LOG_BX>,
;          <LOG_CX>,
;          <LOG_DX>,
;          FMT   = "Request Code = <FMT_BX>  PID = <FMT_CX>",
;          FMT   = "Count = <FMT_DX>"

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall w_SetTraceInfo, ORD_DOSSETTRACEINFO                       ;@SEC
        exitfscrit                    ; exit

if RAS
;***DT  postDOSSETTRACEINFO - DosSetTraceInfo post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSSETTRACEINFO>,
;          TP    = .postDOSSETTRACEINFO,
;          TYPE  = (POST,API),
;          GROUP = TK,
;          DESC  = "(OS) DosSetTraceInfo Post-Invocation",
;          <LOG_RETVAL>,
;          FMT   = "Return code = <FMT_RETVAL>"

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry DOSSETTRACEINFO


BREAK   <DosLogEntry - Log Information into the log buffer >

;***************** START OF SPECIFICATIONS ******************************
;
; SUBROUTINE NAME: DosLogEntry
;
; DESCRIPTIVE NAME: Subsystem API to place data in OS/2 log buffer
;
; FUNCTION: This routine is called by subsystems to place data
;           in the kernel error log circular buffer
;
; NOTE:     The subsystem must first check the LF_LOGENABLE bit
;           in the GlobalInfoSeg before calling this routine.
;
; ENTRY POINT: DosLogEntry
;    LINKAGE:  CALL FAR
;
; INPUT: Caller pushes parameters on stack
;
;        push  WORD  Function
;              0  -  Reserved
;              1  -  Log Data to buffer
;
;        push@ other data - Address of data packets to be place in buffer
;
; EXIT-NORMAL:  AX = 0
;
; EXIT-ERROR:   AX = error code
;                    ERROR_LF_INVALID_FUNCTION
;                    ERROR_LF_SUSPENDED
;                    ERROR_LF_NOT_AVAIL
;
; EFFECTS:
;    Uses:  AX, SP, Flags
;
; EXTERNAL REFERENCES:
;    ROUTINES: w_LogEntry - log data to buffer
;*************** END OF SPECIFICATIONS ********************************

SysEntry DOSLOGENTRY,ORD_DOSLOGENTRY,3

        rplstampptr                   ; RPL stamp buffer pointer
        ld_si                         ; bx:si -> User data to log
        ld_bx
        ld_di                         ; di = Function Code
        farcall w_LogEntry, ORD_DOSLOGENTRY            ; Log data         ;@SEC

EndEntry DOSLOGENTRY

BREAK  <DosGetLogBuffer - Copy Log Buffer to Daemon>

;*************** START OF SPECIFICATIONS ******************************
;
; SUBROUTINE NAME: DosGetLogBuffer
;
; DESCRIPTIVE NAME: Copy Log Buffer
;
; FUNCTION: Copies OS/2 Log Buffer to caller specified area
;
; NOTE:     This API can only be used by the Error Log Daemon.
;
; ENTRY POINT: DosGetLogBuffer
;    LINKAGE:  CALL FAR
;
; INPUT: Caller pushes on stack
;
;        push  WORD  Function
;              0  -  Reserved
;              1  -  Copy error log buffer
;
;        push  WORD  Length of caller's buffer   (0=64K)
;
;        push@ OTHER area - Address of where to place copy of buffer
;
; EXIT-NORMAL:  AX = 0
;
; EXIT-ERROR:   AX = error code
;                    ERROR_LF_INVALID_FUNCTION
;                    ERROR_LF_BUFFER_TOO_SMALL
;                    ERROR_LF_BUFFER_CORRUPTED
;                    ERROR_LF_NOT_AVAIL
;                    ERROR_LF_INVALID_DAEMON
;
; EFFECTS:
;    Uses:  AX, SP, Flags
;
; EXTERNAL REFERENCES:
;    ROUTINES: w_GetLogBuffer - Copy error log buffer
;*************** END OF SPECIFICATIONS ********************************

SysEntry DOSGETLOGBUFFER,ORD_DOSGETLOGBUFFER,4

;
; Taken out for DCR 1152 - now just a stub
;
;        enterfscrit                   ; do not reenter this from same process
;        rplstampptr                   ; RPL stamp buffer pointer
;        ld_di                         ; bx:di -> User buffer
;        ld_bx
;        ld_cx                         ; Length of buffer
;        ld_si                         ; Function Code
;        farcall w_GetLogBuffer, ORD_DOSGETLOGBUFFER ; Copy the buffer  @SEC
;        exitfscrit                    ; exit

EndEntry DOSGETLOGBUFFER


BREAK  <DosLogMode - Manipulate Status of error log facility>

;*************** START OF SPECIFICATIONS ******************************
;
; SUBROUTINE NAME: DosLogMode
;
; DESCRIPTIVE NAME: Control Error Log Facility
;
; FUNCTION: This API performs the following operations:
;
;             -  Initialize Kernel Log Component: Used by the error log
;                daemon and system initialization to activate logging.
;
;             -  Terminate Kernel Log Component: Used by the error log
;                daemon  and System Initialization to terminate the
;                Kernel Log Facility.
;
;             -  Wait for Error Log Daemon to initialize.
;
;             -  Signal Error Log Daemon initialized.
;
;             -  Control Error Log Facility (Suspend/Resume)
;
; NOTE:     Currently only be used by Error Log Daemon, System Initialization,
;           and the SysLog Utility.
;
; ENTRY POINT: DosLogMode
;    LINKAGE:  CALL FAR
;
; INPUT: Caller pushes on stack
;
;        push  WORD  Function
;                0  -  Initialize Kernel Log Component (SysInit)
;                1  -  Initialize Kernel Log Component (Log Daemon)
;                2  -  Synchronize Logging Component   (SysInit or Daemon)
;                3  -  Terminate Kernel Log Component  (SysInit or Daemon)
;                4  -  Control Error Log Facility      (SysLog Utility)
;
;        push  WORD  Log Type
;
;              SysInit Initialize        (Function 0)
;                  0 - LOG=OFF
;                  1 - LOG=ON
;
;              Log Daemon Initialize     (Function 1)
;                  1  -  Allocate 1K buffer
;                        .
;                        .
;                        .
;                        .
;                 64  -  Allocate 64K buffer
;
;              Synchronize Log Component (Function 2)
;                  0  -  Wait until daemon initialized (SysInit)
;                  1  -  Daemon initialized            (Log Daemon)
;
;              Terminate Log Component   (Function 3)
;                  1  -  Error Log
;
;              Control Error Logging     (Function 4)
;                  0  -  Suspend Error Logging
;                  1  -  Resume Error Logging
;
;
; EXIT-NORMAL:  AX = 0
;
; EXIT-ERROR:   AX = error code
;                    ERROR_LF_INVALID_FUNCTION
;                    ERROR_LF_NOT_AVAIL   (No LOG= in config.sys)
;                    ERROR_LF_INVALID_DAEMON
;
; EFFECTS:
;    Uses:  AX, SP, Flags
;
; EXTERNAL REFERENCES:
;    ROUTINES: w_LogMode - Manipulate logging status
;*************** END OF SPECIFICATIONS ********************************

SysEntry DOSLOGMODE,ORD_DOSLOGMODE,2,GDT_DOSLOGMODE

;
; Taken out for DCR 1152 - now just a stub
;
;        ld_dx                         ; dx = Log Type
;        ld_bx                         ; bx = Function Code
;        farcall w_LogMode, ORD_DOSLOGMODE       ; Manipulate logging mode  @SEC

EndEntry DOSLOGMODE


BREAK  <DosSetCp - Dos Set Code Page>

;/********************************************************/
;/*                                                      */
;/* SUBROUTINE NAME: DosSetCp                            */
;/*                                                      */
;/* DESCRIPTIVE NAME:    Dos Set Code Page               */
;/*                                                      */
;/* FUNCTION:   Setup dynamic call to DosSetCp worker    */
;/*             routine which does the following:        */
;/*             This routine will call w_SetCp           */
;/*             to set the current code page             */
;/*                                                      */
;/* NOTES:                                               */
;/*                                                      */
;/* ENTRY POINT:         DosSetCp                        */
;/*   LINKAGE:           CALL                            */
;/*                                                      */
;/* INPUT:     PUSH  WORD  CODEPAGE ;code page id        */
;/*            PUSH  WORD  RESERVED ;reserved, set to 0  */
;/*                                                      */
;/* EXIT-NORMAL:    ax =0                                */
;/*                 code page is set                     */
;/*                                                      */
;/* EXIT_ERROR:                                          */
;/*               ax = Error_invalid_code_page           */
;/*                                                      */
;/*               The valid code pages are the code      */
;/*               pages which were specified in the      */
;/*               CODEPAGE statement in the CONFIG.SYS   */
;/*               and the ROM code page identifier       */
;/*               which is 0.                            */
;/*                                                      */
;/* EFFECTS:      contents of ax are destroyed           */
;/*               all other registers are saved          */
;/*                                                      */
;/* INTERNAL REFERENCES:                                 */
;/*     ROUTINES:                                        */
;/*                                                      */
;/* EXTERNAL REFERENCES:   w_SetCp                       */
;/*     ROUTINES:          SCI - system call interpreter */
;/*                                                      */
;/********************************************************/

SysEntry DOSISETCP,ORD_DOSISETCP,2,GDT_DOSSETCP

        ld_cx                         ; CX = reserved must be 0
        ld_bx                         ; BX = codepage ID

if RAS
;***DT  preDOSISETCP - DosISetCP pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSISETCP>,
;          TP    = .preDOSISETCP,
;          TYPE  = (PRE,API),
;          GROUP = TK,
;          DESC  = "(OS) DosISetCP Pre-Invocation",
;          <LOG_BX>,
;          FMT   = "Codepage ID = <FMT_BX>"

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall w_SetCp, ORD_DOSISETCP                                    ;@SEC

if RAS
;***DT  postDOSISETCP - DosISetCP post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSISETCP>,
;          TP    = .postDOSISETCP,
;          TYPE  = (POST,API),
;          GROUP = TK,
;          DESC  = "(OS) DosISetCP Post-Invocation",
;          <LOG_RETVAL>,
;          FMT   = "Return code = <FMT_RETVAL>"

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry DOSISETCP


;/*********************************************************/
;/*                                                       */
;/* SUBROUTINE NAME:     DosGetCp                         */
;/*                                                       */
;/* DESCRIPTIVE NAME:    Dos Get Code Page                */
;/*                                                       */
;/* FUNCTION:   Setup dynamic call to DosGetCp worker     */
;/*             routine which does the following:         */
;/*             This routine will call w_GetCp to get     */
;/*             the current and prepared code page        */
;/*             for a process.                            */
;/*                                                       */
;/* NOTES:                                                */
;/*        An input list size of 2 bytes  returns only    */
;/*        the current process code page identifier.      */
;/*                                                       */
;/* ENTRY POINT:         DosGetCp                         */
;/*   LINKAGE:           CALL                             */
;/*                                                       */
;/* INPUT:                                                */
;/*    PUSH  WORD  Length      ;len of codepagelist(bytes)*/
;/*    PUSH@ OTHER CodePageList;return area for codepglist*/
;/*    PUSH@ WORD  DataLength  ;length of CodePageList    */
;/*                            ;returned                  */
;/*                                                       */
;/* EXIT-NORMAL:   ax will set to 0                       */
;/*                code pages are returned                */
;/*                to a buffer which is pointed           */
;/*                by CodePageList pointer.               */
;/*                                                       */
;/*            DataLength returned   code pg returned     */
;/*          ----------------------  ---------------------*/
;/*                    2             current cp returned  */
;/*                                                       */
;/*                    4 or more     current followed by  */
;/*                                  system prepared    */
;/*                                  code pages returned  */
;/*                                                       */
;/* EXIT_ERROR:                                           */
;/*               ax = Error_cplist_too_small             */
;/*                    Error_invalid_length               */
;/*                                                       */
;/*                      The error occurs when the        */
;/*                      list length is less than the     */
;/*                      bytes needed to return all       */
;/*                      the prepared system code         */
;/*                      pages then the returned list     */
;/*                      is truncated.                    */
;/*                                                       */
;/* EFFECTS:      contents of ax are destroyed            */
;/*               all other registers are saved           */
;/*                                                       */
;/* INTERNAL REFERENCES:                                  */
;/*     ROUTINES:                                         */
;/*                                                       */
;/* EXTERNAL REFERENCES: w_GetCp                          */
;/*     ROUTINES:        SCI                              */
;/*********************************************************/
SysEntry DOSGETCP,ORD_DOSGETCP,5

        skip_ptr
        ld_di
        ld_ds                       ; DS:DI = returhn area for codepglist
        ld_bx                       ; BX = length of codepagelist in bytes

if RAS

;***DT  preDOSGETCP - DosGetCP pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSGETCP>,
;          TP    = .preDOSGETCP,
;          TYPE  = (PRE,API),
;          GROUP = NLS,
;          DESC  = "(OS) DosGetCP Pre-Invocation",

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall w_GetCp2, ORD_DOSGETCP                                    ;@SEC
        st_cx                       ; save the length actullay returned

if RAS
;***DT  postDOSGETCP - DosGetCP post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSGETCP>,
;          TP    = .postDOSGETCP,
;          TYPE  = (POST,API),
;          GROUP = NLS,
;          DESC  = "(OS) DosGetCP Post-Invocation",

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry DOSGETCP

;***    DOSGGLOBALSEG - Convert a local segment to global
;
;       INVOKE  push@   asciiz name             (2 word)
;               push    word selector           (1 word)
;               push@   word selector           (2 word)
;               call    DOSGLOBALSEG
;
;       RETURN  (ax) = return code
;                       0 - success
;
SysEntry DOSGLOBALSEG,ORD_DOSGLOBALSEG,5,GDT_DOSGLOBALSEG

        enterfscrit
        skip_ptr                        ; skip return pointer
        ld_ax                           ; old local selector
        getusrbufz                      ; copy asciiz string to kernel buffer
        ld_dsdx_norpl                   ; name pointer
        farcall         w_GlobalSeg, ORD_DOSGLOBALSEG                     ;@SEC
        st_ax                           ; return selector
        exitfscrit

EndEntry DOSGLOBALSEG


;***    DOSCLIACCESS - Request CLI/STI Privilege
;
;       INVOKE  call    DOSCLIACCESS
;
;       RETURN  (ax) = return code
;                       0 - success
;
SysEntry DOSCLIACCESS, ORD_DOSCLIACCESS, 0

if RAS
;***DT  preDOSCLIACCESS - DosCliAccess pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSCLIACCESS>,
;          TP    = .preDOSCLIACCESS,
;          TYPE  = (PRE,API),
;          GROUP = TK,
;          DESC  = "(OS) DosCliAccess Pre-Invocation",

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall w_zeroax, ORD_DOSCLIACCESS                                ;@SEC

if RAS
;***DT  postDOSCLIACCESS - DosCliAccess post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSCLIACCESS>,
;          TP    = .postDOSCLIACCESS,
;          TYPE  = (POST,API),
;          GROUP = TK,
;          DESC  = "(OS) DosCliAccess Post-Invocation",
;          <LOG_RETVAL>,
;          FMT   = "Return code = <FMT_RETVAL>"

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry DOSCLIACCESS

;***    DOSPORTACCESS - Request Port Access
;
;       INVOKE  push    word  Reserved           (1 word)
;               push    word  TypeOfAccess       (1 word)
;               push    word  First_Port         (1 word)
;               push    word  Last_Port          (1 word)
;               call    DOSPORTACCESS
;
;       RETURN  (ax) = return code
;                       0 - success
;


SysEntry DOSPORTACCESS, ORD_DOSPORTACCESS, 4


        ld_dx                           ; Last_Port
        ld_cx                           ; First_Port
        ld_bx                           ; TypeOfAccess
        ld_ax                           ; Reserved

if RAS
;***DT  preDOSPORTACCESS - DosPortAccess pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSPORTACCESS>,
;          TP    = .preDOSPORTACCESS,
;          TYPE  = (PRE,API),
;          GROUP = TK,
;          DESC  = "(OS) DosPortAccess Pre-Invocation",
;          <LOG_DX>
;          <LOG_CX>,
;          FMT   = "Last Port = <FMT_DX>  First Port = <FMT_CX>"

        RASpretrace                     ; RAS pre-invocation trace
endif ;RAS

        farcall w_portacc, ORD_DOSPORTACCESS                              ;@SEC

if RAS
;***DT  postDOSPORTACCESS - DosPortAccess post-invocation trace point
;
;    TRACE MINOR = <RAS_POST_DOSPORTACCESS>,
;          TP    = .postDOSPORTACCESS,
;          TYPE  = (POST,API),
;          GROUP = TK,
;          DESC  = "(OS) DosPortAccess Post-Invocation",
;          <LOG_RETVAL>,
;          FMT   = "Return code = <FMT_RETVAL>"

        RASposttrace                    ; RAS post-invocation trace
endif ;RAS

EndEntry DOSPORTACCESS


Procedure w_portacc,hybrid
;
; This procedure is for the previous call DosPortAccess
; This is stub code for driver4 and will be removed when
; this function is actually coded.
;

        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

ACCESS_BIT              equ     1
CONTIG_RANGE            equ     0
MAX_PORT_NUM            equ     400h

        cmp     ax,0                    ; is reserved word 0
        jne     portacc1                ; no, exit with error

        test    bx, NOT ACCESS_BIT      ; is access type valid?
        jnz     portacc1                ; no, exit with error

;        cmp     cx, MAX_PORT_NUM        ; is first port within range? P726444
;        ja      portacc1                ; no, exit with error         P726444

;        cmp     dx, MAX_PORT_NUM        ; is last port in range?      P726444
;        ja      portacc1                ; no, exit with error         P726444

        cmp     cx,dx                   ; last port after first?
                                        ; or equal?
        jbe     portacc2                ; exit with no error
portacc1:
        mov     ax, ERROR_INVALID_PARAMETER             ; load error code
        stc
        jmp     short portacc3
portacc2:
        xor     ax, ax
        clc
portacc3:
        ret

EndProc w_portacc


Procedure w_zeroax,hybrid
;
; This procedure is for the previous two calls DosPortAccess and
; DosCLIAccess.  This is stub code for driver3 and will be removed when
; this function is actually coded.
;
        xor     ax,ax
        ret
EndProc w_zeroax

BREAK   <DosSystrace - Add event to trace buffer>

;/************************** START OF SPECIFICATIONS *****************
;/*
;/*     SUBROUTINE NAME:   DosSystrace
;/*
;/*     DESCRIPTIVE NAME:  Dynamic link call for System Extensions
;/*                        and non-kernel base callers to place
;/*                        events in System Trace Circular Buffer
;/*
;/*
;/*     FUNCTION: Set up dynamic link entry & exit for System Trace,
;/*               which does the following:
;/*               If selected major event code is enabled for
;/*               tracing, then record data to the Buffer.
;/*
;/*     NOTES:
;/*
;/*     ENTRY POINT:  DosSystrace
;/*        LINKAGE:   Call FAR
;/*
;/*     INPUT: Caller pushes onto stack:
;/*
;/*         WORD  Major code = the major trace event code (0-255) -
;/*                            the upper byte will be ignored
;/*         WORD  Length     = the length of the variable length
;/*                            area to be recorded (0-512) - longer
;/*                            data will be truncated to 512 bytes
;/*         WORD  Minor code = The minor trace event code (0-255)
;/*        @OTHER Data       = A pointer to the caller specific data
;/*                            to be included in the trace record
;/*
;/*
;/*     EXIT-NORMAL: AX = Zero (Successful Trace)
;/*                  System Trace Data Area Modified
;/*
;/*     EXIT-ERROR:  AX = ERROR_SYSTEM_TRACE
;/*                  Data not traced - possible reasons are:
;/*                   - Event is disabled
;/*                   - STDA was not allocated
;/*                   - STRP busy processing another trace record
;/*                     (an internal System Trace record is generated
;/*                     to indicate this situation)
;/*
;/*     EFFECTS:
;/*         Uses:  AX, Flags
;/*
;/*     INTERNAL REFERENCES:
;/*        ROUTINES:
;/*
;/*     EXTERNAL REFERENCES:
;/*        ROUTINES: w_systrace - worker routine for dynamic link
;/*                               System Trace to add a trace record
;/*************************** END OF SPECIFICATIONS ******************


CpuMode 386
ReferFlat _cInDos,byte,ifundef

SysEntryBegin DOSSYSTRACE,ORD_DOSSYSTRACE,5,,,0,,,,noprepost

ArgVar UserBP, WORD
ArgVar UserCSIP, <size FarPtr32>
ArgVar Data_pointer,DWORD                        ; Pointer to variable data
ArgVar Minor_code,WORD                           ; Minor Code
ArgVar Data_len,WORD                             ; Variable data length
ArgVar Major_code,WORD                           ; Major Code on stack



   EnterProc

if RAS

   push bp
   push bx                                        ; Save the registers
   push cx
   push dx
   push si
   push di
   push ds
   push es
   pushf                                    ;Save caller FLAG enviornment

   DosContext ds
   mov  di,1                                ; Assume no trace
   cmp  ras_stda_addr,0                     ; Is tracing available?
   je   tr0010                              ; NO, return to caller

   cld                                    ;Reset direction flag
   xor  di,di                             ;clear error flag
   mov  bx,Data_len                       ;variable data length
   .if  <bx ne 0>                         ;User is passing data
     mov  ax,word ptr Data_pointer +2     ;segment of variable data
     StampRPL  ax,di
     mov  word ptr Data_pointer + 2,ax    ;Stamp RPL of user segment
     xor  di,di                           ;No error
     LOADSL cx,ax                         ;Get segment limit
     .if <nz>                             ;ERROR
       inc  di                            ;ERROR occurred
     .else                                ;
       mov  bx,word ptr Data_pointer      ;offset of variable data
       .if  <cx b bx>                     ;already past limit
         inc  di                          ;ERROR occurred
       .else                              ;
         sub  cx,bx                       ;cx = limit bx = offset
         inc  cx                          ;limit is zero based
         mov  bx,Data_len                 ;variable data length
         .if  <bx a cx>                   ;Gone beyond limit
           inc  di                        ;ERROR occurred
         .endif                           ;End gone beyond limit
       .endif                             ;End already past limit
     .endif                               ;End error LoadSL
   .endif                                 ;End user passing data

tr0010:

   .if <di ne 0>                            ;No errors found
   .else  near
     mov  ax,Major_code                     ;major code
     mov  bx,Data_len                       ;variable data length
     mov  dx,Minor_code                     ;minor code into dx
     mov  si,word ptr Data_pointer          ;offset of variable data
     mov  ds,word ptr Data_pointer + 2      ;segment of variable data

     FlatContext es
     mov   byte ptr es:[_cInDos],1

     CALLFAR w_systrace                     ;call worker routine
     .if <nc>                               ;Is there no error
       mov  ax,0                            ;Indicate no error
     .endif                                 ;

     FlatContext es
     mov   byte ptr es:[_cInDos],0

     FlatContext <ds>,dx
     ASSUME  SS:NOTHING
     mov     bp,ss:[TKOPTDA].CurrTCB        ;(SS:BP) = current TCB pointer
     mov     ebx,[_flGlobalActions]         ; Any Global force flags,
     or      ebx,ss:[TKOPTDA].ptda_ForcedActions; Process force flags, or
     or      ebx,[bp].TCBForcedActions      ; TCB force flags?
     CpuMode reset

     .if nz near                                ;cause a reschedule

        popf                                 ;Restore caller FLAG enviornment
        pop es
        pop ds
        pop di                               ; Restore the registers
        pop si
        pop dx
        pop cx
        pop bx
        pop bp
        pop bp

        KMEnterKmodeCallGate <?argwords*2>,noinline,PASCAL
        KMExitKmodeCallGate  <?argwords*2>,noinline,PASCAL
     .endif

   .endif                                   ; End no errors found

   popf                             ;Restore caller FLAG enviornment
   pop es
   pop ds
   pop di                               ;Restore the registers
   pop si
   pop dx
   pop cx
   pop bx
   pop bp

else   ;RAS
     mov  ax,ERROR_SYSTEM_TRACE
endif  ;RAS

   LeaveProc

   RETD   <?argbytes>

EndEntry DOSSYSTRACE,NoGen           ;set up ax and clear stack and return

CpuMode reset



;***    DOSENTERCRITSEC - Enter a Critical Section
;
;       INVOKE  call    DOSENTERCRITSEC:far
;
;       RETURN  nothing
;
;       NOTES   This code has been optimized for performance, and has
;               more than one exit.

        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

SysEntryBegin DOSENTERCRITSEC,ORD_DOSENTERCRITSEC,0,,,0,,,,noprepost
    .386p
        push    bp
        pushf                           ;save user's registers
        cld
        push    ebx
        push    ds
        push    es                      ;** Save es

if RAS
;***DT  preDOSENTERCRITSEC - DosEnterCritSec pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSENTERCRITSEC>,
;          TP    = .preDOSENTERCRITSEC,
;          TYPE  = (PRE,API),
;          GROUP = TK,
;          DESC  = "(OS) DosEnterCritSec Pre-Invocation"
endif ;RAS

Entry preDOSENTERCRITSEC,,,nocheck
        call    w_EnterCritSec          ;enter critical section
                                        ;valid return code in AX now
        ASSUME  DS:DOSGROUP             ;w_EnterCritSec returns DS:DosGroup

if RAS
;***DT  post2DOSENTERCRITSEC - DosEnterCritSec post-invocation trace point
;
;    TRACE MINOR = <RAS_POST2_DOSENTERCRITSEC>,
;          TP    = .post2DOSENTERCRITSEC,
;          TYPE  = (POST,API),
;          GROUP = TK,
;          DESC  = "(OS) DosEnterCritSec Post-Invocation",
;          REGS  = (AX),
;          FMT   = "Return code = <FMT_WORD>"
endif ;RAS

Entry post2DOSENTERCRITSEC,,,nocheck
        FlatContext <ds>
        mov     bp,ss:[TKOPTDA].CurrTCB ;(SS:BP) = current TCB pointer
        mov     ebx,[_flGlobalActions]         ; Any Global force flags,
        or      ebx,ss:[TKOPTDA].ptda_ForcedActions; Process force flags, or
        or      ebx,[bp].TCBForcedActions      ; TCB force flags?
        .if     z                       ;then simply return to the user
            pop     es
            pop     ds                  ;restore registers
            pop     ebx
            popf
            pop     bp
            RETFD                       ;EXIT
        .endif

        pop     es
        pop     ds                      ;restore registers
        pop     ebx
        popf
        pop     bp
        KMEnterKmodeCallGate <?argwords*2>,noinline,PASCAL
        KMExitKmodeCallGate  <?argwords*2>,noinline,PASCAL
    CpuMode reset
EndEntry  DOSENTERCRITSEC,NoGen


;***    DOSEXITCRITSEC - Exit a Critical Section
;
;       INVOKE  call    DOSEXITCRITSEC:far
;
;       RETURN  nothing
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING

SysEntryBegin DOSEXITCRITSEC,ORD_DOSEXITCRITSEC,0,,,0,,,,noprepost

        KMEnterKmodeCallGate <?argwords*2>,,PASCAL

if RAS
;***DT  preDOSEXITCRITSEC - DosExitCritSec pre-invocation trace point
;
;    TRACE MINOR = <RAS_PRE_DOSEXITCRITSEC>,
;          TP    = .preDOSEXITCRITSEC,
;          TYPE  = (PRE,API),
;          GROUP = TK,
;          DESC  = "(OS) DosExitCritSec Pre-Invocation"
endif ;RAS

Entry preDOSEXITCRITSEC,,,nocheck

        call    w_ExitCritSec           ;Exit critical section

if RAS
;***DT  post2DOSEXITCRITSEC - DosExitCritSec post-invocation trace point
;
;    TRACE MINOR = <RAS_POST2_DOSEXITCRITSEC>,
;          TP    = .post2DOSEXITCRITSEC,
;          TYPE  = (POST,API),
;          GROUP = TK,
;          DESC  = "(OS) DosExitCritSec Post-Invocation",
;          REGS  = (AX),
;          FMT   = "Return code = <FMT_WORD>"
endif ;RAS

Entry post2DOSEXITCRITSEC,,,nocheck

        FlatContext <ds,es>,cx
        KMExitKmodeCallGate  <?argwords*2>,,PASCAL
EndEntry  DOSEXITCRITSEC,NoGen

HIGH3CODE  ENDS

        END
