;       SCCSID = @(#)bksclose.asm	6.1 90/11/16
;	SCCSID = @(#)bksclose.asm	6.6 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	BKSCLOSE.ASM - Logical Handle Close

;******************************************************************************
;*******   C H A N G E	     H I S T O R Y   **********************************
;
;	86/12/05  TPL	Destroy KCB only if Focus is ON and Bond Handle is
;			non-zero.
;	87/02/12  TPL	Clear bond handle after successful DosClose.
;	87/07/06  TPL	Call DosEnterCritSec and DosExitCritSec to bracket
;			critical section.
;	87/07/09  TPL	Deregister cleanup routine when Open_Count becomes 0.
;@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 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 data segment
IDSEG	ENDS
;
;	System services routine name(s)
;
	EXTRN	DOSCLOSE:FAR		; Close device handle
	EXTRN	KBDFREEFOCUS:FAR	; Flush Keyboard Input Buffer
	EXTRN	DOSDEVIOCTL:FAR 	; Destroy KCB

;$$#I000
	EXTRN WINCONSOLECLOSEKBD:DWORD	; CDB2
	GDSEG SEGMENT BYTE PUBLIC 'FAR_DATA'                            ;@T52
	GDSEG ENDS
;$$#END

	EXTRN	DOSENTERCRITSEC:FAR	; Enter critical section
	EXTRN	DOSEXITCRITSEC:FAR	; Exit critical section
	EXTRN	DOSEXITLIST:FAR 	; Deregister cleanup routine

	EXTRN	OpenExit:FAR		; Internal cleanup routine

	EXTRN	Open_Count:WORD 	; Per process open count

	PUBLIC	HandleClose

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

;/*********************** START OF SPECIFICATIONS ***************************/
;/* SUBROUTINE NAME: HandleClose					    */
;/*									    */
;/* DESCRIPTIVE NAME: BKS function for KBDCLOSE 			    */
;/*									    */
;/* FUNCTION: Close a virtual keyboard handle opened by KBDOPEN.	    */
;/*									    */
;/* NOTES: If the handle being closed currently has the focus, a call is    */
;/*	   made to KBDFREEFOCUS to free this bond.			    */
;/*									    */
;/* ENTRY POINT: bksclose						    */
;/*	LINKAGE: NEAR CALL  (internal call from BKSMAIN)		    */
;/*									    */
;/* INPUT: push KBDHANDLE - keyboard handle (WORD)  -  [BP].KBD_handle	    */
;/*	   push callersCS - caller's return CS (WORD)                       */
;/*	   push callersIP - caller's return IP (WORD)                       */
;/*	   push func_code - KBDXXX function code (WORD) 		    */
;/*	   push KBDXXX_IP - KBDXXX return IP (WORD)			    */
;/*	   push callersDS - caller's DS save area (WORD)                    */
;/*	   push kbdroutCS - kbdrout return CS (WORD)			    */
;/*	   push kbdroutIP - kbdrout return IP (WORD)			    */
;/*	   push BKSMAINIP - BKSMAIN return IP (WORD)			    */
;/*									    */
;/*	   NOTE:  This routine is called by BKSMAIN.			    */
;/*		  On entry BKSMAIN will set up: 			    */
;/*		    DS = IDSEG selector 				    */
;/*		    BP = pointer to stack parameters			    */
;/*									    */
;/* EXIT-NORMAL: AX = NO_ERROR						    */
;/*									    */
;/* EXIT-ERROR: AX = error code from DOSCLOSE				    */
;/*		AX = error code from KBDFREEFOCUS			    */
;/*									    */
;/* EFFECTS: Calling PID's KCB will be destroyed.                           */
;/*	     Caller's AX is destroyed.                                      */
;/*									    */
;/* INTERNAL								    */
;/* REFERENCES: bond_handle - keyboard handle that currently has a bond     */
;/*   ROUTINES: None.							    */
;/*									    */
;/* EXTERNAL								    */
;/* REFERENCES: None.							    */
;/*   ROUTINES: DOSCLOSE     - close device handle			    */
;/*		KBDFREEFOCUS - release logical keyboard bond		    */
;/*									    */
;/*********************** END OF SPECIFICATIONS *****************************/
	PAGE



;HandleClose PSUEDO CODE
;
;************************************************************************
;*  On entry:  DS = IDSEG selector   AX = 0   BX = [bp].KBD_Handle	*
;************************************************************************
;
;.if <[BP].KBD_Handle eq DS:Bond_Handle>; If handle has a bond
;|  call KBDFREEFOCUS			; Release logical to physical bond
;.endif
;
;.if <NO_ERROR> and
;.if <[BP].KBD_Handle A DEFAULT>	; don't close default handle
;|  call DOSCLOSE			; free handle and flush KIB
;.endif
;
; ret
	PAGE



HandleClose PROC NEAR			; @@ Version 1.1 code - BEGIN
	ASSUME DS:IDSEG
;
;************************************************************************
;*  On entry:  DS = IDSEG   AX = 0   BX = [bp].KBD_Handle		*
;	       ES = GDSEG   DX = KBD_SG 				*
;************************************************************************
;

       .IF <dx a LastBaseSG>		; Winthorn screen group?
	 push	bx			; Free focus first
	 call	KBDFREEFOCUS		;
	 .IF <ax EQ ERROR_KBD_FOCUS_REQUIRED>
	   sub	ax,ax			; Already freed focus
	 .ENDIF 			;
	 or	ax,ax			;
	 .IF Z				; Free focus went successfully?
	   push   hConsole		; Close window console
	   push   [bp].KBD_Handle	;
	   call   ES:WINCONSOLECLOSEKBD ; CDB2
	 .ENDIF 			;
       .ELSE				;
	 test	Flag,FOCUS_ON		;
	.if nz	AND			; Focus ON and BX = Bond Handle?
	.if <bx EQ Bond_Handle> 	;
	  push	bx			; free focus before closing handle
	  call	KBDFREEFOCUS		;
	.endif				;
	 or	ax,ax			; No error encountered in KBDFREEFOCUS?
	.if z				;
	  call	DOSENTERCRITSEC 	;
	  or	bx,bx			;   handle is non-default (handle 0)
	 .if nz 			;
	   push Bond_Handle		;
	   mov	Bond_Handle,bx		;
	   push 0			; Setup:  Address of Dummy DATA
	   push 0			;	    parmlist
	   push ds			;	  Address of INPUT parmlist
	   push OFFSET Bond_Handle	;
	   push 5EH			;	  Function code (destroy KCB)
	   push KEYBOARD		;	  Category code
	   push bx			;	  Device handle
	   call DOSDEVIOCTL		; destroy KCB
	   pop	Bond_Handle		;
	   or	ax,ax			;
	  .if z 			; KCB destroyed successfully?
	    dec Open_Count		; update open count
	   .if z			;
	     push 2			; deregister 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			;
	  .endif			;
	  .if <bx EQ Bond_Handle>	; close bond handle?
	    mov  Bond_Handle,0		; clear bond handle
	  .endif			;
	   push  bx			; close specified keyboard handle
	   call  DOSCLOSE		;
	 .endif 			;
	  call	 DOSEXITCRITSEC 	;
	.endif				;
       .ENDIF				;
	ret				; near return to BKSMAIN

HandleClose ENDP			; @@ Version 1.1 code - END

CSEG	ENDS
	END
