;       SCCSID = @(#)d_find.asm	6.1 91/02/15
;       SCCSID = @(#)d_find.asm	1.6 90/01/22
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************
;***  D_FIND.ASM - API stub routine DosFindFirst
;
;       Member of API library
;       David Silverstein
;       Bill Mershon
;       Copyright MicroSoft Corporation, 1986
;       9-June-1986
;
;       library routine for API simulator
;
;       Called from dos 2.x,3.x compatible dos 5.x applications
;
;       Special Information
;               none
;
;       Modification History
;
;       09-05-86 (billme):  change check at top of DosFindFirst
;       from "equal FIND_CLOSED" to "not equal FIND_OK"... this
;       allows FIND_FAILED to be a valid reentry to DosFindFirst
;       without having to call DosFindClose
;
;       06-Jan-87 (billme): Replace initial pushes and final pops
;       with calls to __api_begin and __api_end resp.  This will
;       reduce the size of FAPI and allow support for signals.
;
; @@    8-May-87 (Tarng): Check reserved dword are zeros.
;                         Check filename/pathname is in the 8.3 range.
;
; @@    18-AUG-87 (robertc): add checking for critical errors
;
; @@    31-AUG-87 (robertc): fix checking for critical errors
;
; @@    25-SEP-87 (robertc): zero out count after error
;
;       07-APR-88 (robertc): 1.2 changes
;
;       02-Jun-88 (robertc): fix info level 3 to init cbList
;
;       15-Sep-88 (lynnaeb):fix DOSFINDFIRST cpd12 p1635 and p1897
;
;       22-Nov-88 (klee):change length of find_path from 129 to 142 bytes
;                        p2846
;
;       22-NOv-88 (klee):fix get_path for p2820
;
;       14-Dec-88 (klee) PTM 3173 modify buffsiz subtraction
;
;       16-Dec-88 (klee) PTM 3253 modify buffer size when it is bigger that
;                                 0xfff5
;
;        5-Jan-89 (klee) PTM 3393 In DosFindNext, if buffer is big enough for
;                        one file but not enough for the number of files given
;                        in count field, no error message is returned and
;                        one file may be lost for subsequent DosFindNext call.
;                        The file lost will be fixed in PTM 3397
;
;       10-Jan-89 (klee) PTM 3397 In DosFindFirst and DosFindNext, when buffer
;                        is not big enough for the files given in the search
;                        count, one file which induce the overflow is lost.
;                        To recover the file in DosFindNext a flag variable is
;                        set and the DTAarea is kept. So in next DosFindNext
;                        the saved DTAarea is copied back and DosFindNext is
;                        emulated.
;
;       22-Feb-89 (klee) p70035 for DBCS
;
;       08-Apr-89 (klee) PB700121 for the returned FindNext file name of '..'
;                        of the int 21h (GetSetFileDT) of the Pinball root
;                        directory. Ignore returned error 1 (changed into 3
;                        by api_get_extended which means ERROR_PATH_NOT_FOUND).
;                        DCR 105 changes the size of cbList to 4 bytes from
;                        2 bytes.
;
;       24-Jul-89 (klee) Point DCrR 105.
;                        The offser error field is 4 bytes long and therefore
;                        the buffer should be adjusted accordingly.
;
;       31-Jul-89 (klee) SM84862
;                        Add new error code ERROR_EAS_DIDNT_FIT from DCR 383.
;

;/********************** START OF SPECIFICATIONS *********************/
;/*                                                                  */
;/* SUBROUTINE NAME: DosFindFirst                                    */
;/*                                                                  */
;/* DESCRIPTIVE NAME: Dos Find First                                 */
;/*                                                                  */
;/* FUNCTION: Finds the first filename that matches the              */
;/*           specified file specification.                          */
;/*                                                                  */
;/*                                                                  */
;/* NOTES:    Real Mode Only                                         */
;/*           Simulates OS/2 call from DOS 2.x,3.x environment       */
;/*                                                                  */
;/* ENTRY POINT: DosFindFirst                                        */
;/*    DosFindFirst(FilePathName, DirHandle, Attribute, ResultBuf,   */
;/*                 ResultBufLen, SearchCount, 0);                   */
;/*                                                                  */
;/*                                                                  */
;/*    LINKAGE: Call Far                                             */
;/*                                                                  */
;/* INPUT: Stack Frame in form of:                                   */
;/*                                                                  */
;/*     PUSH@ ASCIIZ FilePathName - File path name                   */
;/*     PUSH@ WORD   DirHandle - Directory search handle             */
;/*     PUSH  WORD   Attribute - Search Attribute                    */
;/*     PUSH@ OTHER  ResultBuf - Result buffer                       */
;/*     PUSH  WORD   ResultBufLen - Result buffer length             */
;/*     PUSH@ WORD   SearchCount - number of entries to find         */
;/*     PUSH  DWORD  0 - Reserved                                    */
;/*                                                                  */
;/*                                                                  */
;/* EXIT-NORMAL:   AX = 0                                            */
;/*                                                                     */
;/* EXIT-ERROR:    AX = Errorcode                                         */
;/*       may return error code from Dos 2.x, 3.x, OS/2                         */
;/*                                                                     */
;/* EFFECTS:  AX, all other registers preserved                      */
;/*                                                                     */
;/* WARNING:                                                            */
;/*        may return error code from Dos 2.x, 3.x (see dos manuals) */
;/*        Only supports one find/first/next call sequence at a time.*/
;/*                                                                     */
;/*     On sucessfull calls to DOSFINDFIRST, the memory area DTAarea */
;/*     contains the search context information necessary for future */
;/*     DOSFINDNEXT calls.                                              */
;/*                                                                     */
;/*                                                                     */
;/* INTERNAL REFERENCES: none                                        */
;/*                                                                     */
;/*    ROUTINES: none                                                   */
;/*                                                                     */
;/* EXTERNAL REFERENCES:                                                        */
;/*                                                                     */
;/*    ROUTINES: DosFindFirst2                                       */
;/*              __api_begin                                         */
;/*              __api_end                                           */
;/*                                                                  */
;/*********************** END OF SPECIFICATIONS **********************/

include basemaca.inc
include realmac.inc
include dos2equ.inc
include error.inc
include api.inc

        EXTRN   __api_begin:near
        EXTRN   __api_end:near
;       EXTRN   _api_init:far           ; b700035 for dbcs
        EXTRN   api_testdbcs_b:far      ; b700035 for dbcs
        EXTRN   _api_getvrsn:near
        EXTRN   name_check:far          ;@@ added support for 8.3 filename
        EXTRN   api_get_extended:far    ;@@ added support for DOSErrorClass
        EXTRN   crit_err_flag:word       ;@@need to check for critical error

        title   DOSFINDFIRST

_TEXT   segment byte public 'CODE'

        assume  CS:_TEXT, DS:nothing

        public  DOSFINDFIRST

FilePathName    equ     [bp + 26]
DirHandle       equ     [bp + 22]
Attribute       equ     [bp + 20]
ResultBuf       equ     [bp + 16]
ResultBufLen    equ     [bp + 14]
SearchCount     equ     [bp + 10]
Reserved0       equ     [BP +  6]          ;@@ Reserved dword = 0

FIND_CLOSED             equ     0
FIND_OK                 equ     1                       ; valid active dirhandle
FIND_FAILED             equ     2                       ; bad active dirhandle
VALID_DIRHANDLE         equ     1
ALLOC_DIRHANDLE         equ     0ffffh
VALID_ATTR_BITS         equ     110111b                 ; valid attribute bits
MAX_FILENAME_SIZE       equ     13                      ; incs a '.' and null
;MAX_PATH                equ     128
MAX_PATH                equ     260
FINDSTRUCSIZE           equ     23 + MAX_FILENAME_SIZE
L1BUFFSIZE                equ           23
L2BUFFSIZE              equ     27                      ; 4 bytes cbList


FINDSTRUC       STRUC
        FileCreateDate  dw      ?
        FileCreateTime  dw      ?
        FileAccessDate  dw      ?
        FileAccessTime  dw      ?
        FileWriteDate   dw      ?
        FileWriteTime   dw      ?
        FileDataEndLow  dw      ?
        FileDataEndHigh dw      ?
        FileAllocLow    dw      ?
        FileAllocHigh   dw      ?
        FileAttribute    dw      ?
        FileNameLength  db      ?
        FileName        db      MAX_FILENAME_SIZE dup(?)
FINDSTRUC      ENDS

FINDSTRUC2      STRUC
        FileCreateDate2 dw      ?
        FileCreateTime2 dw      ?
        FileAccessDate2 dw      ?
        FileAccessTime2 dw      ?
        FileWriteDate2  dw      ?
        FileWriteTime2  dw      ?
        FileDataEndLow2 dw      ?
        FileDataEndHigh2 dw      ?
        FileAllocLow2   dw      ?
        FileAllocHigh2  dw      ?
        FileAttribute2  dw      ?
        FileCBList2     dd      ?                 ; 4 bytes cbList
        FileNameLength2 db      ?
        FileName2       db      MAX_FILENAME_SIZE dup(?)
FINDSTRUC2     ENDS

EAOP    STRUC
        fpGEAListOffs   dw      ?
        fpGEAListSeg    dw      ?
        fpFEAListOffs   dw      ?
        fpFEAListSeg    dw      ?
        offError        dw      ?
        offError2       dw      ?
EAOP    ends


oldDTA          dd      ?               ; save area for old DTA pointer
DTAarea         DTAFINDSTRUC <>         ; DTA area used in the find calls
FindFlag        db      FIND_CLOSED     ; data at DTA valid for FindNext call
SecondFind      db      ?               ; flag at least 1 file found
FindFirstFlag   db      ?
FindInfoLevel   dw      ?
UseNew          dw      ?
UserCS          dw      ?
UserIP          dw      ?
userBP          dw      ?
FirstCopy       dw      ?
BuffSize        dw      ?
BuffOffs        dw      ?
FEALOffs        dw      ?
;find_path       db      142 dup(?)      ; it was 129 but add 13 by p2704
; find_path had 260, but for copy of a long path name the file name length 13
; is added sl that next variable nptr_find_name is not trashed by rep movsb
; in set_path
find_path       db      273 dup(?)      ; it was 142 but change to 260

nptr_find_name  dw      ?
ovf_buf         db      ?               ; P3397 flag for overflow
ovf_dta         DTAFINDSTRUC <>         ; P3397 save DTAarea for overflow
;llvl            db      ?
eflag           db      ?               ; 1 if GetSetFileDT int 21h returns
                                        ; error for the '..' file name b700121

DOSFINDFIRST    proc    far
; check validity of reserved words
        mov     ax,ERROR_INVALID_PARAMETER ; Prepare error code
        push    bp                      ; Set up stack frame
        mov     bp,sp
        push    bx                      ; Preserve Users BX
        mov     bx,Reserved0            ; reserved words not zeros
        or      bx,Reserved0+2
        pop     bx                      ; Restore Users BX
        jnz     ffErr                   ; then return error

        pop     UserBp                  ; pop off the old bp
        pop     UserCS                  ; pop off the old cs
        pop     UserIP                  ; pop off the old ip
        push    Reserved0               ; Push Reserved Words
        mov     word ptr [Reserved0+2],1  ; Set infolevel
        call    far ptr DosFindFirst2   ; Call the Worker

        push    UserIP                  ; Restore Users IP
        push    UserCS                  ; Restore Users CS
        mov     bp,UserBp               ; Restore Users BP
        ret                             ; Return to User
ffErr:                                  ; Invalid reserved word exit
        pop     bp                      ; Remove bp
        ret     24                      ; Return to User and Lose Parms

DOSFINDFIRST    endp


;/********************** START OF SPECIFICATIONS *********************/
;/*                                                                  */
;/* SUBROUTINE NAME: DosFindFirst2                                   */
;/*                                                                  */
;/* DESCRIPTIVE NAME: Dos Find First                                 */
;/*                                                                  */
;/* FUNCTION: Finds the first filename that matches the              */
;/*           specified file specification.                          */
;/*                                                                  */
;/*                                                                  */
;/* NOTES:    Real Mode Only                                         */
;/*           Simulates OS/2 call from DOS 2.x,3.x environment       */
;/*                                                                  */
;/* ENTRY POINT: DosFindFirst2                                          */
;/*                                                                     */
;/*    LINKAGE: Call Far                                                        */
;/*                                                                     */
;/* INPUT: Stack Frame in form of:                                         */
;/*                                                                     */
;/*     PUSH@ ASCIIZ FilePathName - File path name                   */
;/*     PUSH@ WORD   DirHandle - Directory search handle             */
;/*     PUSH  WORD   Attribute - Search Attribute                    */
;/*     PUSH@ OTHER  ResultBuf - Result buffer                       */
;/*     PUSH  WORD       ResultBufLen - Result buffer length              */
;/*     PUSH@ WORD       SearchCount - number of entries to find             */
;/*     PUSH  WORD       FileInfoLevel -  File data required              */
;/*     PUSH  DWORD  0 - Reserved                                    */
;/*                                                                  */
;/*                                                                  */
;/* EXIT-NORMAL:   AX = 0                                                  */
;/*                                                                     */
;/* EXIT-ERROR:    AX = Errorcode                                               */
;/*       may return error code from Dos 2.x, 3.x, OS/2                         */
;/*                                                                     */
;/* EFFECTS:  AX, all other registers preserved                      */
;/*                                                                  */
;/* INTERNAL REFERENCES: none                                        */
;/*                                                                  */
;/*    ROUTINES: CopyData                                            */
;/*                                                                  */
;/* EXTERNAL REFERENCES: crit_err_flag                               */
;/*                                                                  */
;/*    ROUTINES: __api_begin                                         */
;/*              __api_end                                           */
;/*              name_check                                          */
;/*              api_get_extended                                    */
;/*              _api_get_version                                    */
;/*              Int 21h - GetDTA                                    */
;/*              Int 21h - SetDTA                                    */
;/*              Int 21h - FindFirst                                 */
;/*              Int 21h - FindNext                                  */
;/*              Int 21h - Get/Set File Date/Time Extended Info      */
;/*                                                                  */
;/*********************** END OF SPECIFICATIONS **********************/
        public  DOSFINDFIRST2
FilePathName2    equ     [bp + 28]
DirHandle2       equ     [bp + 24]
Attribute2       equ     [bp + 22]
ResultBuf2       equ     [bp + 18]
ResultBufLen2    equ     [bp + 16]
SearchCount2     equ     [bp + 12]
FileInfoLevel2   equ     [BP + 10]
Reserved02       equ     [BP +  6]          ;@@ Reserved dword = 0


DOSFINDFIRST2    proc    far
        call    __api_begin     ; init bp and save bp,ds,bx,cx,dx,si,di,es
                                ; required to save: bp,ds,es,bx,cx,dx,di,si
        mov     FirstCopy,1             ; let CopyData now it is first time
        mov     si,[FileInfoLevel2]     ; get the file info level

; check validity of version
        call    _api_getvrsn
        mov     bx,1                    ; assume only level 1 valid
        cmp     ax,0A14h
        jb      ff2L1Only
        mov     bx,3                    ; ver >= 10.2 so level 1-3 valid
        mov     UseNew,1                ; We can use 10.2 style int's

ff2L1Only:
; check validity of info level
        mov     ax,Error_Invalid_Level
        cmp     si,bx        ; is level valid?
        mov     cx,si
        mov     word ptr _TEXT:[FindInfoLevel], cx ; save the infolevel for FindNext
        jbe     ff2ChkRes
        jmp     ff2Exit

ff2ChkRes:
; check validity of reserved words
        mov     ax,ERROR_INVALID_PARAMETER      ;@@
        mov     bx, Reserved02                  ;@@ reserved words not zeros
        or      bx,Reserved02+2               ;@@
        jz      ff201                           ;@@
        jmp     ff216                           ;@@ go return with error

ff201:                                          ;@@
        lds     si, [SearchCount2]               ; is > 0 files requested?
        mov     cx, [si]
        test    cx, cx
        mov     ax, error_invalid_parameter     ; load error code
        jnz     ff20
        jmp     ff216                            ; go return with error
ff20:
        test    word ptr [attribute2], NOT VALID_ATTR_BITS
        jz      ff21
        mov     ax, error_invalid_parameter     ; not the correct error code
        jmp     ff216
ff21:
; verify the filename in 8.3 range
        mov     ah,2                    ;@@ meta char is valid
        lds     si, [FilePathName2]       ;@@ set up pointer to filename
        call    name_check               ;@@ check name in 8.3 range
        jnc     name_ok                  ;@@ filename is illegal
        jmp     ff216                    ;@@
name_ok:                                 ;@@
        lds     si, [DirHandle2]                 ; Valid dirhandles are:
        cmp     word ptr [si], VALID_DIRHANDLE  ;    VALID_DIRHANDLE and
        je      ff25                            ;    ALLOC_DIRHANDLE

        ; if VALID_DIRHANDLE is in use, a DOSFINDFIRST with ALLOC_DIRHANDLE
        ; will fail since only one search context is available.

        cmp     _TEXT:[FindFlag], FIND_OK       ; if VALID_DIRHANDLE in use,
        je      ff22                            ; then fail
        cmp     word ptr [si], ALLOC_DIRHANDLE  ; if not ALLOC_DIRHANDLE
        jne     ff22                            ; then fail

        mov     word ptr [si], VALID_DIRHANDLE  ; return(VALID_DIRHANDLE)
        jmp     short ff25
ff22:
        mov     ax, error_invalid_handle
        jmp     ff216
ff25:
        mov     ovf_buf,0                       ; P3397
        mov     ah, D2_GetDTA                   ; Get current disk transfer
        int     21h                             ; address and save it.
        mov     word ptr _TEXT:[oldDTA], bx
        mov     word ptr _TEXT:[oldDTA + 2], es

        mov     ah, D2_SetDTA                   ; Set a new disk transfer
        mov     dx, SEG _TEXT                   ; address for the find first
        mov     ds, dx                          ; call.
        mov     dx, offset _TEXT:[DTAarea]
        int     21h

        mov     bx, cx                           ; get SearchCount
        les     di, [ResultBuf2]                 ; address of return buffer
        mov     BuffOffs,di                      ; save start of buffer
                                                 ; for infolevel 3
        lds     dx, [FilePathName2]              ; set up pointer to filename

        call    get_path                         ;@@ save the path for the
                                                 ; future qpathinfo calls.
        LJC     ff216                            ; 11/21/88 KL
        mov     cx, [Attribute2]                 ; get attribute
; WFM - load findflag with 'closed' in case we hit an error (I suppose)
        mov     byte ptr _TEXT:[FindFlag], FIND_CLOSED
        cld                                     ; clear direction flag
        mov     _TEXT:[SecondFind], 0           ; clear found flag

ff209:
        mov     ax, word ptr [ResultBufLen2]
        mov     BuffSize, ax
ff210:
        cmp     UseNew,1                ;
        je      ff211                   ; for new style let int 21h check
        cmp     word ptr [ResultBufLen2],FINDSTRUCSIZE  ; if enough space
        jae     ff211                                   ; then continue
        xor     ax, ax
        test    _TEXT:[SecondFind], 1                   ; was anything found?
        jz      ff210a                                  ; yes, return ok
        jmp     ff214
ff210a:
        mov     ax, error_buffer_overflow               ; else return error
        jmp     ff214
ff211:

        ; If the search count is greater than one, the call to Dos 2.x
        ; find first is successful and the call to Dos 2.x find next fails
        ; with error_no_more_files, DOSFINDFIRST returns without an error.

        cmp     byte ptr _TEXT:[FindFlag], FIND_OK
        je      ff212
        mov     ah, D2_FindFirst                ; first time in loop
        mov     byte ptr _TEXT:[FindFlag], FIND_OK
        int     21h                             ; Dos 2.x Find First call
        jnc     ff213
ff2115:                                  ;@@
        cmp     cs:crit_err_flag,0ffh   ;@@ did a critical error occur
        jne     ff2115a                 ;@@
        push    bx
        push    cx
        call    api_get_extended        ;@@ added support for DOSErrorClass
        pop     cx
        pop     bx
ff2115a:                                 ;@@

        jmp     short ff214
ff212:
        ; If find next fails with error_no_more_files, we must return with
        ; no error.

        mov     ah, D2_FindNext
        int     21h                             ; Dos 2.x Find Next call
        jnc     ff213
ff2125:                                 ;@@
        cmp     cs:crit_err_flag,0ffh   ;@@ did a critical error occur
        jne     ff2125a                  ;@@
        push    bx
        push    cx
        call    api_get_extended        ;@@ added support for DOSErrorClass
        pop     cx
        pop     bx
        jmp     short   ff214            ;@@
ff2125a:                                 ;@@

        cmp     ax, error_no_more_files         ; if this error occured,
        jne     ff214
        xor     ax, ax                          ; return with no error
        jmp     short ff214
ff213:
        call    CopyData                        ; move data into ResultBuf
        jnc     ff213a                          ; P3393
        test    _TEXT:[SecondFind],1            ; If carry returned in first
        jz      ff215                           ; Find, ax has right error
        cmp     ax,error_buffer_overflow        ; If buffer is big enough for
        jne     ff215                           ; one file then NO error return
        xor     ax,ax
        clc

;       PTM 3397
;       Here buffer is big enough for the file name but not enough for the EA.
;       Set flag (ovf_buf) and copy DTA (DTAarea) to temp area (ovf_dta).
;       In the next DosFindNext the flag can be checked and, if so,
;       then restore the DTA back and emulate the DosFind.
;
        mov     ovf_buf,1                       ; P3397
        savereg <ds, es, di, cx>                ; P3397
        mov     si,SEG _TEXT                    ; P3397
        mov     ds,si                           ; P3397
        mov     es,si                           ; P3397
        lea     si,_TEXT:[DTAarea]              ; P3397
        lea     di,_TEXT:[ovf_dta]              ; P3397
        mov     cx,44                           ; P3397
        rep     movsb                           ; P3397
        restorereg <cx, di, es, ds>
        jmp     ff214
ff213a:
        mov     _TEXT:[SecondFind],1         ; at least 1 file found and copied
        dec     bx                              ; decrement SearchCount
        ljnz    ff210                           ; continue until zero
        xor     ax, ax                          ; no error occured
ff214:
        lds     si, [SearchCount2]
        sub     [si], bx                        ; number of files found
ff215:
        xchg    ax, cx                          ; save error code
        mov     ah, D2_SetDTA                   ; restore old disk transfer area
        lds     dx, dword ptr _TEXT:[oldDTA]
        int     21h
        xchg    cx, ax                          ; restore error code
ff216:
        test    ax, ax                          ; did an error occur?
        jz      ff217

; If buffer overflow occurred, only return error if no information was
; returned
        cmp     ax,ERROR_INVALID_PATH           ; cpd12 p1635
        jne     bufferover                      ; cpd12 p1635
        lds     si, [SearchCount2]              ; cpd12 p1635
        mov     cx, word ptr[si]                ; cpd12 p1635
        cmp     cx, bx                          ; cpd12 p1635
        je      flagdta                         ; cpd12 p1635
        mov     ax, error_buffer_overflow       ; cpd12 p1635

bufferover:                                     ; cpd12 p1635
        cmp     ax, error_buffer_overflow       ; cpd12 p1635
        jne     flagdta                         ; cpd12 p1635
        lds     si, [SearchCount2]              ; cpd12 p1635
        mov     cx, word ptr[si]                ; cpd12 p1635
        cmp     cx, bx                              ; cpd12 p1635
        je      flagdta                         ; cpd12 p1635
        sub     cx, bx                          ; cpd12 p1635
        mov     word ptr[si], cx                ; cpd12 p1635
        xor     ax, ax                          ; cpd12 p1635
        jmp     ff217                           ; cpd12 p3066 12/7/88 KLee

        ; flag DTA data as invalid for future DosFindNext call

flagdta:
        cmp     ax,ERROR_EAS_DIDNT_FIT          ; DTA and search count is still
        je      ff2Exit                         ; valid for EA_DIDNT_FIT error
        lds     si, [SearchCount2]              ;@@@ zero out search count.
        mov     word ptr [si],0

flagdtabad:
        mov     byte ptr _TEXT:[FindFlag], FIND_FAILED
ff217:
ff2Exit:
        mov     FirstCopy,0     ; reset copydata flag
        call    __api_end       ; check sigs & restore es,di,si,dx,cx,bx,ds,bp
        ret     26              ; clear stack of entry parameters (bytes)
DOSFINDFIRST2    endp

;/********************** START OF SPECIFICATIONS *********************/
;/*                                                                  */
;/* SUBROUTINE NAME: DosFindNext                                     */
;/*                                                                  */
;/* DESCRIPTIVE NAME: Dos Find Next                                  */
;/*                                                                  */
;/* FUNCTION: Uses the directory handle received by DosFindFirst     */
;/*           to continue finding files.                             */
;/*                                                                  */
;/*                                                                  */
;/* NOTES:    Real Mode Only                                         */
;/*           Simulates OS/2 call from DOS 2.x,3.x environment       */
;/*                                                                  */
;/* ENTRY POINT: DosFindNext                                         */
;/*                                                                  */
;/*    LINKAGE: Call Far                                             */
;/*                                                                  */
;/* INPUT: Stack Frame in form of:                                   */
;/*                                                                  */
;/*     PUSH  WORD   DirHandle - Directory search handle             */
;/*     PUSH@ OTHER  ResultBuf - Result buffer                       */
;/*     PUSH  WORD   ResultBufLen - Result buffer length             */
;/*     PUSH@ WORD   SearchCount - number of entries to find         */
;/*                                                                  */
;/*                                                                  */
;/* EXIT-NORMAL:   AX = 0                                                  */
;/*                                                                     */
;/* EXIT-ERROR:    AX = Errorcode                                               */
;/*       may return error code from Dos 2.x, 3.x, OS/2                         */
;/*                                                                     */
;/* EFFECTS:  AX, all other registers preserved                      */
;/*                                                                     */
;/* INTERNAL REFERENCES: none                                        */
;/*                                                                  */
;/*    ROUTINES: CopyData                                            */
;/*                                                                  */
;/* EXTERNAL REFERENCES: crit_err_flag                               */
;/*                                                                  */
;/*    ROUTINES: __api_begin                                         */
;/*              __api_end                                               */
;/*              name_check                                               */
;/*              api_get_extended                                    */
;/*              _api_get_version                                    */
;/*              Int 21h - GetDTA                                    */
;/*              Int 21h - SetDTA                                    */
;/*              Int 21h - FindNext                                  */
;/*              Int 21h - Get/Set File Date/Time Extended Info      */
;/*                                                                  */
;/*                                                                  */
;/*********************** END OF SPECIFICATIONS **********************/

;***    DOSFINDNEXT
;
;       simulates DOS 5.0 call from DOS 2.x,3.x environment
;
;       errorcode = unsigned far pascal
;       DosFindNext(DirHandle, ResultBuf, ResultBufLen, SearchCount, 0);
;
;       ENTRY:
;               DirHandle - Directory search handle
;               ResultBuf - Result buffer
;               ResultBufLen - Result buffer length
;               SearchCount - number of entries to find
;
;       RETURN:
;               AX = 0 if no error, else error code (see DOS 5 spec)
;
;       Pseudo Code:
;               save registers
;               use BP as pointer to stack parameters
;               check parameters
;               save & setup DTA
;               for SearchCount
;                   Find file
;                   copy file data into ResultBuf
;               restore DTA
;               restore registers
;               return
;
;       WARNING:
;               may return error code from Dos 2.x, 3.x (see dos manuals)
;               Only supports one find/first/next call sequence at a time.
;
;       EFFECTS:
;               The search context information stored at DTAarea is modified
;               on every subsequent call to DOSFINDNEXT.
;
;
;       EXTRN   DOSFINDNEXT:FAR
;
;       PUSH    @ WORD DirHandle
;       PUSH    @ OTHER ResultBuf
;       PUSH    WORD ResultBufLen
;       PUSH    @ WORD SearchCount
;       CALL    DOSFINDNEXT
;

        public  DOSFINDNEXT

FN_DirHandle    equ     [bp + 16]
FN_ResultBuf    equ     [bp + 12]
FN_ResultBufLen equ     [bp + 10]
FN_SearchCount  equ     [bp + 6]


DOSFINDNEXT     proc    far

        call    __api_begin   ; init bp and save bp,ds,bx,cx,dx,si,di,es
                                ; required to save: bp,ds,es,bx,cx,dx,di,si
        mov     FirstCopy,1             ; flag for copydata

        mov     si,word ptr _TEXT:[FindInfoLevel]     ; get the file info level

; check validity of version
        call    _api_getvrsn
        mov     bx,1                    ; assume only level 1 valid
        cmp     ax,0A14h
        jb      fnL1Only
        mov     bx,3                    ; ver >= 10.2 so level 1-3 valid
        mov     UseNew,1                ; We can use 10.2 style int's

fnL1Only:
; check validity of info level
        mov     ax,Error_Invalid_Level
        cmp     si,bx        ; is level valid?
        mov       cx,si
        jbe     fnChkCnt
        jmp     fn18

fnChkCnt:

        mov     ax, error_invalid_parameter     ; load error code
        lds     si, [FN_SearchCount]            ; is > 0 files requested?
        mov     cx, [si]
        test    cx, cx
        jnz     fn1
        jmp     fn18

fn1:
        ; Is the passed DirHandle valid?

        mov     ax, error_invalid_handle
        cmp     word ptr [FN_DirHandle], VALID_DIRHANDLE
        je      fn2
        jmp     fn16                            ;@@ clear search count
fn2:
        test    byte ptr _TEXT:[FindFlag], FIND_OK ; is the data at DTA valid?
        jnz     fn2a
        jmp     fn16                            ;@@ clear search count
fn2a:
        mov     ah, D2_GetDTA                   ; Get current disk transfer
        int     21h                             ; address and save it.
        mov     word ptr _TEXT:[oldDTA], bx
        mov     word ptr _TEXT:[oldDTA + 2], es

        mov     ah, D2_SetDTA                   ; Set a new disk transfer
        mov      dx, SEG _TEXT                   ; address for find next call
        mov     ds, dx
        mov     dx, offset _TEXT:[DTAarea]
        int      21h

        mov     bx, cx                          ; SearchCount

        les     di, [FN_ResultBuf]              ; address of return buffer
        mov     BuffOffs,di                     ; save start of buffer
                                                ; for infolevel 3
        cld                                     ; clear direction flag
        mov     _TEXT:[SecondFind], 0           ; clear file found indicator

fn9:
        mov     ax, word ptr [FN_ResultBufLen]
        mov       BuffSize, ax
fn10:
        cmp     UseNew,1
        je      fn11                    ; for new call we let the int 21h check
        cmp     BuffSize, FINDSTRUCSIZE  ; enough space?
        jae     fn11
        xor     ax, ax
        test    _TEXT:[SecondFind], 1                      ; if anything found &
        ljnz    fn14                                       ; loaded, return ok
        mov     ax, error_buffer_overflow                  ; load error & exit
        jmp     fn14
fn11:

        ; If the search count is greater than one, the first call to Dos 2.x
        ; find next is successful and the second call to Dos 2.x find next fails
        ; with error_no_more_files, DOSFINDNEXT returns without an error.

        ; PTM 3397
        ; Check whether the ovf_buf flag is set. If so then copy DTAarea from
        ; ovf_dta and emulate the first DosFindNext.

        cmp     ovf_buf,1
        jne     fn11a
        mov     ovf_buf,0                     ; P3397
        savereg <ds, es, cx, di>              ; P3397
        mov     si,SEG _TEXT                  ; P3397
        mov     ds,si                         ; P3397
        mov     es,si                         ; P3397
        lea     si,_TEXT:[ovf_dta]            ; P3397
        lea     di,_TEXT:[DTAarea]            ; P3397
        mov     cx,44                         ; P3397
        rep     movsb                         ; P3397
        restorereg <di, cx, es, ds>           ; P3397
        jmp     fn12                          ; P3397

fn11a:  mov     ah, D2_FindNext
        int     21h                             ; call Dos 2.x FindNext
        jnc     fn12                            ; jmp if no error occured
fn115:                                  ;@@
        cmp     cs:crit_err_flag,0ffh   ;@@ did a critical error occur
        jne     fn115a                  ;@@
        push    bx
        push    cx
        call    api_get_extended        ;@@ added support for DOSErrorClass
        pop     cx
        pop     bx
        jmp     short   fn14
fn115a:                                 ;@@

        test    _TEXT:[SecondFind], 1           ; first find next call?
        jz      fn14                            ; yes, go exit with error
        cmp     ax, error_no_more_files         ; was error no_more_files?
        jne     fn14                            ; no, go exit with error
        xor     ax, ax                          ; yes, clear error code
        jmp     short fn14
fn12:
        call    CopyData                        ; move file data into ResultBuf
        jnc     fn12a                           ; P3393 1/5/89
        test    _TEXT:[SecondFind],1            ; P3393 If this happen first,
        jz      fn15                            ; P3393 ax has correct error
        cmp     ax,error_buffer_overflow        ; P3393
        jne     fn15                            ; P3393
        xor     ax,ax                           ; P3393  clear return code
        clc                                     ; P3393  clear carry

;       PTM 3397
;       Here buffer is big enough for the file name but not enough for the EA.
;       Set flag and copy DTA to temp area. In DosFindNext the flag can be
;       checked and, if so, then restore the DTA and emulate the DosFindNext.

        mov     ovf_buf,1                       ; P3397
        mov     si,SEG _TEXT                    ; P3397
        mov     ds,si                           ; P3397
        mov     es,si                           ; P3397
        lea     si,_TEXT:[DTAarea]              ; P3397
        lea     di,_TEXT:[ovf_dta]              ; P3397
        mov     cx,44                           ; P3397
        rep     movsb                           ; P3397
        jmp     fn14
fn12a:
        mov     _TEXT:[SecondFind],1         ; at least 1 file found and copied
        dec     bx                              ; decrement SearchCount
        ljnz    fn10                            ; continue until zero
        xor     ax, ax                          ; no error occured
fn14:
        lds     si, [FN_SearchCount]
        sub     [si], bx                        ; number of files found
fn15:
        xchg    ax, bx                          ; save error code
        mov     ah, D2_SetDTA                   ; restore old disk transfer area
        lds     dx, dword ptr _TEXT:[oldDTA]
        int     21h
        xchg    bx, ax                          ; restore error code
fn16:
        test    ax, ax                          ; did an error occur?
        jz      fn18                            ; no, go exit

        ; Invalidate FindNext data at DTA except ERROR_EAS_DIDNT_FIT

        cmp     ax,ERROR_EAS_DIDNT_FIT
        je      fn18

        mov     byte ptr _TEXT:[FindFlag], FIND_FAILED
        lds     si, [FN_searchCount]               ;@@@ zero out search count.
        mov     word ptr [si],0
fn18:
        mov     FirstCopy,0     ;reset flag for copydata
        call    __api_end       ; check sigs & restore es,di,si,dx,cx,bx,ds,bp

        ret     12      ; clear stack of entry parameters (bytes)
DOSFINDNEXT     endp


;***    DOSFINDCLOSE
;
;       simulates DOS 5.0 call from DOS 2.x,3.x environment
;
;       errorcode = unsigned far pascal
;       DosFindClose(DirHandle)
;
;       ENTRY:
;                DirHandle - Directory search handle
;
;       RETURN:
;               AX = 0 if no error, else error code (see DOS 5 spec)
;
;       Pseudo Code:
;               save registers
;               use BP as pointer to stack parameters
;               Check for valid DirHandle &
;               return error if invalid
;               restore registers
;               return
;
;       WARNING:
;               may return error code from Dos 2.x, 3.x (see dos manuals)
;
;       EFFECTS:
;               Invalidates the search context at the DTA area so future
;               DOSFINDNEXT calls will fail.
;
;
;       EXTRN   DOSFINDCLOSE:FAR
;
;       PUSH    WORD DirHandle
;       CALL    DOSFINDCLOSE
;

        public  DOSFINDCLOSE

FC_DirHandle    equ     [bp + 6]

DOSFINDCLOSE    proc    far

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

        mov     ax, error_invalid_handle
        cmp     word ptr [FC_DirHandle], VALID_DIRHANDLE
        jne     fc1

        ; is there an active dirhandle?

        test    byte ptr _TEXT:[FindFlag], FIND_OK + FIND_FAILED
        jz      fc1                             ; no, exit with error

        ; flag data at DTA as invalid

        mov     byte ptr _TEXT:[FindFlag], FIND_CLOSED
        xor     ax, ax                          ; no error
fc1:

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

        ret     2       ; clear stack of entry parameters (bytes)
DOSFINDCLOSE    endp


; This routine copies the data on the file found into ResultBuf.
; es:di is updated to point at the end of the data so future copies
; will continue sequentially.

CopyData:
        push    bx
        push    cx
        push    dx
        push    si

        cmp     UseNew,1                ; can we use 10.2 int's
        je      ff2style                ; yes

ffstyle:                                ; use old method
        call    cdTop1_2             ; copy most of the buffer in.
        lea     di, es:[di].FileName
        call    cdName
cd5:
        jmp     cdNoError

ff2style:

; We must make special arrangements for infolevel 3
;   On the first time thru we have to point the fpFEAList to the 13th
;   byte in the buffer (past the EAOP) and leave di pointing to the
;   EAOP. On subsequent times we must adjust fpFEAList to point past
;   all previous data. To do this we will do the following;
;
;       if (Level 3)
;               if (FirstCopy) {
;                       fpFEAListSeg  = es
;                       fpFEAListOffs = BuffOffs+size EAOP
;               }
;       di = BuffOffs
;       get the FEAList
;       di = fpFEAListOffs + [fpFEAList]
;       fpFEAListOffs = di
;       get the name
;       fpFEAListOffs = fpFEAListOffs + Size of name
;
;
        mov     dx,word ptr _TEXT:[FindInfoLevel]

        cmp     dx,3                    ; 12 bytes into the buffer to
        ljb     noShift                 ; leave the EAOP intact
        cmp        FirstCopy,1               ; is this the first level 3
        jne     notFirst0               ; on first time leave room for EAOP

;; Next two instructions execute on first pass only
        mov     di,BuffOffs             ; address start of buffer
        add     di,size EAOP            ; address past the EAOP

; The next instructions execute each pass

notFirst0:

        mov     ax,(D2_GetSetFileDT shl 8) + 02 ; get info
        mov     bx,-1                   ; use a path
        call    set_path                ; concats filename to find_path
                                        ; ds:si = ptr to combined filespec

        mov     cx,BuffSize             ; size of remaining buffer
        cmp     cx,L2BUFFSIZE           ; cpd12 p1635, SM84862
        jnb     getlevel1               ; cpd12 p3114
        jmp     cdbuferr1               ; cpd12 p1635
getlevel1:                              ; cpd12 p1635
        cmp     FirstCopy,1             ; cpd12 p3253
        jne     glvl11                  ; cpd12 p3253
        sub     cx,size EAOP            ; Adjust buffer size taken by EAOP
glvl11:                                 ; cpd12 p3253
        mov     dx,2                    ; get info level 2 data SM84862
        int     21h
        mov     eflag,0                 ; set flag to 0  b700121
        jnc     glvl12
; ptr pb700121
; When the file name is '..' (retrieved from the FindNext) for a root
; directory of Pinball file system, the carry is set and error code of 1
; is returned. This error code 1 is changed into 3 by api_get_extended.
; So, if the error is returned then reset carry flag and ax reg to 0.
        cmp     ax,1                              ; PB700121
        ljne    cdError                           ; PB700121
        call    chkpball                          ; PB700121
        cmp     ax,0
        ljne    cdError

glvl12: mov     dx,3                    ; restore real info level

        mov     di,BuffOffs             ; address start of buffer

        cmp     FirstCopy,1             ; On the first time thru CopyData
        jne     notFirst                ;  for InfoLevel 3 we must move

; The next instruction execute on the first pass only

        mov     es:[di].fpFEAListSeg,es    ; load the FEAList segment
        mov     es:[di].fpFEAListOffs,di        ; load the FEAList offset
        ; point past the EAOP
        add     es:[di].fpFEAListOffs,size EAOP

        ; decrease available buffer for the EAOP
        sub     BuffSize,size EAOP
        mov     FirstCopy,0

; The next instructions execute each pass

notFirst:

        ; decrease available buffer for the level 1 data
        sub     BuffSize,L1BUFFSIZE - 1
        add     es:[di].fpFEAListOffs,L1BUFFSIZE - 1
        mov     si,es:[di].fpFEAListOffs ; si should point to cblist
        mov     cx,BuffSize
        mov     word ptr es:[si],cx  ;@@ cblist must start initialized

noShift:
        mov     ax,(D2_GetSetFileDT shl 8) + 02 ; get info
        mov     bx,-1                   ; use a path
        call    set_path

        mov     cx,BuffSize             ; size of remaining buffer

;       mov     llvl,0
        cmp     dx,1                    ; cpd12 p1635
;       mov     llvl,1
        ja      buffer2                 ; cpd12 p1635
        cmp     cx,L1BUFFSIZE           ; cpd12 p1635
        ljb     cdbuferr1               ; cpd12 p3114
        jmp     gogetinfo               ; cpd12 p1635

buffer2:
        cmp     dx,2                    ; cpd12 p1635
;       mov     llvl,1
        ja      gogetinfo               ; cpd12 p1635
        cmp     cx,L2BUFFSIZE           ; cpd12 p1635
        ljb      cdbuferr1               ; cpd12 p3114

gogetinfo:                              ; cpd12 p1635
        int     21h
        mov     eflag,0                 ; b700121
        jnc     cdL13
;;
;;    DCR 383 has new error ERROR_EAS_DIDNT_FIT
;;    If ax has error_buffer_overflow then put the new error code because
;;    it is for the EA's, not for the level 1 data
;;    SM84862 for the next 9 lines of code
        push    ax                      ; save ax and get extended error
        call    api_get_extended
        cmp     ax,ERROR_BUFFER_OVERFLOW
        pop     ax                      ; restore ax
        jne     check_dots
        cmp     word ptr _TEXT:[FindInfoLevel],3  ; check info level is 3
        jne     check_dots
        sub     BuffSize,1              ; subtract 1 for the cbName
        jmp     cdbuferr3               ; Just copy the cbName and file name
;       ljc     cdError                 ; error if carry
; ptr pb700121
; When the file name is '..' (retrieved from the FindNext) for a root
; directory of Pinball file system, the carry is set and error code of 1
; is returned. This error code 1 is changed into 3 by api_get_extended.
; So, if the error is returned then reset carry flag and ax reg to 0.
check_dots:
        cmp     ax,1                              ; PB700121
        ljne    cdError                           ; PB700121
        call    chkpball                          ; PB700121
        cmp     ax,0
        ljne    cdError

; Get the NULL byte of the ASCIIZ file name
;       push    si                                ; PB700121
;       push    ds
;       lds     si,_TEXT:[DTAarea]                ; Check the file name in DTA
;       add     si,31                             ; skip 30 bytes in DTA
;       cmp     byte ptr [si],'.'                 ; PB700121
;       jne     cdL12                             ; PB700121
;       inc     si                                ; PB700121
;       cmp     byte ptr [si],'.'                 ; PB700121
;       jne     cdL12                             ; PB700121
; Here the file name is '..' and returned error is 1.
; Reset ax and carry to 0
;       mov     ax,0                              ; PB700121
;       clc                                       ; PB700121
;       mov     eflag,1                           ; b700121
;       cmp     llvl,1
;       jne     cdL111
;       cmp     dx,3
;       jge     cdL111
; For info level 1 and 2, copy the file size and attribute from the DTA to
; result buffer.  PB700121
;       mov     si,BuffOffs
;       mov     word ptr es:[si+20],16            ; copy attribute of '..'
;       mov     word ptr es:[si+12],5             ; copy cbFile of '..'
;       mov     word ptr es:[si+16],5             ; copy cbAlloc of '..'
;cdL111: pop     ds
;       pop     si                                ; PB700121
;       jmp     cdL13                             ; PB700121
;cdL12:  pop     ds
;        pop     si                                ; PB700121
;        jmp     cdError                           ; PB700121

; take care of the different infolevel buffer sizes
cdL13:
        cmp     dx,1                    ; level 1?
        ja      cdL2                    ; no check 2

        add     di,L1BUFFSIZE           ; point to name area
        sub     BuffSize,L1BUFFSIZE     ; decrease available buffer
        jmp     short cdGetName

cdL2:
        cmp     dx,2                    ; level 2?
        ja      cdL3                    ; no, check 3

        add     di,L2BUFFSIZE           ; point to name area
        sub     BuffSize,L2BUFFSIZE     ; decrease available buffer
        jmp     short cdGetName
cdL3:
        mov     si,es:[di].fpFEAListOffs ; get the cbList
;        cmp     eflag,1                  ; If there was an error then cbList
;        jne     cdL31                    ; should be 4, just for the size of
;        mov     word ptr [si],4          ; double word size of cbList PB700121

cdL31:  mov     dx,es:[si]
        sub     BuffSize,dx             ; and decrease the available buffer
        sub     BuffSize,1              ; and decrease 1 for cbName field
        add     dx,es:[di].fpFEAListOffs  ; and increase the FEAList offset
        mov     di,dx                   ; and point to name area
        inc     di
cdGetName:
        call    cdName                  ; get the file name into buffer
        jnc     cdNoError               ; cpd12 p1635
cdbuferr:                               ; cpd12 p1635
        cmp     word ptr _TEXT:[FindInfoLevel],3
        je      cdbuferr2
cdbuferr1:
        mov     ax, error_buffer_overflow ; cpd12 p1635
        jmp     erroronbuffer
cdbuferr2:
        mov     di,BuffOffs
        sub     dx,es:[di].fpFEAListOffs ; Let dx have the cbList
        add     BuffSize,dx             ; restore the buffer size
cdbuferr3:
        sub     BuffSize,4              ; subtract for the cbList
        mov     di,es:[di].fpFEAListOffs
;       mov     di,si                   ; Let di have the offset of cbList
        add     di,5                    ; add 1 for cbName, 4 for cbList
        call    cdName                  ; Copy again for the cbName and f-name
        jnc     cdbuferr31
        mov     ax,ERROR_BUFFER_OVERFLOW
        jmp     erroronbuffer
cdbuferr31:
        mov     ax,ERROR_EAS_DIDNT_FIT  ; cp12 SM84862
        jmp     erroronbuffer           ; cpd12 p1635

cdNoError:
        xor     ax,ax
        clc
        jmp     short cdExit

cdError:
        call    api_get_extended

erroronbuffer:                          ; cpd12 p1635
        stc

cdExit:
        pop     si
        pop     dx
        pop     cx
        pop     bx
        ret

;
; This subroutine will copy the createDate; createTime; alterDate;
;       alterTime; writeDate; writeTime; EOF; alloc; and attributes
;       into the users buffer pointed to by es:di. This is used
;       for FileInfoLevels 1 and 2
cdTop1_2:
        mov     ax, SEG _TEXT                           ; code segment
        mov     ds, ax
        lea     si, _TEXT:[DTAarea].find_FileAtt        ; copy data returned
        xor     ax, ax                                  ; from FindFirst and
        mov     es:[di].FileCreateDate, ax              ; and FindNext at DTA
        mov     es:[di].FileCreateTime, ax              ; into ResultBuf
        mov     es:[di].FileAccessDate, ax
        mov     es:[di].FileAccessTime, ax
        mov     es:[di].FileAllocLow, ax
        mov     es:[di].FileAllocHigh, ax
        lodsb
        mov     es:[di].FileAttribute, ax
        lodsw
        mov     es:[di].FileWriteTime, ax
        lodsw
        mov     es:[di].FileWriteDate, ax
        lodsw
        mov     es:[di].FileDataEndLow, ax
        lodsw
        mov     es:[di].FileDataEndHigh, ax
        sub     BuffSize,L1BUFFSIZE
        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Subroutine to copy the name and name length into the users buffer
;       es:di points to beginning of filename area in buffer.
;       on return AX = file name length

cdName:
        mov     cx, MAX_FILENAME_SIZE
        xor     ax, ax

        lea     si, _TEXT:[DTAarea].find_FileName       ; copy data returned
cd1:
        cmp     [si], ah                        ; end of filename?
        je      cd2                             ; found end
        inc     al                              ; char count
        inc     si
        loop    cd1                             ; continue
        dec     al                              ; so al is never filename size
cd2:
        mov     es:[di-1],al                    ; copy in the filename length
        inc     al                              ; include terminator
        mov     cx, ax                          ; get filename length
        cmp     BuffSize,ax                     ;
        jb      cdNameError                     ; cpd12 p3114
        sub     BuffSize,ax                     ; cpd12 p1635
        lea     si, _TEXT:[DTAarea].find_FileName ;
        rep     movsb                           ; copy filename
;       sub     BuffSize,ax                     ; decrease avail buffer
                                            ; p3173 Buffsiz is subtracted twice

        mov     dx,word ptr _TEXT:[FindInfoLevel] ; get the info level
        cmp     dx,3                            ; is it 3
        jb      cdNameExit                      ; if not we are done

        mov     dx,di                           ; save the current index
        mov       di,BuffOffs                        ; point to buffer start
        mov     es:[di].fpFEAListOffs,dx           ; and add the name size to
                                                ; out FEAList Pointer
        mov     di,dx                           ; restore di to end of name
cdNameExit:
        clc                                     ; cpd12 p1635
        ret
cdNameError:
        stc                                     ; cpd12 p1635
        ret                                     ; cpd12 p1635
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



; get_path :    subroutine to initialize find_path and ptr_find_name
;               variables. These are used to save the path that is passed
;               to DosFindFirst so that is can be used later in the calls
;               to int 21h 5702 (qpathinfo).
;
;   ENTRY : DS:DX = ptr to asciiz filespec.
;
;   EXIT  : AX = Error Code if Carry Set
;           find_path = non-null terminated path
;           nptr_find_name = ptr to byte after find_path

get_path:
; Save Registers Used
        push    di
        push    si
        push    cx
        push    es
        push    bx

; Find Length of String
        cld                             ; scan forward
        mov     di,dx                   ; start of string
        push    ds
        pop     es
        mov     cx,MAX_PATH+1           ; look one beyond the max too check for
                                        ; errors
        xor     ax,ax                   ; we are looking for a zero
        repnz   scasb

        jcxz    too_long                ; did we stop due to cx = 0

        mov     ax,MAX_PATH + 1         ; set up counter for reverse loop
        sub     ax,cx
        mov     cx,ax                   ; cx has the length of string
        jcxz    move_it                 ; if cx = 0 then nothing to copy

; Find the D:\PATH\ section of the filespec

        mov     di,dx                   ; ptr to start of string
        add     di,ax                   ; ptr = end of string + 1
;       call    _api_init               ; load dbcs table
        mov     si,dx
        mov     bx,0
        mov     cx,0                    ; set str len counter to 0

dbcs_chk:
        lodsb                           ; scan FORWARD, not backward due to
        inc     cx                      ; the DBCS
        call    api_testdbcs_b          ; check whether it is dbcs
                                        ; if so then automatic bump of si
        jc      chknext                 ; if so then check 2ND NEXT byte
;   check whether it is '/', '\', or ':'.
        dec     si
        dec     cx
        cmp     byte ptr [si],'/'
        je      fnd
        cmp     byte ptr [si],'\'
        je      fnd
        cmp     byte ptr [si],':'
        jne     nfnd
fnd:    mov     bx,si
nfnd:   inc     si
chknext:
        inc     cx
        cmp     si,di
        jl      dbcs_chk
        cmp     bx,0
        jne     found_end
;   no '/', '\', or ':' found in the string
        mov     cx,0
        jmp     move_it

;end_loop:
;        cmp     byte ptr es:[di],'\'    ; back slash
;        je      found_end
;        cmp     byte ptr es:[di],'/'    ; forward slash
;        je      found_end
;        cmp     byte ptr es:[di],':'    ; drive separator
;        je      found_end
;        dec     di                      ; dec ptr
;        loop    end_loop                ; keep looking till done

found_end:
        mov     cx,bx
        sub     cx,dx
        add     cx,2                     ; cx has the actual length of string+1
                                         ; to copy which does not include the
                                         ; characters after the last \, /, :
; Move the D:\PATH\ portion into find_path
move_it:
        mov     si,dx                   ; source = users filespec
        push    cs
        pop     es
        lea     di,find_path            ; dest = cs:find_path
        jcxz    move_it2                ; cpd12 p2820  11/19/88 KL
                                        ; if cx = 0 then no 'rep movsb', so
                                        ; that di should not be decremented.
        rep     movsb

; Now save the offset for later use

        dec     di                      ; cpd12 p1897
move_it2:                               ; cpd12 p2820
        mov     nptr_find_name,di
        clc                             ; no error
        jmp     get_path_exit

too_long:
        stc
        mov     ax,ERROR_BUFFER_OVERFLOW ; 11/21/88  KL

get_path_exit:
        pop     bx
        pop     es
        pop     cx
        pop     si
        pop     di

        ret

; set_path :    subroutine to initialize concat find_path find_name
;
;   ENTRY :     _TEXT:[DTAarea].find_FileName has file name
;               find_name buffer has path in it
;               nptr_find_name has offset to put name into
;
;   EXIT  : ds:si -> find_path

set_path:
; Move the file name into buffer

        push    di
        push    es

        push    cs                      ; dest = point after find_path
        pop     es
        mov     di,nptr_find_name
        push      cs                      ; source = name in DTA
        pop     ds
        lea      si,_TEXT:[DTAarea].find_FileName
        mov     cx,13                   ; copy 8.3+null
        rep     movsb
        lea     si,find_path

        pop     es
        pop     di
        ret

;    chkpball
;       For the '..' in root dorectory of Pinball drive mask out the
;       error (ax = 1) for GetSetFileDT(5702) int 21h
;
chkpball:
        push    si                                ; PB700121
        push    ds
        cmp     byte ptr _TEXT:[DTAarea+30],'.'   ; Check the file name in DTA
        jne     pb1                               ; PB700121
        cmp     byte ptr _TEXT:[DTAarea+31],'.'   ; PB700121
        jne     pb1                               ; PB700121
; Here the file name is '..' and returned error is 1.
; Reset ax and carry flag to 0
        mov     ax,0                              ; PB700121
        mov     eflag,1                           ; PB700121
        clc                                       ; PB700121
; For info level 1, copy the file size and attribute from the DTA to
; result buffer.  PB700121
        cmp     dx,3
        jge     pb1
        mov     si,BuffOffs                       ; PB700121
        mov     es:word ptr [si+20],16            ; copy attribute of '..'
        mov     es:word ptr [si+12],5             ; copy cbFile of '..'
        mov     es:word ptr [si+16],5             ; copy cbAlloc of '..'
pb1:    pop     ds
        pop     si                                ; PB700121
        ret                                       ; PB700121


_TEXT   ends

        end

