Rev 1635 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1065 | Lrz | 1 | ; Copyright (c) 2008-2009, diamond |
2 | ; All rights reserved. |
||
3 | ; |
||
4 | ; Redistribution and use in source and binary forms, with or without |
||
5 | ; modification, are permitted provided that the following conditions are met: |
||
6 | ; * Redistributions of source code must retain the above copyright |
||
7 | ; notice, this list of conditions and the following disclaimer. |
||
8 | ; * Redistributions in binary form must reproduce the above copyright |
||
9 | ; notice, this list of conditions and the following disclaimer in the |
||
10 | ; documentation and/or other materials provided with the distribution. |
||
11 | ; * Neither the name of the |
||
12 | ; names of its contributors may be used to endorse or promote products |
||
13 | ; derived from this software without specific prior written permission. |
||
14 | ; |
||
15 | ; THIS SOFTWARE IS PROVIDED BY Alexey Teplov aka |
||
16 | ; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
17 | ; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
18 | ; DISCLAIMED. IN NO EVENT SHALL |
||
19 | ; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
20 | ; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
21 | ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
22 | ; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
23 | ; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
24 | ; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
25 | ;***************************************************************************** |
||
26 | |||
27 | restore_usa: |
||
28 | ; Update Sequence Array restore |
||
29 | ; in: ds:bx -> USA-protected structure |
||
3555 | Serge | 30 | push bx |
31 | lea di, [bx+1feh] |
||
32 | mov cx, [bx+6] |
||
33 | add bx, [bx+4] |
||
34 | dec cx |
||
1065 | Lrz | 35 | @@: |
3555 | Serge | 36 | mov ax, [bx+2] |
37 | mov [di], ax |
||
38 | inc bx |
||
39 | inc bx |
||
40 | add di, 200h |
||
41 | loop @b |
||
42 | pop bx |
||
43 | ret |
||
1065 | Lrz | 44 | |
45 | find_attr: |
||
46 | ; in: ds:di->file record, ax=attribute |
||
47 | ; out: ds:di->attribute or di=0 if not found |
||
3555 | Serge | 48 | add di, [di+14h] |
1065 | Lrz | 49 | .1: |
50 | ; attributes' codes are formally dwords, but all of them fit in word |
||
3555 | Serge | 51 | cmp word [di], -1 |
52 | jz .notfound |
||
53 | cmp word [di], ax |
||
54 | jnz .continue |
||
1065 | Lrz | 55 | ; for $DATA attribute, scan only unnamed |
3555 | Serge | 56 | cmp ax, 80h |
57 | jnz .found |
||
58 | cmp byte [di+9], 0 |
||
59 | jz .found |
||
1065 | Lrz | 60 | .continue: |
3555 | Serge | 61 | add di, [di+4] |
62 | jmp .1 |
||
1065 | Lrz | 63 | .notfound: |
3555 | Serge | 64 | xor di, di |
1065 | Lrz | 65 | .found: |
3555 | Serge | 66 | ret |
1065 | Lrz | 67 | |
68 | process_mcb_nonres: |
||
69 | ; in: ds:si->attribute, es:di->buffer |
||
70 | ; out: es:di->buffer end |
||
3555 | Serge | 71 | pushad |
72 | pop di |
||
73 | add si, [si+20h] |
||
74 | xor ebx, ebx |
||
1065 | Lrz | 75 | .loop: |
3555 | Serge | 76 | lodsb |
77 | test al, al |
||
78 | jz .done |
||
79 | push invalid_read_request_string |
||
80 | movzx cx, al |
||
81 | shr cx, 4 |
||
82 | jz find_error_sp |
||
83 | xchg ax, dx |
||
84 | and dx, 0Fh |
||
85 | jz find_error_sp |
||
86 | add si, cx |
||
87 | add si, dx |
||
88 | pop ax |
||
89 | push si |
||
90 | dec si |
||
91 | movsx eax, byte [si] |
||
92 | dec cx |
||
93 | jz .l1e |
||
1065 | Lrz | 94 | .l1: |
3555 | Serge | 95 | dec si |
96 | shl eax, 8 |
||
97 | mov al, [si] |
||
98 | loop .l1 |
||
1065 | Lrz | 99 | .l1e: |
3555 | Serge | 100 | xchg ebp, eax |
101 | dec si |
||
102 | movsx eax, byte [si] |
||
103 | mov cx, dx |
||
104 | dec cx |
||
105 | jz .l2e |
||
1065 | Lrz | 106 | .l2: |
3555 | Serge | 107 | dec si |
108 | shl eax, 8 |
||
109 | mov al, byte [si] |
||
110 | loop .l2 |
||
1065 | Lrz | 111 | .l2e: |
3555 | Serge | 112 | pop si |
113 | add ebx, ebp |
||
1065 | Lrz | 114 | ; eax=length, ebx=disk block |
3555 | Serge | 115 | stosd |
116 | mov eax, ebx |
||
117 | stosd |
||
118 | cmp di, 0x8000 - 12 |
||
119 | jbe .loop |
||
1065 | Lrz | 120 | ..attr_overflow: |
3555 | Serge | 121 | mov si, fragmented_string |
122 | jmp find_error_si |
||
1065 | Lrz | 123 | .done: |
3555 | Serge | 124 | xor ax, ax |
125 | stosw |
||
126 | stosw |
||
127 | push di |
||
128 | popad |
||
129 | ret |
||
1065 | Lrz | 130 | |
131 | load_attr: |
||
132 | ; in: ax=attribute, ds:bx->base record |
||
133 | ; out: if found: CF=0, attribute loaded to [freeattr], [freeattr] updated, |
||
3555 | Serge | 134 | ; edx=size of attribute in bytes |
1065 | Lrz | 135 | ; out: if not found: CF=1 |
3555 | Serge | 136 | mov di, [bp + freeattr - dat] |
137 | push ss |
||
138 | pop es |
||
139 | mov byte [es:di], 1 |
||
140 | inc di |
||
141 | cmp di, 0x8000 - 12 |
||
142 | ja ..attr_overflow |
||
143 | or edx, -1 ; file size is not known yet |
||
1065 | Lrz | 144 | ; scan for attribute |
3555 | Serge | 145 | push di |
146 | mov di, bx |
||
147 | add di, [di+14h] |
||
1065 | Lrz | 148 | @@: |
3555 | Serge | 149 | call find_attr.1 |
150 | test di, di |
||
151 | jz .notfound1 |
||
152 | cmp byte [di+8], 0 |
||
153 | jnz .nonresident |
||
154 | mov si, di |
||
155 | pop di |
||
156 | push ds |
||
157 | jmp .resident |
||
1065 | Lrz | 158 | .aux_resident: |
3555 | Serge | 159 | mov ax, ds |
160 | mov si, di |
||
161 | pop di ds bx ds edx |
||
162 | push ss |
||
163 | pop es |
||
164 | push ds |
||
165 | mov ds, ax |
||
1065 | Lrz | 166 | ; resident attribute |
167 | .resident: |
||
3555 | Serge | 168 | dec di |
169 | mov al, 0 |
||
170 | stosb |
||
171 | mov ax, [si+10h] |
||
172 | stosw |
||
173 | push di |
||
174 | add di, ax |
||
175 | cmp di, 0x8000 - 12 |
||
176 | pop di |
||
177 | ja ..attr_overflow |
||
178 | movzx edx, ax ; length of attribute |
||
179 | xchg ax, cx |
||
180 | add si, [si+14h] |
||
181 | rep movsb |
||
182 | mov [bp + freeattr - dat], di |
||
183 | pop ds |
||
184 | ret |
||
1065 | Lrz | 185 | .nonresident: |
186 | ; nonresident attribute |
||
3555 | Serge | 187 | cmp dword [di+10h], 0 |
188 | jnz @b |
||
1065 | Lrz | 189 | ; read start of data |
3555 | Serge | 190 | mov si, di |
191 | mov edx, [di+30h] ; size of attribute |
||
192 | pop di |
||
193 | call process_mcb_nonres |
||
194 | sub di, 4 |
||
195 | push di |
||
1065 | Lrz | 196 | .notfound1: |
3555 | Serge | 197 | pop di |
198 | push edx |
||
1065 | Lrz | 199 | ; $ATTRIBUTE_LIST is always in base file record |
3555 | Serge | 200 | cmp ax, 20h |
201 | jz .nofragmented |
||
1065 | Lrz | 202 | ; try to load $ATTRIBUTE_LIST = 20h |
3555 | Serge | 203 | push ax |
204 | mov ax, 20h |
||
205 | push [bp + freeattr - dat] |
||
206 | mov [bp + freeattr - dat], di |
||
207 | push di |
||
208 | call load_attr |
||
209 | pop di |
||
210 | pop [bp + freeattr - dat] |
||
211 | pop ax |
||
212 | jc .nofragmented |
||
213 | push ds bx |
||
214 | pusha |
||
215 | mov si, di |
||
216 | push ss |
||
217 | pop ds |
||
218 | push 0x8100 |
||
219 | pop es |
||
220 | xor ecx, ecx |
||
221 | mov cl, 0x78 |
||
222 | xor bx, bx |
||
223 | push es |
||
224 | call read_file_chunk |
||
225 | pop ds |
||
226 | jc ..found_disk_error |
||
227 | test cx, cx |
||
228 | jz ..attr_overflow |
||
229 | popa |
||
230 | push ss |
||
231 | pop es |
||
232 | xor bx, bx |
||
1065 | Lrz | 233 | .1: |
3555 | Serge | 234 | cmp [bx], ax |
235 | jnz .continue1 |
||
1065 | Lrz | 236 | ; only unnamed $DATA attributes! |
3555 | Serge | 237 | cmp ax, 80h |
238 | jnz @f |
||
239 | cmp byte [bx+6], 0 |
||
240 | jnz .continue1 |
||
1065 | Lrz | 241 | @@: |
3555 | Serge | 242 | cmp dword [bx+10h], 0 |
243 | jz .continue1 |
||
244 | cmp dword [bx+8], 0 |
||
245 | jnz @f |
||
246 | dec di |
||
247 | cmp di, [bp + freeattr - dat] |
||
248 | lea di, [di+1] |
||
249 | jnz .continue1 |
||
1065 | Lrz | 250 | @@: |
3555 | Serge | 251 | push ds di |
252 | push ax |
||
253 | mov eax, [bx+10h] |
||
254 | mov ecx, [bx+8] |
||
255 | call read_file_record |
||
256 | pop ax |
||
257 | mov di, [14h] |
||
1065 | Lrz | 258 | .2: |
3555 | Serge | 259 | call find_attr.1 |
260 | cmp byte [di+8], 0 |
||
261 | jz .aux_resident |
||
262 | cmp dword [di+10h], ecx |
||
263 | jnz .2 |
||
264 | mov si, di |
||
265 | mov di, sp |
||
266 | cmp dword [ss:di+8], -1 |
||
267 | jnz @f |
||
268 | push dword [si+30h] ; size of attribute |
||
269 | pop dword [ss:di+8] |
||
1065 | Lrz | 270 | @@: |
3555 | Serge | 271 | pop di |
272 | call process_mcb_nonres |
||
273 | sub di, 4 |
||
274 | pop ds |
||
1065 | Lrz | 275 | .continue1: |
3555 | Serge | 276 | add bx, [bx+4] |
277 | cmp bx, dx |
||
278 | jb .1 |
||
279 | pop bx ds |
||
1065 | Lrz | 280 | .nofragmented: |
3555 | Serge | 281 | pop edx |
282 | dec di |
||
283 | cmp di, [bp + freeattr - dat] |
||
284 | jnz @f |
||
285 | stc |
||
286 | ret |
||
1065 | Lrz | 287 | @@: |
3555 | Serge | 288 | inc di |
289 | xor ax, ax |
||
290 | stosw |
||
291 | stosw |
||
292 | mov [bp + freeattr - dat], di |
||
293 | ret |
||
1065 | Lrz | 294 | |
295 | read_file_record: |
||
296 | ; in: eax = index of record |
||
297 | ; out: ds:0 -> record |
||
298 | ; find place in cache |
||
3555 | Serge | 299 | push di |
300 | push si |
||
301 | mov si, cache1head |
||
302 | call cache_lookup |
||
303 | pop si |
||
304 | pushf |
||
305 | sub di, 3400h |
||
306 | shl di, 10-3 |
||
307 | add di, 0x6000 |
||
308 | mov ds, di |
||
309 | popf |
||
310 | pop di |
||
311 | jnc .noread |
||
1065 | Lrz | 312 | ; read file record |
3555 | Serge | 313 | pushad |
314 | push ds |
||
315 | push es |
||
316 | movzx ecx, [bp + frs_size - dat] |
||
317 | shr cx, 9 |
||
318 | mul ecx |
||
319 | push ds |
||
320 | pop es |
||
321 | push ss |
||
322 | pop ds |
||
323 | mov si, 0x4000 |
||
324 | xor bx, bx |
||
325 | push [bp + cur_obj - dat] |
||
326 | mov [bp + cur_obj - dat], mft_string |
||
327 | push es |
||
328 | call read_attr |
||
1065 | Lrz | 329 | ; initialize cache for $INDEX_ALLOCATION for this record |
3555 | Serge | 330 | pop si |
331 | push si |
||
332 | sub si, 0x6000 |
||
333 | mov ax, si |
||
334 | shr si, 10-3 |
||
335 | shr ax, 2 |
||
336 | add si, 3480h |
||
337 | add ax, 3500h |
||
338 | mov [si], si |
||
339 | mov [si+2], si |
||
340 | mov [si+4], ax |
||
341 | pop ds |
||
342 | call restore_usa |
||
343 | pop [bp + cur_obj - dat] |
||
344 | pop es |
||
345 | pop ds |
||
346 | popad |
||
1065 | Lrz | 347 | .noread: |
3555 | Serge | 348 | ret |
1065 | Lrz | 349 | |
350 | read_attr: |
||
351 | ; in: eax = offset in sectors, ecx = size in sectors (<10000h), es:bx -> buffer, ds:si -> attribute |
||
3555 | Serge | 352 | push invalid_read_request_string |
353 | cmp byte [si], 0 |
||
354 | jnz .nonresident |
||
355 | cmp eax, 10000h shr 9 |
||
356 | jae find_error_sp |
||
357 | shl ax, 9 |
||
358 | shl cx, 9 |
||
359 | cmp ax, [si+2] |
||
360 | jae find_error_sp |
||
361 | cmp cx, [si+2] |
||
362 | ja find_error_sp |
||
363 | add si, 3 |
||
364 | add si, ax |
||
365 | mov di, bx |
||
366 | rep movsb |
||
367 | pop ax |
||
368 | ret |
||
1065 | Lrz | 369 | .nonresident: |
3555 | Serge | 370 | inc si |
1065 | Lrz | 371 | .loop: |
3555 | Serge | 372 | mov edx, dword [si] |
373 | add si, 8 |
||
374 | test edx, edx |
||
375 | jz find_error_sp |
||
376 | imul edx, [bp + sect_per_clust - dat] |
||
377 | sub eax, edx |
||
378 | jnc .loop |
||
379 | add eax, edx |
||
380 | sub edx, eax |
||
381 | push cx |
||
382 | cmp ecx, edx |
||
383 | jb @f |
||
384 | mov cx, dx |
||
1065 | Lrz | 385 | @@: |
3555 | Serge | 386 | push bx |
387 | mov ebx, [si-4] |
||
388 | imul ebx, [bp + sect_per_clust - dat] |
||
389 | add eax, ebx |
||
390 | pop bx |
||
391 | call read |
||
392 | jc ..found_disk_error |
||
393 | mov dx, cx |
||
394 | pop cx |
||
395 | xor eax, eax |
||
396 | sub cx, dx |
||
397 | jnz .loop |
||
398 | pop ax |
||
399 | ret |
||
1065 | Lrz | 400 | |
401 | load_file_ntfs: |
||
402 | ; in: ss:bp = 0:dat |
||
403 | ; in: es:bx = address to load file |
||
404 | ; in: ds:si -> ASCIIZ name |
||
405 | ; in: cx = limit in sectors |
||
406 | ; out: bx = status: bx=0 - ok, bx=1 - file is too big, only part has been loaded, bx=2 - file not found |
||
407 | ; out: dx:ax = file size (0xFFFFFFFF if file not found) |
||
3555 | Serge | 408 | push es bx cx |
409 | mov eax, 5 ; root cluster |
||
410 | mov [bp + cur_obj - dat], root_string |
||
1065 | Lrz | 411 | .parse_dir_loop: |
3555 | Serge | 412 | push ds si |
413 | call read_file_record |
||
1065 | Lrz | 414 | ; find attributes $INDEX_ROOT, $INDEX_ALLOCATION, $BITMAP |
3555 | Serge | 415 | mov ax, [bp + freeattr - dat] |
416 | mov [bp + index_root - dat], ax |
||
417 | mov ax, 90h ; $INDEX_ROOT |
||
418 | xor bx, bx |
||
419 | call load_attr |
||
420 | mov si, noindex_string |
||
421 | jc find_error_si |
||
422 | mov ax, [bp + freeattr - dat] |
||
423 | mov [bp + index_alloc - dat], ax |
||
424 | mov ax, 0A0h ; $INDEX_ALLOCATION |
||
425 | call load_attr |
||
426 | jnc @f |
||
427 | mov [bp + index_alloc - dat], bx |
||
1065 | Lrz | 428 | @@: |
3555 | Serge | 429 | push ds |
1065 | Lrz | 430 | ; search for entry |
3555 | Serge | 431 | mov si, [bp + index_root - dat] |
432 | push ss |
||
433 | pop ds |
||
434 | push 0x8100 |
||
435 | pop es |
||
436 | xor ecx, ecx |
||
437 | mov cl, 0x78 |
||
438 | xor bx, bx |
||
439 | push es |
||
440 | call read_file_chunk |
||
441 | pop ds |
||
442 | jc ..found_disk_error |
||
443 | test cx, cx |
||
444 | jz ..attr_overflow |
||
445 | mov si, invalid_read_request_string |
||
446 | cmp word [bx+10], 0 |
||
447 | jnz find_error_si |
||
1065 | Lrz | 448 | ; calculate number of items in cache |
3555 | Serge | 449 | mov di, [bx+8] ; subnode_size |
450 | mov ax, 0x4000 |
||
451 | sub ax, word [bp + frs_size - dat] |
||
452 | cwd |
||
453 | div di |
||
454 | test ax, ax |
||
455 | jz find_error_si |
||
456 | mov si, invalid_volume_msg |
||
457 | test di, 0x1FF |
||
458 | jnz find_error_si |
||
459 | pop cx |
||
460 | mov [bp + cur_index_seg - dat], cx |
||
461 | shl ax, 3 |
||
462 | sub cx, 6000h |
||
463 | mov si, cx |
||
464 | shr cx, 2 |
||
465 | shr si, 10-3 |
||
466 | add cx, ax |
||
467 | add si, 3480h |
||
468 | mov [bp + cur_index_cache - dat], si |
||
469 | add cx, 3500h |
||
470 | mov [ss:si+6], cx |
||
471 | mov dx, di |
||
472 | add bx, 10h |
||
1065 | Lrz | 473 | .scan_record: |
3555 | Serge | 474 | add bx, [bx] |
1065 | Lrz | 475 | .scan: |
3555 | Serge | 476 | test byte [bx+0Ch], 2 |
477 | jnz .look_child |
||
478 | movzx cx, byte [bx+50h] ; namelen |
||
479 | lea di, [bx+52h] ; name |
||
480 | push ds |
||
481 | pop es |
||
482 | pop si ds |
||
483 | push ds si |
||
484 | xor ax, ax |
||
1065 | Lrz | 485 | .1: |
3555 | Serge | 486 | lodsb |
487 | cmp al, '/' |
||
488 | jnz @f |
||
489 | mov al, 0 |
||
1065 | Lrz | 490 | @@: |
3555 | Serge | 491 | cmp al, 'A' |
492 | jb .nocapital |
||
493 | cmp al, 'Z' |
||
494 | ja .nocapital |
||
495 | or al, 20h |
||
1065 | Lrz | 496 | .nocapital: |
3555 | Serge | 497 | cmp al, 'a' |
498 | jb .notletter |
||
499 | cmp al, 'z' |
||
500 | ja .notletter |
||
501 | or byte [es:di], 20h |
||
1065 | Lrz | 502 | .notletter: |
3555 | Serge | 503 | scasw |
504 | loopz .1 |
||
505 | jb .look_child |
||
506 | ja @f |
||
507 | cmp byte [si], 0 |
||
508 | jz .file_found |
||
509 | cmp byte [si], '/' |
||
510 | jz .file_found |
||
1065 | Lrz | 511 | @@: |
3555 | Serge | 512 | push es |
513 | pop ds |
||
514 | add bx, [bx+8] |
||
515 | jmp .scan |
||
1065 | Lrz | 516 | .look_child: |
3555 | Serge | 517 | push es |
518 | pop ds |
||
519 | test byte [bx+0Ch], 1 |
||
520 | jz .not_found |
||
521 | mov si, [bp + index_alloc - dat] |
||
522 | test si, si |
||
523 | jz .not_found |
||
524 | add bx, [bx+8] |
||
525 | mov eax, [bx-8] |
||
526 | mov es, [bp + cur_index_seg - dat] |
||
527 | push si |
||
528 | mov si, [bp + cur_index_cache - dat] |
||
529 | call cache_lookup |
||
530 | pop si |
||
531 | pushf |
||
532 | mov bx, di |
||
533 | mov bh, 0 |
||
534 | shr bx, 3 |
||
535 | imul bx, dx |
||
536 | add bx, [bp + frs_size - dat] |
||
537 | popf |
||
538 | jnc .noread |
||
539 | push es |
||
540 | push dx |
||
541 | push ss |
||
542 | pop ds |
||
543 | movzx ecx, dx |
||
544 | shr cx, 9 |
||
545 | mul [bp + sect_per_clust - dat] |
||
546 | call read_attr |
||
547 | pop dx |
||
548 | pop es |
||
549 | push es |
||
550 | pop ds |
||
551 | call restore_usa |
||
1065 | Lrz | 552 | .noread: |
3555 | Serge | 553 | push es |
554 | pop ds |
||
555 | add bx, 18h |
||
556 | jmp .scan_record |
||
1065 | Lrz | 557 | .not_found: |
3555 | Serge | 558 | pop [bp + cur_obj - dat] |
559 | mov si, error_not_found |
||
560 | jmp find_error_si |
||
1065 | Lrz | 561 | .file_found: |
3555 | Serge | 562 | pop [bp + cur_obj - dat] |
563 | pop cx |
||
564 | mov ax, [bp + index_root - dat] |
||
565 | mov [bp + freeattr - dat], ax |
||
566 | mov eax, [es:bx] |
||
567 | test byte [es:bx+48h+3], 10h |
||
568 | jz .regular_file |
||
569 | cmp byte [si], 0 |
||
570 | jz ..directory_error |
||
571 | inc si |
||
572 | jmp .parse_dir_loop |
||
1065 | Lrz | 573 | .regular_file: |
3555 | Serge | 574 | cmp byte [si], 0 |
575 | jnz ..notdir_error |
||
1065 | Lrz | 576 | ; read entry |
3555 | Serge | 577 | call read_file_record |
578 | xor bx, bx |
||
579 | mov ax, 80h |
||
580 | call load_attr |
||
581 | mov si, nodata_string |
||
582 | jc find_error_si |
||
583 | mov si, [bp + index_root - dat] |
||
584 | mov [bp + freeattr - dat], si |
||
585 | push ss |
||
586 | pop ds |
||
587 | jmp load_file_common_end10000h),> |