        page    80,132
        title   V86CODE\Search.asm

.xlist
.xcref
include v86seg.inc
include mvdmexp.inc
include demsvc.inc
include struc30.inc
include dirent.inc                                                      ;56427;
include devhdr.inc                                                      ;56427;
include harderr.inc                                                     ;72761;
INCL_DOSERRORS = 1                                                      ;72761;
include bseerr.inc                                                      ;72761;
.cref
.list


;---------------------------------------------------------------------- ;56427;
; 93Jan04 - G.L.Fulk                                                    ;56427;
; A Find First on a DOS device driver was not implemented.              ;56427;
;---------------------------------------------------------------------- ;56427;
; 93Aug16 - G.L.Fulk                                                    ;72761;
; If the DTA has too high an offset value it will Trap OS/2.            ;72761;
;---------------------------------------------------------------------- ;72761;
; 93Aug26 - B.M.Russin                                                  ;53664;
; If findfirst was asked to search for X:\BLAH\yyy where yyy is         ;53664;
; the name of a DOS device in the device driver chain, findfirst        ;53664;
; would always return success.  This was changed to return              ;53664;
; success only if the directory exists.                                 ;53664;
;---------------------------------------------------------------------- ;53664;
; 95May05 - ChangeTeam                                                  ;110890;
; If the DTA has too high of an offset value it will trap OS/2.         ;110890;
; An example of this happening is when a newly found subdirectory       ;110890;
; is processed, and the application switches back to its original       ;110890;
; DTA and uses that DTA to call the $find_next process.                 ;110890;
; However, at some point the DTA switched to is not the original        ;110890;
; one and it is invalid (say &XXXX:FFFF), OS/2 will take a trap D in    ;110890;
; demFindNext.                                                          ;110890;
;                                                                       ;110890;
; Changed the .if <<word ptr cs:[DMAADD]> ae -43>  to state             ;110890;
;             .if <<word ptr cs:[DMAADD]> ae <-(size FindFirstDTA)>>    ;110890;
; to explicitly state the value of the FindFirstDTA structure.          ;110890;
; If this error occurs, the program issues an int 24.  It               ;110890;
; is the responsibility of the application programmer to trap this      ;110890;
; int 24, or OS/2 will end the application.                             ;110890;
;                                                                       ;110890;
; A check was added to $find_next, to call dta_too_small when this      ;110890;
; exception occurs.  This checking was not added to $set_dma, because   ;110890;
; DOS allows DMAs to be set at FFFF.                                    ;110890;
;                                                                       ;110890;
;---------------------------------------------------------------------- ;110890;
V86SDA  SEGMENT                                                         ;56427;
        EXTRN   DMAADD:dword                                            ;56427;
        EXTRN   EXTERR:word                                             ;72761;
        EXTRN   EXTERR_LOCUS:byte                                       ;72761;
        EXTRN   EXTERR_ACTION:byte                                      ;72761;
        EXTRN   EXTERR_CLASS:byte                                       ;72761;
V86SDA  ENDS                                                            ;56427;
                                                                        ;72761;
V86DATA SEGMENT                                                         ;72761;
        EXTRN   vheVDM: byte                                            ;72761;
V86DATA ENDS                                                            ;72761;

V86CODE SEGMENT
        ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
        EXTRN   Sys_Return:NEAR
        EXTRN   FCB_Return:NEAR
        EXTRN   DATE16:NEAR             ;Get packed current date/time   ;56427;
        EXTRN   RmDevCheckName:NEAR                                     ;56427;
        EXTRN   Split_Path:NEAR         ;Split a filespec to components ;53664;
        EXTRN   GetVisDrv:NEAR          ;Find if a drive exists         ;53664;

;
;INT 21h (AH=11h) $DIR_SEARCH_FIRST     v86code\demfile.asm        #1/3
;INT 21h (AH=11h) [SVC]demFindFirstFCB  mvdm\demfile2.asm          #2/3
;INT 21h (AH=11h) Dir_Search_First      filesys\search.asm         #3/3
;
; Inputs:
;       DS:DX Points to unopenned FCB
; Function:
;       Directory is searched for first matching entry and the directory
;       entry is loaded at the disk transfer address
; Returns:
;       AL = -1 if no entries matched, otherwise 0
;
        ASSUME  DS:NOTHING,ES:NOTHING

public $DIR_SEARCH_FIRST
$DIR_SEARCH_FIRST proc near
        SVC     SVC_DEMFINDFIRSTFCB
        jmp     FCB_Return
$DIR_SEARCH_FIRST endp

;
;INT 21h (AH=12h) $DIR_SEARCH_NEXT      v86code\demfile.asm        #1/3
;INT 21h (AH=12h) [SVC]demFindNextFCB   mvdm\demfile2.asm          #2/3
;INT 21h (AH=12h) Dir_Search_Next       filesys\search.asm         #3/3
;
; Inputs:
;       DS:DX points to unopenned FCB returned by $DIR_SEARCH_FIRST
; Function:
;       Directory is searched for the next matching entry and the directory
;       entry is loaded at the disk transfer address
; Returns:
;       AL = -1 if no entries matched, otherwise 0

public  $DIR_SEARCH_NEXT
$DIR_SEARCH_NEXT proc near
        SVC     SVC_DEMFINDNEXTFCB
        jmp     FCB_Return
$DIR_SEARCH_NEXT endp

;-----------------------------------------------------------------------
;INT 21h (AH=4Eh) $FIND_FIRST           v86code\demfile.asm        #1/3
;INT 21h (AH=4Eh) [SVC]demFindFirst     mvdm\demfile2.asm          #2/3
;INT 21h (AH=4Eh) w_3xFindFirst         filesys\search.asm         #3/3
;
;   Assembler usage:
;           MOV AH, FindFirst
;           LDS DX, name
;           MOV CX, attr
;           INT 21h
;       ; DMA address has datablock
;
;   Error Returns:
;           AX = error_path_not_found
;              = error_no_more_files
;
        ASSUME  DS:NOTHING,ES:NOTHING

FindFirstDTA    struc                                                   ;56427;
                dw      ?          ;+0 used by OS/2 FileSys,usi_handle  ;56427;
                dw      ?          ;+2 used by OS/2 FileSys,usi_position;56427;
                dd      ?          ;+4 used by OS/2 FileSys,usi_checksum;56427;
                db      ?          ;+8 used by OS/2 FileSys,usi_flag    ;56427;
                dd      ?          ;+9 used by DOS Em. FF Hack          ;56427;
DOS_LastEnt     dw      ?          ;+Dh user undocumented information   ;56427;
                db      6 dup (?)  ;+Fh not used by MVDM...yet          ;56427;
                                                                        ;56427;
find_buf_attr   db      ?               ;+15h attribute                 ;56427;
find_buf_time   dw      ?               ;+16h time                      ;56427;
find_buf_date   dw      ?               ;+18h date                      ;56427;
                dd      ?               ;+1Ah size                      ;56427;
find_buf_pname  db      8+1+3+1 dup (?) ;+1Dh name                      ;56427;
FindFirstDTA    ends                                                    ;56427;

public  $FIND_FIRST
$FIND_FIRST proc near
;        .if     <<word ptr cs:[DMAADD]> ae -43>                        ;72761;110890;
        .if      <<word ptr cs:[DMAADD]> ae <-(size FindFirstDTA)>>     ;110890;
PUBLIC DTA_too_small                                                    ;72761;
DTA_too_small:                                                          ;72761;
          ;---force hard-error to occur                                 ;72761;
          or      cs:[vheVDM].vhe_fbMisc,VHE_FLAG_ACTIVE                ;72761;
          ;---Allowable hard-error choices                              ;72761;
          mov     [vheVDM].vhe_fbAllowed,HDERR_ABORT                    ;72761;
          ;---int 24h error code (i24's DI entry value)                 ;72761;
          mov     [vheVDM].vhe_usPacketErr,ERROR_I24_BAD_LENGTH ;=5     ;72761;
          ;---int 24h AH, =10000110b                                    ;72761;
          mov    [vheVDM].vhe_fbInt24,HE_CHARDEV+HE_LOC_DATA+HE_READ_ERR;72761;
          ;---int 24h AL, drive #                                       ;72761;
          mov     [vheVDM].vhe_bDriveNum,-1                             ;72761;
          ;---response                                                  ;72761;
          mov     [vheVDM].vhe_bResp,HDERR_ABORT                        ;72761;
          ;---Packet error code                                         ;72761;
          mov     ax,ERROR_INVALID_DTA  ;=96                            ;72761;
          mov     [vheVDM].vhe_usFailErr,ax                             ;72761;
          mov     [ExtErr],ax                                           ;72761;
          mov     [ExtErr_CLASS],ERRCLASS_APPERR       ;=7              ;72761;
          mov     [ExtErr_LOCUS],ERRLOC_MEM            ;=5              ;72761;
          mov     [ExtErr_ACTION],ERRACT_ABORT         ;=4              ;72761;
          ;---assign errors to PTDA                                     ;72761;
          SVC     SVC_DEMSVCNOP                                         ;72761;
          ;---indicate failure                                          ;72761;
          stc                                                           ;72761;
          jmp     Sys_return                                            ;72761;
        .endif                                                          ;72761;
        push    cx                                                      ;56427;
        ;entry  DS:DX=asciiz name                                       ;56427;
        call    RmDevCheckName                                          ;56427;
        ;return CY=not DOS dd                                           ;56427;
        ;       NC=is DOS dd, ES:BX=DD header                           ;56427;
        ;       DS:DX unchanged                                         ;56427;
        ;       alters AX,BX,CX,SI,DI,ES                                ;56427;
        assume  es:nothing                                              ;56427;
        pop     cx                                                      ;56427;
        .if     c                                                       ;56427;
          SVC     SVC_DEMFINDFIRST
        .else                                                           ;56427;
          ;Find first for a DOS device driver.                          ;56427;
          ;                                                             ;53664;
          push  bx                                                      ;53664;
          ;see if the asciiz contains a path name                       ;53664;
          ;if it does and the path exists fill the DTA with             ;53664;
          ;dummy continuation info else return path not found           ;53664;
          ;                                                             ;53664;
          ;entry  DS:DX = asciiz name                                   ;53664;
          call Split_Path                                               ;53664;
          ;return AL = drive letter (1-26, 0=none present)              ;53664;
          ;       AH = path offset                                      ;53664;
          ;       BL = basename offset                                  ;53664;
          ;       BH = path length                                      ;53664;
          cmp     bh,1                                                  ;53664;
          .if     be                                                    ;53664;
            ;BH=0 means no sub-dir defined
            ;BH=1 means root defined
            .if     z and
            .if     <NONZERO AL>
              ;FF for "x:\NUL", we need to search for x: drive
              ;entry: AL=drive #
              call    GetVisDrv
              ;exit:  NC=drive ok, CY=invalid drive
            .else
              ;NZ=means no sub-dir specified, DOS assumes device exists
              ;AX=0, FF for "\NUL", DOS assumes device exists
              clc
            .endif
          .else                                                         ;53664;
            ;FF for "?:xxxxx\NUL", we need to verify sub-dir exists     ;53664;
            xor   bh,bh                ;make offset a word              ;53664;
            add   bx,dx                ;DS:BX points to basename        ;53664;
            dec   bx                   ;DS:BX points to slash           ;53664;
            mov   byte ptr [bx],0      ;NULL terminate at end of dir    ;53664;
            push  cx                                                    ;53664;
            mov   cx,0010h             ;see if path exists              ;53664;
            SVC   SVC_DEMFINDFIRST                                      ;53664;
            mov   byte ptr [bx],'\'    ;repair asciiz                   ;53664;
            pop   cx                                                    ;53664;
          .endif                                                        ;53664;
          pop   bx                                                      ;53664;
          .if   c                      ;CY=dir not found                ;53664;
            mov   ax,ERROR_PATH_NOT_FOUND                               ;53664;
          .else                                                         ;53664;
            ;Fill in the DTA with a dummy continuation information.     ;56427;
            ;The "LastEnt" field should be assigned -1(same as real DOS);56427;
            ;The OS2 search information should be filled with zeroes (0);56427;
            ;so that no Find Next can be accidently perfomed.           ;56427;
            ;The "FF Hack" buffer address should be assigned 0 so as to ;56427;
            ;avoid an accidental 2nd pass identification.               ;56427;
            push    es                                                  ;56427;
            LES     DI,cs:[DMAADD]        ;ES:DI=DTA                    ;56427;
            xor     ax,ax                                               ;56427;
            mov     cx,SIZE FindFirstDTA                                ;56427;
            cld                                                         ;56427;
            push    di                                                  ;56427;
            rep     stosb                 ;fill DTA with 0              ;56427;
            pop     di                                                  ;56427;
            mov     es:[di].DOS_LastEnt,-1                              ;56427;
            mov     es:[di].find_buf_attr,attr_device  ;=40h            ;56427;
                                                                        ;56427;
            ;------ Get the current date and time                       ;56427;
            call    DATE16                                              ;56427;
            ;exit:  AX=packed date                                      ;56427;
            ;       DX=packed time                                      ;56427;
            ;       DS=DOS data segment                                 ;56427;
            assume  ds:V86GROUP                                         ;56427;
            mov     es:[di].find_buf_time,dx                            ;56427;
            mov     es:[di].find_buf_date,ax                            ;56427;
                                                                        ;56427;
            add     di,find_buf_pname                                   ;56427;
            mov     si,bx                                               ;56427;
            add     si,SDevName                                         ;56427;
            pop     ds                                                  ;56427;
            mov     cx,8                                                ;56427;
            .repeat                                                     ;56427;
              lodsb                                                     ;56427;
              .leave  <AL eq " ">                                       ;56427;
              stosb                                                     ;56427;
            .loop                                                       ;56427;
          .endif                                                        ;56427;
        .endif                                                          ;53664;
        jmp     Sys_Return                                              ;56427;
$FIND_FIRST endp                                                        ;56427;
;-----------------------------------------------------------------------;56427;



;
;INT 21h (AH=4Fh) $FIND_NEXT         v86code\demfile.asm           #1/3
;INT 21h (AH=4Fh) [SVC]demFindNext   mvdm\demfile2.asm             #2/3
;INT 21h (AH=4Fh) w_3xFindNext       filesys\search.asm            #3/3
;
;   Assembler usage:
;       ; dma points at area returned by find_first
;           MOV AH, findnext
;           INT 21h
;       ; next entry is at dma
;
;   Error Returns:
;           AX = error_no_more_files

        ASSUME  DS:NOTHING,ES:NOTHING

public  $FIND_NEXT
$FIND_NEXT proc near

        .if     <<word ptr cs:[DMAADD]> ae <-(size FindFirstDTA)>>      ;110890;
         jmp    DTA_too_small                                           ;110890;
        .endif                                                          ;110890;
        SVC     SVC_DEMFINDNEXT
        jmp     Sys_Return
$FIND_NEXT endp

V86CODE ENDS

        END
