;       SCCSID = @(#)qthkcode.inc       6.6 92/03/11
;Thunk Compiler Version 13.16  May 15 1989 16:03:22
;Compiled Mon Jul 10 17:54:43 1989

; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; *                                                                          *
; * Change History:                                                          *
; *                                                                          *
; *     MDLL  01/10/94 BJN Page Tune segments for Merged DLL.                *
; *                                                                          *
; ****************************************************************************

;       Static Name Aliases
;

        TITLE   $qthkcode.inc

        .386
.list
;Special equate required until selector values are defined

THK32R2SS       EQU 04Ah

;Error codes taken out of error.h

ERROR_NOT_ENOUGH_MEMORY EQU 8
ERROR_INVALID_PARAMETER EQU 87

;Constants taken out of bsedos.h

QUE_LIFO             EQU 1
QUE_PRIORITY         EQU 2
QUE_CONVERT_ADDRESS  EQU 4

;Constants taken out of ipcqueue.h

Q_BIT32 EQU 4
Q_THUNK EQU 8
E_BIT32 EQU 1

PUBLIC  DOS32CREATEQUEUE
PUBLIC  DOS32OPENQUEUE
PUBLIC  DOS32CLOSEQUEUE
PUBLIC  DOS32READQUEUE
PUBLIC  DOS32WRITEQUEUE
PUBLIC  DOS32PEEKQUEUE
PUBLIC  DOS32PURGEQUEUE
PUBLIC  DOS32QUERYQUEUE
PUBLIC  _OPEN16EVENTSEM
PUBLIC  _POST16EVENTSEM
PUBLIC  _RESET16EVENTSEM
PUBLIC  _CLOSE16EVENTSEM
PUBLIC  Close16EventSem_T
PUBLIC  Reset16EventSem_T
PUBLIC  Post16EventSem_T
PUBLIC  Open16EventSem_T
;PUBLIC  QUEINIT                                                        ;MDLL

CODE_TUNE2 SEGMENT WORD PUBLIC 'CODE' USE16                             ;MDLL
CODE_TUNE2 ENDS                                                         ;MDLL

CODE32_TUNE1  SEGMENT DWORD USE32 PUBLIC 'CODE'                         ;MDLL
EXTRN   DOS32FREEMEM:NEAR                                               ;MDLL
EXTRN   DOS32ALLOCMEM:NEAR                                              ;MDLL
EXTRN   THK32FREEBLOCK:NEAR                                             ;MDLL
EXTRN   THK32HANDLESTRING:NEAR                                          ;MDLL
EXTRN   DOS32OPENEVENTSEM:NEAR                                          ;MDLL
EXTRN   DOS32POSTEVENTSEM:NEAR                                          ;MDLL
EXTRN   DOS32RESETEVENTSEM:NEAR                                         ;MDLL
EXTRN   DOS32FLATTOSEL:NEAR                                             ;MDLL
EXTRN   DOS32SETEXCEPTIONHANDLER:NEAR                                   ;MDLL
CODE32_TUNE1  ENDS                                                      ;MDLL

CODE32_TUNE2  SEGMENT DWORD USE32 PUBLIC 'CODE'                         ;MDLL
EXTRN   THK32ALLOCBLOCK:NEAR                                            ;MDLL
EXTRN   THK32DEALLOC:NEAR                                               ;MDLL
EXTRN   THK32ALLOCVARLEN:NEAR                                           ;MDLL
CODE32_TUNE2  ENDS                                                      ;MDLL

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

CODE32 SEGMENT DWORD USE32 PUBLIC 'CODE'
EXTRN   THK32ALIASMEM:NEAR
EXTRN   THK32ALLOCSTACK:NEAR
EXTRN   THK32FREESTACK:NEAR
EXTRN   DOS32CLOSEEVENTSEM:NEAR
EXTRN   DOS32TIB:ABS
CODE32 ENDS

; EXTRN   THK32XHNDLR:NEAR        ; Queues uses its own exception handler


DATA32  SEGMENT DWORD USE32 PUBLIC 'DATA'

DATA32  ENDS


;****************************************************************
;*** Beginning of my revisions                                ***
;*** Last Modified:  8/12/89                                  ***
;****************************************************************

; conforming data segment to give ring 2 data selector for use in
; _OPEN16EVENTSEM, _POST16EVENTSEM, _RESET16EVENTSEM, and _CLOSE16EVENTSEM

CODE32C EQU     <CODE32>                                        ; DCR 704
CODE32C SEGMENT DWORD USE32 PUBLIC 'CODE'                       ; DCR 704

CODE32C ENDS

DATA32C EQU     <DATA32>                                        ; DCR 704
DATA32C SEGMENT DWORD USE32 PUBLIC 'DATA'                       ; DCR 704
;       DW (?)                                                  ; DCR 704
DATA32C ENDS

;****************************************************************
;*** End of my revisions                                      ***
;*** Last Modified:  8/12/89                                  ***
;****************************************************************

EXTRN   W_DOSCREATEQUEUE:FAR
EXTRN   W_DOSOPENQUEUE:FAR
EXTRN   DOSCLOSEQUEUE:FAR
EXTRN   W_DOSREADQUEUE:FAR
EXTRN   W_DOSWRITEQUEUE:FAR
EXTRN   W_DOSPEEKQUEUE:FAR
EXTRN   DOSPURGEQUEUE:FAR
EXTRN   DOSQUERYQUEUE:FAR
EXTRN   _DYNAINIT:FAR

ThunkExceptionRegistrationRecord        STRUC
TERR_PRV        DD      ?       ; EXCEPTIONREGISTRATIONRECORD prev_structure
TERR_EXH        DD      ?       ; EXCEPTIONREGISTRATIONRECORD ExceptionHandler
TERR_EBX        DD      ?       ; Saved EBX register
TERR_EDI        DD      ?       ; Saved EDI register
TERR_ESI        DD      ?       ; Saved ESI register
TERR_ESP        DD      ?       ; Saved ESP register
TERR_CHN        DD      ?       ; Saved exception handler chain head
TERR_STK        DD      ?       ; Address of thunk stack or zero
ThunkExceptionRegistrationRecord        ENDS

_TEXT   SEGMENT DWORD USE16 PUBLIC 'CODE'                         ; DCR1202


_TEXT   ENDS
;Create a dummy label to trick MASM into correct fixups

_TEXT   SEGMENT

T_W_DOSCREATEQUEUE      LABEL FAR

_TEXT   ENDS


CODE32  SEGMENT
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32CREATEQUEUE PROC

        push    ebp
        mov     ebp,esp


        cld                     ;Assume direction flag clear
        push    0               ; temp storage for return value
        push    esi
        push    edi
        push    0               ; temp storage (flag to w_DOSCREATEQUEUE)
        push    0               ;Error flag for cleanup
        push    0               ; temp storage for Stack Allocation Flags
        push    0               ; temp storage for BMP Flags
        push    0               ; temp storage for Alias Flags
        push    0               ; temp storage for ptr param #1
        push    0               ; temp storage for ptr param #2

;* Set exception handler to capture any fatal traps on behalf of user

        push    0               ;push for stack comparison later (@[EBP-44])
        mov     eax,DOS32TIB    ; Load FS in case user left it
        mov     fs,ax           ;  in corrupted state
        push    fs:[tib_pexchain] ; Save handler chain head (@[EBP-48])
        mov     eax,ebp         ; (EAX) = EBP (-> ESP)
        add     eax,4           ; (EAX) = ESP (-> Return EIP)
        push    eax             ; Save ESP (@[EBP-52])
        push    esi             ; Save ESI (@[EBP-56])
        push    edi             ; Save EDI (@[EBP-60])
        push    ebx             ; Save EBX (@[EBP-64])

        push    OFFSET FLAT:THK32XHNDLR
        push    0
        push    esp             ; -> Queue exception registration record
        call    DOS32SETEXCEPTIONHANDLER ; Install exception handler
        add     esp,4

;* 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
        call    THK32ALLOCSTACK         ; bump the stack down
        mov     dword ptr [ebp-44],eax  ;old stack comparator on old stack
        mov     esp,eax


;Insure that 1 DWORD exists on new stack
        push    eax
L1:


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+8]             ;handle base address

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

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-36],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     L2                      ;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-36],edi

L2:


        mov     esi,[ebp+16]            ;qname base address

;Pointer qname --> qname
        or      esi,esi
        jz      L3

;Pointer Validation:    Read Access

        mov     al,BYTE PTR [esi]

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

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

L3:

; ****> 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: handle  Type: unsigned long
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L4                        ;NULL pointer

        call    DOS32FLATTOSEL

L4:     push    eax


        ;From Name: qflags  Type: unsigned long
        ; parses qflags so that only a valid priority is passed to the 16-bit
        ; worker (thunking status is passed along with flags)
        mov     eax,[ebp+12]
        cmp     eax,(QUE_CONVERT_ADDRESS OR QUE_PRIORITY) ; flag too large
        ja      INVP_DOS32CREATEQUEUE
        cmp     eax,(QUE_PRIORITY OR QUE_LIFO)  ; illegal flag combo
        je      INVP_DOS32CREATEQUEUE
        cmp     eax,QUE_CONVERT_ADDRESS ; thunking bit specified
        jb      short L9
        or      DWORD PTR [ebp-16],Q_THUNK      ; save Q_THUNK bit for flags
        and     eax,NOT QUE_CONVERT_ADDRESS     ; clear thunking bit

L9:     push    ax              ;To:priority (unsigned short)


        ;From Name: qname  Type: string
        mov     eax,DWORD PTR [ebp-40]
        or      eax,eax
        jz      short L5                        ;NULL pointer

        call    DOS32FLATTOSEL

L5:     push    eax



        ;From Name: flags  Type: unsigned short

;Extra parameter needed
        mov     eax,[ebp-16]
        or      eax,Q_BIT32
        push    ax                      ;Push u/short

;* 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_W_DOSCREATEQUEUE


INVP_DOS32CREATEQUEUE:
        mov     eax,ERROR_INVALID_PARAMETER
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L6

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

NOMEM_DOS32CREATEQUEUE:
        mov     eax,ERROR_NOT_ENOUGH_MEMORY
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L6
R_W_DOSCREATEQUEUE:                             ; 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 handle --> handle


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



        mov     edi,[ebp+8]             ;handle original address

;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

L7:             ;No action required

;Undo Pointer qname --> qname


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



        mov     edi,[ebp+16]            ;qname original address
;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      L8
;Handle String Parameters
;Strings are never copied out
        push    -32             ;Alloc Flag Offset
        mov     edx,2

        call    THK32DEALLOC


L8:             ;No action required

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

;* 32-bit return code.

        mov     eax,[ebp-48]            ; (EAX) = handler chain head
        mov     fs:[tib_pexchain],eax   ; Restore handler chain head
        lea     esp,[ebp-44]    ; get the old stack
        pop     ecx                     ;get the new stack
        cmp     ecx,0                   ;is it new
        jz      L8A
        call    THK32FREESTACK          ;deallocate the memory
L8A:
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        mov     esp,ebp
        pop     ebp
        ret                             ; Remove parameters

DOS32CREATEQUEUE endp

CODE32  ENDS

;* 16-bit code to make API call.

_TEXT   SEGMENT

        ASSUME CS:_TEXT
        .errnz ($ - T_W_DOSCREATEQUEUE)

        call    FAR PTR W_DOSCREATEQUEUE                ; call 16-bit version
        jmp     FAR PTR FLAT:R_W_DOSCREATEQUEUE         ; jump back

_TEXT   ENDS


;Create a dummy label to trick MASM into correct fixups

_TEXT   SEGMENT

T_W_DOSOPENQUEUE        LABEL FAR

_TEXT   ENDS


CODE32  SEGMENT
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32OPENQUEUE PROC

        push    ebp
        mov     ebp,esp


        cld                     ;Assume direction flag clear
        push    0               ; temp storage for return value
        push    esi
        push    edi
        push    0               ; temp storage
        push    0               ;Error flag for cleanup
        push    0               ; temp storage for Stack Allocation Flags
        push    0               ; temp storage for BMP Flags
        push    0               ; temp storage for Alias Flags
        push    0               ; temp storage for ptr param #1
        push    0               ; temp storage for ptr param #2
        push    0               ; temp storage for ptr param #3

;* Set exception handler to capture any fatal traps on behalf of user

        push    0               ;push for stack comparison later (@[EBP-48])
        mov     eax,DOS32TIB    ; Load FS in case user left it
        mov     fs,ax           ;  in corrupted state
        push    fs:[tib_pexchain] ; Save handler chain head (@[EBP-52])
        mov     eax,ebp         ; (EAX) = EBP (-> ESP)
        add     eax,4           ; (EAX) = ESP (-> Return EIP)
        push    eax             ; Save ESP (@[EBP-56])
        push    esi             ; Save ESI (@[EBP-60])
        push    edi             ; Save EDI (@[EBP-64])
        push    ebx             ; Save EBX (@[EBP-68])

        push    OFFSET FLAT:THK32XHNDLR
        push    0
        push    esp             ; -> Queue exception registration record
        call    DOS32SETEXCEPTIONHANDLER ; Install exception handler
        add     esp,4

;* 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 L13               ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L13
        call    THK32ALLOCSTACK         ; bump the stack down
        mov     dword ptr [ebp-48],eax  ;old stack comparator on old stack
        mov     esp,eax


;Insure that 1 DWORD exists on stack
        push    eax
L13:


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+8]             ;ownerpid base address

;Pointer ownerpid --> ownerpid
        or      esi,esi
        jz      L14

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-36],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     L14                     ;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-36],edi

L14:


        mov     esi,[ebp+12]            ;handle base address

;Pointer handle --> handle
        or      esi,esi
        jz      L15

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-40],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     L15                     ;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-40],edi

L15:


        mov     esi,[ebp+16]            ;qname base address

;Pointer qname --> qname
        or      esi,esi
        jz      L16

;Pointer Validation:    Read Access

        mov     al,BYTE PTR [esi]

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

        push    -32             ;Alias flag offset
        mov     edx,4           ;Flag Mask
        call    THK32HANDLESTRING
        jc      ERR_DOS32OPENQUEUE                      ;jmp if too long
        mov     [ebp-44],edi

L16:

; ****> 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: ownerpid  Type: unsigned long
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L17                       ;NULL pointer

        call    DOS32FLATTOSEL

L17:    push    eax



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

        call    DOS32FLATTOSEL

L18:    push    eax



        ;From Name: qname  Type: string
        mov     eax,DWORD PTR [ebp-44]
        or      eax,eax
        jz      short L19                       ;NULL pointer

        call    DOS32FLATTOSEL

L19:    push    eax



        ;From Name: callersize  Type: unsigned short

;Extra parameter needed
        push    WORD PTR Q_BIT32        ;Push u/short

;* 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_W_DOSOPENQUEUE


INVP_DOS32OPENQUEUE:
        mov     eax,ERROR_INVALID_PARAMETER
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L20

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

NOMEM_DOS32OPENQUEUE:
        mov     eax,ERROR_NOT_ENOUGH_MEMORY
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L20
R_W_DOSOPENQUEUE:                               ; 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
L20:
;Functions contain pointers, save return code
        mov     [ebp-4],eax             ;Save return code

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


;Undo Pointer ownerpid --> ownerpid


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



        mov     edi,[ebp+8]             ;ownerpid original address

;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

L21:            ;No action required

;Undo Pointer handle --> handle


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



        mov     edi,[ebp+12]            ;handle original address

;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

L22:            ;No action required

;Undo Pointer qname --> qname


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



        mov     edi,[ebp+16]            ;qname original address
;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      L23
;Handle String Parameters
;Strings are never copied out
        push    -32             ;Alloc Flag Offset
        mov     edx,4

        call    THK32DEALLOC


L23:            ;No action required

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

;* 32-bit return code.

        mov     eax,[ebp-52]            ; (EAX) = handler chain head
        mov     fs:[tib_pexchain],eax   ; Restore handler chain head
        lea     esp,[ebp-48]    ; get the old stack
        pop     ecx                     ;get the new stack
        cmp     ecx,0                   ;is it new
        jz      L23A
        call    THK32FREESTACK          ;deallocate the memory
L23A:
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        mov     esp,ebp
        pop     ebp
        ret                             ; Remove parameters

DOS32OPENQUEUE endp

CODE32  ENDS

;* 16-bit code to make API call.

_TEXT   SEGMENT

        ASSUME CS:_TEXT
        .errnz ($ - T_W_DOSOPENQUEUE)

        call    FAR PTR W_DOSOPENQUEUE          ; call 16-bit version
        jmp     FAR PTR FLAT:R_W_DOSOPENQUEUE           ; jump back

_TEXT   ENDS


;Create a dummy label to trick MASM into correct fixups

_TEXT   SEGMENT

T_DOSCLOSEQUEUE LABEL FAR

_TEXT   ENDS


CODE32  SEGMENT
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32CLOSEQUEUE PROC

        push    ebp
        mov     ebp,esp


;* Set exception handler to capture any fatal traps on behalf of user (no
;* handler is needed since there are no addresses passed in by the user)

        push    0               ;push for stack comparison later (@[EBP-4])

;* 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 L28               ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L28
        call    THK32ALLOCSTACK         ; bump the stack down
        mov     dword ptr [ebp-4],eax   ;old stack comparator on old stack
        mov     esp,eax


;Insure that 1 DWORD exists on stack
        push    eax
L28:


; ****> BEGIN Pointer/Structure Section


; ****> 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: handle  Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVP_DOS32CLOSEQUEUE

        push    ax              ;To:unsigned short

;* 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_DOSCLOSEQUEUE


INVP_DOS32CLOSEQUEUE:
        mov     eax,ERROR_INVALID_PARAMETER
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L29
R_DOSCLOSEQUEUE:                                ; 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
L29:

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


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

;* 32-bit return code.

        lea     esp,[ebp-4]     ; get the old stack
        pop     ecx                     ;get the new stack
        cmp     ecx,0                   ;is it new
        jz      L29A
        call    THK32FREESTACK          ;deallocate the memory
L29A:

        mov     esp,ebp
        pop     ebp
        ret                             ; Remove parameters

DOS32CLOSEQUEUE endp

CODE32  ENDS

;* 16-bit code to make API call.

_TEXT   SEGMENT

        ASSUME CS:_TEXT
        .errnz ($ - T_DOSCLOSEQUEUE)

        call    FAR PTR DOSCLOSEQUEUE           ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSCLOSEQUEUE            ; jump back

_TEXT   ENDS


;Create a dummy label to trick MASM into correct fixups

CODE_TUNE2   SEGMENT                                                    ;MDLL

T_W_DOSREADQUEUE        LABEL FAR

CODE_TUNE2   ENDS                                                       ;MDLL


CODE32_TUNE2  SEGMENT                                                   ;MDLL
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32READQUEUE PROC

        push    ebp
        mov     ebp,esp


        cld                     ;Assume direction flag clear
        push    0               ; temp storage for return value
        push    esi
        push    edi
        push    0               ; temp storage (flag from w_DOSREADQUEUE)
        push    0               ;Error flag for cleanup
        push    0               ; temp storage for Stack Allocation Flags
        push    0               ; temp storage for BMP Flags
        push    0               ; temp storage for Alias Flags
        push    0               ; temp storage for ptr param #1
        push    0               ; temp storage for ptr param #2
        push    0               ; temp storage for ptr param #3
        push    0               ; temp storage for ptr param #4

;* Set exception handler to capture any fatal traps on behalf of user

        push    0               ;push for stack comparison later (@[EBP-52])
        mov     eax,DOS32TIB    ; Load FS in case user left it
        mov     fs,ax           ;  in corrupted state
        push    fs:[tib_pexchain] ; Save handler chain head (@[EBP-56])
        mov     eax,ebp         ; (EAX) = EBP (-> ESP)
        add     eax,4           ; (EAX) = ESP (-> Return EIP)
        push    eax             ; Save ESP (@[EBP-60])
        push    esi             ; Save ESI (@[EBP-64])
        push    edi             ; Save EDI (@[EBP-68])
        push    ebx             ; Save EBX (@[EBP-72])

        push    OFFSET FLAT:THK32XHNDLR
        push    0
        push    esp             ; -> Queue exception registration record
        call    DOS32SETEXCEPTIONHANDLER ; Install exception handler
        add     esp,4

;* 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 L31               ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L31
        call    THK32ALLOCSTACK         ; bump the stack down
        mov     dword ptr [ebp-52],eax  ;old stack comparator on old stack
        mov     esp,eax


;Insure that 1 DWORD exists on stack
        push    eax
L31:


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+12]            ;request base address

;Pointer request --> request
        or      esi,esi
        jz      L32

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-36],esi

;Structures are not Identical
;Structures don't have pointers

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

L32:


        mov     esi,[ebp+16]            ;datalength base address

;Pointer datalength --> datalength
        or      esi,esi
        jz      L33

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-40],esi

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

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

;Semantics are NOT input

L33:


        mov     esi,[ebp+20]            ;dataaddress base address

;Pointer dataaddress --> dataaddress
        or      esi,esi
        jz      L36

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-44],esi

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

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

;Semantics are NOT input

L36:


        mov     esi,[ebp+32]            ;elprio base address

;Pointer elprio --> elprio
        or      esi,esi
        jz      L39

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-48],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     L39                     ;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-48],edi

L39:

; ****> 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: handle  Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVP_DOS32READQUEUE

        push    ax              ;To:unsigned short


        ;From Name: request  Type: struct LOCATION32
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L40                       ;NULL pointer

        call    DOS32FLATTOSEL

L40:    push    eax



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

        call    DOS32FLATTOSEL

L41:    push    eax



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

        call    DOS32FLATTOSEL

L42:    push    eax



        ;From Name: elcode  Type: unsigned long
        mov     eax,[ebp+24]
        cmp     eax,0ffffh
        ja      INVP_DOS32READQUEUE

        push    ax              ;To:unsigned short


        ;From Name: nowait  Type: unsigned long
        mov     eax,[ebp+28]
        cmp     eax,0ffffh
        ja      INVP_DOS32READQUEUE

        push    ax              ;To:unsigned short


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

        call    DOS32FLATTOSEL

L43:    push    eax



        ;From Name: semhand  Type: unsigned long
        push    DWORD PTR [ebp+36]      ; To: unsigned long


        ;From Name: flag  Type: unsigned short

;Extra parameter required
        mov     eax,ebp
        sub     eax,16                  ; (EAX) = addr of temp storage (ebp-16)
        ror     eax,16
        shl     ax,3
        or      al,dl
        rol     eax,16
        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_W_DOSREADQUEUE


INVP_DOS32READQUEUE:
        mov     eax,ERROR_INVALID_PARAMETER
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L44

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

NOMEM_DOS32READQUEUE:
        mov     eax,ERROR_NOT_ENOUGH_MEMORY
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L44
R_W_DOSREADQUEUE:                               ; 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
L44:
;Functions contain pointers, save return code
        mov     [ebp-4],eax             ;Save return code

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


;Undo Pointer request --> request


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



        mov     edi,[ebp+12]            ;request original address

;Structures are not Identical
;Structures don't have pointers
;Structure has output semantics
;Return structure to original area


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

;Element processid --> processid

;USHORT --> ULONG

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

;Element requestdata --> requestdata

;Adjust registers after conversion
        add     esi,2
        add     edi,4
;Add 4 bytes of unsigned long to transfer

;Transfer 4 bytes
        movsd

L46:                    ;ErrorLabel D
;Deallocate Temporary Structure


;Stack allocated memory deallocated implicitly

L45:            ;No action required

;Undo Pointer datalength --> datalength


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



        mov     edi,[ebp+16]            ;datalength original address
;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      L47

;Item is fixed size

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

;Space was allocated on stack

;Transfer 4 bytes
        movsd

L51:                    ;ErrorLabel C
;stack deallocated implicitly

L47:            ;No action required

;Undo Pointer dataaddress --> dataaddress


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



        mov     edi,[ebp+20]            ;dataaddress original address
;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      L52

;Item is fixed size

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

;Space was allocated on stack

;Transfer 4 bytes
        movsd

;*************************************************************************
; HAND MODIFICATIONS START
        sub edi,4
; HAND MODIFICATIONS STOP
;*************************************************************************

L56:                    ;ErrorLabel C
;stack deallocated implicitly

L52:            ;No action required

;*************************************************************************
; HAND MODIFICATIONS START
        cmp dword ptr [ebp-4],0
        jnz rnoconv
        cmp dword ptr [ebp-16],QUE_CONVERT_ADDRESS
        jne rnoconv
        mov eax,[edi]
        ror eax,16
        shr ax,3
        rol eax,16
        mov [edi],eax
rnoconv:
; HAND MODIFICATIONS STOP
;*************************************************************************

;Undo Pointer elprio --> elprio


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



        mov     edi,[ebp+32]            ;elprio original address

;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],al

L57:            ;No action required

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

;* 32-bit return code.

        mov     eax,[ebp-56]            ; (EAX) = handler chain head
        mov     fs:[tib_pexchain],eax   ; Restore handler chain head
        lea     esp,[ebp-52]    ; get the old stack
        pop     ecx                     ;get the new stack
        cmp     ecx,0                   ;is it new
        jz      L57A
        call    THK32FREESTACK          ;deallocate the memory
L57A:
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        mov     esp,ebp
        pop     ebp
        ret                             ; Remove parameters

DOS32READQUEUE endp

CODE32_TUNE2  ENDS                                                      ;MDLL

;* 16-bit code to make API call.

CODE_TUNE2   SEGMENT                                                    ;MDLL

        ASSUME CS:CODE_TUNE2                                            ;MDLL
        .errnz ($ - T_W_DOSREADQUEUE)

        call    FAR PTR W_DOSREADQUEUE          ; call 16-bit version
        jmp     FAR PTR FLAT:R_W_DOSREADQUEUE           ; jump back

CODE_TUNE2   ENDS                                                       ;MDLL


;Create a dummy label to trick MASM into correct fixups

CODE_TUNE2   SEGMENT                                                    ;MDLL

T_W_DOSWRITEQUEUE       LABEL FAR

CODE_TUNE2   ENDS                                                       ;MDLL


CODE32_TUNE2  SEGMENT                                                   ;MDLL
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32WRITEQUEUE PROC

        push    ebp
        mov     ebp,esp


        cld                     ;Assume direction flag clear
        push    0               ; temp storage for return value
        push    esi
        push    edi
        push    0               ; temp storage
        push    0               ;Error flag for cleanup
        push    0               ; temp storage for Stack Allocation Flags
        push    0               ; temp storage for BMP Flags
        push    0               ; temp storage for Alias Flags
        push    0               ; temp storage for ptr param #1

;* Set exception handler to capture any fatal traps on behalf of user (no
;* handler is needed since the one address passed in by the user is placed
;* in the queue and not referenced)

        push    0               ;push for stack comparison later (@[EBP-40])

;* 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 L59               ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L59
        call    THK32ALLOCSTACK         ; bump the stack down
        mov     dword ptr [ebp-40],eax  ;old stack comparator on old stack
        mov     esp,eax


;Insure that 1 DWORD exists on stack
        push    eax
L59:


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+20]            ;dataaddress base address

;Pointer dataaddress --> dataaddress
        or      esi,esi
        jz      L60

;Pointer Validation:    Read/Write Access
;
;This may or may not be an address, so don't validate!
;
;       mov     al,BYTE PTR [esi]
;       mov     BYTE PTR [esi],al

        mov     [ebp-36],esi

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

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

;Transfer 1 bytes
        movsb

L60:

; ****> 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: handle  Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVP_DOS32WRITEQUEUE

        push    ax              ;To:unsigned short


        ;From Name: request  Type: unsigned long
        push    DWORD PTR [ebp+12]      ; To: unsigned long


        ;From Name: datalength  Type: unsigned long
        push    DWORD PTR [ebp+16]      ; To: unsigned long


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

        call    DOS32FLATTOSEL

L63:    push    eax



        ;From Name: elprio  Type: unsigned long
        mov     eax,[ebp+24]
        cmp     eax,0ffffh
        ja      INVP_DOS32WRITEQUEUE

        push    ax              ;To:unsigned short


        ;From Name: flag  Type: unsigned short

;Extra parameter needed
        push    WORD PTR E_BIT32        ;Push u/short

;* 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_W_DOSWRITEQUEUE


INVP_DOS32WRITEQUEUE:
        mov     eax,ERROR_INVALID_PARAMETER
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L64

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

NOMEM_DOS32WRITEQUEUE:
        mov     eax,ERROR_NOT_ENOUGH_MEMORY
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L64
R_W_DOSWRITEQUEUE:                              ; 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
L64:
;Functions contain pointers, save return code
        mov     [ebp-4],eax             ;Save return code

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


;Undo Pointer dataaddress --> dataaddress


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



        mov     edi,[ebp+20]            ;dataaddress original address
;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      L65

;Item is fixed size
;stack deallocated implicitly

L65:            ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-40]    ; get the old stack
        pop     ecx                     ;get the new stack
        cmp     ecx,0                   ;is it new
        jz      L65A
        call    THK32FREESTACK          ;deallocate the memory
L65A:
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        mov     esp,ebp
        pop     ebp
        ret                             ; Remove parameters

DOS32WRITEQUEUE endp

CODE32_TUNE2  ENDS                                                      ;MDLL

;* 16-bit code to make API call.

CODE_TUNE2   SEGMENT                                                    ;MDLL

        ASSUME CS:CODE_TUNE2                                            ;MDLL
        .errnz ($ - T_W_DOSWRITEQUEUE)

        call    FAR PTR W_DOSWRITEQUEUE         ; call 16-bit version
        jmp     FAR PTR FLAT:R_W_DOSWRITEQUEUE          ; jump back

CODE_TUNE2   ENDS                                                       ;MDLL


;Create a dummy label to trick MASM into correct fixups

_TEXT   SEGMENT

T_W_DOSPEEKQUEUE        LABEL FAR

_TEXT   ENDS


CODE32  SEGMENT
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PEEKQUEUE PROC

        push    ebp
        mov     ebp,esp


        cld                     ;Assume direction flag clear
        push    0               ; temp storage for return value
        push    esi
        push    edi
        push    0               ; temp storage (flag from w_DOSPEEKQUEUE)
        push    0               ;Error flag for cleanup
        push    0               ; temp storage for Stack Allocation Flags
        push    0               ; temp storage for BMP Flags
        push    0               ; temp storage for Alias Flags
        push    0               ; temp storage for ptr param #1
        push    0               ; temp storage for ptr param #2
        push    0               ; temp storage for ptr param #3
        push    0               ; temp storage for ptr param #4
        push    0               ; temp storage for ptr param #5

;* Set exception handler to capture any fatal traps on behalf of user

        push    0               ;push for stack comparison later (@[EBP-56])
        mov     eax,DOS32TIB    ; Load FS in case user left it
        mov     fs,ax           ;  in corrupted state
        push    fs:[tib_pexchain] ; Save handler chain head (@[EBP-60])
        mov     eax,ebp         ; (EAX) = EBP (-> ESP)
        add     eax,4           ; (EAX) = ESP (-> Return EIP)
        push    eax             ; Save ESP (@[EBP-64])
        push    esi             ; Save ESI (@[EBP-68])
        push    edi             ; Save EDI (@[EBP-72])
        push    ebx             ; Save EBX (@[EBP-76])

        push    OFFSET FLAT:THK32XHNDLR
        push    0
        push    esp             ; -> Queue exception registration record
        call    DOS32SETEXCEPTIONHANDLER ; Install exception handler
        add     esp,4

;* 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 L70               ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L70
        call    THK32ALLOCSTACK         ; bump the stack down
        mov     dword ptr [ebp-56],eax  ;old stack comparator on old stack
        mov     esp,eax


;Insure that 1 DWORD exists on stack
        push    eax
L70:


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+12]            ;request base address

;Pointer request --> request
        or      esi,esi
        jz      L71

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-36],esi

;Structures are not Identical
;Structures don't have pointers

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

L71:


        mov     esi,[ebp+16]            ;datalength base address

;Pointer datalength --> datalength
        or      esi,esi
        jz      L72

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-40],esi

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

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

;Semantics are NOT input

L72:


        mov     esi,[ebp+20]            ;dataaddress base address

;Pointer dataaddress --> dataaddress
        or      esi,esi
        jz      L75

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-44],esi

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

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

;Semantics are NOT input

L75:


        mov     esi,[ebp+24]            ;elcode base address

;Pointer elcode --> elcode
        or      esi,esi
        jz      L78

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-48],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     L78                     ;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-48],edi
        mov     eax,[esi]
        cmp     eax,0ffffh
        ja      INVP_DOS32PEEKQUEUE             ;Jmp on large value

        mov     [edi],ax

L78:


        mov     esi,[ebp+32]            ;elprio base address

;Pointer elprio --> elprio
        or      esi,esi
        jz      L79

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-52],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     L79                     ;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-52],edi

L79:

; ****> 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: handle  Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVP_DOS32PEEKQUEUE

        push    ax              ;To:unsigned short


        ;From Name: request  Type: struct LOCATION32
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L80                       ;NULL pointer

        call    DOS32FLATTOSEL

L80:    push    eax



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

        call    DOS32FLATTOSEL

L81:    push    eax



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

        call    DOS32FLATTOSEL

L82:    push    eax



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

        call    DOS32FLATTOSEL

L83:    push    eax



        ;From Name: nowait  Type: unsigned long
        mov     eax,[ebp+28]
        cmp     eax,0ffffh
        ja      INVP_DOS32PEEKQUEUE

        push    ax              ;To:unsigned short


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

        call    DOS32FLATTOSEL

L84:    push    eax



        ;From Name: semhand  Type: unsigned long
        push    DWORD PTR [ebp+36]      ; To: unsigned long


        ;From Name: flag  Type: unsigned short

;Extra parameter required
        mov     eax,ebp
        sub     eax,16                  ; (EAX) = addr of temp storage (ebp-16)
        ror     eax,16
        shl     ax,3
        or      al,dl
        rol     eax,16
        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_W_DOSPEEKQUEUE


INVP_DOS32PEEKQUEUE:
        mov     eax,ERROR_INVALID_PARAMETER
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L85

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

NOMEM_DOS32PEEKQUEUE:
        mov     eax,ERROR_NOT_ENOUGH_MEMORY
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L85
R_W_DOSPEEKQUEUE:                               ; 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
L85:
;Functions contain pointers, save return code
        mov     [ebp-4],eax             ;Save return code

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


;Undo Pointer request --> request


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



        mov     edi,[ebp+12]            ;request original address

;Structures are not Identical
;Structures don't have pointers
;Structure has output semantics
;Return structure to original area


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

;Element processid --> processid

;USHORT --> ULONG

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

;Element requestdata --> requestdata

;Adjust registers after conversion
        add     esi,2
        add     edi,4
;Add 4 bytes of unsigned long to transfer

;Transfer 4 bytes
        movsd

L87:                    ;ErrorLabel D
;Deallocate Temporary Structure


;Stack allocated memory deallocated implicitly

L86:            ;No action required

;Undo Pointer datalength --> datalength


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



        mov     edi,[ebp+16]            ;datalength original address
;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      L88

;Item is fixed size

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

;Space was allocated on stack

;Transfer 4 bytes
        movsd

L92:                    ;ErrorLabel C
;stack deallocated implicitly

L88:            ;No action required

;Undo Pointer dataaddress --> dataaddress


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



        mov     edi,[ebp+20]            ;dataaddress original address
;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      L93

;Item is fixed size

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

;Space was allocated on stack

;Transfer 4 bytes
        movsd

;*************************************************************************
; HAND MODIFICATIONS START
        sub edi,4
; HAND MODIFICATIONS STOP
;*************************************************************************

L97:                    ;ErrorLabel C
;stack deallocated implicitly

L93:            ;No action required

;*************************************************************************
; HAND MODIFICATIONS START
        cmp dword ptr [ebp-4],0
        jnz pnoconv
        cmp dword ptr [ebp-16],QUE_CONVERT_ADDRESS
        jne pnoconv
        mov eax,[edi]
        ror eax,16
        shr ax,3
        rol eax,16
        mov [edi],eax
pnoconv:
; HAND MODIFICATIONS STOP
;*************************************************************************

;Undo Pointer elcode --> elcode


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



        mov     edi,[ebp+24]            ;elcode original address

;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

L98:            ;No action required

;Undo Pointer elprio --> elprio


        mov     esi,[ebp-52]            ;elprio temp address
        or      esi,esi
        jz      L99



        mov     edi,[ebp+32]            ;elprio original address

;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],al

L99:            ;No action required

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

;* 32-bit return code.

        mov     eax,[ebp-60]            ; (EAX) = handler chain head
        mov     fs:[tib_pexchain],eax   ; Restore handler chain head
        lea     esp,[ebp-56]    ; get the old stack
        pop     ecx                     ;get the new stack
        cmp     ecx,0                   ;is it new
        jz      L99A
        call    THK32FREESTACK          ;deallocate the memory
L99A:
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        mov     esp,ebp
        pop     ebp
        ret                             ; Remove parameters

DOS32PEEKQUEUE endp

CODE32  ENDS

;* 16-bit code to make API call.

_TEXT   SEGMENT

        ASSUME CS:_TEXT
        .errnz ($ - T_W_DOSPEEKQUEUE)

        call    FAR PTR W_DOSPEEKQUEUE          ; call 16-bit version
        jmp     FAR PTR FLAT:R_W_DOSPEEKQUEUE           ; jump back

_TEXT   ENDS


;Create a dummy label to trick MASM into correct fixups

_TEXT   SEGMENT

T_DOSPURGEQUEUE LABEL FAR

_TEXT   ENDS


CODE32  SEGMENT
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PURGEQUEUE PROC

        push    ebp
        mov     ebp,esp


;* Set exception handler to capture any fatal traps on behalf of user (no
;* handler is needed since there are no addresses passed in by the user)

        push    0               ;push for stack comparison later (@[EBP-4])

;* 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 L101              ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L101
        call    THK32ALLOCSTACK         ; bump the stack down
        mov     dword ptr [ebp-4],eax   ;old stack comparator on old stack
        mov     esp,eax


;Insure that 1 DWORD exists on stack
        push    eax
L101:


; ****> BEGIN Pointer/Structure Section


; ****> 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: handle  Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVP_DOS32PURGEQUEUE

        push    ax              ;To:unsigned short

;* 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_DOSPURGEQUEUE


INVP_DOS32PURGEQUEUE:
        mov     eax,ERROR_INVALID_PARAMETER
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L102
R_DOSPURGEQUEUE:                                ; 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
L102:

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


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

;* 32-bit return code.

        lea     esp,[ebp-4]     ; get the old stack
        pop     ecx                     ;get the new stack
        cmp     ecx,0                   ;is it new
        jz      L102A
        call    THK32FREESTACK          ;deallocate the memory
L102A:
        mov     esp,ebp
        pop     ebp
        ret                             ; Remove parameters

DOS32PURGEQUEUE endp

CODE32  ENDS

;* 16-bit code to make API call.

_TEXT   SEGMENT

        ASSUME CS:_TEXT
        .errnz ($ - T_DOSPURGEQUEUE)

        call    FAR PTR DOSPURGEQUEUE           ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSPURGEQUEUE            ; jump back

_TEXT   ENDS


;Create a dummy label to trick MASM into correct fixups

CODE_TUNE2   SEGMENT                                                    ;MDLL

T_DOSQUERYQUEUE LABEL FAR

CODE_TUNE2   ENDS                                                       ;MDLL


CODE32_TUNE2  SEGMENT                                                   ;MDLL
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32QUERYQUEUE PROC

        push    ebp
        mov     ebp,esp


        cld                     ;Assume direction flag clear
        push    0               ; temp storage for return value
        push    esi
        push    edi
        push    0               ; temp storage
        push    0               ;Error flag for cleanup
        push    0               ; temp storage for Stack Allocation Flags
        push    0               ; temp storage for BMP Flags
        push    0               ; temp storage for Alias Flags
        push    0               ; temp storage for ptr param #1

;* Set exception handler to capture any fatal traps on behalf of user

        push    0               ;push for stack comparison later (@[EBP-40])
        mov     eax,DOS32TIB    ; Load FS in case user left it
        mov     fs,ax           ;  in corrupted state
        push    fs:[tib_pexchain] ; Save handler chain head (@[EBP-44])
        mov     eax,ebp         ; (EAX) = EBP (-> ESP)
        add     eax,4           ; (EAX) = ESP (-> Return EIP)
        push    eax             ; Save ESP (@[EBP-48])
        push    esi             ; Save ESI (@[EBP-52])
        push    edi             ; Save EDI (@[EBP-56])
        push    ebx             ; Save EBX (@[EBP-60])

        push    OFFSET FLAT:THK32XHNDLR
        push    0
        push    esp             ; -> Queue exception registration record
        call    DOS32SETEXCEPTIONHANDLER ; Install exception handler
        add     esp,4

;* 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 L104              ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L104
        call    THK32ALLOCSTACK         ; bump the stack down
        mov     dword ptr [ebp-40],eax  ;old stack comparator on old stack
        mov     esp,eax


;Insure that 1 DWORD exists on stack
        push    eax
L104:


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+12]            ;numel base address

;Pointer numel --> numel
        or      esi,esi
        jz      L105

;Pointer Validation:    Read/Write Access

        mov     al,BYTE PTR [esi]
        mov     BYTE PTR [esi],al

        mov     [ebp-36],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     L105                    ;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-36],edi

L105:

; ****> 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: handle  Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVP_DOS32QUERYQUEUE

        push    ax              ;To:unsigned short


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

        call    DOS32FLATTOSEL

L106:   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_DOSQUERYQUEUE


INVP_DOS32QUERYQUEUE:
        mov     eax,ERROR_INVALID_PARAMETER
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L107

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

NOMEM_DOS32QUERYQUEUE:
        mov     eax,ERROR_NOT_ENOUGH_MEMORY
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L107
R_DOSQUERYQUEUE:                                ; 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
L107:
;Functions contain pointers, save return code
        mov     [ebp-4],eax             ;Save return code

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


;Undo Pointer numel --> numel


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



        mov     edi,[ebp+12]            ;numel original address

;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

L108:           ;No action required

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

;* 32-bit return code.

        mov     eax,[ebp-44]            ; (EAX) = handler chain head
        mov     fs:[tib_pexchain],eax   ; Restore handler chain head
        lea     esp,[ebp-40]    ; get the old stack
        pop     ecx                     ;get the new stack
        cmp     ecx,0                   ;is it new
        jz      L108A
        call    THK32FREESTACK          ;deallocate the memory
L108A:
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        mov     esp,ebp
        pop     ebp
        ret                             ; Remove parameters

DOS32QUERYQUEUE endp

CODE32_TUNE2  ENDS                                                      ;MDLL

;* 16-bit code to make API call.

CODE_TUNE2 SEGMENT                                                      ;MDLL

        ASSUME CS:CODE_TUNE2                                            ;MDLL
        .errnz ($ - T_DOSQUERYQUEUE)

        call    FAR PTR DOSQUERYQUEUE           ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSQUERYQUEUE            ; jump back

CODE_TUNE2 ENDS                                                         ;MDLL


;****************************************************************
;*** THUNK to call 32-bit Semaphore code from w_DosWriteQueue ***
;****************************************************************
; code which emulates following THUNK compiler directives
;
; API32         DOS32OPENEVENTSEM(PSZ semname, PULONG semhandle)
; API16         OPEN16EVENTSEM(ULONG semhandle)
; {
;   semhandle = input
; }
; OPEN16EVENTSEM => DOS32OPENEVENTSEM
;
;****************************************************************

;*******************************************
;**** 32 Bit code stub to make API call ****
;*******************************************

CODE32C SEGMENT

ASSUME CS:FLAT,DS:FLAT,ES:FLAT

Open16EventSem_T:

call    Dos32OpenEventSem        ;call 32 bit event semaphore open function
jmp     FAR PTR Open16EventSem_R ;return to 16 bit code

CODE32C ENDS


_TEXT  SEGMENT

ASSUME CS:_TEXT

_OPEN16EVENTSEM  PROC FAR

push    bp                      ;store old BP
mov     bp,sp                   ;point BP at current top of stack
push    ds                      ; save current ds
push    bx

movzx   eax,sp                  ; store old ss:sp for later use
push    ss
push    eax

;sub     sp,2                    ;dword align stack
and     sp,0FFFCh

;Now, convert bp so that old ss:sp can be restored after call to 32-bit
mov     ax,ss
shr     ax,3
shl     eax,16
mov     ax,bp
mov     ebp,eax                 ;eax now holds new EBP

;create call frame
; Dos32OpenEventSem takes 2 arguments; pointer to ASCIIZ semname and pointer
; to semhandle
lea     eax,[ebp+6]
push    eax                     ; push pointer to semhandle
push    DWORD   PTR 0           ; push null pointer for ASCIIZ name

;Now, convert stack pointer
mov     ax,sp                   ;eax now holds new ESP

;based on current SS CPL bits, we need to load new segment registers
mov     bx,ss
and     bx,03h
cmp     bx,03h
jne     O_NotRing3

push    SEG FLAT:DATA32         ;push selector for ring 3 code onto stack
mov     bx,SEG FLAT:DATA32
jmp     O_SegmentSwitch

O_NotRing3:                     ;If not ring 3, then must be ring 2.
                                ;   Ring 0 not allowed.

push    THK32R2SS               ;push selector for ring 2 code onto stack
mov     bx,SEG FLAT:DATA32
dec     bx

O_SegmentSwitch:

push    eax                     ;push new ESP onto stack

movzx   esp,sp                  ;zero extend stack pointer
lss     esp,[esp]               ;move new stack pointer from stack into ESP

mov     ds,bx                   ;move new data segment into ds

;Make call to 32-bit code to make call to 32-bit function
jmp     FAR PTR FLAT:Open16EventSem_T

Open16EventSem_R:

;Restore stack
lss     esp,[ebp-10]            ;must reference esp from ebp since
                                ;  stack was word-aligned
pop     bx
pop     ds

mov     sp,bp                   ;restore stack pointer
pop     bp
ret     0

_OPEN16EVENTSEM  ENDP

_TEXT  ENDS


;****************************************************************
;*** THUNK to call 32-bit Semaphore code from w_DosWriteQueue ***
;****************************************************************
; code which emulates following THUNK compiler directives
;
; API32         DOS32POSTEVENTSEM(ULONG semhandle)
; API16         POST16EVENTSEM(ULONG semhandle)
; {
;   semhandle = input
; }
; POST16EVENTSEM => DOS32POSTEVENTSEM
;
;****************************************************************

;*******************************************
;**** 32 Bit code stub to make API call ****
;*******************************************

CODE32C SEGMENT

ASSUME CS:FLAT,DS:FLAT,ES:FLAT

Post16EventSem_T:

call    Dos32PostEventSem        ;call 32 bit event semaphore clear function
jmp     FAR PTR Post16EventSem_R ;return to 16 bit code

CODE32C ENDS


_TEXT  SEGMENT

ASSUME CS:_TEXT

_POST16EVENTSEM  PROC FAR

push    bp                      ;store old BP
mov     bp,sp                   ;point BP at current top of stack
push    ds                      ; save current ds
push    bx

movzx   eax,sp                  ; store old ss:sp for later use
push    ss
push    eax

;sub     sp,2                    ;dword align stack
and     sp,0FFFCh

;create call frame
;ULONG
push    DWORD   PTR [bp+6]      ; push pointer to semhandle onto stack

;Now, convert bp so that old ss:sp can be restored after call to 32-bit
mov     ax,ss
shr     ax,3
shl     eax,16
mov     ax,bp
mov     ebp,eax                 ;eax now holds new EBP

;Now, convert stack pointer
mov     ax,sp                   ;eax now holds new ESP

;based on current SS CPL bits, we need to load new segment registers
mov     bx,ss
and     bx,03h
cmp     bx,03h
jne     W_NotRing3

push    SEG FLAT:DATA32         ;push selector for ring 3 code onto stack
mov     bx,SEG FLAT:DATA32
jmp     W_SegmentSwitch

W_NotRing3:                     ;If not ring 3, then must be ring 2.
                                ;   Ring 0 not allowed.

push    THK32R2SS               ;push selector for ring 2 code onto stack
mov     bx,SEG FLAT:DATA32
dec     bx

W_SegmentSwitch:

push    eax                     ;push new ESP onto stack

movzx   esp,sp                  ;zero extend stack pointer
lss     esp,[esp]               ;move new stack pointer from stack into ESP

mov     ds,bx                   ;move new data segment into ds

;Make call to 32-bit code to make call to 32-bit function
jmp     FAR PTR FLAT:Post16EventSem_T

Post16EventSem_R:

;Restore stack
lss     esp,[ebp-10]            ;must reference esp from ebp since
                                ;  stack was word-aligned
pop     bx
pop     ds

mov     sp,bp                   ;restore stack pointer
pop     bp
ret     0

_POST16EVENTSEM  ENDP

_TEXT  ENDS


;****************************************************************
;*** THUNK to call 32-bit Semaphore code from w_DosReadQueue  ***
;***   and w_DosPeekQueue                                     ***
;****************************************************************
; code which emulates following THUNK compiler directives
;
; API32         DOS32RESETEVENTSEM(ULONG semhandle, PULONG postcnt)
; API16         RESET16EVENTSEM(ULONG semhandle)
; {
;   semhandle = input
; }
; RESET16EVENTSEM => DOS32RESETEVENTSEM
;
;****************************************************************

;*******************************************
;**** 32 Bit code stub to make API call ****
;*******************************************

CODE32C SEGMENT

ASSUME CS:FLAT,DS:FLAT,ES:FLAT

Reset16EventSem_T:

call    Dos32ResetEventSem        ;call 32 bit event semaphore set function
jmp     FAR PTR Reset16EventSem_R ;return to 16 bit code

CODE32C ENDS



_TEXT  SEGMENT

ASSUME CS:_TEXT

_RESET16EVENTSEM  PROC FAR

; store old BP and point new BP at current top of stack
push    bp                      ;store old BP
mov     bp,sp                   ;point BP at current top of stack
push    ds                      ; save current ds
push    bx

movzx   eax,sp                  ; store ss:sp for later use
push    ss
push    eax

;sub     sp,2                    ;dword align stack
and     sp,0FFFCh

mov     edx,DWORD PTR [bp+6]    ; save semhandle for later use when building
                                ; 32-bit stack frame

; Now, convert bp so that old ss:sp can be restored after call to 32-bit
mov     ax,ss
shr     ax,3
shl     eax,16
mov     ax,bp                   ;eax now holds new EBP
mov     ebp,eax

;Now, convert stack pointer
mov     ax,sp                   ;eax now holds new ESP

;based on current SS CPL bits, we need to load new segment registers
mov     bx,ss
and     bx,03h
cmp     bx,03h
jne     R_NotRing3

push    SEG FLAT:DATA32         ;push selector for ring 3 code onto stack
mov     bx,SEG FLAT:DATA32
jmp     R_SegmentSwitch

R_NotRing3:                     ;If not ring 3, then must be ring 2.
                                ;  Ring 0 not allowed.

push    THK32R2SS               ;push selector for ring 2 code onto stack
mov     bx,SEG FLAT:DATA32
dec     bx

R_SegmentSwitch:

push    eax                     ;push new ESP onto stack

movzx   esp,sp                  ;zero extend stack pointer
lss     esp,[esp]               ;move new stack pointer from stack into ESP

; create 32-bit call frame
; Dos32ResetEventSem takes 2 arguments; semhandle and a pointer to a long
; word in which is returned the 'post count' for the semaphore.
;
push    dword ptr 0             ; make room for 'Post count' variable
push    esp                     ; address of above variable
push    edx                     ; semhandle passed by caller

mov     ds,bx                   ;move new data segment into ds

;Make call to 32-bit code to make call to 32-bit function
jmp     FAR PTR FLAT:Reset16EventSem_T

Reset16EventSem_R:

;Restore stack
lss     esp,[ebp-10]            ;must reference esp from ebp since
                                ;  stack was word-aligned
pop     bx
pop     ds

mov     sp,bp                   ;restore stack pointer
pop     bp
ret     0                       ;remove parameters

_RESET16EVENTSEM  ENDP

_TEXT  ENDS


;****************************************************************
;*** THUNK to call 32-bit Semaphore code from w_DosReadQueue  ***
;***   and w_DosPeekQueue         Defect 65343  D.B.          ***
;****************************************************************
; code which emulates following THUNK compiler directives
;
; API32         DOS32CLOSEEVENTSEM(ULONG semhandle)
; API16         CLOSE16EVENTSEM(ULONG semhandle)
; {
;   semhandle = input
; }
; CLOSE16EVENTSEM => DOS32CLOSEEVENTSEM
;
;****************************************************************

;*******************************************
;**** 32 Bit code stub to make API call ****
;*******************************************

CODE32C SEGMENT

ASSUME CS:FLAT,DS:FLAT,ES:FLAT

Close16EventSem_T:

call    Dos32CloseEventSem        ;call 32 bit event semaphore close function
jmp     FAR PTR Close16EventSem_R ;return to 16 bit code

CODE32C ENDS


_TEXT  SEGMENT

ASSUME CS:_TEXT

_CLOSE16EVENTSEM  PROC FAR

push    bp                      ;store old BP
mov     bp,sp                   ;point BP at current top of stack
push    ds                      ; save current ds
push    bx

movzx   eax,sp                  ; store old ss:sp for later use
push    ss
push    eax

;sub     sp,2                    ;dword align stack
and     sp,0FFFCh

;create call frame
;ULONG
push    DWORD   PTR [bp+6]      ; push pointer to semhandle onto stack

;Now, convert bp so that old ss:sp can be restored after call to 32-bit
mov     ax,ss
shr     ax,3
shl     eax,16
mov     ax,bp
mov     ebp,eax                 ;eax now holds new EBP

;Now, convert stack pointer
mov     ax,sp                   ;eax now holds new ESP

;based on current SS CPL bits, we need to load new segment registers
mov     bx,ss
and     bx,03h
cmp     bx,03h
jne     C_NotRing3

push    SEG FLAT:DATA32         ;push selector for ring 3 code onto stack
mov     bx,SEG FLAT:DATA32
jmp     C_SegmentSwitch

C_NotRing3:                     ;If not ring 3, then must be ring 2.
                                ;   Ring 0 not allowed.

push    THK32R2SS               ;push selector for ring 2 code onto stack
mov     bx,SEG FLAT:DATA32
dec     bx

C_SegmentSwitch:

push    eax                     ;push new ESP onto stack

movzx   esp,sp                  ;zero extend stack pointer
lss     esp,[esp]               ;move new stack pointer from stack into ESP

mov     ds,bx                   ;move new data segment into ds

;Make call to 32-bit code to make call to 32-bit function
jmp     FAR PTR FLAT:Close16EventSem_T

Close16EventSem_R:

;Restore stack
lss     esp,[ebp-10]            ;must reference esp from ebp since
                                ;  stack was word-aligned
pop     bx
pop     ds

mov     sp,bp                   ;restore stack pointer
pop     bp
ret     0

_CLOSE16EVENTSEM  ENDP

_TEXT  ENDS


;MDLL CODE32  SEGMENT
;MDLL         ASSUME CS:FLAT,DS:FLAT,ES:FLAT
;MDLL QUEINIT PROC
;MDLL
;MDLL         push    ebp
;MDLL         mov     ebp,esp
;MDLL
;MDLL
;MDLL         push    0               ;push for stack comparison later (@[EBP-4])
;MDLL
;MDLL ;* Compare stack selector against FLAT:R3DSB
;MDLL ;* If the selector is not equal, then don't bump stack.
;MDLL
;MDLL         mov     ax,ss
;MDLL         cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
;MDLL         jne     short L110              ; if not, skip bumping code
;MDLL
;MDLL ;* Bump the stack down if too near 64K boundary.
;MDLL
;MDLL         mov     eax,esp
;MDLL         cmp     ax,1024
;MDLL         jae     short L110
;MDLL         call    THK32ALLOCSTACK         ; bump the stack down
;MDLL         mov     dword ptr [ebp-4],eax   ;old stack comparator on old stack
;MDLL         mov     esp,eax
;MDLL
;MDLL
;MDLL ;Insure that 1 DWORD exists on stack
;MDLL         push    eax
;MDLL L110:
;MDLL
;MDLL
;MDLL ; ****> BEGIN Pointer/Structure Section
;MDLL
;MDLL
;MDLL ; ****> END Pointer/Structure Section
;MDLL
;MDLL ;* Create new call frame, using 16-bit semantics.
;MDLL
;MDLL         push    es
;MDLL         push    ebp                     ; save ebp
;MDLL         mov     eax,esp                 ; save current esp
;MDLL         push    ss
;MDLL         push    eax
;MDLL
;MDLL
;MDLL         mov     dx,ss                   ; get cpl bits to use as dpl bits
;MDLL         and     dx,3                    ; mask off rest of register
;MDLL
;MDLL         or      dl,4                    ;Force LDT bit on
;MDLL
;MDLL ;* Convert SS:ESP to 16-bit SS:SP.
;MDLL
;MDLL         mov     eax,esp                 ; use CRMA on ESP
;MDLL         ror     eax,16
;MDLL         shl     ax,3
;MDLL         or      al,dl
;MDLL         rol     eax,16
;MDLL
;MDLL         push    eax                     ; push new stack pointer
;MDLL         lss     sp,DWORD PTR [esp]      ; ss:sp = 16-bit ptr
;MDLL
;MDLL ;* Jump to 16-bit segment to issue call (so that 16-bit API can RETF).
;MDLL
;MDLL         jmp     FAR PTR T__DYNAINIT
;MDLL
;MDLL
;MDLL INVP_QUEINIT:
;MDLL         mov     eax,ERROR_INVALID_PARAMETER
;MDLL         mov     BYTE PTR [ebp-20],1             ;Set flag
;MDLL         jmp     short L111
;MDLL R__DYNAINIT:                            ; label defining return jmp location
;MDLL
;MDLL
;MDLL ;* Restore 32-bit SS:ESP - it is on top of stack.
;MDLL
;MDLL         movzx   esp,sp                  ; make sure that esp is correct
;MDLL         lss     esp,[esp]
;MDLL         pop     ebp
;MDLL         pop     es
;MDLL
;MDLL
;MDLL
;MDLL ;Convert Return Code
;MDLL ;USHORT --> ULONG
;MDLL         movzx   eax,ax
;MDLL L111:
;MDLL
;MDLL ; ****> BEGIN Pointer/Structure Unpack Section
;MDLL
;MDLL
;MDLL ; ****> END Pointer/Structure Unpack Section
;MDLL
;MDLL ;* 32-bit return code.
;MDLL
;MDLL         lea     esp,[ebp-4]     ; get the old stack
;MDLL         pop     ecx                     ;get the new stack
;MDLL         cmp     ecx,0                   ;is it new
;MDLL         jz      L111A
;MDLL         call    THK32FREESTACK          ;deallocate the memory
;MDLL L111A:
;MDLL         mov     esp,ebp
;MDLL         pop     ebp
;MDLL         ret                             ; Remove parameters
;MDLL
;MDLL QUEINIT endp
;MDLL
;MDLL CODE32  ENDS
;MDLL
;MDLL ;* 16-bit code to make API call.
;MDLL
;MDLL ;Create a dummy label to trick MASM into correct fixups
;MDLL
;MDLL _TEXT   SEGMENT
;MDLL
;MDLL T__DYNAINIT     LABEL FAR
;MDLL
;MDLL _TEXT   ENDS
;MDLL
;MDLL
;MDLL _TEXT   SEGMENT
;MDLL
;MDLL         ASSUME CS:_TEXT
;MDLL         .errnz ($ - T__DYNAINIT)
;MDLL
;MDLL         call    FAR PTR _DYNAINIT               ; call 16-bit version
;MDLL         jmp     FAR PTR FLAT:R__DYNAINIT                ; jump back
;MDLL
;MDLL _TEXT   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

THK32XHNDLR PROC

        mov     eax,[esp+4]                     ; (EAX) = -> Xcpt Report Rec
        mov     eax,[eax].ExceptionNum          ; (EAX) = exception number
        cmp     eax,XCPT_ACCESS_VIOLATION       ; Is this access violation?
        je      short TEHTrap                   ; Yes, handle exception
        mov     eax,XCPT_CONTINUE_SEARCH        ; No, don't handle exception
        ret                                     ;  and return to dispatcher

TEHTrap:
        mov     eax,[esp+8]                     ; (EAX) = -> Xcpt Reg Rec
        mov     ecx,[eax].TERR_CHN              ; (ECX) = handler chain head
        mov     fs:[tib_pexchain],ecx           ; Restore handler chain head
        mov     ecx,[eax].TERR_STK              ; (ECX) = -> Thunk stack
        mov     ebx,[eax].TERR_EBX              ; Restore EBX
        mov     edi,[eax].TERR_EDI              ; Restore EDI
        mov     esi,[eax].TERR_ESI              ; Restore ESI
        mov     eax,[eax].TERR_ESP              ; (EAX) = ESP
        mov     esp,eax                         ; Restore ESP
        mov     ebp,[esp-4]                     ; Restore EBP from stack
        cmp     ecx,0                           ; Was thunk stack allocated?
        je      TEHExit                         ; No, return to user
        call    THK32FREESTACK                  ; Yes, free thunk stack

TEHExit:
        mov     eax,ERROR_INVALID_PARAMETER     ; Set return code
        ret                                     ; Return to user

THK32XHNDLR ENDP
CODE32  ENDS

;*************************************************************************
; HAND MODIFICATIONS START
        END ;QUEINIT                                                    ;MDLL
; HAND MODIFICATIONS STOP
;*************************************************************************

