-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdoslfn.asm
More file actions
8313 lines (7909 loc) · 206 KB
/
doslfn.asm
File metadata and controls
8313 lines (7909 loc) · 206 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;Lange Dateinamen unter nacktem DOS
;Noch zu tun:
;* Untersttzung von Sektorl„nge 128..4096 Bytes
;* Umbenennen gleiche Datei
;* korrektes L”schen mit Wildcards
;* HeapWalker
;N: Most Protected Mode DOS extenders doesn't translate the LFN API to
; Real Mode. (When running Windows9x, Windows makes that task, effectively
; disabling the DOS extender.)
; For DPMI programs, it is up to the programmer to translate these DOS
; calls to Real Mode, using DPMI services at INT31. Best solution would
; be a DLL that makes this task at load time, hooking the protected mode
; INT21 chain.
; When running Windows3 in Enhanced Mode,
; DOSLFN auto-loads an LFNXLAT.386 VxD that translates these APIs.
; With this VxD, there is no need for translation for Windows programs.
; Unfortunately, Win32s programs cannot see long file names,
; unless someone publish a great patch of one Win32s DLL.
; The rarely used Standard Mode should be configured to load the DLL
; (above mentioned) at startup - but DOSLFN requires a 386 itself.
%NOLIST
include prolog.asm
public COMentry ;damit's mit SoftICE klappt
P386
JUMPS
REQfunc equ 7146h ;in AX
REQcode equ 9877h ;in DX
ANScode equ 8766h ;in AX; DX=Segmentadresse
DEFHEAPSIZE = 1000 ;fr einige FindInfos
FDChangeTime = 3*18 ;Neue DPB einlesen nach 3 Sekunden Inaktivit„t
CDChangeTime = 7*18 ;dauert naturgem„á viel l„nger,
;auch das Einlesen der ersten CD-Sektoren und der Link-Tabelle
macro INT3
ifdef DEBUG
INT 3
endif
endm
USEOLDDOS = 0 ;1 to enable LFN filtering on legacy find fns
USEWIN = 0 ;1 to enable Windows recognition code
USECP = 0 ;1 to enable codepage changing
USEDBCS = 0 ;1 to enable double-byte character sets
USEWINTIME = 0 ;1 to enable real Win <-> DOS time conversions
USEXP = 0 ;1 to enable reading of XP lowercase 8.3 names
USEFREESPC = 0 ;1 to enable DPB free space writing
;In MS-DOS 7, writing directly to disk causes the free cluster count to become
;unknown. For large drives or frequent calling, this introduces a noticeable
;slowdown. Fortunately, there is a function to set the free cluster count.
;Enabling the above feature will: get the extended DPB, write to disk, and
;restore the free space from the DPB. Do not enable this feature if the
;extended functions are not available (Int21/AX=730[245]).
USEFASTOPEN = 0 ;1 to enable the FASTOPEN cache
;FastOpen is now disabled by default, since it doesn't recognise disc changes
;and doesn't seem to impact performance (at least with modern DOS).
USELANG = 0 ;Make COM smaller by omitting German strings
USEUNI = 0 ;Make COM smaller by omitting Unicode support
USECD = 0 ;Make COM smaller by omitting CD-ROM support
;********************
;** DOS structures **
;********************
struc tExDPB ;structure returned by INT21/AH=32, valid: DOS 4.0+
Drive db ? ;{0=A}
UnitNo db ? ;number of device driver unit
SecLen dw ? ;{Bytes pro Sektor}
HiSec db ? ;{Anzahl Sektoren pro Cluster -1, 2**n-1}
Shift db ? ;{Verschiebung n}
ResSec dw ? ;{Reservierte Sektoren am Anfang des Laufwerks}
FATs db ? ;{Anzahl der FATs}
RootEn dw ? ;{Anzahl Wurzelverzeichniseintr„ge}
UsrSec dw ? ;{1. Sektor mit Userdaten}
HiClus dw ? ;{Anzahl Cluster -1}
SecFAT dw ? ;{Sektoren pro FAT}
SecDir dw ? ;{Sektornummer 1.Dir}
unused db 5 dup (?) ;Luft zum FAT32-DPB, der beginnt ab Ofs.24
;from here starts extended trail from INT21/AH=73
dpb_flags db ?
next_dpb dd ? ;Pointer
start_search_cluster dw ?
free_clusters dd ?
mirroring dw ?
file_system_info_sector dw ?
backup_boot_sector dw ?
first_sector dd ?
max_cluster dd ?
sectors_per_fat dd ?
root_cluster dd ?
free_space_cluster dd ?
filler db ? ;"gerade" Strukturl„nge!
ends
struc tRWRec ;DOS structure for reading and writing sectors
sect dd ? ;sector number, allowing partitions up to 2 Terabyte
numb dw ? ;sector count
addr dd ? ;FAR address of sector data
ends
struc TSearchRec ;DOS legacy search record, returned at INT21/AH=4E&4F
;N: All undocumented fields are not used to maintain compatibility with
; non-MS clones of DOS or some TSRs
Drive db ? ;bit7 set at network drives and FAT32, undocumented
SName db 8 dup (?)
SExt db 3 dup (?)
SAttr db ?
DirNo dw ?
union
struc
Clus dw ?
Res dd ?
ends
struc
Clus32 dd ? ;on FAT32
DirNoHi dw ? ;eventually high part of DirNo?
ends
ends
Attr db ? ;here the documented part begins
Time dd ?
fsize dd ?
FName db 13 dup (?) ;in DOS form, with dot if extension follows
ends
;N: Length "undocumented" = 21 bytes, "documented" = 22 bytes
struc TW32FindData ;DOS new and Win32 search record, at INT21/AX=714E&4F
;N: This is the same structure as WIN32_FIND_DATA, but file names will return
; in OEM character set rather than ANSI
attr dd ? ;bits 0..6: like DOS, bit 8: temporary (not used)
timec dq ? ;file creation time FAT stepping: 10 ms
timea dq ? ;last access time FAT stepping: 1 day
timem dq ? ;last modification time FAT stepping: 2 s
;On CDFS, all times have 1 s stepping
sizeh dd ? ;(not used) high part of file length (in wrong order)
sizel dd ? ;file length (FAT, CDFS: up to 2GB)
res dq ? ;maybe compressed file length? inode number? security?
lname db 260 dup (?) ;long name (LFN), alone if short
sname db 13 dup (?) ;short name (SFN), also called "alias"
ends
struc tErrInfo ;for Set_Error_Info INT21/AX=5D0A DS:DX=pointer
err_AX dw ?
err_BX dw ?
err_CX dw ?
err_DX dw ?
err_SI dw ?
err_DI dw ?
err_DS dw ?
err_ES dw ?
res dw ?
cid dw ? ;computer ID (0 for localhost)
pid dw ? ;process ID (same as PSP)
ends
struc tWinStart ;Format of Windows (W3) Startup Information Structure
ver_major db ? ;major version of info structure (3)
ver_minor db ? ;minor version of info structure (0)
next dd ? ;pointer to next tWinStart structure or 0000h:0000h
vxd_fname dd ? ;pointer to ASCIZ name of virtual device file or zero
vxd_rdata dd ? ;virtual device reference data
idata dd ? ;pointer to instance data records
ends
struc tEMM ;Extended Memory Move
len dd ? ;length (must be even)
srch dw ? ;source handle
srco dd ? ;source offset
dsth dw ? ;destination handle
dsto dd ? ;destination offset
ends
;*************************
;** FAT/CDFS structures **
;*************************
struc tDirEnt ;legacy directory entry on FAT media (FAT12, FAT16, FAT32)}
;source: Ralf Brown Interrupt List, SIZE=32
;N: First character (byte) has special meaning:
; 00: no more following DirEnts (a new cluster will be filled with zeroes)
; 05: first character is E5
; E5: deleted entry, undeleted DirEnts may follow
FName db 11 dup (?) ;FCB form without dot, upper-case letters
Attr db ?
resv db ? ;Win95: Null (maybe high part of file size)
timeC10ms db ? ;Win95: 10ms additional value to timeC [0..199]
timeC dd ? ;Win95: creation time (all local time)
timeA dw ? ;Win95: last access date
ClusH dw ? ;FAT32: high part of first cluster
timeM dd ? ;modification time
ClusL dw ? ;first cluster, FAT32: low part of first cluster
fsize dd ? ;file size
ends
struc TLfnDirEnt ;FAT LFN directory entry structure, SIZE=32
;N: The NameX protions of this structure are not directly used;
; they are addressed by "LODSW" and the gaps skipped by "ADD SI,space"
count db ? ;Bit 0..5: number (1+), Bit 6=last entry
Name1 dw 5 dup (?) ;five Unicode name characters
Attr dw ? ;always 000Fh
check db ? ;SFN checksum link
Name2 dw 6 dup (?) ;six Unicode name characters
Clus1 dw ? ;always zero
Name3 dw 2 dup (?) ;two Unicode name characters
ends
struc TCD_DirEnt ;CD (ISO and Joliet) directory entry structure
;N: A bunch of entries are ignored, SIZE>=34
r db ? ;the number of bytes in this record
ea db ? ;number of sectors in extended attribute record, zero
sect dd ? ;Logical Block Number of file start
sectm dd ? ;same for Motorola
fsize dd ? ;file or directory length in bytes, always divisable
;by sector size (2048) for directory length
fsizem dd ? ;same for Motorola
year db ? ;years past 1900 (all local time)
month db ? ;1 = January
day db ? ;1 = 1.
hour db ? ;0..23
minu db ? ;0..59
seco db ? ;0..59, mostly an even number(?)
tz db ? ;time zone of local time, signed, 15min, +east, -west
flags db ? ;attributes, Bit0=hidden, Bit1=Dir, Bit7=more DirEnts
;(Bit 7 is not correct on most CDs)
isiz db ? ;for interleaving, unused
igap db ? ;for interleaving, unused
vsn dw ? ;volume sequence number, unused
vsnm dw ?
fnamelen db ? ;file name length in Bytes (always even if Unicode,
; except for "." and ".." entries)
fname db ? ;file name (Motorola byte order if Unicode)
ends
;********************************
;** DOSLFN internal structures **
;********************************
;N: These structures are used inside DOSLFNs heap
;== part 1: DriveInfo data ==
IF 0
;bits for following <dtype>
DTM_mask =7 ;lower three bits are for general mode switch
DTM_FB =0 ;no bit set if FallBack
DTM_FAT =1 ;001 if FAT mode
DTM_ISO =2 ;010 if ISO mode
DTM_JOL =3 ;011 if Joliet mode, other codes are for future:
DTM_PT =4 ;100 PipeThrough (For this drive, there is an
; underlying LFN API, e.g. NTFSREAD)
;DTM_X =5 ;101 extfs2 (Linux) via LTOOLS
;DTM_UDF =6 ;110 UDF (Universal Disc Format, DVD)
;DTM_LFNBK =7 ;111 LFNBK file based LFN support - or some network
DT_Joliet =1 ;if not, take LFNs from ISO (these may also be long)
DT_CDFS =2 ;bit 1 acts as CDFS switch too
DT_BigDos =8 ;use extended INT25/26 interface
DT_FAT16 =16 ;FAT quantity, otherwise, it's FAT12
DT_FAT32 =32 ;don't use INT25/26, use INT21/AH=73 instead
;DT_SmartOS =64 ;set if OS already remove LFNs (MS-DOS7+) - no dtype!
DT_Locked =128 ;set if drive was locked (for writing, MS-DOS7+)
;N: Depending on DTM_mask'ed value if <dtype>, DOSLFN works in nearly
; complete different modi
; * FAT mode for diskettes and hard drives (even a ZIP drive uses FAT)
; * CD mode (rarely used) for ISO CDs with "long" ISO file names
; * Joliet mode, typical for Windows9x CDs
; * fall-back mode for all other drives
; This mode does not only map LFN_FindFirst/Next to its
; legacy companion, it also makes the extended pattern matching.
; Equally, LFN_Delete may delete multiple files using wildcards
; calling "legacy delete" multiple times.
; From the view of a programmer, it is very nice to have an LFN API
; on _all_ drives, and there is no need to make ugly cases.
; Note that also Win9x does wrap e.g. DOS network drives (Novell Lite)
; with its LFN API - therefore, FallBack is a "must" for compatibility.
; However, it conflicts with actual versions of NTFSREAD.
; Another useful mode would be an LFNBK mode, simply using a file
; for keeping long file names - this would instantly work on all drives.
struc TDI_FAT
shift db ? ;shift count for sector->cluster
shift2 db ? ;shift count for byte->sector (always 9)
fatsec dd ? ;first sector of active FAT
dirsec dd ? ;sector of root directory
usrsec dd ? ;sector of first cluster (ie cluster # 2)
lastsec dd ? ;last valid sector of user data
ends
ENDIF
struc TDI_ISO
voldesc dd ? ;volume descriptor
rootdir dd ? ;root directory sector
rootlen dw ? ;count of root directory sectors
ends
IF 0
struc TDI ;linked structure for all media ("Drive Info")
next dw ? ;NEXT pointer into LocalHeap, zero if last
prev dw ?
time dw ? ;for discarding after a while (removable media only)
drive db ? ;drive number (0=A:)
dtype db ? ;control flags (DT_xxx constants)
secsiz dw ? ;sector size (DOSLFN is able to process any size?)
union
fat TDI_FAT <> ;additional data for FAT media
iso TDI_ISO <> ;additional data for ISO media
ends
ends
;N: drive information is kept in a cache of 2..4 entries. Otherwise,
; copy actions (between different drives) would often retrieve the
; drive info, and clumsy-DOS seems to always read in boot area
ENDIF
;== part 2: SectorCache data ==
IF 0
struc TSC ;linked "sector cache" entry; sector data follows!
next dw ? ;NEXT pointer into LocalHeap, zero if last
prev dw ?
secnum dd ? ;sector number (of first sector)
count db ? ;sector count (always 1)
drive db ? ;drive number (0=A:)
dirty dw ? ;16 "dirty" (="modified") bits for up to 16 sectors
ends
;N: sector data is held in cache because MS-DOS doesn't cache anything,
; even when SmartDrv is loaded, when direct disc access is detected.
; Especially CD access is too slow without internal cacheing of at least
; two sectors. The LocalHeap is used up for cacheing until no more
; memory is available. All other memory allocations free least-recently
; used SectorCache entries to get necessary space.
ENDIF
;== part 3: FindHandle data ==
struc TFI_FAT ;size=6
entry dw ? ;offset from start of sector to current DirEnt
sect dd ? ;sector number of current DirEnt
ends
struc TFI_ISO ;size=10
entry dw ? ;offset from start of sector to current DirEnt
sect dd ? ;sector number of current DirEnt
count dw ? ;number of sectors to end of directory
num dw ? ;directory entry number (for SHSUCDX tilde generation)
ends
struc TFI_FB ;size=21
dta db 21 dup (?) ;space for undocumented DTA part
ends
struc TFI ;interal representation of FindHandle ("FindInfo")
magic db ? ;MagicByte (to detect invalid handles)
drive db ? ;drive number (0=A:)
attr dw ? ;Search (LowByte) and MustMatch (HighByte) attributes
union
fb TFI_FB <> ;additional for FallBack
fat TFI_FAT <> ;additional for FAT
iso TFI_ISO <> ;additional for ISO
ends
fflags db ? ;file flags (only DotAtEnd flag is used)
;N: fflags cannot be adressed easily. Structure fill and read-out
; is intended using LODSx and STOSx, respective.
;N: The file match pattern follows, but if it had a dot (.) at end,
; these dot is stripped from pattern and DotAtEnd flag is set
; due to special meaning of such a pattern
;N: For FallBack, also the file match pattern follows, but is only
; necessary if File_Flag_Is_LFN or _Char_High bits are in fflags
ends
IF 1
struc tFindInfo ;als interne Repr„sentation von FindHandle
usage db ? ;MagicByte
drive db ? ;Laufwerk
attr dw ? ;Attribute
entry dw ? ;Eintrags-Nr. (DirEnt-Zeiger)
sect dd ? ;Sektor-Nummer
ends
struc tFB_FindInfo
usage db ? ;ein anderes MagicByte
undoc db 21 dup (?) ;"undokumentierter" DTA-Bereich
mmattr db ? ;Attribut (CX beim Aufruf)
fflags db ? ;(nicht mehr wesentlich: File_Flag_DotAtEnd)
;anschlieáend: Maske
;(nur n”tig wenn File_Flag_Is_LFN oder Char_High)
ends
MAGIC_hFind =0ACh ;Magic-Byte fr gltiges Find-Handle
MAGIC_FB_hFind =0ADh ;dito fr Rckfallmodus
ENDIF
;== part 4: FastOpen data ==
IF 0
struc TFO ;linked structure for FastOpen
next dw ?
prev dw ?
drive db ? ;0=A:
ends
;N: FastOpen is absolutely necessary for reasonable speed.
; For multi-drive and copy-on-single-drive support, FastOpen
; is now organized as a cache with multiple entries.
ENDIF
struc TDirCache ;32 bytes (if it grows, check cache_temp)
longname dw 0 ;0 = no long name
;1 = longname is in shortname
;otherwise pointer to longname in heap
shortname db 13 dup (0) ;the shortname (might need to upcase)
drive db -1 ;drive containing name
parent dd -1 ;beginning sector of directory containing name
start db 12 dup (0) ;cache data
;directory:
; dd ? ;sector containing start of directory
; dw ? ;number of sectors of directory (CD)
;
;name:
; dw ? ;offset of entry
; dd ? ;sector of entry
; dd ? ;sector of long entry (FAT)
; dw ? ;offset of long entry (FAT)
ends
;== done with the 4 parts ==
;N: All caches are organized as linked lists with most-recently used
; entries on head and least-recently used entries at tail of the lists.
; A cache hit moves the matched entry onto queue's head and updates
; the time stamp. Otherwise, a new structure is put onto head, and
; trailing entries may discarded to maintain maximum entry count
; (for drive info and FastOpen) or to get room (for sector cache).
; Because moving-to-head is done at access, and DOSLFN must not be
; reentered, static list pointers are also work area pointers.
;bits for main function control byte <ctrl0>
CTRL_Main =bit 7 ;main switch whether DOSLFN is active or turned off
CTRL_Write =bit 6 ;allow write access (except for DELETE/UNLINK/MOVE)
CTRL_Tilde =bit 5 ;tilde usage (HKLM/.../NameNumericTail)
CTRL_Tunnel =bit 4 ;tunnel effect
CTRL_CDROM =bit 3 ;CDROM support (default is ON if SHSUCDX was loaded)
CTRL_FB =bit 2 ;fallback mode
CTRL_RoBit =bit 1 ;write-protect attribute for CDROM files (like NORO)
CTRL_SmartOS =bit 0 ;"smart" (LFN entry deleting) DOS (MS-DOS7) detected
;**********************************
;** static variables in PSP area **
;**********************************
;N: "Program Segment Prefix" area is used to reduce memory consumption
; of DOSLFN. Area before 5Ch is apparently used by some DOS extenders.
; Because DOS is not reentrant, LFNDOS doesn't need to be reentrant,
; therefore, these handy variables and buffers are allowed and usable.
org 5Ch
argv0 dw ? ;points to heap
argv0file dw ? ;points behind last backslash, 13 bytes space
;60h
LocalHeap dw ? ;zeigt auf Anfang des Heaps
TrailMinLen dw ? ;TrailByte: Minimum und Anzahl
DriverChain dd ? ;Zeiger ins DOS auf Treiber-Kette
lead_byte_table dd ? ;Zeiger ins DOS fr Fhrungsbyte-Bereiche
uppercase_table dd ? ;Zeiger ins DOS fr Zeichen >=80h
;Offset ist um 7Eh vermindert fr direktes XLAT
;70h
CurSector dd ? ;current "working" sector \
CD_Residual dw ? ;count of directory sectors |- order relied on!
CD_Num dw ? ;directory entry number /
longpos_s dd ? ;internal, set by Locate_DirEnt (FAT) \
longpos_a dw ? ; -"- /
DPB_Drive db ? ;{Drive Parameter Block: Laufwerk, 0=A} \
DriveType db ? ;{Schalter fr Festplatten-Zugriffsart} /
DT_Joliet =bit 0 ;Joliet (if also DT_CDFS)
DT_RR =bit 1 ;Rock Ridge (if also DT_CDFS)
DT_FAT12 =3 ;FAT12/16/32 = number of nibbles
DT_FAT16 =bit 2 ;wegen FAT-Zugriff
DT_FAT32 =bit 3 ;gr”áere Žnderungen (kein INT25/26)
DT_CDFS =bit 4 ;genauer: Joliet
;DT_Int2526 =bit 5 ;wenn Int21/AX=7305 (SmartDrv) nicht geht
DT_Locked =bit 6 ;wenn geschrieben wurde (MS-DOS7+)
DT_Dirty =bit 7 ;Sektor muss geschrieben werden!
;In Abh„ngigkeit von DriveType arbeitet das Programm genaugenommen
;in 3 Modi (mehr sind nicht allgemein machbar):
;* FAT-Modus fr Disketten und Festplatten
;* Joliet fr Windows9x-typische CDs
;* Rckfallmodus fr alles andere: LFN_FindFirst u.a. wird mittels "normaler"
; Funktionen nachgebildet (wie es sonst jedes Programm zu Fuá tun máte,
; und das ist beim Programmieren nervenaufreibend, verflixte DTAs und
; das erweiterte Globbing)
;Sehr nett w„re ja noch ein "Netzwerk-Modus", bspw. per NFS oder DOS-Samba,
;aber wer liefert mir den Quelltext?
;Weiterhin ein "lfnbk"-Modus, mit Abbildung der langen Dateinamen ber
;eine regul„re Hilfsdatei
;This command-line area must not contain variables that initialize at startup
;80h - following 32 bytes are used (at least) three times!
ErrInfo TErrInfo <> ;overloads following
org 80h
FCB_Name db 11 dup (?) ;used for building unique file name
;Never contains 05h as first byte
ShortName db 13 dup (?) ;filled by (CD_)Locate_DirEnt
;here we have 8 bytes room - temporary needed for reading ISO file names
org 80h
DirEnt_Copy TDirEnt <> ;32 bytes space for moving FAT DirEnt while
;inserting LFN, may have 05h as first byte
;A0h
DPB_FAT1Sec dd ? ;FAT: Startsektor 1. FAT
DPB_DirSec dd ? ;{Sektor Hauptverzeichnis (nur FAT)}
DPB_UsrSec dd ? ;{Sektor des 1. Clusters (mit Nr. 2)}
DPB_LastSec dd ? ;{Letzter Sektor der Partition}
;B0h
DPB_Shift db ? ;{Verschiebung fr Sektoren pro Cluster}
LFN_DirEnts db ? ;Anzahl DirEnts beim Schreiben des LFN
CurPathComp dw ? ;Momentan "aktive" Pfad-Komponente oder Maske
cache_temp TDirCache ? ;temporary storage for one cache item
Medium TDI_ISO <> ;all specific medium Information
SearchAttr dw ? ;Such-Attribut, enth„lt im Low-Teil
;die invertierten Attribut-Flags und im High-Teil die
;Must-Match-Attribute. Das Attribut 88h dient (sp„ter) dem
;Aufsuchen gel”schter Eintr„ge wie bei Novell-DOS
MatchPtr dw ? ;"Virtuelle" Methode Match&Stop
SuchSektor dd ? ;fr gegenseitige Suche auf Joliet-CD
;auch: Start-Sektor Ziel-Vrz. bei mkdir, creat und move
num_cluster dw ? ;Anzahl Cluster fr Verzeichnis
subst_root dw ? ;Anzahl Zeichen fr SUBST
;in Truename: Zeiger in LongBuffer, normal LongBuffer+2
throw_fi dw ? ;Zeiger auf Exit-Behandlung (wegen lfn_move)
shortbuffer dw ? ;Puffer fr kurze 8.3-Dateinamen
shortbuffer3 dw ? ;[shortbuffer] + 3
longbuffer dw ? ;Zwischenpuffer fr Zerlegung/TRUENAME
longbuffer2 dw ? ;[longbuffer] + 2
longbuffer_end dw ? ;2 Bytes hier spart 6 Bytes im Code
longname dw ? ;Puffer fr LFN von NextDirEnt()
longname_26 dw ? ;[longname] - 13*2
tunnel2 dw ?;0 ;Kopie fr MOVE-Vorgang \
Sektorp dw ?;Sektor |- initialised at inst.
SektorEnde dw ?;Sektor+512 /
;100h - three bytes for JMP are free for use
LastAccessTime dw ?
subst_drive db ? ;Zeichen, geSUBSTetes (virtuelles) Laufwerk
;Program Control Flag Byte Assignment:
PF_Fail_Uni2Oem =bit 0 ;Nicht zu OEM konvertierbarer Unicode-Name
PF_Follow =bit 1 ;Sektor-Verfolgung nach DirScan
PF_LFN_Input =bit 2 ;LongName-API Namensinterpretation
PF_Slash =bit 3 ;Entfernter Slash bei Gen_Alias
PF_Tunnel_Save =bit 4 ;save LFN before calling OldInt21
PF_Tunnel_Restore=bit 5 ;restore LFN after calling OldInt21
PF_Install_Short=bit 6 ;install the shortname directory entry
;*****************************
;** Stack Frame Assignments **
;*****************************
;N: Due to complex data processing inside DOSLFN, it's not worth
; to keep register data. Registers are pushed onto stack, and with setting
; BP, these registers are easily available via stack frame, ie
; BP and a small offset value, as defined below.
; This technique is known from Windows VxD programming.
;N: Some bit registers are kept onto stack too, their bit-access consumes
; one byte less op-codes than bit-access to a static variable.
File_Flags equ byte bp-6 ;properties of last path component
FuncNum equ byte bp-5 ;{properties of drive used}
Client_E_DX equ word bp-4 ;high part of EDX (unreferenced)
Client_E_AX equ word bp-2 ;high part of EAX (unreferenced)
Client_DI equ word bp ;frame of "pusha" op-code
Client_SI equ word bp+2
Client_BP equ word bp+4 ;(unreferenced)
;Client_SP equ word bp+6 ;free space for us - never popped
PFlags equ byte bp+6 ;input control flags
ctrl equ byte bp+7 ;program control flags
Client_BX equ word bp+8
Client_DX equ word bp+0Ah
Client_CX equ word bp+0Ch
Client_AX equ word bp+0Eh
Client_ES equ word bp+10h
Client_DS equ word bp+12h
Client_FS equ word bp+14h ;(unreferenced)
Client_IP equ word bp+16h ;(unreferenced)
Client_CS equ word bp+18h ;(unreferenced)
Client_Flags equ word bp+1Ah
Client_DXBX equ dword bp+8
Client_CXDX equ dword bp+0Ah ;CX=High, DX=Low, in einem Schlag
Client_AXCX equ dword bp+0Ch
Client_AL equ byte LOW Client_AX
Client_AH equ byte HIGH Client_AX
Client_BL equ byte LOW Client_BX
Client_BH equ byte HIGH Client_BX
Client_CL equ byte LOW Client_CX
Client_CH equ byte HIGH Client_CX
Client_DL equ byte LOW Client_DX
Client_DH equ byte HIGH Client_DX
;*******************************
;** Start of program and ISRs **
;*******************************
;N: Both Interrupt Service Routines (ISRs) are moved to start of .COM
; image to reduce possible offset changes during development.
; Offset changes made resident DOSLFN indeinstallable, and I had to reboot
org 100h
jmp transient
ctrl0 db 11110110b ;8 Ein/Aus-Schalter
;Bit7: global ein/aus
;Bit6: Schreiben e/a
;Bit5: Schlangen e/a
;Bit4: Tunneleffekt e/a
;Bit3: CDROM-Code vorhanden e/a
;Bit2: fallback mode e/a
;Bit1: Schreibschutz-Attribut fr CD e/a (NORO.COM Gegenstck)
;Bit0: SmartOS gefunden (l”scht LFN-Eintr„ge selbst„ndig)
proc NewInt21 far ;Neue INT21-Routine
;D: Int21 handler, always returns with IRET, chaining to OldInt21
; by jumping rather than calling preserves stack frame for odd-behaved
; other APIs (if any)
; Contains Installation Check of DOSLFN (maybe moved to Int2F)
pushf
cmp ax,REQfunc ;Installationscheck?
jne I21cont
cmp dx,REQcode
jne I21cont
mov ax,ANScode
mov dx,cs
popf
iret
endp
if USEWIN or USECP
proc NewInt2F far
;D: Because of dummies and for easier usage, DOSLFN (version 0.32j+)
; traps Int2F for following actions:
; * Disables itself when Win9x starts, giving a hint message
; * Loads an API translating VxD "LFNXLAT.386" when Win3x starts
; * giving a warning message pointing to missing API translation
; when Win3x or Win2x start in Standard Mode (=PM286)
; * Loads the appropriate OEM<->Unicode conversion table when
; NLSFUNC changes the code page
; * Future Installation Check of DOSLFN may reside here
pushf
if USEWIN
cmp ax,1605h ;Windows Enhanced Mode Init Broadcast
jz @@handle
cmp ax,1606h ;Exit Broadcast
jz @@handle
endif ;USEWIN
if USECP
cmp ax,1401h ;NLSFUNC.COM CallOut BX=Codeseite
jz @@handle
; cmp ax,0AD01h ;DISPLAY.SYS API Aufruf BX=Codeseite
; jz @@handle
endif ;USECP
@@e: popf
JMPF ;= db 0EAh
OldInt2F dd ?
@@handle:
popf
pushf
call [cs:OldInt2F]
call HandleWindowsOrCP
iret
endp
endif ;USEWIN or USECP
proc I21cont far
test [cs:ctrl0],CTRL_Main
jz @@isrend ;do nothing if main switch is OFF
xchg ah,al ;AL comparings are shorter
cmp al,71h ;LFN functions?
je @@yes_lfn
cmp al,3Ah ;SFN rmdir?
je @@yes_sfn ;remove LFN entry, prepare tunnel!
cmp al,41h ;SFN unlink?
je @@yes_sfn ;remove LFN entry, prepare tunnel!
cmp al,56h ;SFN move? (dst=ES:DI)
je @@yes_sfn ;remove LFN, prepare&apply tunnel!
cmp al,39h ;SFN mkdir?
je @@yes_sfn ;apply tunnel!
cmp al,3Ch ;SFN creat?
je @@yes_sfn ;apply tunnel IF file doesn't exist
cmp al,5Bh ;SFN create new?
je @@yes_sfn ;apply tunnel!
cmp ax,006Ch ;SFN extended open/create?
je @@yes_sfn ;apply tunnel IF..., take DS:SI!
if USEOLDDOS
cmp al,4Eh ;SFN FindFirst?
xchg ah,al
je @@filter0F ;filter out volume labels!
cmp ah,4Fh ;SFN FindNext?
je @@filter0F ;filter out volume labels too!
cmp ah,11h ;FCB FindFirst?
je @@FCB_11 ;filter out volume labels!
cmp ah,12h ;FCB FindNext?
je @@FCB_12 ;filter out volume labels too!
else
xchg ah,al
endif
@@isrend: popf
JMPF ;jmp far (db 0EAh)
OldInt21 dd ? ;only this kind of jump makes no trouble
if USEOLDDOS
@@filter0F: ;bei FindFirst/FindNext Rckgaben mit Attribut 0Fh auswerfen
popf
call sfn_find
@@cfiret:
push bp
mov bp,sp
pushf
shr [by bp+6],1 ;shift out old value of carry
popf
rcl [by bp+6],1 ;rotate in new value
pop bp
iret
@@FCB_11:
popf
call sfn_find_FCB
mov ah,11h ;set back (may be altered to 12h)
iret
@@FCB_12:
popf
call sfn_find_FCB
iret
endif
@@yes_lfn:
INT3
@@yes_sfn:
popf ;save two bytes of stack needed
xchg ah,al
call IncInDosFlag
sti ;reentrancy should be detected by caller
push fs ds es ;bp+14h .. bp+10h
pusha ;ax=bp+0Eh, cx..dx..bx..sp..bp..si..di=BP+0
mov bp,cs
mov ds,bp
mov es,bp
mov bp,sp
push eax ;High-Teile retten fr PKZIP
mov al,[ctrl0]
mov [ctrl],al ;access needs less bytes
pop ax
push edx
push [throw_sp] ;needed due to SHSUCDX causing reentrancy
cld
mov [throw_sp],sp ;prepare and beautiful error exit, less "jc"
mov [throw_fi],ofs _fcb_retu ;standard finalizer
mov fs,[Client_DS] ;h„ufig ben”tigt
cmp ah,71h
je @@yes_long
mov al,PF_Tunnel_Restore
cmp ah,3Ah
je @@rm
cmp ah,41h
je @@rm
cmp ah,56h
jne @@cr
mov al,PF_Tunnel_Save or PF_Tunnel_Restore
;jmp @@cr
db 0a9h ;test ax,nnnn
@@rm: mov al,PF_Tunnel_Save
@@cr: mov [PFlags],al
call sfn_process ;all writing SFN functions
jmp __no_func
@@yes_long:
if USECP
call CheckLoadCP
endif
mov [PFlags],PF_LFN_Input
mov [FuncNum],al
mov di,ofs verteiler
call case
jc @@chain
inc [counter_i2171]
call [wo di]
__no_func:
jnc @@no_ax
mov [Client_AX],ax
@@no_ax:
ife USEOLDDOS
pushf
shr [by LOW Client_Flags],1 ;CY ausschieben
popf
rcl [by LOW Client_Flags],1 ;CY einschieben
endif
pop [throw_sp]
pop edx
push ax
pop eax
popa
pop es ds fs
call DecInDosFlag
if USEOLDDOS
jmp @@cfiret
else
iret
endif
chain:
mov [DPB_Drive],-1
mov sp,[throw_sp]
@@chain:
;unrecognised function, pass it along to the OS (for Udo's DR-DOS
;42h 64-bit seek function)
mov ax,[Client_Flags]
if USEOLDDOS
or al,1 ; explicitly set carry to assume failure
mov [Client_Flags],ax
endif
mov [oflags],ax
pop [throw_sp]
pop edx
push ax
pop eax
popa
pop es ds fs
call DecInDosFlag
push 1234h
oflags = wo $-2
jmp @@isrend
endp
if USECD
proc Check_CDFS_Throw
call Check_CDFS
jnz SetErr5
ret
endp
endif
;THROW-Geschichten...
SetErr18:
mov al,18
db 0B9h ;mov cx,nnnn
SetErr5:
mov al,5
db 0B9h ;mov cx,nnnn
SetErr3:
mov al,3
db 0B9h ;mov cx,nnnn
SetErr2:
mov al,2
SetError:
;DOS-Fehler (fr Int21 AH=59h) setzen (fr momentanes PSP)
;Tats„chlich ben”tigt Win95 COMMAND.COM diese Funktion!
mov ah,0 ;alles "kleine" Fehler
push ax
mov di,ofs ErrInfo
mov dx,di
stosw
mov cx,(SIZE ErrInfo)/2 -2
xor ax,ax
rep stosw ;dazwischen lauter Nullen
mov ah,62h
call CallOld ;PSP ermitteln
xchg bx,ax ;als letztes
stosw
mov ax,5D0Ah
call CallOld ;Fehler setzen
pop ax
stc
proc Throw
ifdef PROFILE
call throw_profile
endif
mov sp,8086
throw_sp = wo $-2
call [throw_fi]
jmp __no_func
endp
;***************
;** Profiling **
;***************
;N: use the Pentium time-stamp counter to provide timing information. Currently
; setup to allow a profile to be enabled and disabled, but not vice versa.
; Multiple profiles can be used, but there is no "child" information.
ifdef PROFILE
profile_ebx dd 0
struc Tprofile
count dd 0 ;number of times called
ticks dd 0 ;tick count
tick_h dw 0 ;high word of tick count
off db 0 ;enabled
throw db 0 ;throw should disable
start dd 0 ;start tick
desc db 16 dup (0) ;description
ends
profile_data = $
profile_read Tprofile <,,,,,,'read sector'>
profile_write Tprofile <,,,,,,'write sector'>
profile_exist Tprofile <,,,1,1,,'exist'>
profile_install Tprofile <,,,,,,'install'>
profile_open Tprofile <,,,,,,'open'>
profile_attr Tprofile <,,,,,,'attr'>
;profile_ Tprofile <,,,,,,''>
ifdef PROFILECACHE
profile_putc Tprofile <,,,,,,'put to cache'>
profile_termc Tprofile <,,,,,,'terminate cache'>
profile_findc Tprofile <,,,,,,'find in cache'>
endif
profile_stop = $
macro start_profile prof
push ofs profile_&prof
call _start_profile
macro end_profile
push ofs profile_&prof
call _end_profile
endm
endm
macro enable_profile prof
mov [(Tprofile profile_&prof).off],0
macro disable_profile
mov [(Tprofile profile_&prof).off],1
endm
endm
proc _start_profile
mov [profile_ebx],ebx
pop ebx ;return address (LO) and profile parameter (HI)
push bx
pushf
rol ebx,16
cmp [(Tprofile bx).off],0 ;disabled?
jne @@e
push eax edx
db 0fh,31h ;rdtsc
mov [(Tprofile bx).start],eax
inc [(Tprofile bx).count]
pop edx eax
@@e: popf
mov ebx,[profile_ebx]
ret
endp
proc _end_profile
mov [profile_ebx],ebx
pop ebx
push bx
pushf
rol ebx,16
cmp [(Tprofile cs:bx).off],0 ;disabled?
jne @@e
push eax edx
db 0fh,31h ;rdtsc
sub eax,[(Tprofile bx).start] ;assume individual profiles are
add [(Tprofile bx).ticks],eax ;dword but overall
adc [(Tprofile bx).tick_h],0 ;is 48-bit
and [(Tprofile bx).start],0 ;reset for throw
pop edx eax
@@e: popf
mov ebx,[profile_ebx]
ret
endp
proc throw_profile
mov bx,ofs profile_data
@@l: cmp [(Tprofile bx).start],0
je @@n
push bx
call _end_profile
mov cl,[(Tprofile bx).throw]
mov [(Tprofile bx).off],cl
@@n: add bx,size Tprofile
cmp bx,ofs profile_stop
jne @@l
stc
ret
endp
else
macro start_profile
endm
macro end_profile
endm
macro enable_profile
endm
macro disable_profile
endm
endif ;PROFILE
;***************************
;** Legacy API twiddeling **
;***************************
;N: Except MS-DOS7+, other DOS versions generate some garbage on
; FindFirst/Next: they list out LFNs as volume labels.
; Well-behaved file managers ignore these entries, but some other
; like COMMAND.COM's built-in DIR doesn't.
; Therefore, it's up to DOSLFN to wipe out such returns, proceeding
; with next DirEnt.
; And while we twiddle with DirEnts, this is a good chance to
; remove the ugly ReadOnly bits out of CD DirEnts, but is not yet done.
if USEOLDDOS
proc noentry_sfn_find
;D: DirEnts with attribute 0Fh (LFN designator) must be wiped out.
; (MS-DOS 7+ and Windows NT [DOS 5] do this;
; this is necessary for all other DOS versions)
;I: registers unchanged, _without_ BP stack frame!
;F: INT21/4E&4F alter AX even if successful! 09/01, claude.caillet@free.fr
@@rept: