;       SCCSID = @(#)setcp.asm  6.2 91/04/01
;       SCCSID = @(#)setcp.asm  6.2 91/04/01
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************
        page    ,132
        .286p

        TITLE   setcp

;               - DOSSETCP
;               - DOSSETPROCCP


;***
;       - implement the visible DOSSETCP API for user applications that
;         correctly interface with VIO and KBD.
;
;         Since we have the requirement that the VIO/KBD routine must occur to
;         ring 3 code, and that the DOSSETCP needs to call VIO/KBD from
;         ring 0, this implies that DOSSETCP needs to be exist as ring 3
;         code and, hence, why they appear in the DOSCALL1 dynlink library.
;
;
;
;       Modification History:
;
;       4/7/87          CWY     Add DOSSETCP to DOSCALL1
;
;       6/17/87         CWY     see ptm5575. If ax is not zero after
;                               DOSISETCP just exit instead of moving
;                               "472" to ax.
;
;       8/06/87         PGM     added DosSetProcCp which will just set
;                               the process code page
;
.xlist
        include basemaca.inc
;       include error.inc
        include error2.inc
        include infoseg.inc
        include struc.inc
        include dc1segs.inc                                     ; DCR 704
        .LFCOND                         ; Show false conditionals
        .SALL                           ; Supress macro expansion
.list



EXTRN   DOSISETCP:FAR                   ; @@
EXTRN   DOSCALLBACK:FAR
EXTRN   DOSGETINFOSEG:FAR
EXTRN   KBDSETCP:FAR                    ; settable address for KBDSETCP ;MDLL
EXTRN   VIOSETCP:FAR                    ; settable address for VIOSETCP ;MDLL


DATA    SEGMENT                                                 ; DCR 704
DATA    ENDS


CODE      SEGMENT                                               ; DCR 704
        assume  cs:code, ds:nothing, es:nothing, ss:nothing

;**     DOSSETCP - set the system codepage for the current process
;
;       DOSSETCP is used to set the codepage which was defined by user for the
;                current process user's. It calls KBDSETCP and VIOSETCP
;                if the codepage ID is prepared for the system.
;                It calls KBDSETCP first, if the call to KBDSETCP fails,
;                we still call VIOSETCP but also return an error.
;
;
;       ENTRY:              WORD    The desired Code Page ID
;                           WORD    reserved
;
;       EXIT:
;               If successful then
;                   AX = 0
;                   the CP is set in PTDA area
;               if failure then
;                   AX = error code
;                        AX = ERROR_INVALID_CODE_PAGE
;                        AX = ERROR_CP_SWITCH_INCOMPLETE
;       USES:   FLAGS
;

;***DT  preDOSSETCP - Pre-Invocation Dynamic Trace
;
;   TRACE MINOR = <RAS_DC1_PRE_DOSSETCP>,
;         TP    = .DOSSETCP,
;         TYPE  = (PRE,API),
;         GROUP = NLS,
;         DESC  = "(OS) DosSetCp Pre-Invocation",
;         MEM   = (RSS+SP+6,D,2),
;         FMT   = "Code Page Id= <FMT_C_WORD>"

;***DT  postDOSSETCP - Post-Invocation Dynamic Trace
;
;   TRACE MINOR = <RAS_DC1_POST_DOSSETCP>,
;         TP    = .postDOSSETCP,
;         TYPE  = (POST,API),
;         GROUP = NLS,
;         DESC  = "(OS) DosSetCp Post-Invocation",
;         REGS  = (AX),
;         FMT   = "Return Code= <FMT_WORD>"

procedure   DOSSETCP,FAR

ArgVar      reserved,WORD
ArgVar      cp_id,WORD
Localvar    GDTSel      WORD
Localvar    LDTSel      WORD

        EnterProc
        push    ss
        lea     ax,GDTSEL
        push    ax
        push    ss
        lea     ax,LDTSEL
        push    ax
        call    DOSGETINFOSEG
        mov     ax,LDTSel
        mov     es,ax

        .if     <es:LIS_ProcType b LIS_PT_PRESMGR>,NEAR
           push    ds
           mov     ax,data
           mov     ds,ax
           assume  ds:data

           push    dx                      ; save dx register
           xor     dx,dx                   ; clear dx

           push    cp_id                   ; the desired codepage id
           push    reserved                ; reserved field
           call    DOSISETCP               ; call the internal setcp routine

           .IF  <zero ax>                  ; if no error and
                push    ax                 ; reserved
                push    cp_id              ; codepage id
                push    ax                 ; kbdhandle
                mov     ax,cs
                and     al,03H
                .if <al eq 3>              ; are we at level three?
                   call KBDSETCP                                        ;MDLL
                .else
                   push cs                                              ;MDLL
                   push offset KBDSETCP                                 ;MDLL
                   call DOSCALLBACK
                .endif
                .IF  <nonzero ax>          ; if KBDSETCP error
                     mov  dx, ERROR_CP_SWITCH_INCOMPLETE
                .ENDIF

                push    0                  ; reserved
                push    cp_id              ; codepage id
                push    0                  ; viohandle

                mov     ax,cs
                and     al,03H
                .if <al eq 3>              ; are we at level three?
                   call VIOSETCP           ; yes                        ;MDLL
                .else
                   push cs                                              ;MDLL
                   push offset VIOSETCP                                 ;MDLL
                   call DOSCALLBACK
                .endif
                .IF  <nonzero ax>          ; if viosetcp failed
                     mov  ax, ERROR_CP_SWITCH_INCOMPLETE
                     stc                   ; vio setcp may clear carry bit
                .ENDIF
           .ENDIF
            pop     dx
            pop     ds
        .ELSE
                mov     ax,1               ; ERROR_INVALID_FUNCTION
        .ENDIF

        PUBLIC  postDOSSETCP
postDOSSETCP:                              ; RAS post-invocation trace

        LeaveProc
        ret     ?aframe
EndProc DOSSETCP

;**     DOSSETPROCCP - set the system codepage for the current process
;
;       DOSSETPROCCP is used to set the codepage which was defined by user for the
;                current process.
;
;       ENTRY:              WORD    The desired Code Page ID
;                           WORD    reserved
;
;       EXIT:
;               If successful then
;                   AX = 0
;                   the CP is set in PTDA area
;               if failure then
;                   AX = error code
;                        AX = ERROR_INVALID_CODE_PAGE
;       USES:   FLAGS
;

;***DT  preDOSSETPROCCP - DosSetProcCp Pre-Invocation Dynamic Trace
;
;   TRACE MINOR = <RAS_DC1_PRE_DOSSETPROCCP>,
;         TP    = .DOSSETPROCCP,
;         TYPE  = (PRE,API),
;         GROUP = NLS,
;         DESC  = "(OS) DosSetProcCp Pre-Invocation",
;         MEM   = (RSS+SP+6,D,2),
;         FMT   = "Code Page Id= <FMT_C_WORD>"

;***DT  postDOSSETPROCCP - Post-Invocation Dynamic Trace
;
;   TRACE MINOR = <RAS_DC1_POST_DOSSETPROCCP>,
;         TP    = .postDOSSETPROCCP,
;         TYPE  = (POST,API),
;         GROUP = NLS,
;         DESC  = "(OS) DosSetProcCp Post-Invocation",
;         REGS  = (AX),
;         FMT   = "Return Code= <FMT_WORD>"


procedure   DOSSETPROCCP,FAR

ArgVar      reserved,WORD
ArgVar      cp_id,WORD

        EnterProc

        push    cp_id                   ; the desired codepage id
        push    reserved                ; option field

        call    DOSISETCP               ; call the internal setcp routine

        PUBLIC  postDOSSETPROCCP
postDOSSETPROCCP:                       ; RAS post-invocation trace

        LeaveProc
        ret     ?aframe
EndProc DOSSETPROCCP


CODE   ENDS
END
