;       SCCSID = @(#)bksopen.asm	6.1 90/11/16
;	SCCSID = @(#)bksopen.asm	1.9 90/03/13
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
	PAGE	60,132
	TITLE	BKSOPEN.ASM - Logical Keyboard Open

;******************************************************************************
;*******   C H A N G E	     H I S T O R Y   **********************************
;
;	87/07/09  TPL	Register cleanup routine for outstanding open.
;			Add KCB cleanup routine.
;	88/02/11  THG	Added call to DosGetCP after DosOpen
;@T52	90/01/15  TPL	DCR 704 work
;B711747 THG 03-05-90 Ensure that CS passed to DOSEXITLIST is for ring 3
;******************************************************************************

	.286p				; 286 Protect Mode instructions

	.xlist
	INCLUDE error.inc		; DOS error file
	INCLUDE error2.inc		; Extended error code file
	INCLUDE struc.inc		; Structured Macros
	INCLUDE bksxxx.inc		; Equates and structure template file
	INCLUDE bksextrn.inc		; External data declaration file
	.list

CSEG	SEGMENT BYTE PUBLIC 'CODE'
CSEG	ENDS

IDSEG	SEGMENT BYTE PUBLIC 'DATA'      ; Per process instance data segment
IDSEG	ENDS

GDSEG	SEGMENT BYTE PUBLIC 'FAR_DATA'  ; Global data segment shared    ;@T52
GDSEG	ENDS				;   among all session in the system
;
;	System services routine name(s)
;
	EXTRN	DOSOPEN:FAR		; Get device handle from file system
	EXTRN	DOSDEVIOCTL:FAR 	; Create KCB
	EXTRN	DOSEXITLIST:FAR 	; Register cleanup routine
	EXTRN	DOSGETCP:FAR		; Get process codepage		;THG
	EXTRN	DOSCLOSE:FAR		; Close handle			;THG

;$$#I000
	EXTRN WINCONSOLEOPENKBD:DWORD	;CDB2
;$$#END

	EXTRN	Open_Count:WORD 	; Per process open count

	PUBLIC	HandleOpen
	PUBLIC	OpenExit

CSEG	SEGMENT BYTE PUBLIC 'CODE'
	ASSUME	CS:CSEG,DS:NOTHING,ES:NOTHING
	PAGE

;********************START OF SPECIFICATIONS****************************
;
; SUBROUTINE NAME:	HandleOpen
;
; DESCRIPTIVE NAME:	Per Process Keyboard Open
;
; FUNCTION:	Allocate a Handle Control Block and call DosOpen to
;		get a handle to the Keyboard Device Driver.  DosFreeSeg
;		will be called if DosOpen failed.
;
; ENTRY POINT:		HandleOpen
;
;    LINKAGE:		Near Call
;
; INPUT PARAMETERS
;    SYMBOLIC NAME:	Handle
;
;    DESCRIPTION:	Address of Keyboard Handle
;
;    TYPE:		Selector-Offset (on stack) pointing to
;			a word
;
;    USAGE:		Keyboard Handle to be returned
;
; EXIT-NORMAL:		AX  =	0
;
; EXIT-ERROR:		AX  =	ERROR_KBD_NO_MORE_HANDLE
;				ERROR_KBD_UNABLE_TO_CREATE_KCB
;
; INTERNAL REFERENCES:	GDSEG	- Global Data Segment
;	   ROUTINES:	none
;
; EXTERNAL REFERENCES:	none
;	   ROUTINES	DosOpen - Get private handle to KBD D/D
;
;******************END OF SPECIFICATIONS********************************



;HanldeOpen PROC NEAR
;
; CALLFAR DOSOPEN			; Get private handle to KBD D/D
;.IF <Error>
;|  map DOS error to KBD error return code
;.ENDIF
; ret
	PAGE



HandleOpen PROC NEAR			; @@ Version 1.1 code - BEGIN
	ASSUME	ES:GDSEG
;
;************************************************************************
;   On entry:  DS = IDSEG   ES = GDSEG	 AX = 0   DX = KBD_SG		*
;************************************************************************
;

;$$#I001
	.IF <dx a LastBaseSG>		; Winthorn screen group?
	  push	hConsole		; Shield console handle ;@@DTF1
	  push	[bp].Handle_Sel 	; @ of handle to be returned
	  push	[bp].Handle_Off 	;
	  Call	ES:WINCONSOLEOPENKBD	; Open KBD thru Winthorn CDB2
	.ELSE near			;				;THG
;$$#END

	  push	es			; Setup:  Address of device name
	  push	OFFSET Dev_Name 	;
	  push	[bp].Handle_Sel 	;	  Address of device handle
	  push	[bp].Handle_Off 	;	    to be returned by DOS
	  push	es			;	  Address of action taken
	  push	OFFSET Action_Taken	;	    by DOS
	  push	ax			;	  file size = 0 (2 words)
	  push	ax			;
	  push	ax			;	  file attribute
	  push	01H			;	  open flag - fail if device
					;	    does not exists
	  push	0C2H			;	  open mode = ISSSRAAA
					;		      11000010
					;	  I   - Private handle
					;	  SSS - Deny None access
					;	  R   - Reserved must be 0
					;	  AAA - Read/Write access
	  push	ax			;	  double words of 0
	  push	ax			;
	  call	DOSOPEN 		;
	  or	ax,ax
	 .IF Z				; No error encountered?
	   push   ax			; Allocate local storage	;THG
	   mov	  bx,sp 		; SS:BX -> codepage ID		;THG
	   push   2			; Length of list		;THG
	   push   ss			; Address of return list	;THG
	   push   bx			;				;THG
	   push   es			; Length of returned list	;THG
	   push   OFFSET Action_Taken	;				;THG
	   call   DOSGETCP		; Get process codepage		;THG
	   les	  di,DWORD PTR [bp].Handle_Off; ES:DI -> Handle 	;THG
	   push   es:[di]		; Put handle on stack		;THG
	   mov	  bx,sp 		; SS:BX -> Handle & current cpID;THG
	   sub	  ax,ax 		; Ignore any DOSGETCP error	;THG
	   push ax			; Setup:  Address of Dummy DATA
	   push ax			;	    parmlist
	   push ss			;	  Address of INPUT parmlist
	   push bx			;
	   push 5DH			;	  Function code (create KCB)
	   push KEYBOARD		;	  Category code
	   push Dev_Handle		;	  Device handle
	   call DOSDEVIOCTL		; Create KCB
	   add	sp,4			; Deallocate local storage from ;THG
	   or	ax,ax			;
	  .IF Z 			; Encountered error?
	    inc Open_Count		; Update open count
	   .IF <Open_Count EQ 1>	; 1st open?
	     push Open_Count		; Register cleanup routine
	     push cs			;
	     pop  ax			;			       ;B711747
	     or   ax,3			;Ensure CS is for ring 3       ;B711747
	     push ax			;			       ;B711747
	     push OFFSET OpenExit	;
	     call DOSEXITLIST		;
	   .ENDIF			;
	  .ELSE 			;
	    push  es:[di]		; Close handle			;THG
	    call  DOSCLOSE		;				;THG
	    mov   ax,ERROR_KBD_CANNOT_CREATE_KCB
	  .ENDIF			;
	 .ELSEIF <ax EQ ERROR_TOO_MANY_OPEN_FILES> ; Map DOS error
	    mov   ax,ERROR_KBD_NO_MORE_HANDLE
	 .ENDIF 			;
;$$#I002
       .ENDIF				;
;$$#END
	ret

HandleOpen ENDP 			; @@ Version 1.1 code - END


OpenExit   PROC FAR
;	int	3
	push	ds			; Save DS
	mov	ax,IDSEG		;
	mov	ds,ax			;
	mov	Open_Count,-1		;
	sub	ax,ax			;
	push	ax			; Setup:  Address of Dummy DATA
	push	ax			;	    parmlist
	push	ds			;	  Address of INPUT parmlist
	push	OFFSET Open_Count	;
	push	5EH			;	  Function code (destroy KCB)
	push	KEYBOARD		;	  Category code
	push	Dev_Handle		;	  Device handle
	call	DOSDEVIOCTL		; destroy all KCBs
	pop	ds			; Restore DS
	push	3			; call next DOSEXITLIST routine
	push	cs			;
	pop	ax			;			       ;B711747
	or	ax,3			;Ensure CS is for ring 3       ;B711747
	push	ax			;			       ;B711747
	push	OFFSET OpenExit 	;
	call	DOSEXITLIST

OpenExit   ENDP

CSEG	ENDS
	END
