;       SCCSID = @(#)d_duphan.asm	6.1 91/02/15
;	SCCSID = @(#)d_duphan.asm	1.4 90/01/22
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
;***  d_duphan.asm - API stub routine DosDupHandle
;
;	Member of API library
;	Steve Salisbury & Bill Mershon
;	Copyright MicroSoft Corporation, 1986
;	18-Feb-1986
;
;	library routine for API simulator
;
;	Called from dos 2.x,3.x compatible dos 5.x applications
;
;	Special Information
;		none
;
;	Modification History
;
;	7-25-86 (billme):  add code to always translate INVALID_HANDLE
;	to INVALID_TARGET_HANDLE
;
;	8-28-86 (billme):  change code to be more discriminatory about
;	changing INVALID_HANDLE to INVALID_TARGET_HANDLE
;
;	06-Jan-87 (billme): Replace initial pushes and final pops
;	with calls to __api_begin and __api_end resp.  This will
;	reduce the size of FAPI and allow support for signals.
;
;	15-Jan-87 (billme): Change reference to __api_dev_table to
;	call to __api_devtab_ptr ... to reduce code size.
;
;
;	04-May-87 (robertc): Install hooks for DOSErrorClass Support.
;	All int 21h errors are passed through api_get_extended to get the
;	extended errorcode and to provide the class, action, and locus for
;	the dynamic error FIFO queue.
;
;	17-June-87 (stevee): fix to insure that all FAPI file handles are
;	less than MAX_HANDLES (p5553)
;


INCLUDE dos2equ.inc
INCLUDE basemaca.inc
INCLUDE error.inc
INCLUDE api.inc

	EXTRN	api_get_extended:far	;@@ added support for DOSErrorClass
	EXTRN	__api_devtab_ptr:near
	EXTRN	__api_begin:near
	EXTRN	__api_end:near


;***	DOSDUPHANDLE - stub to emulate DOSDUPHANDLE function call
;
;	simulates DOS 5.0 call from DOS 2.x,3.x environment
;
;	errorcode = unsigned far pascal
;	DosDupHandle (OldFileHandle,NewFileHandle)
;
;	ENTRY:
;		OldFileHandle - existing file handle
;		NewFileHandle - new file handle
;
;	RETURN:
;		AX = 0 if no error, else error code (see DOS 5 spec)
;
;	EXIT:
;		word at NewFileHandle contains duplicate file handle
;
;	USES:
;		AX
;
;	Pseudo Code:
;		save registers
;		use BP as pointer to stack parameters
;		load registers for int 21 call
;		if New == -1 then use function 45h
;		else use function 46h
;		restore registers
;		return
;
;	WARNING:
;		may return error code from Dos 2.x, 3.x (see dos manuals)
;
;	EFFECTS:
;		none
;

	title	DOSDUPHANDLE - stub to emulate DOSDUPHANDLE function call
;
;	EXTRN	DOSDUPHANDLE:FAR
;
;	PUSH	WORD OldFileHandle
;	PUSH	@ WORD NewFileHandle
;	CALL	DOSDUPHANDLE
;


_TEXT	segment byte public 'CODE'

	assume	CS:_TEXT,DS:NOTHING

	extrn __api_dev_table : word

	public	DOSDUPHANDLE

OldFileHandle	equ	[BP+10]
NewFileHandle	equ	[BP+6]

DOSDUPHANDLE	proc	far

	call	__api_begin	; init bp and save bp,ds,bx,cx,dx,si,di,es
				; required to save: bp,ds,es,bx,cx,si,di

	push	bp			; save bp for __api_end

	; NOTE: error on source handle will be caught by dos 3 ...
	; DOS 3 would also catch error on target handle, but with incorrect
	; error number - DOS 5 requires "invalid target handle"

	mov	bx,[OldFileHandle]	; BX <- handle for call to DUP
	mov	si,bx			; SI <- old handle
	cmp	si,MAX_HANDLES		; in range for real mode?
	jb	dup0			; ok, continue
	mov	ax,ERROR_INVALID_HANDLE ; error, old out of range
	jmp	short NormalExit	; quit

dup0:
	lds	bp,[NewFileHandle]
	mov	cx,DS:[bp]		; CX <- new file handle for ForceDUP
	cmp	cx,0FFFFh
	jne	ForceDup
;
;	Regular Duplicate Handle
;
	mov	ah,D2_DupFileHndl
	int	21h
	jc	ErrorExit

	mov	DS:[bp],ax		; return new file handle
	mov	di,ax			; DI <- new handle
	jmp	short	OkayExit
;
;	Force Duplicate Handle
;
ForceDup:
	cmp	cx,MAX_HANDLES		; if handle is too large
	mov	ax,ERROR_INVALID_TARGET_HANDLE
	jae	NormalExit		; then return error
	mov	ah,D2_ForceDupFileHndl
	int	21h
	jc	ErrorExit

	mov	DS:[bp],cx		; return new file handle
	mov	di,cx			; DI <- new handle
;
OkayExit:

	cmp	di,0ffh			;
	jae	okay1			;
	cmp	di,MAX_HANDLES		;is handle valid in FAPI?
	jb	okay1			;yes
	mov	ah,D2_CloseHndl		;invalid handle must be closed
	mov	bx,di			;bx contains handle for int call
	int	21h			;
	mov	ax,ERROR_TOO_MANY_OPEN_FILES ; error code on bad new handle
	jmp	short NormalExit	;quit
;
;	copy table entry for old handle into entry for new handle
;
okay1:
	cld				; clear direction for use of rep

	; NOTE: optimize for size NOT speed (faster to use moves rather
	; than push/pop) ... time wasted in int 21 calls overpowering anyway

	; DS:SI <- offset into table of old handle
	push	cs			; DS <- segment of table
	pop	ds
	mov	ax,si			; AX <- old handle
	call	__api_devtab_ptr	; BX <- address of entry
	mov	si,bx			; SI <- address of entry

	; ES:DI <- offset into table of new handle
	push	cs			; ES <- segment of table
	pop	es
	mov	ax,di			; AX <- new handle
	call	__api_devtab_ptr	; BX <- address of entry
	mov	di,bx			; SI <- address of entry

	mov	cx,HANDINFO_SIZE
	rep	movsb			; more expensive but less error prone
					; (in case SIZE changes) than word move
	xor	ax,ax			; clear error
	jmp	NormalExit		;@@ Added support for DOSErrorClass
ErrorExit:				;@@ added support for DOSErrorClass
	call	api_get_extended	;@@ added support for DOSErrorClass
NormalExit:				;@@ added support for DOSErrorClass

	pop	bp			; restore bp for api_end

	call	__api_end	; check sigs & restore es,di,si,dx,cx,bx,ds,bp

	ret	6	; clear stack of entry parameters (bytes)
DOSDUPHANDLE	endp

_TEXT	ends

	end

