;**********************************************************************
;      SCCSID = @(#)doseathk.asm        6.6 92/03/04
;
;        IBM/Microsoft Confidential
;
;        Copyright (c) IBM Corporation 1987, 1989
;        Copyright (c) Microsoft Corporation 1987, 1989
;
;        All Rights Reserved
;
; Hand coded thunks for Doscall1.dll
;
; These thunks handle the API's which require EA buffers.
;
;***  Change History:                                             ***
;***   noto  11/18/93  Define which segment for Page Tuning DLL   ***
;***                                                              ***
; 01/09/95  Change Team   108596  subroutine: DOS32PFINDFIRST            ;108596
; After copying the internal buffer to the user's buffer, DS:SI contains the    ;108596 
; address pointing to the end of the internal buffer.  When thk32freealias   ;108596
; is called to free the memory allocated to the internal buffer it fails.           ;108596
; After THK32COPYBLOCK is called pop edi so that it contains the              ;108596
; starting address of the internal buffer.                                                         ;108596

include error.inc
include dc1segs.inc
        TITLE   $doseathk.asm

        .386

; External Public Variables for converting pointers in packed region.

EXTRN   FenceLAddr:dword

PUBLIC  DOS32POPEN
PUBLIC  DOS32PPROTECTOPEN
PUBLIC  DOS32PQUERYFILEINFO
PUBLIC  DOS32PPROTECTQUERYFILEINFO
PUBLIC  DOS32PENUMATTRIBUTE
PUBLIC  DOS32PPROTECTENUMATTRIBUTE
PUBLIC  DOS32PCREATEDIR
PUBLIC  DOS32PSETFILEINFO
PUBLIC  DOS32PPROTECTSETFILEINFO
PUBLIC  DOS32PFINDFIRST
PUBLIC  DOS32PQUERYPATHINFO
PUBLIC  DOS32PSETPATHINFO


CODE32_TUNE1  SEGMENT DWORD USE32 PUBLIC 'CODE'
EXTRN   DOS32ALLOCMEM:NEAR
EXTRN   DOS32FREEMEM:NEAR
EXTRN   THK32FREEBLOCK:NEAR
EXTRN   THK32HANDLESTRING:NEAR
EXTRN   DOS32FLATTOSEL:NEAR            ; External Routines for converting
CODE32_TUNE1  ENDS

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

CODE32_TUNE3  SEGMENT DWORD USE32 PUBLIC 'CODE'
CODE32_TUNE3  ENDS

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

CODE32  SEGMENT DWORD USE32 PUBLIC 'CODE'
EXTRN   THK32ALIASMEM:NEAR
EXTRN   THK32ALLOCSTACK:NEAR           ; ABest- to fix DOS32POPEN stack alloc
EXTRN   THK32FREESTACK:NEAR            ; ABest- to fix DOS32POPEN stack alloc
CODE32  ENDS

DATA32  SEGMENT

DATA32  ENDS

EXTRN   DOSOPEN2:FAR
EXTRN   DOSPROTECTOPEN:FAR
EXTRN   DOSIFINDFIRST:FAR
EXTRN   DOSFINDNEXT:FAR
EXTRN   DOSMKDIR2:FAR
EXTRN   DOSENUMATTRIBUTE:FAR
EXTRN   DOSPROTECTENUMATTRIBUTE:FAR

EXTRN   DOSQFILEINFO:FAR
EXTRN   DOSPROTECTQFILEINFO:FAR
EXTRN   DOSQPATHINFO:FAR
EXTRN   DOSISETFILEINFO:FAR
EXTRN   DOSIPROTECTSETFILEINFO:FAR
EXTRN   DOSISETPATHINFO:FAR


CODE16C_TUNE1 SEGMENT DWORD USE16 PUBLIC 'CODE'
CODE16C_TUNE1 ENDS
CODE16C_TUNE2 SEGMENT DWORD USE16 PUBLIC 'CODE'
CODE16C_TUNE2 ENDS
CODE16C_TUNE3 SEGMENT DWORD USE16 PUBLIC 'CODE'
CODE16C_TUNE3 ENDS
CODE16C_TUNE4 SEGMENT DWORD USE16 PUBLIC 'CODE'
CODE16C_TUNE4 ENDS
CODE16C SEGMENT DWORD USE16 PUBLIC 'CODE'
CODE16C ENDS


;Create a dummy label to trick MASM into correct fixups


CODE16C_TUNE2 SEGMENT

T_DOSOPEN2      LABEL FAR

CODE16C_TUNE2 ENDS


CODE32_TUNE2  SEGMENT
; align 4 54686
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32POPEN 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 storage
        push    eax             ;Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags
        push    eax             ; temp storage for ptr param #1
        push    eax             ; temp storage for ptr param #2
        push    eax             ; temp storage for ptr param #3
        push    eax             ; temp storage for ptr param #4
        push    eax             ; temp storage for ptr param #5
        push    eax             ; temp storage for ptr param #6
;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

        push    0000            ; ABest- to fix DOS32POPEN stack alloc
        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           ; ABest- to fix DOS32POPEN stack alloc

        pop     ecx             ; ABest- to fix DOS32POPEN stack alloc
        call    THK32ALLOCSTACK ; ABest- to fix DOS32POPEN stack alloc
        push    eax             ; ABest- to fix DOS32POPEN stack alloc

        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+8]             ; base address

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

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

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

L2:


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

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

        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     L3                      ;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

L3:


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

;Pointer pusAction --> pusAction
        or      esi,esi
        jz      L4

        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     L4                      ;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

L4:


        mov     esi,[ebp+36]            ;pEABuf base address

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

        mov     [ebp-48],esi

;Structures are Identical
;Structures have pointers

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


;Element fpGEAList --> fpGEAList
;Pointer converted later

;Element fpFEAList --> fpFEAList
;Pointer converted later

;Element offError --> offError
;Add 4 bytes of unsigned long to transfer

;Transfer 12 bytes

        mov     ecx,3
        rep     movsd

;***KWR
;
; The fpGEAList is ignored by DosOpen2, and therefore will be
; ignored here.

;Fixup imbedded pointer fpFEAList

        mov     esi,[ebp-48]            ;Get parents pointer
        mov     esi,[esi+4]             ;Get Fixups pointer

;Pointer fpFEAList --> fpFEAList
        or      esi,esi
        jz      L10

        mov     [ebp-56],esi

;Structures are Identical
;Structures don't have pointers

;Treat structure same as buffer

;The length of this structure is the first DWORD.
;Get the length, and insure that it doesn't cross a boundary.

        mov     eax,[esi]
        movzx   ecx,ax
        cmp     eax,ecx
        jne     INVPDOS32POPEN

        mov     eax,esi
        neg     ax
        jz      L10

        cmp     ax,cx
        jae     L10

;
        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEMDOS32POPEN
        mov     [ebp-56],edi
        or      edx,edx
        js      short L8                ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],64            ;Set Flag
        dec     edx
        js      short L10               ;Aliases not copied

L8:                     ;Variable Length Copy

; Copy ECX bytes from ESI to EDI
        push    esi

        call    THK32COPYBLOCK

        pop     esi

L10:

;Patch in new pointer value
        mov     edi,[ebp-48]            ;Get parents pointer
        mov     esi,[ebp-56]            ;Get Fixups new pointer
;Convert 0:32 --> 16:16
        or      esi,esi
        jz      short L13

        cmp     esi,[FenceLAddr]
        jae     L13CRMA
        mov     eax,esi
        call    DOS32FLATTOSEL
        mov     esi,eax
        jmp     short L13

L13CRMA:
        ror     esi,16
        shl     si,3
        mov     ax,ss
        and     ax,3
        or      al,4
        or      si,ax
        rol     esi,16

L13:
        mov     [edi+4],esi             ;Put Fixups pointer

L5:

; ****> END Pointer/Structure Section

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

        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: string
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L14                       ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     L14CRMA
        call    DOS32FLATTOSEL
        jmp     short L14

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

L14:    push    eax


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

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



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

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



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


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

        push    ax              ;To:unsigned short


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

        push    ax              ;To:unsigned short


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


        ;From Name: pEABuf  Type: struct EAOP
        mov     eax,DWORD PTR [ebp-48]
        or      eax,eax
        jz      short L17                       ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     L17CRMA
        call    DOS32FLATTOSEL
        jmp     short L17

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

L17:    push    eax


        ;From Name:   Type: unsigned long

;Extra parameter needed: Push a zero
        push    0               ;Push U/LONG

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


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

NOMEMDOS32POPEN:
        push    8
        pop     eax

ERRDOS32POPEN:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L18
R_DOSOPEN2:                             ; 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


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

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


;Undo Pointer  -->


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



        mov     edi,[ebp+8]             ; 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      L19
;Handle String Parameters
;Strings are never copied out
        push    -32             ;Alloc Flag Offset
        mov     edx,1

        call    THK32DEALLOC


L19:            ;No action required

;Undo Pointer phf --> phf


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



        mov     edi,[ebp+12]            ;phf 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

L23:            ;No action required

;Undo Pointer pusAction --> pusAction


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



        mov     edi,[ebp+16]            ;pusAction 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

L24:            ;No action required

;Undo Pointer pEABuf --> pEABuf


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



        mov     edi,[ebp+36]            ;pEABuf original address

;Structures are Identical
;Structures have pointers
;Structure has output semantics
;Return structure to original area


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

;Element fpGEAList --> fpGEAList
;Pointer elements not copied out
;Element fpFEAList --> fpFEAList
;Pointer elements not copied out

;Copy out only the oError value

        mov     eax,[esi+8]
        mov     [edi+8],eax

L26:                    ;ErrorLabel D

;Unpack imbedded pointer fpFEAList

        mov     esi,[ebp-56]            ;Get pointer to temporary
        or      esi,esi         ;Ignore if NULL
        jz      L32

        cmp     [edi+4],esi
        je      L32

        push    -32
        mov     edx,64
        call    THK32DEALLOC


L32:

;Deallocate Temporary Structure


;Stack allocated memory deallocated implicitly

L25:            ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-60]    ; ABest- to fix DOS32POPEN stack alloc
        pop     ecx             ; ABest- to fix DOS32POPEN stack alloc
;TPL01  cmp     ecx,0           ; ABest- to fix DOS32POPEN stack alloc
        jecxz   short STACKFIX  ; ABest- to fix DOS32POPEN stack alloc
        call    THK32FREESTACK  ; ABest- to fix DOS32POPEN stack alloc
STACKFIX:                       ; ABest- to fix DOS32POPEN stack alloc

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

DOS32POPEN endp

CODE32_TUNE2  ENDS

;* 16-bit code to make API call.

CODE16C_TUNE2 SEGMENT

        ASSUME CS:CODE16C_TUNE2
        .errnz ($ - T_DOSOPEN2)

        call    FAR PTR DOSOPEN2                ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSOPEN2         ; jump back

CODE16C_TUNE2 ENDS


CODE16C SEGMENT

T_DOSPROTECTOPEN      LABEL FAR

CODE16C ENDS

CODE32  SEGMENT
;ALIGN 4
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PPROTECTOPEN 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 storage
        push    eax             ;Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags
        push    eax             ; temp storage for ptr param #1
        push    eax             ; temp storage for ptr param #2
        push    eax             ; temp storage for ptr param #3
        push    eax             ; temp storage for ptr param #4
        push    eax             ; temp storage for ptr param #5
        push    eax             ; temp storage for ptr param #6
        push    eax             ; temp storage for ptr param #7 (new)
;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

        push    0000            ; ABest- to fix DOS32POPEN stack alloc
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short PL1                ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short PL1

;       xor     ax,ax           ; ABest- to fix DOS32POPEN stack alloc

        pop     ecx             ; ABest- to fix DOS32POPEN stack alloc
        call    THK32ALLOCSTACK ; ABest- to fix DOS32POPEN stack alloc
        push    eax             ; ABest- to fix DOS32POPEN stack alloc

        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+8]             ; base address

;Pointer  -->  pszFileName
        or      esi,esi
        jz      PL2

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

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

PL2:


        mov     esi,[ebp+12]       ;phf base address (filehandle buffer ptr)

;Pointer phf --> phf
        or      esi,esi
        jz      PL3

        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                ;Enough room for 4 bytes?
        jbe     PL3                      ;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

PL3:


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

;Pointer pusAction --> pusAction
        or      esi,esi
        jz      PL4

        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     PL4                      ;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

PL4:

        mov     esi,[ebp+36]            ;pEABuf base address

;Pointer pEABuf --> pEABuf
        or      esi,esi
        jz      PL5

;        mov     [ebp-48],esi  old code
        mov     [ebp-52],esi

;Structures are Identical
;Structures have pointers

; Allocate space on stack
        sub     esp,12                  ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
;        mov     [ebp-48],edi   old code
        mov     [ebp-52],edi
;Copy structure to new area


;Element fpGEAList --> fpGEAList
;Pointer converted later

;Element fpFEAList --> fpFEAList
;Pointer converted later

;Element offError --> offError
;Add 4 bytes of unsigned long to transfer

;Transfer 12 bytes

        mov     ecx,3
        rep     movsd

;***KWR
;
; The fpGEAList is ignored by DosOpen2, and therefore will be
; ignored here.

;Fixup imbedded pointer fpFEAList

;        mov     esi,[ebp-48]  old code  Get parents pointer
        mov     esi,[ebp-52]            ;Get parents pointer
        mov     esi,[esi+4]             ;Get Fixups pointer

;Pointer fpFEAList --> fpFEAList
        or      esi,esi
        jz      PL10

;        mov     [ebp-56],esi  old code
        mov     [ebp-60],esi

;Structures are Identical
;Structures don't have pointers

;Treat structure same as buffer

;The length of this structure is the first DWORD.
;Get the length, and insure that it doesn't cross a boundary.

        mov     eax,[esi]
        movzx   ecx,ax
        cmp     eax,ecx
        jne     INVPDOS32PPOPEN

        mov     eax,esi
        neg     ax
        jz      PL10

        cmp     ax,cx
        jae     PL10

;
        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEMDOS32PPOPEN
;        mov     [ebp-56],edi  old code
        mov     [ebp-60],edi
        or      edx,edx
        js      short PL8                ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],64            ;Set Flag
        dec     edx
        js      short PL10               ;Aliases not copied

PL8:                     ;Variable Length Copy

; Copy ECX bytes from ESI to EDI
        push    esi

        call    THK32COPYBLOCK

        pop     esi

PL10:

;Patch in new pointer value
;        mov     edi,[ebp-48]  old code  Get parents pointer
        mov     edi,[ebp-52]            ;Get parents pointer
;        mov     esi,[ebp-56]  old code  Get Fixups new pointer
        mov     esi,[ebp-60]            ;Get Fixups new pointer
;Convert 0:32 --> 16:16
        or      esi,esi
        jz      short PL13

        cmp     esi,[FenceLAddr]
        jae     PL13CRMA
        mov     eax,esi
        call    DOS32FLATTOSEL
        mov     esi,eax
        jmp     short PL13

PL13CRMA:
        ror     esi,16
        shl     si,3
        mov     ax,ss
        and     ax,3
        or      al,4
        or      si,ax
        rol     esi,16

PL13:
        mov     [edi+4],esi             ;Put Fixups pointer

PL5:
        mov     esi,[ebp+40]     ;pFilehandleLockID base address

;Pointer pFileHandleLockID --> pFileHandleLockID
        or      esi,esi
        jz      PL5a

        mov     [ebp-48],esi

;Check Boundary Crossing - fixed size item
        cmp     si,65532                ;Enough room for 4 bytes?
        jbe     PL5a                     ;Enough room

        xor     esi, esi                ; create NULL pFileHandleLockID
        mov     [ebp-48],esi            ;

;; Allocate space on stack. this code probably not needed since parm is defined
;; as a DWORD
;
;        sub     esp,4                   ;Alloc Mem
;        and     esp,0FFFFFFFCh          ;DWORD align
;        mov     edi,esp                 ;Points to new data area
;        mov     [ebp-48],edi

PL5a:

; ****> END Pointer/Structure Section

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

        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: string
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short PL14                       ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     PL14CRMA
        call    DOS32FLATTOSEL
        jmp     short PL14

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

PL14:    push    eax


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

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



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

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



        ;From Name:   Type: unsigned long, cbFile (file size)
        push    DWORD PTR [ebp+20]      ; To: unsigned long


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

        push    ax              ;To:unsigned short


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

        push    ax              ;To:unsigned short


        ;From Name:   Type: unsigned long, fsOpenMode
        push    DWORD PTR [ebp+32]      ; To: unsigned long


        ;From Name: pEABuf  Type: struct EAOP
;        mov     eax,DWORD PTR [ebp-48] old code
        mov     eax,DWORD PTR [ebp-52]
        or      eax,eax
        jz      short PL17                       ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     PL17CRMA
        call    DOS32FLATTOSEL
        jmp     short PL17

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

PL17:    push    eax

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

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


        ;From Name:   Type: unsigned long

;Extra parameter needed: Push a zero
        push    0               ;Push U/LONG

;* 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_DOSOPEN2   old code
        jmp     FAR PTR T_DOSPROTECTOPEN


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

NOMEMDOS32PPOPEN:
        push    8
        pop     eax

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

; R_DOSOPEN2:                   old code         label defining return jmp location
R_DOSPROTECTOPEN:                       ; 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


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

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


;Undo Pointer  -->


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



        mov     edi,[ebp+8]             ; 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      PL19
;Handle String Parameters
;Strings are never copied out
        push    -32             ;Alloc Flag Offset
        mov     edx,1

        call    THK32DEALLOC


PL19:            ;No action required

;Undo Pointer phf --> phf


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



        mov     edi,[ebp+12]            ;phf 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

PL23:            ;No action required

;Undo Pointer pusAction --> pusAction


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



        mov     edi,[ebp+16]            ;pusAction 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

PL24:            ;No action required

;Undo Pointer pEABuf --> pEABuf


;        mov     esi,[ebp-48]  old code  pEABuf temp address
        mov     esi,[ebp-52]            ;pEABuf temp address
        or      esi,esi
        jz      PL25



        mov     edi,[ebp+36]            ;pEABuf original address

;Structures are Identical
;Structures have pointers
;Structure has output semantics
;Return structure to original area


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

;Element fpGEAList --> fpGEAList
;Pointer elements not copied out
;Element fpFEAList --> fpFEAList
;Pointer elements not copied out

;Copy out only the oError value

        mov     eax,[esi+8]
        mov     [edi+8],eax

PL26:                    ;ErrorLabel D

;Unpack imbedded pointer fpFEAList

;        mov     esi,[ebp-56]   old code  Get pointer to temporary
        mov     esi,[ebp-60]            ;Get pointer to temporary
        or      esi,esi         ;Ignore if NULL
        jz      PL32

        cmp     [edi+4],esi
        je      PL32

        push    -32
        mov     edx,64
        call    THK32DEALLOC


PL32:

;Deallocate Temporary Structure


;Stack allocated memory deallocated implicitly

PL25:            ;No action required

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

;* 32-bit return code.

;        lea     esp,[ebp-60]  old code  ABest- to fix DOS32POPEN stack alloc
        lea     esp,[ebp-64]    ; ABest- to fix DOS32POPEN stack alloc
        pop     ecx             ; ABest- to fix DOS32POPEN stack alloc
;TPL01  cmp     ecx,0           ; ABest- to fix DOS32POPEN stack alloc
        jecxz   short PSTACKFIX ; ABest- to fix DOS32POPEN stack alloc
        call    THK32FREESTACK  ; ABest- to fix DOS32POPEN stack alloc
PSTACKFIX:                      ; ABest- to fix DOS32POPEN stack alloc

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

DOS32PPROTECTOPEN endp

CODE32  ENDS

;* 16-bit code to make API call.

CODE16C SEGMENT

        ASSUME CS:CODE16C
;        .errnz ($ - T_DOSOPEN2)
        .errnz ($ - T_DOSPROTECTOPEN)

;        call    FAR PTR DOSOPEN2        old code  call 16-bit version
;        jmp     FAR PTR FLAT:R_DOSOPEN2   old code  jump back

        call    FAR PTR DOSPROTECTOPEN          ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSPROTECTOPEN         ; jump back

CODE16C ENDS


; This API contains one polymorphic parameters. Its type is indicated
; by the FileInfoLevel (parameter #2), and can assume one of the following
; values:
;
;       FileInfoLevel   pfstsInfo
;
;       0x0001          22 bytes

FILESTATUS_SIZE equ     22

;
;typedef struct _FILESTATUS {    /* fsts */
;    FDATE  fdateCreation;
;    FTIME  ftimeCreation;
;    FDATE  fdateLastAccess;
;    FTIME  ftimeLastAccess;
;    FDATE  fdateLastWrite;
;    FTIME  ftimeLastWrite;
;    ULONG  cbFile;
;    ULONG  cbFileAlloc;
;    USHORT attrFile;
;} FILESTATUS;
;
;       0x0002          26 bytes

FILESTATUS2_SIZE        equ     26

;typedef struct _FILESTATUS2 {    /* fsts */
;    FDATE  fdateCreation;
;    FTIME  ftimeCreation;
;    FDATE  fdateLastAccess;
;    FTIME  ftimeLastAccess;
;    FDATE  fdateLastWrite;
;    FTIME  ftimeLastWrite;
;    ULONG  cbFile;
;    ULONG  cbFileAlloc;
;    USHORT attrFile;
;    ULONG  cbList;
;} FILESTATUS2;
;
;
;       0x0003  EAOPbuf - Copy in
;                               fpGEAbuf
;                               fpFEA length (rest of buffer not copy in)
;                       - Copy Out
;                               fpFEA
;
;
;       0x0004  EAOPbuf - Copy in
;                               fpGEAbuf Ignored
;                               fpFEA length (rest of buffer not copy in)
;                       - Copy Out
;                               fpFEA
;
;


;Create a dummy label to trick MASM into correct fixups

CODE16C_TUNE3 SEGMENT

T_DOSQFILEINFO  LABEL FAR

CODE16C_TUNE3 ENDS


CODE32_TUNE3  SEGMENT
; align 4 54686
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PQUERYFILEINFO PROC

d32qfi_InfoLevel equ DWORD PTR [ebp+12]


        push    ebp
        mov     ebp,esp


        cld                     ;Assume direction flag clear
        xor     eax,eax

tmpStore equ DWORD PTR [ebp-4]

        push    eax             ; temp storage for return value
        push    esi
        push    edi
        push    eax             ; temp storage
        push    eax             ;Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags

        push    eax             ; temp storage for ptr param #1

d32qfi_GEAtempptr equ DWORD PTR [ebp-40]
d32qfi_FEAtempptr equ DWORD PTR [ebp-44]

        push    eax             ; Storage for EAOP Ptr 1
        push    eax             ; Storage for EAOP Ptr 2

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

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short L301              ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L301

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01

        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section



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

;Pointer pfstsInfo --> pfstsInfo
        or      esi,esi
        jz      L302

        mov     [ebp-36],esi

; Determine the type based on the FileInfoLevel
;
        mov     eax,d32qfi_InfoLevel

        cmp     eax,1           ;Is it FILESTATUS?
        jne     L301b
;
;At this point, we know that the pointer is to a FILESTATUS parameter
;There is no change between 32 and 16 bits
;Just insure that data doesn't cross boundary.

        cmp     si,(- FILESTATUS_SIZE)
        jbe     L302

        ;It crosses. Take space from stack
; Allocate space on stack
        sub     esp,FILESTATUS_SIZE     ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
        mov     [ebp-36],edi

        ;Output only parameter.

        jmp     L302
L301b:
        cmp     eax,2           ;Is it FILESTATUS2?
        jne     L301c

        ;FILESTATUS2 is different between 32 and 16 bits.

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


;There are only three options left. It is either 3, 4, or not supported
;The only difference between 3 and 4 is that 4 ignores the GEA list.
;
L301c:
        cmp     eax,3
        je      short L301d
        cmp     eax,4
        je      short L301d
        cmp     eax,5                    ;###46681 Level five returns fealist from gealist
        je      short L301d              ;###46681 if fealist exsists for a file

;
; Oh No! We have a bad InfoLevel. Crap out of the deal
;
        mov     eax,ERROR_INVALID_LEVEL
        jmp     ERRDOS32PQUERYFILEINFO



;
; We know we have an EA buffer. Handle it.
; EAbufs require pointer conversions. Make a new copy of buffer
;
L301d:

        sub     esp,12                  ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
        mov     [ebp-36],edi

        cmp     eax,4                   ;Is it infolevel 4
        je      L301h

;
;
; We are at info level 3, and need to copy in the GEA list
;
        mov     esi,[esi]               ;Get PTR to GEA list
        or      esi,esi
        jz      L301g                   ;If GEA is null, go handle FEA
        mov     d32qfi_GEAtempptr,esi

        mov     ecx,[esi]               ;Get the length

        movzx   eax,cx                  ;Check for > 64k length
        cmp     eax,ecx
        jne     INVPDOS32PQUERYFILEINFO

        mov     eax,esi
        neg     ax
        jz      L301g

        cmp     ax,cx
        jae     L301g

;
;The boundary has been crossed. Handle it.
;

        call    THK32HANDLEBOUNDARY
        or      eax,eax
        jnz     NOMEMDOS32PQUERYFILEINFO
        mov     d32qfi_GEAtempptr,edi
        or      edx,edx
        js      short L301f             ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],2             ;Set Flag
        dec     edx
        js      short L301g             ;Aliases not copied

L301f:                  ;Variable Length Copy

; Copy ECX bytes from ESI to EDI
        call    THK32COPYBLOCK

L301g:
        mov     esi,[ebp+16]            ;Reload original source
L301h:

;
        mov     esi,[esi+4]             ;Get PTR to FEA list
        or      esi,esi
        jz      L302

        mov     d32qfi_FEAtempptr,esi

        mov     ecx,[esi]               ;Get the length

        movzx   eax,cx                  ;Check for > 64k length
        cmp     eax,ecx
        jne     INVPDOS32PQUERYFILEINFO

        mov     eax,esi
        neg     ax
        jz      L302                    ;0=full 64k of room

        cmp     ax,cx
        jae     L302                    ;Enough room

;
;
;The boundary has been crossed. Handle it.
;
;

        call    THK32HANDLEBOUNDARY
        or      eax,eax
        jnz     NOMEMDOS32PQUERYFILEINFO
        mov     d32qfi_FEAtempptr,edi
        or      edx,edx
        js      short L301j             ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],4             ;Set Flag
        dec     edx
        js      short L302              ;Aliases not copied

L301j:
        mov     eax,[esi]               ;Only copy in the length
        mov     [edi],eax

L302:
        mov     cx,ss
        and     cx,3
        or      cx,4                    ;Force LDT on

        mov     esi,[ebp-36]            ;Get new EAOP into source
        mov     eax,d32qfi_GEAtempptr
        or      eax,eax
        jz      short L302a

        cmp     eax,[FenceLAddr]
        jae     L302aCRMA
        call    DOS32FLATTOSEL
        jmp     short L302a

L302aCRMA:
        ror     eax,16
        shl     ax,3
        or      al,cl
        rol     eax,16

L302a:
        mov     [esi],eax               ;Store new PTR


        mov     eax,d32qfi_FEAtempptr
        or      eax,eax
        jz      short L302b

        cmp     eax,[FenceLAddr]
        jae     L302bCRMA
        call    DOS32FLATTOSEL
        jmp     short L302b

L302bCRMA:
        ror     eax,16
        shl     ax,3
        or      al,cl
        rol     eax,16

L302b:
        mov     [esi+4],eax             ;Store new PTR





; ****> END Pointer/Structure Section

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

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


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

        or      dl,4                    ;Force LDT bit on


        ;From Name:   Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVPDOS32PQUERYFILEINFO

        push    ax              ;To:unsigned short


        ;From Name:   Type: unsigned long
        mov     eax,[ebp+12]
        cmp     eax,0ffffh
        ja      INVPDOS32PQUERYFILEINFO

        push    ax              ;To:unsigned short


        ;From Name: pfstsInfo  Type: struct FILESTATUS2
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L303                      ;NULL pointer

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



        ;From Name: cbInfoBuf  Type: unsigned long
        mov     eax,[ebp+20]
        cmp     eax,0ffffh
        ja      INVPDOS32PQUERYFILEINFO

        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_DOSQFILEINFO


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

NOMEMDOS32PQUERYFILEINFO:
        push    8
        pop     eax

ERRDOS32PQUERYFILEINFO:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L304
R_DOSQFILEINFO:                         ; 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


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

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

;Undo Pointer pfstsInfo --> pfstsInfo

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

        mov     edi,[ebp+16]            ;pfstsInfo original address
        mov     eax,d32qfi_InfoLevel

        cmp     eax,1
        jne     L304a

;
;InfoLevel = 1. If esi != edi, copy out the buffer
;
        test    BYTE PTR[ebp-20],1              ;Check for errors
        jnz     L305

        cmp     esi,edi
        je      L305

        mov     ecx,FILESTATUS_SIZE

        call    THK32COPYBLOCK

        jmp     L305

L304a:
        cmp     eax,2
        jne     L304b

;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     L305                    ;No copy if error

;Element fdateCreation --> fdateCreation

;Element date --> date
;Add 2 bytes of short to transfer

;Transfer 20 bytes
        mov     ecx,5
        rep     movsd

;Element attrFile --> ulattrFile
;Transfer an additional 2 bytes
        movsw

;Transfer 2 bytes of zero to high word of ulattrFile
        mov  es:[edi],cx

;ReAlignment
        add     edi,2
;Add 4 bytes of unsigned long to transfer

;Element ulcbList --> ulcbList
;Transfer 4 bytes
        movsd

        jmp     L305

L304b:

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

        mov     ecx,[esi+8]             ;Place error offset into buffer
        mov     [edi+8],ecx

L304c:
        cmp     eax,3           ;If level 3, then GEA might need help
        je      L304ca

        cmp     eax,4           ;If not level 4 then we can't handle it
        je      L304e

        cmp     eax,5           ;###46681 If level 5, then GEA might need help
        je      L304ca          ;###46681

        jmp     L305

;Save pointers to current buffers.
L304ca:
        push    esi
        push    edi

;GEA op needs to be checked for deallocation


        mov     esi,d32qfi_GEAtempptr
        cmp     [edi],esi               ;Check against original
        je      L304d                   ;Leave it alone

;We don't need to copy this guy out.

        push    -32                     ;Offset of ALIAS flags
        mov     edx,2
        call    THK32DEALLOC

L304d:
        pop     edi
        pop     esi
L304e:


        mov     edi,[edi+4]     ;Get FEA pointers
        mov     esi,d32qfi_FEAtempptr

        cmp     esi,edi
        je      L305

;
; Need to copy this fellow out
;
        mov     eax,[esi]               ;Get the length
        movzx   ecx,ax                  ;Check for > 64k length
                                        ; b724654

        push    esi
        call    THK32COPYBLOCK
        pop     esi

        push    -32                     ;Offset of ALIAS flags
        mov     edx,4
        call    THK32DEALLOC

L305:           ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-48]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        leave
        ret                             ; Remove parameters

DOS32PQUERYFILEINFO endp

CODE32_TUNE3  ENDS

;***DONE

;* 16-bit code to make API call.

CODE16C_TUNE3 SEGMENT

        ASSUME CS:CODE16C_TUNE3
        .errnz ($ - T_DOSQFILEINFO)

        call    FAR PTR DOSQFILEINFO               ; call 16-bit worker routine
        jmp     FAR PTR FLAT:R_DOSQFILEINFO        ; jump back

CODE16C_TUNE3 ENDS



CODE16C SEGMENT

T_DOSPROTECTQFILEINFO  LABEL FAR

CODE16C ENDS


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

d32qfi_InfoLevel equ DWORD PTR [ebp+12]


        push    ebp
        mov     ebp,esp


        cld                     ;Assume direction flag clear
        xor     eax,eax

tmpStore equ DWORD PTR [ebp-4]

        push    eax             ; temp storage for return value
        push    esi
        push    edi
        push    eax             ; temp storage
        push    eax             ;Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags

        push    eax             ; temp storage for ptr param #1

d32qfi_GEAtempptr equ DWORD PTR [ebp-40]
d32qfi_FEAtempptr equ DWORD PTR [ebp-44]

        push    eax             ; Storage for EAOP Ptr 1
        push    eax             ; Storage for EAOP Ptr 2

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

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short PL301              ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short PL301

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01

        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section



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

;Pointer pfstsInfo --> pfstsInfo
        or      esi,esi
        jz      PL302

        mov     [ebp-36],esi

; Determine the type based on the FileInfoLevel
;
        mov     eax,d32qfi_InfoLevel

        cmp     eax,1           ;Is it FILESTATUS?
        jne     PL301b
;
;At this point, we know that the pointer is to a FILESTATUS parameter
;There is no change between 32 and 16 bits
;Just insure that data doesn't cross boundary.

        cmp     si,(- FILESTATUS_SIZE)
        jbe     PL302

        ;It crosses. Take space from stack
; Allocate space on stack
        sub     esp,FILESTATUS_SIZE     ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
        mov     [ebp-36],edi

        ;Output only parameter.

        jmp     PL302
PL301b:
        cmp     eax,2           ;Is it FILESTATUS2?
        jne     PL301c

        ;FILESTATUS2 is different between 32 and 16 bits.

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


;There are only three options left. It is either 3, 4, or not supported
;The only difference between 3 and 4 is that 4 ignores the GEA list.
;
PL301c:
        cmp     eax,3
        je      short PL301d
        cmp     eax,4
        je      short PL301d
        cmp     eax,5                     ;###46681 Level five returns fealist from gealist
        je      short PL301d              ;###46681 if fealist exsists for a file

;
; Oh No! We have a bad InfoLevel. Bail out!
;
        mov     eax,ERROR_INVALID_LEVEL
        jmp     ERRDOS32PPQUERYFILEINFO



;
; We know we have an EA buffer. Handle it.
; EAbufs require pointer conversions. Make a new copy of buffer
;
PL301d:

        sub     esp,12                  ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
        mov     [ebp-36],edi

        cmp     eax,4                   ;Is it infolevel 4
        je      PL301h

;
;
; We are at info level 3, and need to copy in the GEA list
;
        mov     esi,[esi]               ;Get PTR to GEA list
        or      esi,esi
        jz      PL301g                   ;If GEA is null, go handle FEA
        mov     d32qfi_GEAtempptr,esi

        mov     ecx,[esi]               ;Get the length

        movzx   eax,cx                  ;Check for > 64k length
        cmp     eax,ecx
        jne     INVPDOS32PPQUERYFILEINFO

        mov     eax,esi
        neg     ax
        jz      PL301g

        cmp     ax,cx
        jae     PL301g

;
;The boundary has been crossed. Handle it.
;

        call    THK32HANDLEBOUNDARY
        or      eax,eax
        jnz     NOMEMDOS32PPQUERYFILEINFO
        mov     d32qfi_GEAtempptr,edi
        or      edx,edx
        js      short PL301f             ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],2             ;Set Flag
        dec     edx
        js      short PL301g             ;Aliases not copied

PL301f:                  ;Variable Length Copy

; Copy ECX bytes from ESI to EDI
        call    THK32COPYBLOCK

PL301g:
        mov     esi,[ebp+16]            ;Reload original source
PL301h:

;
        mov     esi,[esi+4]             ;Get PTR to FEA list
        or      esi,esi
        jz      PL302

        mov     d32qfi_FEAtempptr,esi

        mov     ecx,[esi]               ;Get the length

        movzx   eax,cx                  ;Check for > 64k length
        cmp     eax,ecx
        jne     INVPDOS32PPQUERYFILEINFO

        mov     eax,esi
        neg     ax
        jz      PL302                    ;0=full 64k of room

        cmp     ax,cx
        jae     PL302                    ;Enough room

;
;
;The boundary has been crossed. Handle it.
;
;

        call    THK32HANDLEBOUNDARY
        or      eax,eax
        jnz     NOMEMDOS32PPQUERYFILEINFO
        mov     d32qfi_FEAtempptr,edi
        or      edx,edx
        js      short PL301j             ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],4             ;Set Flag
        dec     edx
        js      short PL302              ;Aliases not copied

PL301j:
        mov     eax,[esi]               ;Only copy in the length
        mov     [edi],eax

PL302:
        mov     cx,ss
        and     cx,3
        or      cx,4                    ;Force LDT on

        mov     esi,[ebp-36]            ;Get new EAOP into source
        mov     eax,d32qfi_GEAtempptr
        or      eax,eax
        jz      short PL302a

        cmp     eax,[FenceLAddr]
        jae     PL302aCRMA
        call    DOS32FLATTOSEL
        jmp     short PL302a

PL302aCRMA:
        ror     eax,16
        shl     ax,3
        or      al,cl
        rol     eax,16

PL302a:
        mov     [esi],eax               ;Store new PTR


        mov     eax,d32qfi_FEAtempptr
        or      eax,eax
        jz      short PL302b

        cmp     eax,[FenceLAddr]
        jae     PL302bCRMA
        call    DOS32FLATTOSEL
        jmp     short PL302b

PL302bCRMA:
        ror     eax,16
        shl     ax,3
        or      al,cl
        rol     eax,16

PL302b:
        mov     [esi+4],eax             ;Store new PTR





; ****> END Pointer/Structure Section

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

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

        push    ax              ;To:unsigned short


        ;From Name: InfoLevel  Type: unsigned long
        mov     eax,[ebp+12]
        cmp     eax,0ffffh
        ja      INVPDOS32PPQUERYFILEINFO

        push    ax              ;To:unsigned short


        ;From Name: pfstsInfo (InfoBuf)  Type: struct FILESTATUS2
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short PL303                      ;NULL pointer

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



        ;From Name: cbInfoBuf  Type: unsigned long
        mov     eax,[ebp+20]
        cmp     eax,0ffffh
        ja      INVPDOS32PPQUERYFILEINFO

        push    ax              ;To:unsigned short


        ;From Name:   Type: unsigned long FileHandleLockID
        mov     eax,[ebp+24]
        push    eax              ;To:unsigned long


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


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

NOMEMDOS32PPQUERYFILEINFO:
        push    8
        pop     eax

ERRDOS32PPQUERYFILEINFO:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short PL304
R_DOSPROTECTQFILEINFO:                     ; 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


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

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

;Undo Pointer pfstsInfo --> pfstsInfo

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

        mov     edi,[ebp+16]            ;pfstsInfo original address
        mov     eax,d32qfi_InfoLevel

        cmp     eax,1
        jne     PL304a

;
;InfoLevel = 1. If esi != edi, copy out the buffer
;
        test    BYTE PTR[ebp-20],1              ;Check for errors
        jnz     PL305

        cmp     esi,edi
        je      PL305

        mov     ecx,FILESTATUS_SIZE

        call    THK32COPYBLOCK

        jmp     PL305

PL304a:
        cmp     eax,2
        jne     PL304b

;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     PL305                    ;No copy if error

;Element fdateCreation --> fdateCreation

;Element date --> date
;Add 2 bytes of short to transfer

;Transfer 20 bytes
        mov     ecx,5
        rep     movsd

;Element attrFile --> ulattrFile
;Transfer an additional 2 bytes
        movsw

;Transfer 2 bytes of zero to high word of ulattrFile
        mov  es:[edi],cx

;ReAlignment
        add     edi,2
;Add 4 bytes of unsigned long to transfer

;Element ulcbList --> ulcbList
;Transfer 4 bytes
        movsd

        jmp     PL305

PL304b:

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

        mov     ecx,[esi+8]             ;Place error offset into buffer
        mov     [edi+8],ecx

PL304c:
        cmp     eax,3           ;If level 3, then GEA might need help
        je      PL304ca

        cmp     eax,4           ;If not level 4 then we can't handle it
        je      PL304e

        cmp     eax,5           ;###46681 If level 5, then GEA might need help
        je      PL304ca          ;###46681

        jmp     PL305

;Save pointers to current buffers.
PL304ca:
        push    esi
        push    edi

;GEA op needs to be checked for deallocation


        mov     esi,d32qfi_GEAtempptr
        cmp     [edi],esi               ;Check against original
        je      PL304d                   ;Leave it alone

;We don't need to copy this guy out.

        push    -32                     ;Offset of ALIAS flags
        mov     edx,2
        call    THK32DEALLOC

PL304d:
        pop     edi
        pop     esi
PL304e:


        mov     edi,[edi+4]     ;Get FEA pointers
        mov     esi,d32qfi_FEAtempptr

        cmp     esi,edi
        je      PL305

;
; Need to copy this fellow out
;
        mov     eax,[esi]               ;Get the length
        movzx   ecx,ax                  ;Check for > 64k length
                                        ; b724654

        push    esi
        call    THK32COPYBLOCK
        pop     esi

        push    -32                     ;Offset of ALIAS flags
        mov     edx,4
        call    THK32DEALLOC

PL305:           ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-48]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        leave
        ret                             ; Remove parameters

DOS32PPROTECTQUERYFILEINFO endp

CODE32  ENDS

;***DONE

;* 16-bit code to make API call.

CODE16C SEGMENT

        ASSUME CS:CODE16C
        .errnz ($ - T_DOSPROTECTQFILEINFO)

        call    FAR PTR DOSPROTECTQFILEINFO        ; call 16-bit worker routine
        jmp     FAR PTR FLAT:R_DOSPROTECTQFILEINFO ; jump back

CODE16C ENDS


CODE16C SEGMENT

T_DOSSETFILEINFO        LABEL FAR

CODE16C ENDS


CODE32  SEGMENT
; align 4 54686
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PSETFILEINFO PROC


sfi_InfoLevel   equ     DWORD PTR [ebp+12]
sfi_InfoBuf     equ     DWORD PTR [ebp+16]


        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 storage
        push    eax             ; Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags
        push    eax             ; temp storage for ptr param #1

sfi_GEAptr      equ     DWORD PTR [ebp-40]
sfi_FEAptr      equ     DWORD PTR [ebp-44]

        push    eax             ; temp storage for ptr param #2
        push    eax             ; temp storage for ptr param #3
;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short L401              ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L401

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01

        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section

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

;Pointer pfstsBuf --> pfstsBuf
        or      esi,esi
        jz      L407
        mov     [ebp-36],esi



        cmp     sfi_InfoLevel,1
        jne     L405


; FileInfoBuf with Infolevel of 1 contains a 12-byte structure.
;
; Insure that the buffer length is at least 12 bytes.
;
;
        mov     eax,12
        cmp     [ebp+20],eax

        jb      L404E

        add     ax,si           ;Does it cross boundary?
        jnc     L407            ;No


        sub     esp,12                  ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
        mov     [ebp-36],edi

        mov     ecx,3
        rep     movsd
        jmp     L407


L404E:  mov     eax,ERROR_INSUFFICIENT_BUFFER
        jmp     ERRDOS32PSETFILEINFO

L404F:  mov     eax,ERROR_INVALID_LEVEL
        jmp     ERRDOS32PSETFILEINFO

L405:
        cmp     sfi_InfoLevel,2         ;Insure it is 2
        jne     L404F                   ;Error out if not


;Structures are Identical
;Structures have pointers

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

        mov     ecx,3
        rep     movsd

;Fixup imbedded pointer fpFEAList

        mov     esi,[ebp-36]            ;Get parents pointer
        mov     esi,[esi+4]             ;Get Fixups pointer

;Pointer fpFEAList --> fpFEAList
        or      esi,esi
        jz      L407

        mov     sfi_FEAptr,esi

;Structures are Identical
;Structures don't have pointers

;Treat structure same as buffer

;The length of this structure is the first DWORD.
;Get the length, and insure that it doesn't cross a boundary.

        mov     eax,[esi]
        movzx   ecx,ax
        cmp     eax,ecx
        jne     INVPDOS32PSETFILEINFO


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

        cmp     ax,cx
        jae     L406a           ;Enough room

;
        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEMDOS32PSETFILEINFO
        mov     sfi_FEAptr,edi
        or      edx,edx
        js      short L406              ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],4             ;Set Flag
        dec     edx
        js      short L406a             ;Aliases not copied

L406:                   ;Variable Length Copy

; Copy ECX bytes from ESI to EDI
        push    esi

        call    THK32COPYBLOCK

        pop     esi

L406a:

;Patch in new pointer value
        mov     edi,[ebp-36]            ;Get parents pointer
        mov     esi,sfi_FEAptr  ;Get Fixups new pointer
;Convert 0:32 --> 16:16
        or      esi,esi
        jz      short L406b

        cmp     esi,[FenceLAddr]
        jae     L406bCRMA
        mov     eax,esi
        call    DOS32FLATTOSEL
        mov     esi,eax
        jmp     short L406b

L406bCRMA:
        ror     esi,16
        shl     si,3
        mov     ax,ss
        and     ax,3
        or      al,4
        or      si,ax
        rol     esi,16

L406b:  mov     [edi+4],esi             ;Put Fixups pointer

L407:


; ****> END Pointer/Structure Section

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

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


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

        or      dl,4                    ;Force LDT bit on


        ;From Name:   Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVPDOS32PSETFILEINFO

        push    ax              ;To:unsigned short


        ;From Name:   Type: unsigned long
        mov     eax,[ebp+12]
        cmp     eax,0ffffh
        ja      INVPDOS32PSETFILEINFO

        push    ax              ;To:unsigned short


        ;From Name: pfstsBuf  Type: struct EAOP
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L411                      ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     L411CRMA
        call    DOS32FLATTOSEL
        jmp     short L411

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

L411:   push    eax



        ;From Name: cbBuf  Type: unsigned long
        mov     eax,[ebp+20]
        cmp     eax,0ffffh
        ja      INVPDOS32PSETFILEINFO

        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_DOSSETFILEINFO


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

NOMEMDOS32PSETFILEINFO:
        push    8
        pop     eax

ERRDOS32PSETFILEINFO:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L412
R_DOSSETFILEINFO:                               ; 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


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

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


;Undo Pointer pfstsBuf --> pfstsBuf

        cmp     sfi_InfoLevel,2         ;If it isn't an EA buf, then
        jne     L413                    ;no more processing required

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

        mov     edi,[ebp+16]            ;pfstsBuf original address


        mov     eax,[esi+8]
        mov     [edi+8],eax

;Unpack imbedded pointer fpFEAList

        mov     esi,sfi_FEAptr          ; Get pointer to temporary
        or      esi,esi                 ; Ignore if NULL
        jz      L418

        mov     edi,[ebp+16]            ; Get parents original pointer
        mov     edi,[edi+4]             ; Get Fixups original address

        cmp     esi,edi
        je      L418


;
; FEA needs to be deallocated
;

        push    -32
        mov     edx,4
        call    THK32DEALLOC

L418:
L413:           ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-48]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax                     ; Pop saved return code
        leave
        ret                             ; Remove parameters

DOS32PSETFILEINFO endp

CODE32  ENDS

;* 16-bit code to make API call.

CODE16C SEGMENT

        ASSUME CS:CODE16C
        .errnz ($ - T_DOSSETFILEINFO)

        call    FAR PTR DOSISETFILEINFO                 ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSSETFILEINFO           ; jump back

CODE16C ENDS


CODE16C SEGMENT

T_DOSPROTECTSETFILEINFO        LABEL FAR

CODE16C ENDS


CODE32  SEGMENT
;ALIGN 4
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PPROTECTSETFILEINFO PROC


sfi_InfoLevel   equ     DWORD PTR [ebp+12]
sfi_InfoBuf     equ     DWORD PTR [ebp+16]


        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 storage
        push    eax             ; Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags
        push    eax             ; temp storage for ptr param #1

sfi_GEAptr      equ     DWORD PTR [ebp-40]
sfi_FEAptr      equ     DWORD PTR [ebp-44]

        push    eax             ; temp storage for ptr param #2
        push    eax             ; temp storage for ptr param #3
;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short PL401              ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short PL401

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01

        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section

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

;Pointer pfstsBuf --> pfstsBuf
        or      esi,esi
        jz      PL407
        mov     [ebp-36],esi



        cmp     sfi_InfoLevel,1
        jne     PL405


; FileInfoBuf with Infolevel of 1 contains a 12-byte structure.
;
; Insure that the buffer length is at least 12 bytes.
;
;
        mov     eax,12
        cmp     [ebp+20],eax

        jb      PL404E

        add     ax,si           ;Does it cross boundary?
        jnc     PL407            ;No


        sub     esp,12                  ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
        mov     [ebp-36],edi

        mov     ecx,3
        rep     movsd
        jmp     PL407


PL404E:  mov     eax,ERROR_INSUFFICIENT_BUFFER
        jmp     ERRDOS32PPSETFILEINFO

PL404F:  mov     eax,ERROR_INVALID_LEVEL
        jmp     ERRDOS32PPSETFILEINFO

PL405:
        cmp     sfi_InfoLevel,2         ;Insure it is 2
        jne     PL404F                   ;Error out if not


;Structures are Identical
;Structures have pointers

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

        mov     ecx,3
        rep     movsd

;Fixup imbedded pointer fpFEAList

        mov     esi,[ebp-36]            ;Get parents pointer
        mov     esi,[esi+4]             ;Get Fixups pointer

;Pointer fpFEAList --> fpFEAList
        or      esi,esi
        jz      PL407

        mov     sfi_FEAptr,esi

;Structures are Identical
;Structures don't have pointers

;Treat structure same as buffer

;The length of this structure is the first DWORD.
;Get the length, and insure that it doesn't cross a boundary.

        mov     eax,[esi]
        movzx   ecx,ax
        cmp     eax,ecx
        jne     INVPDOS32PPSETFILEINFO


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

        cmp     ax,cx
        jae     PL406a           ;Enough room

;
        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEMDOS32PPSETFILEINFO
        mov     sfi_FEAptr,edi
        or      edx,edx
        js      short PL406              ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],4             ;Set Flag
        dec     edx
        js      short PL406a             ;Aliases not copied

PL406:                   ;Variable Length Copy

; Copy ECX bytes from ESI to EDI
        push    esi

        call    THK32COPYBLOCK

        pop     esi

PL406a:

;Patch in new pointer value
        mov     edi,[ebp-36]            ;Get parents pointer
        mov     esi,sfi_FEAptr  ;Get Fixups new pointer
;Convert 0:32 --> 16:16
        or      esi,esi
        jz      short PL406b

        cmp     esi,[FenceLAddr]
        jae     PL406bCRMA
        mov     eax,esi
        call    DOS32FLATTOSEL
        mov     esi,eax
        jmp     short PL406b

PL406bCRMA:
        ror     esi,16
        shl     si,3
        mov     ax,ss
        and     ax,3
        or      al,4
        or      si,ax
        rol     esi,16

PL406b:  mov     [edi+4],esi             ;Put Fixups pointer

PL407:


; ****> END Pointer/Structure Section

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

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


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

        or      dl,4                    ;Force LDT bit on


        ;From Name:   Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVPDOS32PPSETFILEINFO

        push    ax              ;To:unsigned short


        ;From Name:   Type: unsigned long
        mov     eax,[ebp+12]
        cmp     eax,0ffffh
        ja      INVPDOS32PPSETFILEINFO

        push    ax              ;To:unsigned short


        ;From Name: pfstsBuf  Type: struct EAOP
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short PL411                      ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     PL411CRMA
        call    DOS32FLATTOSEL
        jmp     short PL411

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

PL411:   push    eax



        ;From Name: cbBuf  Type: unsigned long
        mov     eax,[ebp+20]
        cmp     eax,0ffffh
        ja      INVPDOS32PPSETFILEINFO

        push    ax              ;To:unsigned short


        ;From Name: FileHandleLockID  Type: unsigned long
        mov     eax,[ebp+24]
        push    eax              ;To:unsigned long

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


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

NOMEMDOS32PPSETFILEINFO:
        push    8
        pop     eax

ERRDOS32PPSETFILEINFO:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short PL412
R_DOSPROTECTSETFILEINFO:                  ; 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


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

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


;Undo Pointer pfstsBuf --> pfstsBuf

        cmp     sfi_InfoLevel,2         ;If it isn't an EA buf, then
        jne     PL413                    ;no more processing required

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

        mov     edi,[ebp+16]            ;pfstsBuf original address


        mov     eax,[esi+8]
        mov     [edi+8],eax

;Unpack imbedded pointer fpFEAList

        mov     esi,sfi_FEAptr          ; Get pointer to temporary
        or      esi,esi                 ; Ignore if NULL
        jz      PL418

        mov     edi,[ebp+16]            ; Get parents original pointer
        mov     edi,[edi+4]             ; Get Fixups original address

        cmp     esi,edi
        je      PL418


;
; FEA needs to be deallocated
;

        push    -32
        mov     edx,4
        call    THK32DEALLOC

PL418:
PL413:           ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-48]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax                     ; Pop saved return code
        leave
        ret                             ; Remove parameters

DOS32PPROTECTSETFILEINFO endp

CODE32  ENDS

;* 16-bit code to make API call.

CODE16C SEGMENT

        ASSUME CS:CODE16C
        .errnz ($ - T_DOSPROTECTSETFILEINFO)

        call    FAR PTR DOSIPROTECTSETFILEINFO          ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSPROTECTSETFILEINFO    ; jump back

CODE16C ENDS


CODE16C_TUNE2 SEGMENT

T_DOSSETPATHINFO        LABEL FAR

CODE16C_TUNE2 ENDS


CODE32_TUNE2  SEGMENT
; align 4 54686
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PSETPATHINFO PROC


spi_InfoLevel   equ     DWORD PTR [ebp+12]
spi_InfoBuf     equ     DWORD PTR [ebp+16]


        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 storage
        push    eax             ;Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags
        push    eax             ; temp storage for ptr param #1

spi_Buf         equ     DWORD PTR [ebp-40]
spi_GEAptr      equ     DWORD PTR [ebp-44]
spi_FEAptr      equ     DWORD PTR [ebp-48]

        push    eax             ; temp storage for ptr param #2
        push    eax             ; temp storage for ptr param #3
        push    eax             ; temp storage for ptr param #4
;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short L901              ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L901

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01

        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+8]             ; base address

;Pointer  -->
        or      esi,esi
        jz      L902

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

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

L902:




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

;Pointer pfstsBuf --> pfstsBuf
        or      esi,esi
        jz      L907
        mov     spi_Buf,esi



        cmp     spi_InfoLevel,1
        jne     L905


; PATHInfoBuf with Infolevel of 1 contains a 12-byte structure.
;
; Insure that the buffer length is at least 12 bytes.
;
;
        mov     eax,12
        cmp     [ebp+20],eax

        jb      L904E

        add     ax,si           ;Does it cross boundary?
        jnc     L907            ;No


        sub     esp,12                  ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
        mov     spi_Buf,edi

        mov     ecx,3
        rep     movsd
        jmp     L907


L904E:  mov     eax,ERROR_INSUFFICIENT_BUFFER
        jmp     ERRDOS32PSETPATHINFO

L904F:  mov     eax,ERROR_INVALID_LEVEL
        jmp     ERRDOS32PSETPATHINFO

L905:
        cmp     spi_InfoLevel,2         ;Insure it is 2
        jne     L904F                   ;Error out if not


;Structures are Identical
;Structures have pointers

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

        mov     ecx,3
        rep     movsd

;Fixup imbedded pointer fpFEAList

        mov     esi,spi_Buf             ;Get parents pointer
        mov     esi,[esi+4]             ;Get Fixups pointer

;Pointer fpFEAList --> fpFEAList
        or      esi,esi
        jz      L907

        mov     spi_FEAptr,esi

;Structures are Identical
;Structures don't have pointers

;Treat structure same as buffer

;The length of this structure is the first DWORD.
;Get the length, and insure that it doesn't cross a boundary.

        mov     eax,[esi]
        movzx   ecx,ax
        cmp     eax,ecx
        jne     INVPDOS32PSETPATHINFO



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

        cmp     ax,cx
        jae     L906a                   ;Enough room

;
        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEMDOS32PSETPATHINFO
        mov     spi_FEAptr,edi
        or      edx,edx
        js      short L906              ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],4             ;Set Flag
        dec     edx
        js      short L906a             ;Aliases not copied

L906:                   ;Variable Length Copy

; Copy ECX bytes from ESI to EDI
        push    esi

        call    THK32COPYBLOCK

        pop     esi

L906a:

;Patch in new pointer value
        mov     edi,spi_Buf             ;Get parents pointer
        mov     esi,spi_FEAptr  ;Get Fixups new pointer
;Convert 0:32 --> 16:16
        or      esi,esi
        jz      short L906b

        cmp     esi,[FenceLAddr]
        jae     L906bCRMA
        mov     eax,esi
        call    DOS32FLATTOSEL
        mov     esi,eax
        jmp     short L906b

L906bCRMA:
        ror     esi,16
        shl     si,3
        mov     ax,ss
        and     ax,3
        or      al,4
        or      si,ax
        rol     esi,16
L906b:
        mov     [edi+4],esi             ;Put Fixups pointer

L907:


; ****> END Pointer/Structure Section

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

        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: string
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L906kwr                   ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     L906kwrCRMA
        call    DOS32FLATTOSEL
        jmp     short L906kwr

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

L906kwr:push    eax


        ;From Name:   Type: unsigned long
        mov     eax,[ebp+12]
        cmp     eax,0ffffh
        ja      INVPDOS32PSETPATHINFO

        push    ax              ;To:unsigned short


        ;From Name: pfstsBuf  Type: struct EAOP
        mov     eax,DWORD PTR spi_Buf
        or      eax,eax
        jz      short L911                      ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     L911CRMA
        call    DOS32FLATTOSEL
        jmp     short L911

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

L911:   push    eax



        ;From Name: cbBuf  Type: unsigned long
        mov     eax,[ebp+20]
        cmp     eax,0ffffh
        ja      INVPDOS32PSETPATHINFO

        push    ax              ;To:unsigned short


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

        push    ax              ;To:unsigned short


        push    0               ;Reserved DWORD


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


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

NOMEMDOS32PSETPATHINFO:
        push    8
        pop     eax

ERRDOS32PSETPATHINFO:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L912
R_DOSSETPATHINFO:                               ; 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


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

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


;Undo Pointer  -->


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



        mov     edi,[ebp+8]             ; 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      L909
;Handle String Parameters
;Strings are never copied out
        push    -32             ;Alloc Flag Offset
        mov     edx,1

        call    THK32DEALLOC


L909:           ;No action required




;Undo Pointer pfstsBuf --> pfstsBuf

        cmp     spi_InfoLevel,2         ;If it isn't an EA buf, then
        jne     L913                    ;no more processing required

        mov     esi,spi_Buf             ;pfstsBuf temp address
        or      esi,esi
        jz      L913

        mov     edi,[ebp+16]            ;pfstsBuf original address


        mov     eax,[esi+8]
        mov     [edi+8],eax

;Unpack imbedded pointer fpFEAList

        mov     esi,spi_FEAptr          ;Get pointer to temporary
        or      esi,esi                 ;Ignore if NULL
        jz      L918

        mov     edi,[ebp+16]            ;Get parents original pointer
        mov     edi,[edi+4]             ;Get Fixups original address

        cmp     esi,edi
        je      L918


;
; FEA needs to be deallocated
;

        push    -32
        mov     edx,4
        call    THK32DEALLOC

L918:
L913:           ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-52]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        leave
        ret                             ; Remove parameters

DOS32PSETPATHINFO endp

CODE32_TUNE2  ENDS

;* 16-bit code to make API call.

CODE16C_TUNE2 SEGMENT

        ASSUME CS:CODE16C_TUNE2
        .errnz ($ - T_DOSSETPATHINFO)

        call    FAR PTR DOSISETPATHINFO                 ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSSETPATHINFO           ; jump back

CODE16C_TUNE2 ENDS



CODE16C SEGMENT

T_DOSENUMATTRIBUTE      LABEL FAR

CODE16C ENDS


CODE32  SEGMENT
; align 4 54686
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PENUMATTRIBUTE 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 storage
        push    eax             ;Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags
        push    eax             ; temp storage for ptr param #1
        push    eax             ; temp storage for ptr param #2
        push    eax             ; temp storage for ptr param #3
;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short L1501             ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L1501

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01

        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section


        mov     esi,[ebp+12]            ; base address

;Pointer pvFile --> pvFile
        or      esi,esi
        jz      L1502

        mov     [ebp-36],esi
        mov     ecx,[ebp+8]             ; RefType flag
        or      ecx,ecx                 ; if 0, then handle
        jz      L1501a                  ; if 1, then string
        cmp     ecx,1                   ; if not either, then error
        jne     INVPDOS32PENUMATTRIBUTE ;   Invalid Parameter

;Handle String Parameter
                                        ; pvFile points to string
        push    -32                     ; Alias flag offset
        push    1                       ; Flag mask
        pop     edx
        call    THK32HANDLESTRING
        jc      ERRDOS32PENUMATTRIBUTE  ; jmp if too long
        mov     [ebp-36],edi
        jmp     short L1502


L1501a:                                 ; pvFile points to handle

;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     L1502                   ;Enough room

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

;Item is input only. Not saving new pointer
;Deallocated implicitly
        mov     eax,[esi]
        cmp     eax,0ffffh
        ja      INVPDOS32PENUMATTRIBUTE         ;Jmp on large value

        mov     [edi],ax


L1502:


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

;Pointer pvBuf --> pvBuf
        or      esi,esi
        jz      L1503

        mov     [ebp-40],esi
        mov     ecx,[ebp+24]            ;Get Size Parameter
        or      ecx,ecx
        jz      L1503           ;Nothing to check
;ECX holds size in bytes

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

        cmp     ax,cx
        jae     L1503                   ;Enough room

        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEMDOS32PENUMATTRIBUTE                        ;
        mov     [ebp-40],edi
        or      edx,edx
        js      short L1504             ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],2             ;Set Flag

L1504:                  ;Variable Length Copy

;Item semantics are NOT input

L1505:                  ;Variable Length No Copy

L1503:


        mov     esi,[ebp+28]            ;pulCt base address

;Pointer pulCt --> pulCt
        or      esi,esi
        jz      L1506

        mov     [ebp-44],esi

;Check Boundary Crossing - fixed size item
        cmp     si,65532
        jbe     L1506                   ;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

;Transfer 4 bytes
        movsd

L1506:

; ****> END Pointer/Structure Section

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

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


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

        or      dl,4                    ;Force LDT bit on


        ;From Name:   Type: unsigned long
        mov     eax,[ebp+8]
        cmp     eax,0ffffh
        ja      INVPDOS32PENUMATTRIBUTE

        push    ax              ;To:unsigned short


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

        cmp     eax,[FenceLAddr]
        jae     L1509CRMA
        call    DOS32FLATTOSEL
        jmp     short L1509

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

L1509:  push    eax



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


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

        cmp     eax,[FenceLAddr]
        jae     L1510CRMA
        call    DOS32FLATTOSEL
        jmp     short L1510

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

L1510:  push    eax



        ;From Name: cbBuf  Type: unsigned long
        push    DWORD PTR [ebp+24]      ; To: unsigned long


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

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



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


        ;From Name:   Type: unsigned long

;Extra parameter needed: Push a zero
        push    0               ;Push U/LONG

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


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

NOMEMDOS32PENUMATTRIBUTE:
        push    8
        pop     eax

ERRDOS32PENUMATTRIBUTE:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L1512
R_DOSENUMATTRIBUTE:                             ; 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


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

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


;Undo Pointer  -->


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



        mov     edi,[ebp+12]            ; original address
        mov     ecx,[ebp+8]              ; flag for type of buffer
        or      ecx,ecx
        jz      L1512a                  ; jmp if file handle

;String parameter
        cmp     esi,edi
        je      L1513
;Handle String Parameters
;Strings are never copied out
        push    -32
        mov     edx,1
        call    THK32DEALLOC


L1512a:                                 ; File Handle

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

L1513:          ;No action required

;Undo Pointer pvBuf --> pvBuf


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



        mov     edi,[ebp+20]            ;pvBuf 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      L1514

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

;Get size for copy out
        mov     ecx,[ebp+24]            ;Get Size
;ECX holds size in bytes

;If aliased, then skip over possible copyout
        test    BYTE PTR[ebp-32],2              ;Test Alias Flag
        jnz     L1516
;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
L1516:                  ;Aliased Label
        push    -32             ;Alloc Flag Offset
        mov     edx,2

        call    THK32DEALLOC



L1515:                  ;ErrorLabel A

L1514:          ;No action required

;Undo Pointer pulCt --> pulCt


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



        mov     edi,[ebp+28]            ;pulCt 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      L1519

;Item is fixed size

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

;Space was allocated on stack

;Transfer 4 bytes
        movsd

L1523:                  ;ErrorLabel C
;stack deallocated implicitly

L1519:          ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-48]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        leave
        ret                             ; Remove parameters

DOS32PENUMATTRIBUTE endp

CODE32  ENDS

;* 16-bit code to make API call.

CODE16C SEGMENT

        ASSUME CS:CODE16C
        .errnz ($ - T_DOSENUMATTRIBUTE)

        call    FAR PTR DOSENUMATTRIBUTE                ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSENUMATTRIBUTE         ; jump back

CODE16C ENDS


CODE16C SEGMENT

T_DOSPROTECTENUMATTRIBUTE      LABEL FAR

CODE16C ENDS


CODE32  SEGMENT
;ALIGN 4
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PPROTECTENUMATTRIBUTE 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 storage
        push    eax             ; Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags
        push    eax             ; temp storage for ptr param #1
        push    eax             ; temp storage for ptr param #2
        push    eax             ; temp storage for ptr param #3
;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short PL1501             ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short PL1501

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01
        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section


        mov     esi,[ebp+12]            ; base address of FileRef

;Pointer pvFile --> pvFile
        or      esi,esi
        jz      PL1502

        mov     [ebp-36],esi
        mov     ecx,[ebp+8]             ; RefType flag
        or      ecx,ecx                 ; if 0, then handle
        jz      PL1501a                 ; if 1, then string
        cmp     ecx,1                   ; if not either, then error
        jne     INVPDOS32PPENUMATTRIBUTE ;   Invalid Parameter

;Handle String Parameter
                                        ; pvFile points to string
        push    -32                     ; Alias flag offset
        push    1                       ; Flag mask
        pop     edx
        call    THK32HANDLESTRING
        jc      ERRDOS32PPENUMATTRIBUTE  ; jmp if too long
        mov     [ebp-36],edi
        jmp     short PL1502


PL1501a:                                 ; pvFile points to handle

;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     PL1502                   ;Enough room

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

;Item is input only. Not saving new pointer
;Deallocated implicitly
        mov     eax,[esi]
        cmp     eax,0ffffh
        ja      INVPDOS32PPENUMATTRIBUTE         ;Jmp on large value

        mov     [edi],ax


PL1502:


        mov     esi,[ebp+20]            ;pvBuf (EnumBuf) base address

;Pointer pvBuf --> pvBuf
        or      esi,esi
        jz      PL1503

        mov     [ebp-40],esi
        mov     ecx,[ebp+24]            ;Get Size Parameter
        or      ecx,ecx
        jz      PL1503           ;Nothing to check
;ECX holds size in bytes

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

        cmp     ax,cx
        jae     PL1503                   ;Enough room

        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEMDOS32PPENUMATTRIBUTE                        ;
        mov     [ebp-40],edi
        or      edx,edx
        js      short PL1504             ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],2             ;Set Flag

PL1504:                  ;Variable Length Copy

;Item semantics are NOT input

PL1505:                  ;Variable Length No Copy

PL1503:


        mov     esi,[ebp+28]            ;pulCt (EnumCnt) base address

;Pointer pulCt --> pulCt
        or      esi,esi
        jz      PL1506

        mov     [ebp-44],esi

;Check Boundary Crossing - fixed size item
        cmp     si,65532
        jbe     PL1506                   ;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

;Transfer 4 bytes
        movsd

PL1506:

; ****> END Pointer/Structure Section

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

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

        push    ax              ;To:unsigned short


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

        cmp     eax,[FenceLAddr]
        jae     PL1509CRMA
        call    DOS32FLATTOSEL
        jmp     short PL1509

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

PL1509:  push    eax



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


        ;From Name: pvBuf (EnumBuf)  Type: char
        mov     eax,DWORD PTR [ebp-40]
        or      eax,eax
        jz      short PL1510                     ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     PL1510CRMA
        call    DOS32FLATTOSEL
        jmp     short PL1510

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

PL1510:  push    eax



        ;From Name: cbBuf (EnumBufSize)  Type: unsigned long
        push    DWORD PTR [ebp+24]      ; To: unsigned long


        ;From Name: pulCt (EnumCnt)  Type: unsigned long
        mov     eax,DWORD PTR [ebp-44]
        or      eax,eax
        jz      short PL1511                     ;NULL pointer

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



        ;From Name: InfoLevel  Type: unsigned long
        push    DWORD PTR [ebp+32]      ; To: unsigned long


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


        ;From Name:   Type: unsigned long

;Extra parameter needed: Push a zero
        push    0               ;Push U/LONG

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


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

NOMEMDOS32PPENUMATTRIBUTE:
        push    8
        pop     eax

ERRDOS32PPENUMATTRIBUTE:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short PL1512
R_DOSPROTECTENUMATTRIBUTE:                ; 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


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

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


;Undo Pointer  -->


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



        mov     edi,[ebp+12]            ; original address
        mov     ecx,[ebp+8]              ; flag for type of buffer
        or      ecx,ecx
        jz      PL1512a                  ; jmp if file handle

;String parameter
        cmp     esi,edi
        je      PL1513
;Handle String Parameters
;Strings are never copied out
        push    -32
        mov     edx,1
        call    THK32DEALLOC


PL1512a:                                 ; File Handle

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

PL1513:          ;No action required

;Undo Pointer pvBuf --> pvBuf


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



        mov     edi,[ebp+20]            ;pvBuf 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      PL1514

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

;Get size for copy out
        mov     ecx,[ebp+24]            ;Get Size
;ECX holds size in bytes

;If aliased, then skip over possible copyout
        test    BYTE PTR[ebp-32],2              ;Test Alias Flag
        jnz     PL1516
;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
PL1516:                  ;Aliased Label
        push    -32             ;Alloc Flag Offset
        mov     edx,2

        call    THK32DEALLOC



PL1515:                  ;ErrorLabel A

PL1514:          ;No action required

;Undo Pointer pulCt --> pulCt


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



        mov     edi,[ebp+28]            ;pulCt 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      PL1519

;Item is fixed size

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

;Space was allocated on stack

;Transfer 4 bytes
        movsd

PL1523:                  ;ErrorLabel C
;stack deallocated implicitly

PL1519:          ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-48]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        leave
        ret                     ; Remove parameters

DOS32PPROTECTENUMATTRIBUTE endp

CODE32  ENDS

;* 16-bit code to make API call.

CODE16C SEGMENT

        ASSUME CS:CODE16C
        .errnz ($ - T_DOSPROTECTENUMATTRIBUTE)

        call    FAR PTR DOSPROTECTENUMATTRIBUTE             ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSPROTECTENUMATTRIBUTE      ; jump back

CODE16C ENDS


CODE16C_TUNE4 SEGMENT

T_DOSIFINDFIRST LABEL FAR

CODE16C_TUNE4 ENDS


CODE32_TUNE4  SEGMENT
; align 4 54686
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PFINDFIRST PROC


dff_InfoLevel   equ     DWORD PTR [ebp+32]

        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 storage
        push    eax             ;Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags
        push    eax             ; temp storage for ptr param #1
        push    eax             ; temp storage for ptr param #2

dff_EAOPptr     equ     DWORD PTR [ebp-44]
        push    eax             ; temp storage for ptr param #3

dff_GEAptr      equ     DWORD PTR [ebp-48]
dff_GEAtemp     equ     DWORD PTR [ebp-52]

        push    eax             ; temp storage for ptr param #4
        push    eax             ; temp storage for ptr param #5
        push    eax             ; temp storage for ptr param #6
;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short L501              ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L501

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01
        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+8]             ; base address

;Pointer  -->
        or      esi,esi
        jz      L502

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

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

L502:


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

;Pointer phdir --> phdir
        or      esi,esi
        jz      L503

        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
        mov     eax,[esi]
        cmp     si,65532
        jbe     L504                    ;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     [edi],ax
        mov     [ebp-40],edi

L504:

;Allowable Value List


        cmp     eax,0ffffffffh
        je      L505

        cmp     eax,0ffffh
        ja      INVP_DOS32PFINDFIRST            ;Jmp on large value

L505:
L503:


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

;
; Based on the value found in the InfoLevel, pFindBuf returns different
; values.
;



;Pointer pFindBuf --> pFindBuf
        or      esi,esi
        jz      L506

        mov     dff_EAOPptr,esi

        mov     eax,dff_InfoLevel

        cmp     eax,4           ;###46681 Check for info level 4
        je      L505d           ;###46681

        cmp     eax,3           ;Check for info level 3
        je      L505d

        cmp     eax,2           ;Check for info level 2
        je      L504a
        cmp     eax,1
        je      L504a

        mov     eax,ERROR_INVALID_LEVEL ;Don't know this info level
        jmp     ERR_DOS32PFINDFIRST

;
; Infolevel's 1 and 2 don't require any repacking. Therefore, just check
; the buffer for boundary crossing.
;

L504a:
        mov     ecx,[ebp+24]    ;Get length of buffer
        movzx   eax,cx          ;Check for buffer too big
        cmp     eax,ecx
        jne     INVP_DOS32PFINDFIRST



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

        cmp     ax,cx
        jae     L506                    ;Enough room

        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEM_DOS32PFINDFIRST
        mov     dff_EAOPptr,edi
        or      edx,edx
        js      L506            ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],4             ;Set Flag
        jmp     L506

        ;This is output only, so ignore any copy in operation



;
; Now we know we have an extended attribute. In this case, only GEA list
; is copied in. fpFEAList is ignored.
;
; This particular API packs the EAOP and file information into the same
; buffer. We are going to change the pointers in place, so that everything
; works out correctly. This could cause a problem with multi-threaded apps
; if another thread tries to use this buffer. However, we are going to be
; writing to this buffer anyway, so shame on the app for not serializing
; access to this data structure.
;

L505d:  mov     ecx,[ebp+24]    ;Get length of buffer
        movzx   eax,cx
        cmp     ecx,eax
        jne     INVP_DOS32PFINDFIRST



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

        cmp     ax,cx
        jae     L505g                   ;Enough room

        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEM_DOS32PFINDFIRST
        mov     dff_EAOPptr,edi
        or      edx,edx
        js      L505g           ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],4             ;Set Flag


; Now EDI points at the useable buffer. The only useful input information
; is the pointer to the GEA list. We may be about to clobber the original,
; so we need to store it in our local frame. We will stick it in the place
; normally used for the FEA temp ptr.

L505g:
        mov     esi,[esi]               ;esi = GEAptr
        mov     dff_GEAtemp,esi         ;Store in temp storage
        or      esi,esi
        jz      L505j

        mov     dff_GEAptr,esi          ;Set temp ptr

        mov     ecx,[esi]               ;Get its length
        movzx   eax,cx                  ;Check Length
        cmp     eax,ecx
        jne     INVP_DOS32PFINDFIRST

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

        cmp     ax,cx
        jae     L505j                   ;Enough room

        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEM_DOS32PFINDFIRST
        mov     dff_GEAptr,edi
        or      edx,edx
        js      L505i           ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],8             ;Set Flag
        dec     edx
        js      L505j           ;Aliases don't copy in

L505i:
        call    THK32COPYBLOCK

L505j:

        mov     esi,dff_EAOPptr ;Patch in new pointer
        mov     eax,dff_GEAptr

        or      eax,eax
        jz      L505ja

        cmp     eax,[FenceLAddr]
        jae     L505jaCRMA
        call    DOS32FLATTOSEL
        jmp     short L505ja

L505jaCRMA:
        ror     eax,16
        shl     ax,3
        mov     cx,ss
        and     cx,3
        or      cl,7
        or      al,cl
        rol     eax,16

L505ja:
        mov     [esi],eax               ;Store in useable buffer




L506:   mov     esi,[ebp+28]            ;pusSearchCount base address

;Pointer pusSearchCount --> pusSearchCount
        or      esi,esi
        jz      L507

        mov     [ebp-56],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
        mov     eax,[esi]
        cmp     si,65532
        jbe     L508                    ;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     [edi],ax
        mov     [ebp-56],edi

L508:
        cmp     eax,0ffffh
        jbe     L507                    ;For any value greater than 64K-1,
        mov     eax,0ffffh              ;  Use 64K-1  (-1)

L507:

; ****> END Pointer/Structure Section

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

        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: string
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L509                      ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     L509CRMA
        call    DOS32FLATTOSEL
        jmp     short L509

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

L509:   push    eax



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

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



        ;From Name:   Type: unsigned long
        mov     eax,[ebp+16]
        cmp     eax,0ffffh
        ja      INVP_DOS32PFINDFIRST

        push    ax              ;To:unsigned short


        ;From Name: pFindBuf  Type: struct EAOP
        mov     eax,DWORD PTR [ebp-44]
        or      eax,eax
        jz      short L511                      ;NULL pointer

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



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

        push    ax              ;To:unsigned short


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

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



        ;From Name: ulInfoLevel Type: unsigned long
        mov     eax,[ebp+32]
        cmp     eax,0ffffh
        ja      INVP_DOS32PFINDFIRST

        push    ax              ;To:unsigned short


        ;From Name: pFlatReturnData Type: unsigned long
        mov     eax,[ebp+36]
        push    eax             ;To:unsigned long


        ;From Name: pFlatResultBuf Type: unsigned long
        mov     eax,[ebp+40]
        push    eax             ;To:unsigned long


        ;From Name: pFlatSearchCtPtr Type: unsigned long
        mov     eax,[ebp+44]
        push    eax             ;To:unsigned long


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


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

NOMEM_DOS32PFINDFIRST:
        push    8
        pop     eax

ERR_DOS32PFINDFIRST:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L513
R_DOSIFINDFIRST:                                ; 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


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

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


;Undo Pointer  -->


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



        mov     edi,[ebp+8]             ; 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      L514
;Handle String Parameters
;Strings are never copied out
        push    -32             ;Alloc Flag Offset
        mov     edx,1

        call    THK32DEALLOC


L514:           ;No action required

;Undo Pointer phdir --> phdir


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



        mov     edi,[ebp+12]            ;phdir 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

L518:           ;No action required

;
; pFindBuf
;
;

;Undo Pointer pFindBuf --> pFindBuf


        mov     esi,dff_EAOPptr         ;pFindBuf temp address
        or      esi,esi
        jz      L519

        mov     edi,[ebp+20]            ;pFindBuf original address


;
; Check to see what it is
;

        cmp     dff_InfoLevel,4         ;###46681 Is it EABuf?
        je      L519a                   ;###46681

        cmp     dff_InfoLevel,3         ;Is it EABuf?
        je      L519a

        cmp     dff_InfoLevel,2         ;One of the others?
        je      L518a
        cmp     dff_InfoLevel,1
        jne     L519                    ;Nothing we know about. Skip it

;
; Its directory information
;

L518a:

        cmp     esi,edi                 ;Did we copy it?
        je      L519                    ;Jump if not

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

        mov     ecx,[ebp+24]    ;Get length of buffer

        push    esi             ;Copy it out
        call    THK32COPYBLOCK
;       pop     edi             ;108596
        pop     esi             ;

L519b:
        push    -32
        mov     edx,4
        call    THK32DEALLOC
        jmp     L519

L519a:

;
; Handle GEA list
;

        mov     esi,dff_GEAptr          ;Get pointer to temporary
        or      esi,esi                 ;Ignore if NULL
        jz      L522

        mov     edi,dff_GEAtemp         ;Get original pointer

        cmp     esi,edi                 ;Did we make a new copy?
        je      L522                    ;Jump if not
;
; The GEA list is thrown away
;

        push    -32
        mov     edx,8
        call    THK32DEALLOC


;
; Handle the main buffer
;

L522:
        mov     esi,dff_EAOPptr         ;Get ptr to temp copy
        or      esi,esi                 ;Ignore it if null
        jz      L519

        mov     edi,[ebp+20]            ;Get original address
        cmp     edi,esi                 ;Was there a change?
        je      L523                    ;Jump if not

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


        test    BYTE PTR[ebp-32],4      ;Was it aliased?
        jnz     L522b                   ;Jump if yes

        mov     ecx,[ebp+24]            ;Get length of buffer

;
; This buffer needs to be copied out
;
        push    esi
        call    THK32COPYBLOCK
        pop     esi


L522b:
;
; Deallocate
;
        push    -32
        mov     edx,4
        call    THK32DEALLOC

L523:
        mov     edi,[ebp+20]
        mov     eax,dff_GEAtemp         ;Restore original GEA ptr
        mov     [edi],eax


L519:           ;No action required

;Undo Pointer pusSearchCount --> pusSearchCount


        mov     esi,[ebp-56]            ;pusSearchCount temp address
        or      esi,esi
        jz      L531



        mov     edi,[ebp+28]            ;pusSearchCount 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

L531:           ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-60]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        leave
        ret                             ; Remove parameters

DOS32PFINDFIRST endp

CODE32_TUNE4  ENDS

;* 16-bit code to make API call.

CODE16C_TUNE4 SEGMENT

        ASSUME CS:CODE16C_TUNE4
        .errnz ($ - T_DOSIFINDFIRST)

        call    FAR PTR DOSIFINDFIRST           ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSIFINDFIRST            ; jump back

CODE16C_TUNE4 ENDS






;Create a dummy label to trick MASM into correct fixups

CODE16C_TUNE2 SEGMENT

T_DOSQPATHINFO  LABEL FAR

CODE16C_TUNE2 ENDS


CODE32_TUNE2  SEGMENT
; align 4 54686
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PQUERYPATHINFO PROC

d32qpi_InfoLevel equ DWORD PTR [ebp+12]


        push    ebp
        mov     ebp,esp


        cld                     ;Assume direction flag clear
        xor     eax,eax

tmpStore equ DWORD PTR [ebp-4]

        push    eax             ; temp storage for return value
        push    esi
        push    edi
        push    eax             ; temp storage
        push    eax             ; Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags

        push    eax             ; temp storage for ptr param #1

d32qpi_ResBuf   equ DWORD PTR [ebp-40]
        push    eax             ; temp storage for ptr param #2

d32qpi_GEAtempptr equ DWORD PTR [ebp-44]
d32qpi_FEAtempptr equ DWORD PTR [ebp-48]

        push    eax             ; Storage for EAOP Ptr 1
        push    eax             ; Storage for EAOP Ptr 2

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

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32              ; standard 32 bit stack?
        jne     short L801              ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L801

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01

        mov     esp,eax         ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section


        mov     esi,[ebp+8]             ; base address

;Pointer  -->
        or      esi,esi
        jz      L801a

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

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

L801a:



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

;Pointer pfstsInfo --> pfstsInfo
        or      esi,esi
        jz      L802

        mov     d32qpi_ResBuf,esi

; Determine the type based on the PATHInfoLevel
;
        mov     eax,d32qpi_InfoLevel

        cmp     eax,1           ;Is it FILESTATUS?
        jne     L801b
;
;At this point, we know that the pointer is to a FILESTATUS parameter
;There is no change between 32 and 16 bits
;Just insure that data doesn't cross boundary.

        cmp     si,(- FILESTATUS_SIZE)
        jbe     L802

        ;It crosses. Take space from stack
; Allocate space on stack
        sub     esp,FILESTATUS_SIZE     ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
        mov     d32qpi_ResBuf,edi

        ;Output only parameter.

        jmp     L802z
L801b:
        cmp     eax,2           ;Is it FILESTATUS2?
        jne     L801c

        ;FILESTATUS2 is different between 32 and 16 bits.

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


;The only difference between 3 and 4 is that 4 ignores the GEA list.
;
L801c:
        cmp     eax,3
        je      short L801d
        cmp     eax,4
        je      short L801d
        cmp     eax,8           ;###46681 level 8 will not fill in get eas if cblist
        je      short L801d     ;###46681 for the file is 4 (no ea's present)

        cmp     eax,5
        je      Linfo5
        cmp     eax,7
        je      Linfo7


;
; Oh No! We have a bad InfoLevel. Crap out of the deal
;

        mov     eax,ERROR_INVALID_LEVEL
        jmp     ERRDOS32PQUERYPATHINFO

; Infolevel 5 DOSQPATHINFO or Infolevel 7 DOSQPATHINFO
; We now have a buffer with a size parameter
;
;

Linfo5:
Linfo7:
        mov     ecx,[ebp+20]            ;Get length
        movzx   eax,cx
        cmp     eax,ecx
        jne     INVPDOS32PQUERYPATHINFO ;Buffer too long



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

        cmp     ax,cx
        jae     L802z                   ;Enough room


        call    THK32HANDLEBOUNDARY
        or      eax,eax
        jnz     NOMEMDOS32PQUERYPATHINFO
        mov     d32qpi_ResBuf,edi
        or      edx,edx
        js      L802z           ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],2             ;Set Flag
        jmp     L802z



;
; We know we have an EA buffer. Handle it.
; EAbufs require pointer conversions. Make a new copy of buffer
;


L801d:

        sub     esp,12                  ;Alloc Mem
        and     esp,0FFFFFFFCh          ;DWORD align
        mov     edi,esp                 ;Points to new data area
        mov     d32qpi_ResBuf,edi

        cmp     eax,4                   ;Is it infolevel 4
        je      L801h

;
;
; We are at info level 3, and need to copy in the GEA list
;
        mov     esi,[esi]               ;Get PTR to GEA list
        or      esi,esi
        jz      L801g                   ;If GEA is null, go handle FEA
        mov     d32qpi_GEAtempptr,esi

        mov     ecx,[esi]               ;Get the length

        movzx   eax,cx                  ;Check for > 64k length
        cmp     eax,ecx
        jne     INVPDOS32PQUERYPATHINFO

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

        cmp     ax,cx
        jae     L801g                   ;Enough room


;
;The boundary has been crossed. Handle it.
;

        call    THK32HANDLEBOUNDARY
        or      eax,eax
        jnz     NOMEMDOS32PQUERYPATHINFO
        mov     d32qpi_GEAtempptr,edi
        or      edx,edx
        js      short L801f             ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],4             ;Set Flag
        dec     edx
        js      short L801g             ;Aliases not copied

L801f:                  ;Variable Length Copy

; Copy ECX bytes from ESI to EDI
        call    THK32COPYBLOCK

L801g:
        mov     esi,[ebp+16]            ;Reload original source
L801h:

;
        mov     esi,[esi+4]             ;Get PTR to FEA list
        or      esi,esi
        jz      L802

        mov     d32qpi_FEAtempptr,esi

        mov     ecx,[esi]               ;Get the length

        movzx   eax,cx                  ;Check for > 64k length
        cmp     eax,ecx
        jne     INVPDOS32PQUERYPATHINFO

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

        cmp     ax,cx
        jae     L802                    ;Enough room


;
;
;The boundary has been crossed. Handle it.
;
;

        call    THK32HANDLEBOUNDARY
        or      eax,eax
        jnz     NOMEMDOS32PQUERYPATHINFO
        mov     d32qpi_FEAtempptr,edi
        or      edx,edx
        js      short L801j             ;Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],8             ;Set Flag
        dec     edx
        js      short L802              ;Aliases not copied

L801j:
        mov     eax,[esi]               ;Only copy in the length
        mov     [edi],eax

L802:
        mov     cx,ss
        and     cx,3
        or      cx,4                    ;Force LDT on

        mov     esi,d32qpi_ResBuf               ;Get new EAOP into source
        mov     eax,d32qpi_GEAtempptr
        or      eax,eax
        jz      short L802a

        cmp     eax,[FenceLAddr]
        jae     L802aCRMA
        call    DOS32FLATTOSEL
        jmp     short L802a

L802aCRMA:
        ror     eax,16
        shl     ax,3
        or      al,cl
        rol     eax,16

L802a:  mov     [esi],eax               ;Store new PTR


        mov     eax,d32qpi_FEAtempptr
        or      eax,eax
        jz      short L802b

        cmp     eax,[FenceLAddr]
        jae     L802bCRMA
        call    DOS32FLATTOSEL
        jmp     short L802b

L802bCRMA:
        ror     eax,16
        shl     ax,3
        or      al,cl
        rol     eax,16

L802b:
        mov     [esi+4],eax             ;Store new PTR



L802z:

; ****> END Pointer/Structure Section

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

        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: string
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L806zz                    ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     L806zzCRMA
        call    DOS32FLATTOSEL
        jmp     short L806zz

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

L806zz: push    eax


        ;From Name:   Type: unsigned long
        mov     eax,[ebp+12]
        cmp     eax,0ffffh
        ja      INVPDOS32PQUERYPATHINFO

        push    ax              ;To:unsigned short


        ;From Name: pfstsInfo  Type: struct FILESTATUS2
        mov     eax,d32qpi_ResBuf
        or      eax,eax
        jz      short L803                      ;NULL pointer

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



        ;From Name: cbInfoBuf  Type: unsigned long
        mov     eax,[ebp+20]
        cmp     eax,0ffffh
        ja      INVPDOS32PQUERYPATHINFO

        push    ax                      ; To:unsigned short

        push    0                       ; Reserved DWORD

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


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

NOMEMDOS32PQUERYPATHINFO:
        push    8
        pop     eax

ERRDOS32PQUERYPATHINFO:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L804
R_DOSQPATHINFO:                         ; 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


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

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


;Undo Pointer  -->


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



        mov     edi,[ebp+8]             ; 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      L809zz
;Handle String Parameters
;Strings are never copied out
        push    -32             ;Alloc Flag Offset
        mov     edx,1

        call    THK32DEALLOC


L809zz:         ;No action required




;Undo Pointer pfstsInfo --> pfstsInfo

        mov     esi,d32qpi_ResBuf               ;pfstsInfo temp address
        or      esi,esi
        jz      L805

        mov     edi,[ebp+16]            ;pfstsInfo original address
        mov     eax,d32qpi_InfoLevel




        cmp     eax,1
        je      L804a

        cmp     eax,2
        je      L804b

        cmp     eax,3
        je      L804bb

        cmp     eax,4
        je      L804bb

        cmp     eax,5
        je      L804bba

        cmp     eax,7
        je      L804bba

        cmp     eax,8         ;###46681 Level 8 is treated as a level 3
        je      L804bb        ;###46681

        ;Do nothing for level 6 or >

        jmp     L805

;
;InfoLevel = 1. If esi != edi, copy out the buffer
;
L804a:
        test    BYTE PTR[ebp-20],1              ;Check for errors
        jnz     L805

        cmp     esi,edi
        je      L805

        mov     ecx,FILESTATUS_SIZE

        call    THK32COPYBLOCK

        jmp     L805

;
; InfoLevel 2
;

L804b:

;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     L805                    ;No copy if error

        mov     ecx,5
        rep     movsd
        movsw

;Transfer 2 bytes of zero to high word of ulattrFile
        mov  es:[edi],cx

;ReAlignment
        add     edi,2

        movsd

        jmp     L805


;
; InfoLevel 5
; InfoLevel 7
;


L804bba:

;
; If esi=edi, then no buffer copy was done.
;
        cmp     esi,edi
        je      L805                    ;Nothing to do

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

        mov     ecx,[ebp+20]            ;Get Length

        push    esi
        call    THK32COPYBLOCK
        pop     esi

L804bc:
        push    -32
        mov     edx,4
        call    THK32DEALLOC
        jmp     L805

;
; It is an EAOP
;
;

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

        mov     ecx,[esi+8]             ;Place error offset into buffer
        mov     [edi+8],ecx

;
; At this point, we are either InfoLevel 3 or InfoLevel 4
;


L804c:
        cmp     eax,4           ;If level 3, then GEA might need help
        je      L804e

;Save pointers to current buffers.

        push    esi
        push    edi

;GEA op needs to be checked for deallocation


        mov     esi,d32qpi_GEAtempptr
        cmp     [edi],esi               ;Check against original
        je      L804d                   ;Leave it alone

;We don't need to copy this guy out.

        push    -32                     ;Offset of ALIAS flags
        mov     edx,4
        call    THK32DEALLOC

L804d:
        pop     edi
        pop     esi

;
; Infolevel 4
;


L804e:
        mov     edi,[edi+4]     ;Get FEA pointers
        mov     esi,d32qpi_FEAtempptr

        cmp     esi,edi
        je      L805

;
; Need to copy this fellow out
;
        test    BYTE PTR[ebp-20],1              ;Check for errors D
        jnz     L804z                   ;No copy if error

        mov     ecx,[esi]
        push    esi
        call    THK32COPYBLOCK
        pop     esi

;
; Deallocate temp buffer
;

L804z:
        push    -32                     ;Offset of ALIAS flags
        mov     edx,8
        call    THK32DEALLOC

L805:           ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-52]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        leave
        ret                             ; Remove parameters

DOS32PQUERYPATHINFO endp

CODE32_TUNE2  ENDS


;* 16-bit code to make API call.

CODE16C_TUNE2 SEGMENT

        ASSUME CS:CODE16C_TUNE2
        .errnz ($ - T_DOSQPATHINFO)

        call    FAR PTR DOSQPATHINFO                    ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSQPATHINFO             ; jump back

CODE16C_TUNE2 ENDS



CODE16C_TUNE4 SEGMENT

T_DOSMKDIR2     LABEL FAR

CODE16C_TUNE4 ENDS


CODE32_TUNE4  SEGMENT
; align 4 54686
        ASSUME CS:FLAT,DS:FLAT,ES:FLAT
DOS32PCREATEDIR 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 storage
        push    eax             ;Error flag for cleanup
        push    eax             ; temp storage for Stack Allocation Flags
        push    eax             ; temp storage for BMP Flags
        push    eax             ; temp storage for Alias Flags
        push    eax             ; temp storage for ptr param #1
        push    eax             ; temp storage for ptr param #2
        push    eax             ; temp storage for ptr param #3
        push    eax             ; temp storage for ptr param #4
;* Compare stack selector against FLAT:R3DSB
;* If the selector is not equal, then don't bump stack.

        push    0000            ; push for stack comparison later       ;TPL01
        mov     ax,ss
        cmp     ax,seg FLAT:DATA32      ; standard 32 bit stack?
        jne     short L1201             ; if not, skip bumping code

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

        mov     eax,esp
        cmp     ax,1024
        jae     short L1201

;       xor     ax,ax                                                   ;TPL01

        pop     ecx             ; old stack comparator                  ;TPL01
        call    THK32ALLOCSTACK ; bump the stack down                   ;TPL01
        push    eax             ; old stack comparator on old stack     ;TPL01

        mov     esp,eax                 ; bump the stack down


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


; ****> BEGIN Pointer/Structure Section



        mov     esi,[ebp+8]             ; base address

;Pointer psz --> psz
        or      esi,esi
        jz      L1202

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

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

L1202:


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

;Pointer pEABuf --> pEABuf
        or      esi,esi
        jz      L1203

        mov     [ebp-40],esi

;Structures are Identical
;Structures have pointers

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


;Element fpGEAList --> fpGEAList
;Pointer converted later

;Element fpFEAList --> fpFEAList
;Pointer converted later

;Element offError --> offError
;Add 4 bytes of unsigned long to transfer

;Transfer 12 bytes

        mov     ecx,3
        rep     movsd

;***
;
; The fpGEAList is ignored by DosMkDir2, and therefore will be
; ignored here

;Fixup imbedded pointer fpFEAList

        mov     esi,[ebp-40]            ;Get parents pointer
        mov     esi,[esi+4]             ;Get Fixups pointer

;Pointer fpFEAList --> fpFEAList
        or      esi,esi
        jz      L1208

        mov     [ebp-48],esi

;Structures are Identical
;Structures don't have pointers

;Treat structure same as buffer

;The length of this structure is the first DWORD
;Get the length, and insure that it doesn't cross a boundary

        mov     eax,[esi]
        movzx   ecx,ax
        cmp     eax,ecx
        jne     INVPDOS32PCREATEDIR


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

        cmp     ax,cx
        jae     L1208                   ;Enough room

        call    Thk32HandleBoundary
        or      eax,eax
        jnz     NOMEMDOS32PCREATEDIR
        mov     [ebp-48],edi
        or      edx,edx
        js      short L1208a            ; Alloced Mem
        or      BYTE PTR [ebp+(edx*4)-32],16    ; Set Flag
        dec     edx
        js      short L1208

L1208a:                                 ; variable length copy

; Copy ECX bytes from ESI to EDI
        push    esi
        call    THK32COPYBLOCK
        pop     esi


L1208:

;Patch in new pointer value
        mov     edi,[ebp-40]            ;Get parents pointer
        mov     esi,[ebp-48]            ;Get Fixups new pointer
;Convert 0:32 --> 16:16
        or      esi,esi
        jz      short L1211

        cmp     esi,[FenceLAddr]
        jae     L1211CRMA
        mov     eax,esi
        call    DOS32FLATTOSEL
        mov     esi,eax
        jmp     short L1211

L1211CRMA:
        ror     esi,16
        shl     si,3
        mov     ax,ss
        and     ax,3
        or      al,4
        or      si,ax
        rol     esi,16

L1211:
        mov     [edi+4],esi             ;Put Fixups pointer

L1203:

; ****> END Pointer/Structure Section

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

        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: string
        mov     eax,DWORD PTR [ebp-36]
        or      eax,eax
        jz      short L1212             ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     L1212CRMA
        call    DOS32FLATTOSEL
        jmp     short L1212

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

L1212:  push    eax



        ;From Name: pEABuf  Type: struct EAOP
        mov     eax,DWORD PTR [ebp-40]
        or      eax,eax
        jz      short L1213             ;NULL pointer

        cmp     eax,[FenceLAddr]
        jae     L1213CRMA
        call    DOS32FLATTOSEL
        jmp     short L1213

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

L1213:  push    eax



        ;From Name:   Type: unsigned long

;Extra parameter needed: Push a zero
        push    0               ;Push U/LONG

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


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

NOMEMDOS32PCREATEDIR:
        push    8
        pop     eax

ERRDOS32PCREATEDIR:
        mov     BYTE PTR [ebp-20],1             ;Set flag
        jmp     short L1214
R_DOSMKDIR2:                            ; 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


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

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


;Undo Pointer psz --> psz


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



        mov     edi,[ebp+8]             ; 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      L1215
;Handle String Parameters
;Strings are never copied out
        push    -32                     ;Alloc Flag Offset
        mov     edx,1

        call    THK32DEALLOC


L1215:          ;No action required

;Undo Pointer pEABuf --> pEABuf


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



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

;Structures are Identical
;Structures have pointers
;Structure has output semantics
;Return structure to original area


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

;Element fpGEAList --> fpGEAList
;Pointer elements not copied out

;Element fpFEAList --> fpFEAList
;Pointer elements not copied out

; Copy out only the offError value

        mov     eax,[esi+8]
        mov     [edi+8],eax

L1220:                  ;ErrorLabel D


;Unpack imbedded pointer fpFEAList

        mov     esi,[ebp-48]            ;Get pointer to temporary
        or      esi,esi                 ;Ignore if NULL
        jz      L1226

        cmp     [edi+4],esi
        je      L1226

        push    -32
        mov     edx,16
        call    THK32DEALLOC

L1226:

;Deallocate Temporary Structure


;Stack allocated memory deallocated implicitly

L1219:          ;No action required

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

;* 32-bit return code.

        lea     esp,[ebp-52]    ; get the old stack                     ;TPL01
        pop     ecx             ; get the new stack                     ;TPL01
        jecxz   short @f        ; is it new                             ;TPL01
        call    THK32FREESTACK  ; deallocate the memory                 ;TPL01
@@:                                                                     ;TPL01
        lea     esp,[ebp-12]
        pop     edi
        pop     esi
        pop     eax             ;Pop saved return code
        leave
        ret                             ; Remove parameters

DOS32PCREATEDIR endp

CODE32_TUNE4  ENDS

;* 16-bit code to make API call.

CODE16C_TUNE4 SEGMENT

        ASSUME CS:CODE16C_TUNE4
        .errnz ($ - T_DOSMKDIR2)

        call    FAR PTR DOSMKDIR2               ; call 16-bit version
        jmp     FAR PTR FLAT:R_DOSMKDIR2                ; jump back

CODE16C_TUNE4 ENDS




CODE32  SEGMENT
; align 4 54686


        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
