;/*static char *SCCSID = "@(#)msg32put.asm      6.4 92/03/04";*/
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
;
; SOURCE FILE NAME:   MSG32PUT.ASM
;
;		     This file defines the thunks needed to call
;		     from Dos32TrueGetMessage to DosTrueGetMessage.
;
;   Modification history
;
;B019 PB723669 08/10/91 MSR: Thunks dont address 16-bit segment packing
;B026 PB726437 10/28/91 MSR: 32-bit message routines destroy EBX
;***   noto    11/18/93 Define which segment for Page Tuning DLL
;
	TITLE	$msg32put

	.386

;Error codes taken out of error.h
ERROR_NOMEMORY EQU 8
ERROR_INVALIDPARAM EQU 87

.xlist
.xcref
include dc1segs.inc						; DCR 704
.cref
.list

PUBLIC	DOS32PUTMESSAGE


CODE32_TUNE1  SEGMENT DWORD USE32 PUBLIC 'CODE'
EXTRN	THK32HANDLESTRING:NEAR
EXTRN	DOS32FLATTOSEL:NEAR		;BN019; Convert ptrs in packed region
CODE32_TUNE1  ENDS

CODE32_TUNE2  SEGMENT DWORD USE32 PUBLIC 'CODE'
EXTRN	THK32DEALLOC:NEAR
CODE32_TUNE2  ENDS

CODE32_TUNE4  SEGMENT DWORD USE32 PUBLIC 'CODE'
EXTRN	THK32HANDLEBOUNDARY:NEAR
CODE32_TUNE4  ENDS

CODE32	SEGMENT DWORD USE32 PUBLIC 'CODE'
CODE32	ENDS


CODE16C  SEGMENT DWORD USE16 PUBLIC 'CODE'
CODE16C  ENDS


DATA32	SEGMENT
DATA32	ENDS


EXTRN	DOSPUTMESSAGE:FAR

;Create a dummy label to trick MASM into correct fixups
CODE16C  SEGMENT
T_DOSPUTMESSAGE LABEL FAR
CODE16C  ENDS


CODE32	SEGMENT
	ASSUME CS:FLAT,DS:FLAT,ES:FLAT
;/********************** START OF SPECIFICATIONS **********************/
;/*								      */
;/* ENTRY POINT:  DOS32PUTMESSAGE				      */
;/*								      */
;/* DESCRIPTIVE NAME:  32 bit entry point for DosPutMessage	      */
;/*								      */
;/* FUNCTION:  Converts 32 bit parameters to 16:16 so that	      */
;/*	       DosPutMessage can use them.			      */
;/*								      */
;/* NOTES:							      */
;/*    Here is what the stack looks like:			      */
;/*								      */
;/*	+16-> Pointer to message				      */
;/*	+12-> Length of Message 				      */
;/*	 +8-> Output File Handle				      */
;/*    BP+4-> Return address					      */
;/*	 BP-> Saved BP						      */
;/*    BP-4-> Saved Return value				      */
;/*	 -8-> Saved ESI 					      */
;/*	-12-> Saved EDI 					      */
;/*	-16-> Temp Storage					      */
;/*	-20-> Err Flag						      */
;/*	-24-> Stack Alloc Flag					      */
;/*	-28-> BMP Flag						      */
;/*	-32-> Alias Flag					      */
;/*	-36-> Addr of Message					      */
;/*	-40-> Saved EBX 				       ;BN026;*/
;/*								      */
;/* INTERNAL REFERENCES:					      */
;/*		T_DOSPUTMESSAGE 				      */
;/*								      */
;/* EXTERNAL REFERENCES:					      */
;/*		THK32HANDLEBOUNDARY				      */
;/*		THK32HANDLESTRING				      */
;/*		THK32DEALLOC					      */
;/*								      */
;/*********************** END OF SPECIFICATIONS ***********************/
DOS32PUTMESSAGE PROC
	push	ebp
	mov	ebp,esp

	cld			;Assume direction flag clear
	xor	eax,eax
	push	eax		  ; temp stg for return value
	push	esi
	push	edi
	push	eax		  ; temp storage
	push	eax		  ;Error flag for cleanup
	push	eax		  ; temp stg for Stack Allocation Flags
	push	eax		  ; temp stg for BMP Flags
	push	eax		  ; temp stg for Alias Flags
	push	eax		  ; temp stg for parm 1 - addr of message
	push	ebx	    ;BN026; save EBX

;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

	mov	ax,ss
	cmp	ax,seg FLAT:DATA32		; standard 32 bit stack?
	jne	short L1		; if not, skip bumping code

;* Bump the stack down if too near 64K boundary.

	mov	eax,esp
	cmp	ax,1024
	jae	short L1
	xor	ax,ax
	mov	esp,eax 	; bump the stack down


;Insure that 1 DWORD exists on stack
	push	eax


; ****> BEGIN Pointer/Structure Section

L1:
	mov	esi,[ebp+16]		; Addr of Message

;Pointer  --> buf
	or	esi,esi
	jz	L2

	mov	[ebp-36],esi
	mov	ecx,[ebp+12]		; Length of Message
	or	ecx,ecx
	jz	L2		;Nothing to check

;DWORD --> WORD sized length. Error if Size > 64k
	cmp	ecx,10000h
	jae	INVP_DOS32PUTMESSAGE			;jmp if too long
;ECX holds size in bytes

;Check Boundary Crossing
	mov	eax,esi
	neg	ax
	jz	L2			;0=full 64k of room

	cmp	ax,cx
	jae	L2			;Enough room

	call	Thk32HandleBoundary
	or	eax,eax
	ja	NOMEM_DOS32PUTMESSAGE			;
	mov	[ebp-36],edi
	or	edx,edx
	jb	short L3		;Alloced Mem
	or	DWORD PTR [ebp+(edx*4)-32],1		;Set Flag
	dec	edx
	ja	short L4		;Aliases not copied

L3:			;Variable Length Copy

; Copy ECX bytes from ESI to EDI
	call	THK32COPYBLOCK

L4:			;Variable Length No Copy

L2:

; ****> END Pointer/Structure Section

;* Create new call frame, using 16-bit semantics.

	push	es
	push	ebp			; save ebp
	mov	eax,esp 		; save current esp
	push	ss
	push	eax


	mov	dx,ss			; get cpl bits to use as dpl bits
	and	dx,3			; mask off rest of register

	or	dl,4			;Force LDT bit on


	;From Name:   Type: unsigned long	; handle
	mov	eax,[ebp+8]			; Output File Handle
	cmp	eax,0ffffh
	ja	INVP_DOS32PUTMESSAGE

	push	ax		;To:unsigned short


	;From Name:   Type: unsigned long	; msg length
	mov	eax,[ebp+12]			; Length of Message
	cmp	eax,0ffffh
	ja	INVP_DOS32PUTMESSAGE

	push	ax		;To:unsigned short


	;From Name:   Type: char		; msg address
	mov	eax,DWORD PTR [ebp-36]
	or	eax,eax
	jz	short L5			;NULL pointer

      ; ror	eax,16			;BD019; CRMA on structure pointer
      ; shl	ax,3			;BD019;
      ; or	al,dl			;BD019;
      ; rol	eax,16			;BD019;
	call	DOS32FLATTOSEL		;BN019; Convert in packed region
L5:	push	eax


;* Convert SS:ESP to 16-bit SS:SP.

	mov	eax,esp 		; use CRMA on ESP
	ror	eax,16
	shl	ax,3
	or	al,dl
	rol	eax,16

	push	eax			; push new stack pointer
	lss	sp,DWORD PTR [esp]	; ss:sp = 16-bit ptr

;* Jump to 16-bit segment to issue call (so that 16-bit API can RETF).

	jmp	FAR PTR T_DOSPUTMESSAGE


INVP_DOS32PUTMESSAGE:
	mov	eax,ERROR_INVALIDPARAM
	mov	BYTE PTR [ebp-20],1		;BN019; Set flag
	jmp	short L6

NOMEM_DOS32PUTMESSAGE:
	mov	eax,ERROR_NOMEMORY
	mov	BYTE PTR [ebp-20],1		;BN019; Set flag
	jmp	short L6



R_DOSPUTMESSAGE:				; label defining return jmp location

;* Restore 32-bit SS:ESP - it is on top of stack.

	movzx	esp,sp			; make sure that esp is correct
	lss	esp,[esp]
	pop	ebp
	pop	es



;Convert Return Code
;USHORT --> ULONG
	movzx	eax,ax
L6:
;Functions contain pointers, save return code
	mov	[ebp-4],eax		;Save return code

; ****> BEGIN Pointer/Structure Unpack Section


;Undo Pointer  --> buf


	mov	esi,[ebp-36]		; temp address
	or	esi,esi
	jz	L7



	mov	edi,[ebp+16]		; Addr of Message
;Types are identical and no imbedded pointers exist
;This means that we treated the pointer as a buffer
;If temp address == original address then no work required
	cmp	esi,edi
	je	L7
	push	-32		;Alloc Flag Offset
	mov	edx,1

	call	THK32DEALLOC


L7:		;No action required

; ****> END Pointer/Structure Unpack Section

;* 32-bit return code.

	mov	ebx,[ebp-40]	;BN026; Restore EBX

	lea	esp,[ebp-12]
	pop	edi
	pop	esi
	pop	eax		;Pop saved return code
      ; mov	esp,ebp 	;BD019;
      ; pop	ebp		;BD019;
	leave			;BN019;
	ret				; Remove parameters

DOS32PUTMESSAGE endp

CODE32	ENDS

;* 16-bit code to make API call.

CODE16C  SEGMENT

	ASSUME CS:CODE16C
	.errnz ($ - T_DOSPUTMESSAGE)

	call	FAR PTR DOSPUTMESSAGE		; call 16-bit version
	jmp	FAR PTR FLAT:R_DOSPUTMESSAGE		; jump back

CODE16C  ENDS



CODE32	SEGMENT


	ASSUME CS:FLAT,DS:FLAT,SS:FLAT

THK32COPYBLOCK:

; Copy ECX bytes from ESI to EDI
	mov	eax,3
	and	eax,ecx
	shr	ecx,2
	rep movsd
	mov	ecx,eax
	rep movsb

	ret

CODE32	ENDS

	END
