summaryrefslogtreecommitdiff
path: root/v4.0/src/MAPPER/F_FIRST.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/MAPPER/F_FIRST.ASM')
-rw-r--r--v4.0/src/MAPPER/F_FIRST.ASM354
1 files changed, 354 insertions, 0 deletions
diff --git a/v4.0/src/MAPPER/F_FIRST.ASM b/v4.0/src/MAPPER/F_FIRST.ASM
new file mode 100644
index 0000000..90f6e7f
--- /dev/null
+++ b/v4.0/src/MAPPER/F_FIRST.ASM
@@ -0,0 +1,354 @@
1page 80,132
2
3title CP/DOS DosFindFirst mapper
4
5
6 include find.inc
7
8FindSegment segment word public 'find'
9
10 public SearchCount
11SearchCount dw 0
12 public ReturnBufferSave
13ReturnBufferSave dd 0
14 public CurrentDTA
15CurrentDTA dw 0
16 public ReturnLengthToGo
17ReturnLengthToGo dw 0
18
19 public SaveDTA
20SaveDTA Label dword
21 public SaveDTAOffset
22SaveDTAOffset dw 0
23 public SaveDTASegment
24SaveDTASegment dw 0
25 public SaveDTAFlag
26SaveDTAFlag db 0 ; 0 -> not saved
27 ; 1 -> is saved
28
29; We will use the offset into the segment 'FindSegment' as the handle that we
30; return and use in subsequent FindNext and FindClose calls. The data that is
31; in the word is the offset into the 'FindSegment' to the DTA that we should
32; use.
33
34 public FindDTAs
35FindDTAs label word
36 rept MaxFinds
37 dtastr <>
38 endm
39
40 public FindHandles
41FindHandles label word
42FindDTAIndex = 0
43 rept MaxFinds
44 dw FindDTAs + FindDTAIndex
45FindDTAIndex = FindDTAIndex + size dtastr
46 endm
47
48
49FindSegment ends
50
51dosxxx segment byte public 'dos'
52 assume cs:dosxxx,ds:nothing,es:nothing,ss:nothing
53
54; ************************************************************************* *
55; *
56; * MODULE: DosFindFirst
57; *
58; * FILE NAME: DOS021.ASM
59; *
60; * FUNCTION: This module Finds the first filename that matches the
61; * specified file specification. The directory handle
62; * parameter passed will be ignored since PC/DOS does not
63; * support directory handles. The last access, last write
64; * and the creation date and time are all set to the same,
65; * because PC/DOS does not have seperate last access and
66; * last write fields in the directory. The allocation
67; * fields are set equal to the eod because of the same
68; * reason.
69; *
70; * CALLING SEQUENCE:
71; *
72; * PUSH@ ASCIIZ FileName ; File path name
73; * PUSH@ WORD DirHandle ; Directory search handle
74; * PUSH WORD Attribute ; Search attribute
75; * PUSH@ OTHER ResultBuf ; Result buffer
76; * PUSH DWORD ResultBufLen ; Result buffer length
77; * PUSH@ WORD SearchCount ; # of entries to find
78; * PUSH DWORD 0 ; Reserved (must be zero)
79; * CALL DosFindFirst
80; *
81; * RETURN SEQUENCE:
82; *
83; * IF ERROR (AX not = 0)
84; *
85; * AX = Error Code:
86; *
87; * o Invalid file path name
88; *
89; * o Invalid search attribute
90; *
91; * MODULES CALLED: DOS int 21H function 2FH
92; * DOS int 21H function 4EH
93; * DOS int 21H function 4FH
94; *
95; *************************************************************************
96;
97 public DosFindFirst
98 .sall
99 .xlist
100 include macros.inc
101 .list
102
103
104str struc
105old_bp dw ?
106return dd ?
107ReservedZero dd 0 ; reserved
108FindCountPtr dd ? ; number of entries to find
109FindBufferLen dw ? ; result buffer lenght
110FindBufferPtr dd ? ; result buffer pointer
111FileAttribute dw ? ; search attribute
112DirHandlePtr dd ? ; directory search handle
113PathNamePtr dd ? ; file path name pointer
114str ends
115
116
117DosFindFirst proc far
118
119 Enter DosFindFirst
120
121 mov ax,seg FindSegment ; get address to our data
122 mov ds,ax
123 assume ds:FindSegment
124
125; Search for an available Find Handle
126
127; The Dir handle that we will return is the offset into the 'FindSegment' that
128; the pointer to the DTA for that handle is at. Two special things:
129;
130; 1) when we see file handle one, will use the first pointer and DTA
131; 2) the high order bit of the DTA pointer is used to indicate that
132; the handle is allocated
133
134 mov si,offset FindSegment:FindHandles
135 mov cx,MaxFinds
136
137; DS:[SI] -> Find DTA Pointer Table
138; CX = number of Find DTAs
139
140; Incoming DirHandle = -1 ==> allocate a new dir handle
141
142 les di,[bp].DirHandlePtr
143 mov ax,es:[di]
144 cmp ax,-1
145 je AllocateHandle
146
147; Incoming DirHandle = 1, we will use the first DTA
148
149 cmp ax,1
150 je HandleFound
151
152; We have not been requested to allocate a new handle, and we are not using
153; DirHandle 1. At this time, we need to reuse the incoming handle, but only
154; if it is a valid (ie - previously allocated by us) DirHandle
155
156 mov si,ax ; verify it is an active handle
157 test ds:[si],OpenedHandle
158 jnz HandleFound ; jump if true
159
160 mov ax,6 ; else set error code
161 jmp ErrorExit ; return
162
163; Allocate a new handle from the DTA pointer list
164
165AllocateHandle:
166 add si,2
167 dec cx
168
169FindHandleLoop:
170 test ds:[si],OpenedHandle
171 jz HandleFound
172
173 add si,2
174 loop FindHandleLoop
175
176; No Handles available, return error
177
178 mov ax,4 ; report 'no handles available'
179 jmp ErrorExit ; error return - buffer not large enough
180
181
182; We have a handle, let's look for the file(s)
183
184HandleFound:
185 mov ax,ds:[si] ; get the dta pointer
186 or ds:[si],OpenedHandle ; allocate the handle
187 and ax,not OpenedHandle
188 mov CurrentDTA,ax
189
190 les di,[bp].DirHandlePtr ; the handle number we return is the
191 mov es:[di],si ; offset to the entry in FindSegment
192
193; save the callers dta so we can restore it later
194
195 mov ah,02fh ; get callers DTA
196 int 21h
197
198 mov SaveDTAOffset,bx ; save it
199 mov SaveDTASegment,es
200 mov SaveDTAFlag,1
201
202; Set the dta to our area
203
204 mov dx,CurrentDTA ; set DTA address
205 mov ah,1ah
206 int 21h
207
208; Get the count of files to search for
209
210 les di,[bp].FindCountPtr ; load result buffer pointer
211 mov ax,es:[di] ; save the search
212 mov SearchCount,ax ; count
213 mov es:word ptr [di],0 ; set found count to zero
214
215 cmp ax,0 ; just in case they try to trick us!
216 jne DoSearch
217
218 jmp SearchDone
219
220; Find first file
221
222DoSearch:
223 lds dx,[bp].PathNamePtr ; load address of asciiz string
224 assume ds:nothing
225 mov cx,[bp].FileAttribute ; load the attribute
226 mov ax,04E00h
227 int 21h ; find the first occurance of file
228 jnc FindFirstOK ; continue
229
230 jmp ErrorExit
231
232FindFirstOK:
233 mov ax,seg FindSegment
234 mov ds,ax
235 assume ds:FindSegment
236
237 mov ax,[bp].FindBufferLen ; load the buffer length
238 mov ReturnLengthToGo,ax ; save low order buffer length
239
240 les di,[bp].FindBufferPtr ; load result buffer pointer
241
242 mov word ptr ReturnBufferSave+0,di
243 mov word ptr ReturnBufferSave+2,es
244
245; Move find data into the return areas
246
247MoveFindData:
248 sub ReturnLengthToGo,size FileFindBuf ; check if result buffer is larg enough
249 jnc BufferLengthOk ; it is ok
250
251 mov ax,8 ; report 'Insufficient memory'
252 jmp ErrorExit ; error return - buffer not large enough
253
254BufferLengthOk:
255 mov si,CurrentDTA ; DS:SI -> our dta area
256 les di,ReturnBufferSave
257
258; At this point, the following MUST be true:
259; es:di -> where we are to put the resultant data
260; ds:si -> DTA from find (either first or next)
261
262 mov ax,ds:[si].DTAFileDate ; save date
263 mov es:[di].Create_Date,ax
264 mov es:[di].Access_Date,ax
265 mov es:[di].Write_Date,ax
266
267 mov ax,ds:[si].DTAFileTime ; save time
268 mov es:[di].Create_Time,ax
269 mov es:[di].Access_Time,ax
270 mov es:[di].Write_Time,ax
271
272 mov ax,ds:word ptr [si].DTAFileSize+0 ; save file size
273 mov es:word ptr [di].File_Size+0,ax
274 mov es:word ptr [di].FAlloc_Size+0,ax
275 mov ax,ds:word ptr [si].DTAFileSize+2
276 mov es:word ptr [di].File_Size+2,ax
277 mov es:word ptr [di].FAlloc_Size+2,ax
278
279 test es:word ptr [di].FAlloc_Size,001ffh
280 jz AllocateSizeSet
281
282 and es:word ptr [di].FAlloc_Size,not 001ffh
283 add es:word ptr [di].FAlloc_Size,00200h
284
285AllocateSizeSet:
286 xor ax,ax
287 mov al,ds:[si].DTAFileAttrib
288 mov es:[di].Attributes,ax
289
290 mov cx,12
291 mov bx,0
292
293MoveNameLoop:
294 mov al,ds:[si+bx].DTAFileName
295 cmp al,0
296 je EndOfName
297
298 mov es:[di+bx].File_Name,al
299 inc bx
300 loop MoveNameLoop
301
302EndOfName:
303 mov es:[di+bx].File_Name,0
304 mov ax,bx
305 mov es:[di].String_len,al
306
307 add di,bx
308 mov word ptr ReturnBufferSave+0,di
309 mov word ptr ReturnBufferSave+2,es
310
311 les di,[bp].FindCountPtr
312 inc word ptr es:[di]
313
314;
315; Check if the request was for more than one
316;
317 dec SearchCount
318 jz SearchDone
319
320 mov ax,04f00h ; set opcode
321 int 21h ; find next matching file
322 jc ErrorExit ; jump if error
323
324 les di,ReturnBufferSave ;
325 jmp MoveFindData
326
327SearchDone:
328 sub ax,ax ; set good return code
329
330ErrorExit:
331 push ax
332 mov ax,seg FindSegment
333 mov ds,ax
334 assume ds:FindSegment
335 cmp SaveDTAFlag,0
336 je DoNotRestore
337
338 mov SaveDTAFlag,0
339
340 lds dx,SaveDTA
341 mov ah,1ah ; load opcode
342 int 21h ; setup DTA
343
344DoNotRestore:
345 pop ax
346
347 mexit ; pop registers
348 ret size str - 6 ; return
349
350DosFindFirst endp
351
352dosxxx ends
353
354 end