Microsoft (R) Macro Assembler Version 5.10                  5/16/24 23:40:12
CP/DOS  DosFindFirst  mapper                                Page     1-1


				page 80,132
				
				title CP/DOS  DosFindFirst  mapper
				
				
				        include find.inc
			     C	; find.inc
			     C	
			     C	
			     C	FileFindBuf     struc
 0000  0000                  C	Create_Date     dw      ?
 0002  0000                  C	Create_Time     dw      ?
 0004  0000                  C	Access_Date     dw      ?
 0006  0000                  C	Access_Time     dw      ?
 0008  0000                  C	Write_Date      dw      ?
 000A  0000                  C	Write_Time      dw      ?
 000C  00000000              C	File_Size       dd      ?
 0010  00000000              C	FAlloc_Size     dd      ?
 0014  0000                  C	Attributes      dw      ?
 0016  00                    C	String_Len      db      ?
 0017  000C[                 C	File_Name       db      12 dup (?)
	   ??                C	
			 ]   C	
			     C	
 0023                        C	FileFindBuf     ends
			     C	
			     C	;
			     C	; dta buffer structure
			     C	;
			     C	
			     C	dtastr  struc
 0000  0015[                 C	                db      21 dup (?)
	   ??                C	
			 ]   C	
			     C	
 0015  00                    C	DTAFileAttrib   db      ?
 0016  0000                  C	DTAFileTime     dw      ?
 0018  0000                  C	DTAFileDate     dw      ?
 001A  00000000              C	DTAFileSize     dd      ?
 001E  000D[                 C	DTAFileName     db      13 dup (?)
	   ??                C	
			 ]   C	
			     C	
 002B                        C	dtastr  ends
			     C	
 = 0008                      C	MaxFinds        equ     8
 = 8000                      C	OpenedHandle    equ     08000h
			     C	
			     C	
				
 0000				FindSegment     segment word public 'find'
				
				                        public  SearchCount
 0000  0000			SearchCount             dw      0
				                        public  ReturnBufferSave
 0002  00000000			ReturnBufferSave        dd      0
				                        public  CurrentDTA
 0006  0000			CurrentDTA              dw      0
				                        public  ReturnLengthToGo
 0008  0000			ReturnLengthToGo        dw      0
				
				                        public  SaveDTA
 000A				SaveDTA                 Label   dword
				                        public  SaveDTAOffset
 000A  0000			SaveDTAOffset           dw      0
				                        public  SaveDTASegment
 000C  0000			SaveDTASegment          dw      0
				                        public  SaveDTAFlag
 000E  00			SaveDTAFlag             db      0               ; 0 -> not saved
				                                                ; 1 -> is saved
				
				; We will use the offset into the segment 'FindSegment' as the handle that we
				;  return and use in subsequent FindNext and FindClose calls.  The data that is
				;  in the word is the offset into the 'FindSegment' to the DTA that we should
				;  use.
				
Microsoft (R) Macro Assembler Version 5.10                  5/16/24 23:40:12
CP/DOS  DosFindFirst  mapper                                Page     1-2


				                public  FindDTAs
 000F				FindDTAs        label   word
				                rept    MaxFinds
				                dtastr  <>
				                endm
 000F  0015[                 1	                dtastr  <> 
 0024  00                    1	
 0025  0000                  1	
 0027  0000                  1	
 0029  00000000              1	
 002D  000D[                 1	
 003A  0015[                 1	                dtastr  <> 
 004F  00                    1	
 0050  0000                  1	
 0052  0000                  1	
 0054  00000000              1	
 0058  000D[                 1	
 0065  0015[                 1	                dtastr  <> 
 007A  00                    1	
 007B  0000                  1	
 007D  0000                  1	
 007F  00000000              1	
 0083  000D[                 1	
 0090  0015[                 1	                dtastr  <> 
 00A5  00                    1	
 00A6  0000                  1	
 00A8  0000                  1	
 00AA  00000000              1	
 00AE  000D[                 1	
 00BB  0015[                 1	                dtastr  <> 
 00D0  00                    1	
 00D1  0000                  1	
 00D3  0000                  1	
 00D5  00000000              1	
 00D9  000D[                 1	
 00E6  0015[                 1	                dtastr  <> 
 00FB  00                    1	
 00FC  0000                  1	
 00FE  0000                  1	
 0100  00000000              1	
 0104  000D[                 1	
 0111  0015[                 1	                dtastr  <> 
 0126  00                    1	
 0127  0000                  1	
 0129  0000                  1	
 012B  00000000              1	
 012F  000D[                 1	
 013C  0015[                 1	                dtastr  <> 
 0151  00                    1	
 0152  0000                  1	
 0154  0000                  1	
 0156  00000000              1	
 015A  000D[                 1	
				
				                public  FindHandles
 0167				FindHandles     label   word
 = 0000				FindDTAIndex    =       0
				                rept    MaxFinds
				                dw      FindDTAs + FindDTAIndex
				FindDTAIndex    =       FindDTAIndex + size dtastr
				                endm
 0167  000F R                1	                dw      FindDTAs + FindDTAIndex 
 0169  003A R                1	                dw      FindDTAs + FindDTAIndex 
 016B  0065 R                1	                dw      FindDTAs + FindDTAIndex 
 016D  0090 R                1	                dw      FindDTAs + FindDTAIndex 
 016F  00BB R                1	                dw      FindDTAs + FindDTAIndex 
 0171  00E6 R                1	                dw      FindDTAs + FindDTAIndex 
 0173  0111 R                1	                dw      FindDTAs + FindDTAIndex 
 0175  013C R                1	                dw      FindDTAs + FindDTAIndex 
				
				
 0177				FindSegment     ends
				
 0000				dosxxx  segment byte public 'dos'
				        assume  cs:dosxxx,ds:nothing,es:nothing,ss:nothing
				
Microsoft (R) Macro Assembler Version 5.10                  5/16/24 23:40:12
CP/DOS  DosFindFirst  mapper                                Page     1-3


				; ************************************************************************* *
				; *
				; *      MODULE: DosFindFirst
				; *
				; *      FILE NAME: DOS021.ASM
				; *
				; *      FUNCTION: This module Finds the first filename that matches the
				; *                specified file specification.  The directory handle
				; *                parameter passed will be ignored since PC/DOS does not
				; *                support directory handles.  The last access, last write
				; *                and the creation date and time are all set to the same,
				; *                because PC/DOS does not have seperate last access and
				; *                last write fields in the directory.  The allocation
				; *                fields are set equal to the eod because of the same
				; *                reason.
				; *
				; *      CALLING SEQUENCE:
				; *
				; *                PUSH@ ASCIIZ  FileName      ; File path name
				; *                PUSH@ WORD    DirHandle     ; Directory search handle
				; *                PUSH  WORD    Attribute     ; Search attribute
				; *                PUSH@ OTHER   ResultBuf     ; Result buffer
				; *                PUSH  DWORD   ResultBufLen  ; Result buffer length
				; *                PUSH@ WORD    SearchCount   ; # of entries to find
				; *                PUSH  DWORD   0             ; Reserved (must be zero)
				; *                CALL  DosFindFirst
				; *
				; *      RETURN SEQUENCE:
				; *
				; *                IF ERROR (AX not = 0)
				; *
				; *                   AX = Error Code:
				; *
				; *                   o   Invalid file path name
				; *
				; *                   o   Invalid search attribute
				; *
				; *      MODULES CALLED:  DOS int 21H function 2FH
				; *                       DOS int 21H function 4EH
				; *                       DOS int 21H function 4FH
				; *
				; *************************************************************************
				;
				        public  DosFindFirst
				        .sall
				        .list
				
				
				str     struc
 0000  0000			old_bp          dw      ?
 0002  00000000			return          dd      ?
 0006  00000000			ReservedZero    dd      0       ; reserved
 000A  00000000			FindCountPtr    dd      ?       ; number of entries to find
 000E  0000			FindBufferLen   dw      ?       ; result buffer lenght
 0010  00000000			FindBufferPtr   dd      ?       ; result buffer pointer
 0014  0000			FileAttribute   dw      ?       ; search attribute
 0016  00000000			DirHandlePtr    dd      ?       ; directory search handle
 001A  00000000			PathNamePtr     dd      ?       ; file path name pointer
 001E				str     ends
				
				
 0000				DosFindFirst  proc   far
				
				        Enter   DosFindFirst
				
 000C  B8 ---- R		        mov     ax,seg FindSegment      ; get address to our data
 000F  8E D8			        mov     ds,ax
				        assume  ds:FindSegment
				
				; Search for an available Find Handle
				
				; The Dir handle that we will return is the offset into the 'FindSegment' that
				;  the pointer to the DTA for that handle is at.  Two special things:
				;
				;       1) when we see file handle one, will use the first pointer and DTA
				;       2) the high order bit of the DTA pointer is used to indicate that
Microsoft (R) Macro Assembler Version 5.10                  5/16/24 23:40:12
CP/DOS  DosFindFirst  mapper                                Page     1-4


				;           the handle is allocated
				
 0011  BE 0167 R		        mov     si,offset FindSegment:FindHandles
 0014  B9 0008			        mov     cx,MaxFinds
				
				; DS:[SI] -> Find DTA Pointer Table
				; CX = number of Find DTAs
				
				; Incoming DirHandle = -1 ==> allocate a new dir handle
				
 0017  C4 7E 16			        les     di,[bp].DirHandlePtr
 001A  26: 8B 05		        mov     ax,es:[di]
 001D  3D FFFF			        cmp     ax,-1
 0020  74 13			        je      AllocateHandle
				
				; Incoming DirHandle = 1, we will use the first DTA
				
 0022  3D 0001			        cmp     ax,1
 0025  74 23			        je      HandleFound
				
				; We have not been requested to allocate a new handle, and we are not using
				; DirHandle 1.  At this time, we need to reuse the incoming handle, but only
				; if it is a valid (ie - previously allocated by us) DirHandle
				
 0027  8B F0			        mov     si,ax                     ; verify it is an active handle
 0029  F7 04 8000		        test    ds:[si],OpenedHandle
 002D  75 1B			        jnz     HandleFound               ; jump if true
				
 002F  B8 0006			        mov     ax,6                      ; else set error code
 0032  E9 015B R		        jmp     ErrorExit                 ; return
				
				; Allocate a new handle from the DTA pointer list
				
 0035				AllocateHandle:
 0035  83 C6 02			        add     si,2
 0038  49			        dec     cx
				
 0039				FindHandleLoop:
 0039  F7 04 8000		        test    ds:[si],OpenedHandle
 003D  74 0B			        jz      HandleFound
				
 003F  83 C6 02			        add     si,2
 0042  E2 F5			        loop    FindHandleLoop
				
				; No Handles available, return error
				
 0044  B8 0004			        mov     ax,4               ; report 'no handles available'
 0047  E9 015B R		        jmp     ErrorExit          ; error return - buffer not large enough
				
				
				; We have a handle, let's look for the file(s)
				
 004A				HandleFound:
 004A  8B 04			        mov     ax,ds:[si]              ; get the dta pointer
 004C  81 0C 8000		        or      ds:[si],OpenedHandle    ; allocate the handle
 0050  25 7FFF			        and     ax,not OpenedHandle
 0053  A3 0006 R		        mov     CurrentDTA,ax
				
 0056  C4 7E 16			        les     di,[bp].DirHandlePtr    ; the handle number we return is the
 0059  26: 89 35		        mov     es:[di],si              ;  offset to the entry in FindSegment
				
				; save the callers dta so we can restore it later
				
 005C  B4 2F			        mov     ah,02fh                 ; get callers DTA
 005E  CD 21			        int     21h
				
 0060  89 1E 000A R		        mov     SaveDTAOffset,bx        ; save it
 0064  8C 06 000C R		        mov     SaveDTASegment,es
 0068  C6 06 000E R 01		        mov     SaveDTAFlag,1
				
				; Set the dta to our area
				
 006D  8B 16 0006 R		        mov     dx,CurrentDTA           ; set DTA address
 0071  B4 1A			        mov     ah,1ah
 0073  CD 21			        int     21h
				
Microsoft (R) Macro Assembler Version 5.10                  5/16/24 23:40:12
CP/DOS  DosFindFirst  mapper                                Page     1-5


				; Get the count of files to search for
				
 0075  C4 7E 0A			        les     di,[bp].FindCountPtr    ; load result buffer pointer
 0078  26: 8B 05		        mov     ax,es:[di]              ; save the search
 007B  A3 0000 R		        mov     SearchCount,ax          ;                count
 007E  26: C7 05 0000		        mov     es:word ptr [di],0      ; set found count to zero
				
 0083  3D 0000			        cmp     ax,0                    ; just in case they try to trick us!
 0086  75 03			        jne     DoSearch
				
 0088  E9 0159 R		        jmp     SearchDone
				
				;  Find first file
				
 008B				DoSearch:
 008B  C5 56 1A			        lds     dx,[bp].PathNamePtr    ; load address of asciiz string
				        assume  ds:nothing
 008E  8B 4E 14			        mov     cx,[bp].FileAttribute  ; load the attribute
 0091  B8 4E00			        mov     ax,04E00h
 0094  CD 21			        int     21h                    ; find the first occurance of file
 0096  73 03			        jnc     FindFirstOK            ; continue
				
 0098  E9 015B R		        jmp     ErrorExit
				
 009B				FindFirstOK:
 009B  B8 ---- R		        mov     ax,seg FindSegment
 009E  8E D8			        mov     ds,ax
				        assume  ds:FindSegment
				
 00A0  8B 46 0E			        mov     ax,[bp].FindBufferLen  ; load the buffer length
 00A3  A3 0008 R		        mov     ReturnLengthToGo,ax    ; save low order buffer length
				
 00A6  C4 7E 10			        les     di,[bp].FindBufferPtr  ; load result buffer pointer
				
 00A9  89 3E 0002 R		        mov     word ptr ReturnBufferSave+0,di
 00AD  8C 06 0004 R		        mov     word ptr ReturnBufferSave+2,es
				
				; Move find data into the return areas
				
 00B1				MoveFindData:
 00B1  83 2E 0008 R 23		        sub     ReturnLengthToGo,size FileFindBuf ; check if result buffer is larg enough
 00B6  73 06			        jnc     BufferLengthOk         ; it is ok
				
 00B8  B8 0008			        mov     ax,8                   ; report 'Insufficient memory'
 00BB  E9 015B R		        jmp     ErrorExit              ; error return - buffer not large enough
				
 00BE				BufferLengthOk:
 00BE  8B 36 0006 R		        mov     si,CurrentDTA          ; DS:SI -> our dta area
 00C2  C4 3E 0002 R		        les     di,ReturnBufferSave
				
				; At this point, the following MUST be true:
				;       es:di -> where we are to put the resultant data
				;       ds:si -> DTA from find (either first or next)
				
 00C6  8B 44 18			        mov     ax,ds:[si].DTAFileDate    ; save date
 00C9  26: 89 05		        mov     es:[di].Create_Date,ax
 00CC  26: 89 45 04		        mov     es:[di].Access_Date,ax
 00D0  26: 89 45 08		        mov     es:[di].Write_Date,ax
				
 00D4  8B 44 16			        mov     ax,ds:[si].DTAFileTime    ; save time
 00D7  26: 89 45 02		        mov     es:[di].Create_Time,ax
 00DB  26: 89 45 06		        mov     es:[di].Access_Time,ax
 00DF  26: 89 45 0A		        mov     es:[di].Write_Time,ax
				
 00E3  8B 44 1A			        mov     ax,ds:word ptr [si].DTAFileSize+0    ; save file size
 00E6  26: 89 45 0C		        mov     es:word ptr [di].File_Size+0,ax
 00EA  26: 89 45 10		        mov     es:word ptr [di].FAlloc_Size+0,ax
 00EE  8B 44 1C			        mov     ax,ds:word ptr [si].DTAFileSize+2
 00F1  26: 89 45 0E		        mov     es:word ptr [di].File_Size+2,ax
 00F5  26: 89 45 12		        mov     es:word ptr [di].FAlloc_Size+2,ax
				
 00F9  26: F7 45 10 01FF	        test    es:word ptr [di].FAlloc_Size,001ffh
 00FF  74 0C			        jz      AllocateSizeSet
				
 0101  26: 81 65 10 FE00	        and     es:word ptr [di].FAlloc_Size,not 001ffh
 0107  26: 81 45 10 0200	        add     es:word ptr [di].FAlloc_Size,00200h
Microsoft (R) Macro Assembler Version 5.10                  5/16/24 23:40:12
CP/DOS  DosFindFirst  mapper                                Page     1-6


				
 010D				AllocateSizeSet:
 010D  33 C0			        xor     ax,ax
 010F  8A 44 15			        mov     al,ds:[si].DTAFileAttrib
 0112  26: 89 45 14		        mov     es:[di].Attributes,ax
				
 0116  B9 000C			        mov     cx,12
 0119  BB 0000			        mov     bx,0
				
 011C				MoveNameLoop:
 011C  8A 40 1E			        mov     al,ds:[si+bx].DTAFileName
 011F  3C 00			        cmp     al,0
 0121  74 07			        je      EndOfName
				
 0123  26: 88 41 17		        mov     es:[di+bx].File_Name,al
 0127  43			        inc     bx
 0128  E2 F2			        loop    MoveNameLoop
				
 012A				EndOfName:
 012A  26: C6 41 17 00		        mov     es:[di+bx].File_Name,0
 012F  8B C3			        mov     ax,bx
 0131  26: 88 45 16		        mov     es:[di].String_len,al
				
 0135  03 FB			        add     di,bx
 0137  89 3E 0002 R		        mov     word ptr ReturnBufferSave+0,di
 013B  8C 06 0004 R		        mov     word ptr ReturnBufferSave+2,es
				
 013F  C4 7E 0A			        les     di,[bp].FindCountPtr
 0142  26: FF 05		        inc     word ptr es:[di]
				
				;
				;  Check if the request was for more than one
				;
 0145  FF 0E 0000 R		        dec     SearchCount
 0149  74 0E			        jz      SearchDone
				
 014B  B8 4F00			        mov     ax,04f00h          ; set opcode
 014E  CD 21			        int     21h                ; find next matching file
 0150  72 09			        jc      ErrorExit          ; jump if error
				
 0152  C4 3E 0002 R		        les     di,ReturnBufferSave     ;
 0156  E9 00B1 R		        jmp     MoveFindData
				
 0159				SearchDone:
 0159  2B C0			        sub     ax,ax              ; set good return code
				
 015B				ErrorExit:
 015B  50			        push    ax
 015C  B8 ---- R		        mov     ax,seg FindSegment
 015F  8E D8			        mov     ds,ax
				        assume  ds:FindSegment
 0161  80 3E 000E R 00		        cmp     SaveDTAFlag,0
 0166  74 0D			        je      DoNotRestore
				
 0168  C6 06 000E R 00		        mov     SaveDTAFlag,0
				
 016D  C5 16 000A R		        lds     dx,SaveDTA
 0171  B4 1A			        mov     ah,1ah                     ; load opcode
 0173  CD 21			        int     21h                        ; setup DTA
				
 0175				DoNotRestore:
 0175  58			        pop     ax
				
				        mexit                              ; pop registers
 0182  CA 0018			        ret     size str - 6               ; return
				
 0185				DosFindFirst endp
				
 0185				dosxxx  ends
				
				        end

Microsoft (R) Macro Assembler Version 5.10                  5/16/24 23:40:12
CP/DOS  DosFindFirst  mapper                                Symbols-1


Macros:

		N a m e			Lines

ENTER  . . . . . . . . . . . . .  	   3
MEXIT  . . . . . . . . . . . . .  	   3
POPAL  . . . . . . . . . . . . .  	   9
PUSHAL . . . . . . . . . . . . .  	   9

Structures and Records:

                N a m e                 Width   # fields
                                        Shift   Width   Mask    Initial

DTASTR . . . . . . . . . . . . .  	002B	0006
  DTAFILEATTRIB  . . . . . . . .  	0015
  DTAFILETIME  . . . . . . . . .  	0016
  DTAFILEDATE  . . . . . . . . .  	0018
  DTAFILESIZE  . . . . . . . . .  	001A
  DTAFILENAME  . . . . . . . . .  	001E
FILEFINDBUF  . . . . . . . . . .  	0023	000B
  CREATE_DATE  . . . . . . . . .  	0000
  CREATE_TIME  . . . . . . . . .  	0002
  ACCESS_DATE  . . . . . . . . .  	0004
  ACCESS_TIME  . . . . . . . . .  	0006
  WRITE_DATE . . . . . . . . . .  	0008
  WRITE_TIME . . . . . . . . . .  	000A
  FILE_SIZE  . . . . . . . . . .  	000C
  FALLOC_SIZE  . . . . . . . . .  	0010
  ATTRIBUTES . . . . . . . . . .  	0014
  STRING_LEN . . . . . . . . . .  	0016
  FILE_NAME  . . . . . . . . . .  	0017
STR  . . . . . . . . . . . . . .  	001E	0009
  OLD_BP . . . . . . . . . . . .  	0000
  RETURN . . . . . . . . . . . .  	0002
  RESERVEDZERO . . . . . . . . .  	0006
  FINDCOUNTPTR . . . . . . . . .  	000A
  FINDBUFFERLEN  . . . . . . . .  	000E
  FINDBUFFERPTR  . . . . . . . .  	0010
  FILEATTRIBUTE  . . . . . . . .  	0014
  DIRHANDLEPTR . . . . . . . . .  	0016
  PATHNAMEPTR  . . . . . . . . .  	001A

Segments and Groups:

                N a m e         	Length	 Align	Combine Class

DOSXXX . . . . . . . . . . . . .  	0185	BYTE	PUBLIC	'DOS'
FINDSEGMENT  . . . . . . . . . .  	0177	WORD	PUBLIC	'FIND'

Symbols:            

                N a m e         	Type	 Value	 Attr

ALLOCATEHANDLE . . . . . . . . .  	L NEAR	0035	DOSXXX
ALLOCATESIZESET  . . . . . . . .  	L NEAR	010D	DOSXXX

BUFFERLENGTHOK . . . . . . . . .  	L NEAR	00BE	DOSXXX

CurrentDTA . . . . . . . . . . .  	L WORD	0006	FINDSEGMENT	Global

DONOTRESTORE . . . . . . . . . .  	L NEAR	0175	DOSXXX
DOSEARCH . . . . . . . . . . . .  	L NEAR	008B	DOSXXX
DosFindFirst . . . . . . . . . .  	F PROC	0000	DOSXXX	Global	Length = 0185

ENDOFNAME  . . . . . . . . . . .  	L NEAR	012A	DOSXXX
ERROREXIT  . . . . . . . . . . .  	L NEAR	015B	DOSXXX

FINDDTAINDEX . . . . . . . . . .  	NUMBER	0158	
FindDTAs . . . . . . . . . . . .  	L WORD	000F	FINDSEGMENT	Global
FINDFIRSTOK  . . . . . . . . . .  	L NEAR	009B	DOSXXX
FINDHANDLELOOP . . . . . . . . .  	L NEAR	0039	DOSXXX
FindHandles  . . . . . . . . . .  	L WORD	0167	FINDSEGMENT	Global

HANDLEFOUND  . . . . . . . . . .  	L NEAR	004A	DOSXXX

Microsoft (R) Macro Assembler Version 5.10                  5/16/24 23:40:12
CP/DOS  DosFindFirst  mapper                                Symbols-2


MAXFINDS . . . . . . . . . . . .  	NUMBER	0008	
MOVEFINDDATA . . . . . . . . . .  	L NEAR	00B1	DOSXXX
MOVENAMELOOP . . . . . . . . . .  	L NEAR	011C	DOSXXX

OPENEDHANDLE . . . . . . . . . .  	NUMBER	8000	

ReturnBufferSave . . . . . . . .  	L DWORD	0002	FINDSEGMENT	Global
ReturnLengthToGo . . . . . . . .  	L WORD	0008	FINDSEGMENT	Global

SaveDTA  . . . . . . . . . . . .  	L DWORD	000A	FINDSEGMENT	Global
SaveDTAFlag  . . . . . . . . . .  	L BYTE	000E	FINDSEGMENT	Global
SaveDTAOffset  . . . . . . . . .  	L WORD	000A	FINDSEGMENT	Global
SaveDTASegment . . . . . . . . .  	L WORD	000C	FINDSEGMENT	Global
SearchCount  . . . . . . . . . .  	L WORD	0000	FINDSEGMENT	Global
SEARCHDONE . . . . . . . . . . .  	L NEAR	0159	DOSXXX

@CPU . . . . . . . . . . . . . .  	TEXT  0101h		
@FILENAME  . . . . . . . . . . .  	TEXT  f_first		
@VERSION . . . . . . . . . . . .  	TEXT  510		


    437 Source  Lines
    485 Total   Lines
     68 Symbols

  46998 + 313380 Bytes symbol space free

      0 Warning Errors
      0 Severe  Errors
