;/*static char *SCCSID = "@(#)qmsg32.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:   MSG32GET.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	$qmsg32.asm

	.386

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

.xlist						;BN019;
.xcref						;BN019;
include struc30.inc				;BN019;
include dc1segs.inc				;BC019;
.cref						;BN019;
.list						;BN019;


PUBLIC	DOS32IQUERYMESSAGECP




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 						; DCR 704
DATA32	ENDS



EXTRN	DOSIQUERYMESSAGECP:FAR

;Create a dummy label to trick MASM into correct fixups

CODE16C  SEGMENT
T_DOSIQUERYMESSAGECP	LABEL FAR
CODE16C  ENDS

CODE32	SEGMENT
	ASSUME CS:FLAT,DS:FLAT,ES:FLAT
;/********************** START OF SPECIFICATIONS **********************/
;/*								      */
;/* ENTRY POINT:  DOS32IQUERYMESSAGECP				      */
;/*								      */
;/* DESCRIPTIVE NAME:  32 bit entry point for DosIWueryMessageCP      */
;/*								      */
;/* FUNCTION:  Converts 32 bit parameters to 16:16 so that	      */
;/*	       DosIQueryMessageCP can use them. 		      */
;/*								      */
;/* NOTES:							      */
;/*    Here is what the stack looks like:			      */
;/*								      */
;/*	+24-> Pointer to message segment			      */
;/*	+20-> Pointer to return length				      */
;/*	+16-> Pointer to file name				      */
;/*	+12-> Length of data buffer				      */
;/*	 +8-> Pointer to data buffer				      */
;/*    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 data buffer				      */
;/*	-40-> Addr of file name 				      */
;/*	-44-> Addr of return length				      */
;/*	-48-> Addr of message segment				      */
;/*	-52-> Saved EBX 				       ;BN026;*/
;/*								      */
;/* INTERNAL REFERENCES:					      */
;/*		T_DOSIQUERYMESSAGECP				      */
;/*								      */
;/* EXTERNAL REFERENCES:					      */
;/*		THK32HANDLEBOUNDARY				      */
;/*		THK32HANDLESTRING				      */
;/*		THK32DEALLOC					      */
;/*								      */
;/*********************** END OF SPECIFICATIONS ***********************/
DOS32IQUERYMESSAGECP PROC
	push	ebp
	mov	ebp,esp

	cld			;Assume direction flag clear
	xor	eax,eax
	push	eax		; temp storage for return value
	push	esi
	push	edi
	push	eax		; temp stg
	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 buffer
	push	eax		; temp stg for parm 2 - addr of file name
	push	eax		; temp stg for parm 3 - addr of return length
	push	eax		; temp stg for parm 4 - addr of message seg
	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+8]		; Addr of Buffer

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

	mov	[ebp-36],esi

;;;;;;;;;;;;;;;;;;  WARNING THIS CODE HAS BEEN CHANGED BY HAND
; I couldn't convince the thunk compiler that the size on input
; was the length specified by the user and the length of output
; was specified by QuerymessageCP so here I check the length
; specified by the user and let the thunk compiler handle the
; case where we're coming out of Querymessagecp.
;
	mov	ecx,[ebp+12]		; Length of Buffer
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Check for NULL pointer
	or	ecx,ecx
	jz	L2		;Nothing to check

;;;;;;;;;;;;;;;;;;;;;;;;;;; AND WE HAVE TO DO IT AGAIN (ECX REALLY HAS THE SIZE)
				;ecx has pointer to size
;	mov	ecx,[ecx]		;Get Size
;	or	ecx,ecx
;	jz	L2		;Nothing to check
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;DWORD --> WORD sized length. Error if Size > 64k
	cmp	ecx,10000h
	jae	INVP_DOS32IQUERYMESSAGECP			;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
	jnz	NOMEM_DOS32IQUERYMESSAGECP			;
	mov	[ebp-36],edi
	or	edx,edx
	js	short L3		;Alloced Mem
	or	BYTE PTR [ebp+(edx*4)-32],1		;Set Flag

L3:			;Variable Length Copy

;Item semantics are NOT input

L4:			;Variable Length No Copy

L2:


	mov	esi,[ebp+16]		; Addr of File Name

;Pointer  --> name
	or	esi,esi
	jz	L5

	mov	[ebp-40],esi
;Handle String Parameters

	push	-32		;Alias flag offset
	push	2		;Flag Mask
	pop	edx
	call	THK32HANDLESTRING
	jc	ERR_DOS32IQUERYMESSAGECP			;jmp if too long
	mov	[ebp-40],edi

L5:


	mov	esi,[ebp+20]		; Addr of Return Length

;Pointer  --> msglen
	or	esi,esi
	jz	L6

	mov	[ebp-44],esi

;Have PU/LONG, want PU/SHORT
;Use the LONG as buffer, only if it doesn't
;cross boundary

;Check Boundary Crossing - fixed size item
	cmp	si,65532
	jbe	L6			;Enough room

; Allocate space on stack
	sub	esp,2			;Alloc Mem
	and	esp,0FFFFFFFCh		;DWORD align
	mov	edi,esp 		;Points to new data area
	mov	[ebp-44],edi

L6:


	mov	esi,[ebp+24]		; Addr of Message Segment

;Pointer  -->
	or	esi,esi
	jz	L7

	mov	[ebp-48],esi

;Check Boundary Crossing - fixed size item
	cmp	si,65535
	jbe	L7			;Enough room

; Allocate space on stack
	sub	esp,1			;Alloc Mem
	and	esp,0FFFFFFFCh		   ;DWORD align
	mov	edi,esp 		;Points to new data area
	mov	[ebp-48],edi

;Transfer 1 bytes
	movsb

L7:

; ****> END Pointer/Structure Section

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

	push	es
;BC026; push	ebx
	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: char
	mov	eax,DWORD PTR [ebp-36]
	or	eax,eax
	jz	short L10			;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
L10:	push	eax



	;From Name:   Type: unsigned long
	mov	eax,[ebp+12]			; Length of Buffer
	cmp	eax,0ffffh
	ja	INVP_DOS32IQUERYMESSAGECP

	push	ax		;To:unsigned short


	;From Name:   Type: string
	mov	eax,DWORD PTR [ebp-40]
	or	eax,eax
	jz	short L11			;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
L11:	push	eax



	;From Name:   Type: unsigned long
	mov	eax,DWORD PTR [ebp-44]
	or	eax,eax
	jz	short L12			;NULL pointer

	ror	eax,16			; CRMA on structure pointer
	shl	ax,3
	or	al,dl
	rol	eax,16
L12:	push	eax



	;From Name:   Type: char
	mov	eax,DWORD PTR [ebp-48]
	or	eax,eax
	jz	short L13			;NULL pointer

      ; ror	eax,16			 ;BD019; CRMA on pointer     @@sjb
      ; shl	ax,3			 ;BD019;		     @@sjb
      ; or	al,dl			 ;BD019;		     @@sjb
      ; rol	eax,16			 ;BD019;		     @@sjb
	call	DOS32FLATTOSEL		 ;BN019; Convert in packed region
L13:	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_DOSIQUERYMESSAGECP


INVP_DOS32IQUERYMESSAGECP:
	push	87
	pop	eax
	mov	BYTE PTR [ebp-20],1		;Set flag
	jmp	short L14

NOMEM_DOS32IQUERYMESSAGECP:
	push	8
	pop	eax

ERR_DOS32IQUERYMESSAGECP:
	mov	BYTE PTR [ebp-20],1		;Set flag
	jmp	short L14



R_DOSIQUERYMESSAGECP:				; 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
;BC026; pop	ebx
	pop	es



;Convert Return Code
;USHORT --> ULONG
	movzx	eax,ax
L14:
;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	L15



	mov	edi,[ebp+8]		; Addr of Buffer
;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	L15

	test	BYTE PTR[ebp-20],1		;Check for errors A
	jnz	L16			;No copy if error

;Get size for copy out

;Size was referenced by a pointer.
;Since only shorts/longs are used as sizeof
;parameters, the space allocated for the temporary
;location is on the stack. It still exists, so it
;is still safe to use the temporary pointer

	mov	ecx,[ebp-44]		;Get Size Pointer
	mov	ecx,[ecx]		;Get Size
;ECX holds size in bytes

;If aliased, then skip over possible copyout
	test	BYTE PTR[ebp-32],1		;Test Alias Flag
	jnz	L17
;Copy out ecx bytes
	push	esi		;Save ptr to temp object

; Copy ECX bytes from ESI to EDI
	call	THK32COPYBLOCK
	pop	esi		;Get ptr to temp object
L17:			;Aliased Label
	push	-32		;Alloc Flag Offset
	mov	edx,1

	call	THK32DEALLOC



L16:			;ErrorLabel A

L15:		;No action required

;Undo Pointer  --> name


	mov	esi,[ebp-40]		; temp address
	or	esi,esi
	jz	L20



	mov	edi,[ebp+16]		; Addr of File Name
;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	L20
;Handle String Parameters
;Strings are never copied out
	push	-32		;Alloc Flag Offset
	mov	edx,2

	call	THK32DEALLOC


L20:		;No action required

;Undo Pointer  --> msglen


	mov	esi,[ebp-44]		; temp address
	or	esi,esi
	jz	L24



	mov	edi,[ebp+20]		; Address of Return Length

;This item is either on the stack, or is still
;in its original position.
;Output semantics convert in place

	movzx	eax,WORD PTR[esi]
	mov	[edi],eax

L24:		;No action required

;Undo Pointer  -->


	mov	esi,[ebp-48]		; temp address
	or	esi,esi
	jz	L25



	mov	edi,[ebp+24]		; Addr of Message Segment
;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	L25

;Item is fixed size
;stack deallocated implicitly

L25:		;No action required

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

;* 32-bit return code.

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

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

DOS32IQUERYMESSAGECP endp

CODE32	ENDS

;* 16-bit code to make API call.

CODE16C  SEGMENT

	ASSUME CS:CODE16C
	.errnz ($ - T_DOSIQUERYMESSAGECP)

	call	FAR PTR DOSIQUERYMESSAGECP		; call 16-bit version
	jmp	FAR PTR FLAT:R_DOSIQUERYMESSAGECP	     ; 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
