File: /~heha/hs/dos/doslfn/

Ÿ For english text see middle of file
Ÿ For changes.log see end of file

³DOSLFN - Treiber fr lange Dateinamen unter nacktem DOS³

Sicher h„tte ich dieses Programm seit etwa 1996 gebraucht, aber damals dachte
ich, irgendjemand wird's ja wohl schreiben. Also wartete ich, und wartete...
und fand erst 2000 ein halbwegs geeignetes Programm LFNDOS.EXE, geschrieben

Offenbar wurde jenes Programm fr die Win9x COMMAND.COM geschrieben,
denn mit dem Volkov Commander (VC) geht es nicht (man kann nicht in
Verzeichnisse mit langem Namen hineinwechseln), und es ist schrecklich
Auáerdem will der Treiber gleich mal 64 KB Speicher haben.

Beim Anlegen von Verzeichnissen wird alles grundlos in Groábuchstaben
umgewandelt, man hat keine M”glichkeit, den Schlangen zu entkommen
(NameNumericTail=0), und, der Hammer, beim Umlaut-Test fiel das Programm
komplett durch! Unicode scheint immer noch ein Fremdwort zu sein.
Ich fand schlieálich auch noch andere solche Programme, mit „hnlichen
Effekten, so sie denn berhaupt liefen.

So muáte ich also (mal wieder!) feststellen, dass Warten nicht lohnt,
und dass offenbar der Rest der Welt unf„hig ist, richtig zu programmieren;-)
Nebenbei, den Quelltext zu LFNDOS zu finden ist mit Netscape unm”glich;
nur mit Internet Explorer kommt man an die Seite mit dem Quelltext heran.
Ergo: selbst das an sich kinderleichte HTML kann nicht jeder.

³Der eigene Versuch:
Natrlich schreibt man ein solches Programm in Assembler und nur in Assembler.
Und da ich Borland Turbo Assembler habe, habe ich diesen genommen, und
verwende den IDEAL-Modus, um in den Genuss lokaler Strukturelemente
zu kommen und dem Rest der Welt (der offenbar nur MASM verwendet) ein kleines
Schnippchen zu schlagen.

Ich wollte natrlich in allen kritikwrdigen Punkten deutlich besser sein,
und auch noch CDFS (genauer: Joliet) untersttzen.
Dann w„re es ja auch "richtig" verwendbar.

Hauptaugenmerk liegt in der gnstigen Verwendbarkeit in Verbindung mit
dem Volkov Commander, den ich fr den besten Norton-Commander-Klon halte,
auch wenn da noch ein paar Sachen wirklich fehlen. Nachdem in der krzlich
erschienenen neuesten Version endlich Alt+F7 funktioniert, vermisse ich
nun noch einen NC-Link, m”glichst auch noch via ECP (ca. 500KB/s).

W„hrend der Programmierung nun stellte sich heraus, dass es doch nicht
ganz so einfach ist, die Funktionalit„ten so abzubilden, wie es Windows tut.
Also nun doch kein Wunder, dass man sich da so schwer tat. Von den einst
anvisierten 4KB resident bin ich schon wieder weit entfernt, und es
funktioniert beileibe noch vieles nicht. Beispielsweise ist die Funktion
von "cd .." klar, von "cd ..." merkwrdig und neuartig, aber nett,
und "cd ...." konsequent. Oder aber dass die COMMAND.COM ausgiebig von
der DOS-Funktion "Erweiterte Fehler-Information holen" Gebrauch macht,
um letztlich doch nur den Fehlerkode zu verwenden, erfordert andererseits
den Gebrauch der (l„stigen) Umkehrfunktion zum Setzen des DOS-Fehlerkodes.

Die Implementation des Joliet-Zugriffs fhrte jedoch zur totalen Ausuferung.
Nicht nur, dass ich mittels Hilfsprogrammen gezwungen war, aus der drftigen
Information zu Joliet einen brauchbaren Zugriff hinzubekommen, musste
ein Problem gel”st werden, worum, wie sich sp„ter herausstellte, sich sogar
Windows 9x und Windows NT auf „hnlichen, aber leicht anderen Wegen,
herumdrcken. Es geht um die Verbindung zweier an sich selbst„ndiger
Verzeichnis-B„ume, ISO und Joliet. Windows verwendet nur den Joliet-Baum,
falls vorhanden, und "erfindet" neue, andere kurze DOS-Namen, als die im
ISO-Baum enthaltenen. Stellt sich die Frage nach "Querverbindungen".

Das Programm WinOnCD speichert freundlicherweise eine "link table" auf die
CD, die genau diesen Brckenschlag m”glich macht, aber andere Brennprogramme
tun dies nicht. Das nachtr„gliche Erstellen einer solchen Tabelle ist
aufw„ndig (will sagen: je nach Komplexit„t der CD langsam) und im brigen
nicht immer m”glich, bspw. bei leeren Verzeichnissen oder unterschiedlichen
Dateien zwischen ISO und Joliet (noch nicht beobachtet, aber m”glich).
Drei L”sungswege standen deshalb offen, in Anbetracht der schwierigen Lage,
und dass man unter nacktem DOS nicht gerade als Diskjockey arbeiten wird:

* Dynamisches Anlegen der Link-Tabelle (noch grӇeres TSR)
* Anlegen der Tabelle beim CD-Zugriff (u.U. reaktionstr„ges TSR)
* Bereitstellung der Tabelle durch ein externes Programm auf Festplatte

Wenn eine WinOnCD-gebrannte CD gefunden wird, entfallen diese Probleme.

Entwickelt wurde unter NT4, getestet mit SoftICE. Ist zwar etwas hart,
wegen der DOS-Box gleich den ganzen Rechner samt Netzkarte einzufrieren,
aber SoftICE ist eben auch kaum aus der Ruhe zu bringen (es sei denn, man
schieát damit die DOS-Box ab, dann kann man auch gleich das NT booten).

Zuerst wurden die Lesezugriffe implementiert. Noch war des TSR sch”n klein,
mit reichlich 3 KB resident. Dabei stellte sich heraus, dass der VC wie
auch bei den anderen LFN-Treibern sehr langsam wurde. Ursache sind viele
LFN<->SFN-Konvertierungen, die der VC ausl”st, und dass offenbar das DOS
nicht cachen will, wenn man (auch nur lesend) auf Diskette oder Platte
zugreift. Bei jeder Pfadkomponente musste das entsprechende Verzeichnis
durchsucht werden, und da l„ppert sich einiges zusammen. Die Verwendung
"undokumentierter" Felder im DTA bei FindFirst fiel aus, weil's dann nicht
mehr unter NT4 funktionieren wrde, und wohl auch bei anderen DOS-Exoten
wie OS/2-DOS oder Caldera. (Linux DOSEMU wird wohl nicht untersttzt.)
Das Problem gab's schon mal frher, und die L”sung nannte MS FASTOPEN.
Das war anfangs ein .SYS-Treiber (?), und sp„ter fest eingebaut. Kurz und
gut, genauso etwas habe ich noch mit eingebaut (h„lt die Verbindung
kurzer Name, langer Name und Startcluster), und der Geschwindigkeits-
vorteil ist so enorm, dass ich da das halbe Kilobyte extra gerne spendiere.

Wegen der von vornherein eingebauten FAT32-Untersttzung und wegen
vieler kleiner weiterer Annehmlichkeiten beim Programmieren habe ich
das Programm auf Mindestanspruch 386er festgelegt. So kann ich mit
32-bit-Registern hantieren, und das Segment-Register FS als "Quell-Segment"
verwenden. Geschwindigkeit und KodegrӇe profitieren davon.
Ansonsten arbeitet das Programm im Speichermodell TINY (CS=DS!=SS), wrde
jedoch im Speichermodell SMALL genauso effektiv arbeiten. Andere Modelle
w„ren hier schlichtweg Platzverschwendung.

Die Art der Adressierung von gepushten "Client-Registern" sollte jedem
sofort bekannt vorkommen, der schon mal VxDs programmiert hat: ist
eine wirklich sch”ne Idee, und gar nicht so schwer.

Selbstverst„ndlich ist dieses Programm deinstallierbar (wie auch die
"Konkurrenz" LFNDOS), das ist ja heutzutage Standard, auáer bei Microsoft.
Zwei Sprachen bietet das Programm ber eine Art String-Ressource.
Meldet das DOS den L„nderkode Deutschland, ™sterreich oder Schweiz, wird
automatisch Deutsch ausgegeben, sonst englisch. Bei Nichtgefallen dieser
Automatik gibt es einen Kommandozeilen-Schalter.

Bei der Implementierung des Schreibzugriffes kam ich jedoch vom Hundertsten
ins Tausendste: man muss das Verzeichnis einen oder sogar mehrere Cluster
verl„ngern, wenn der LFN-Eintrag nicht hineinpasst. (Ob die Konkurrenz
diesen Fall berhaupt beachtet, habe ich noch gar nicht getestet.)
DOS hat intern solche Routinen, die sowohl fr Dateien als auch fr
Verzeichnisse gut sind, aber leider fehlen dazu die dokumentierten Einsprnge.
Handarbeit ist angesagt, und da man soviel wie m”glich Arbeit auf
andere(n Kode) abw„lzen sollte, l”se ich das Problem ber eine tempor„re
kreuzverbundene Datei im Wurzelverzeichnis. Zwei Pferdefáe: da muss
im Wurzelverzeichnis noch ein Eintrag Platz sein - aber das bis zum Rand
zu fllen ist sowieso eine tickende Zeitbombe. Und falls diese Datei
irrtmlicherweise liegenbleibt, passiert der GAU, wenn man sie l”scht.
(Also: NICHT l”schen, stattdessen SCANDISK oder DISKEDIT starten!)

³Getestet in folgenden Situationen:
* MS Windows NT 4 DOS-Box, FAT12- und FAT16-Laufwerk
  (aber man sollte doch besser zum NTLFN-Paket greifen, ist auch Freeware)
* MS-DOS 6.2
* MS-DOS 7.10, FAT32
* DR-DOS 7, magneto-optisches Laufwerk

jeweils mit Windows 9x COMMAND.COM (zum Start h#s GiveVer benutzen!) und
Volkov Commander 4.99.08, Schreibzugriffe sicherheitshalber nur auf Disketten

³Erkl„rung einiger Schalter:
~ Tilde: Normalerweise verh„lt sich Windows9x wie folgt:

  * "Kurze" Dateinamen (d.h. 8.3-Form und keine unerlaubten Zeichen) komplett
    in Groábuchstaben und ohne Umlaut bekommen berhaupt keinen LFN-Eintrag
  * "Kurze" Dateinamen mit Kleinbuchstaben oder Umlauten erhalten einen
    LFN-Eintrag; der (normale) FCB-Name bekommt keine Schlange (Tilde)
  * Alles andere bekommt einen eindeutigen FCB-Namen mit ~1, ~2 usw.,
    wobei als Extensions-Trenner der LETZTE Punkt gilt. Nur im LFN erlaubte
    Zeichen werden durch '_' ersetzt, mit der Ausnahme '.' und Leerzeichen,
    diese fallen ganz weg. NT setzt hinter die Tilde einen zweistelligen
    Buchstaben-Zahlen-Code, DOSLFN und 9x arbeiten mit fortlaufenden Zahlen.

  Mit dem Registry-Schalter NameNumericTail=0 l„sst sich (nicht unter NT)
  die Tilde-Einfgung verhindern, falls der kurze Name noch eindeutig
  bleibt. Vorteil: man kann die Datei mit ihrem langen Namen auch noch
  unter DOS (ohne LFN-Treiber), nach einem (fatalen) Angriff alter
  Direktzugriffs-Software oder bei einem versauten System ansprechen,
  weil DOS intern auf 8.3 krzt.
  Nachteil: Es ist nicht nachtr„glich m”glich, eine echte 8.3-Datei neu
  zu erstellen, wenn der Name passt, oder schlimmer noch, der Inhalt wird
  (ungewollt) gel”scht, im Glauben, unter LFN adressieren zwei verschiedene
  Dateinamen zwei verschiedene Dateien.
  Also: ~- entspricht NameNumericTail=0 und ~+ dem Standard.

t Tunneleffekt: Programme, speziell Text-Editoren fr DOS, die keine
  langen Dateinamen untersttzen, speichern, indem sie

  * eine Datei *.bak l”schen
  * die Datei *.txt in *.bak umbenennen
  * die Datei *.txt neu erstellen.

  Damit wrde der lange Dateiname der *.txt verloren gehen.
  Der "Tunneleffekt" sorgt dafr, dass bei der Umbenennung der dem kurzen
  Namen zugeordnete lange Name gespeichert wird und beim Wieder-Erzeugen
  der kurzen Datei der lange Name mit etwas "Zauberei" wieder herangeheftet
  wird. Die Speicherzeit ist lt. Dokumentation auf 15 s begrenzt, eigene
  Tests konnten bei 9x keinerlei "Ged„chtnisschwund" nachweisen.
  Es wird getunnelt von

  * l”schen -> erstellen
  * umbenennen -> erstellen
  * l”schen -> umbenennen -> erstellen

  Windows9x hat mehrere gleichzeitig arbeitende Speicher, die auch
  kompliziertere "Datei-Man”ver" und auch Verzeichnisse berwachen;
  aus Aufwandsgrnden wird es in DOSLFN bei maximal einem Tunnel bleiben.

c (CDROM-Untersttzung): Schaltet die CDROM-Untersttzung ein.
  Damit ben”tigt DOSLFN erheblich mehr RAM fr den Code zur
  CDROM-Initialisierung und -Zugriff sowie als Datenpuffer fr eine
  .JLT-Datei und zwei Sektorenpuffer (je 2 KB).
  Je nach Anwesenheit von MSCDEX beim Laden ist die Vorgabe Ein oder Aus.
  Sie mssen diesen Schalter auf c+ setzen, wenn Sie DOSLFN _vor_ MSCDEX
  laden und lange CD-Dateinamen haben wollen!

i (InDOS-Flag-Benutzung): Zur Untersttzung von speicherresidenten Programmen
  (TSRs), welche ihrerseits LFNs verwenden oder auch nur Dateien l”schen
  [DOSLFN versucht, LFN-Verzeichniseintr„ge zu l”schen] oder anlegen
  [DOSLFN versucht, per Tunneleffekt einen LFN hinzuzusetzen],
  schaltet DOSLFN das InDOS-Flag w„hrend seiner "Arbeitszeit" ein,
  um reentrante Aufrufe zu verhindern.
  Leider steigt so der Wert von InDOS auf 2, wenn DOSLFN den OldInt21 ruft,
  was problematisch sein k”nnte, aber ich wsste keinen besseren
  (kugelsicheren) Weg, wie DOSLFN InDOS auf <>0 halten und DOS aufrufen soll.
  Falls Probleme auftauchen, bitte diesen Schalter ausschalten.

z Standardm„áig arbeitet DOSLFN mit der aktuellen Codeseite, um
  die Umwandlung OEM<->Unicode durchzufhren; das gengt auch fr die
  Verarbeitung der deutschen Umlaute. Man kann aber auch eine andere
  Codeseite zur Konvertierung laden, so z.B. cp850uni.tbl fr die (bl”derweise)
  blichere Codeseite 850, die einfach nur ein paar mehr akzentuierte
  Buchstaben hat (und sich deshalb besser mit dem Windows-Zeichensatz deckt),
  oder aber kyrillische Tabellen.
  Problem unter DOS: Fr die Anzeige der langen Dateinamen wird die momentan
  geladene Codeseite herangezogen, d.h. Umlaute, die in kyrillisch nicht
  enthalten sind, werden als '_' ausgegeben; rein kyrillische Namen unter
  437 sehen so aus: '_____ ____ ___.___'
  Problem unter Windows9x: Windows hat auf Anwender-Ebene praktisch kein
  Unicode, und auch der Explorer zeigt nur Zeichensalat an. SCANDISK
  findet solche LFN-Eintr„ge unpassend und will sie l”schen.
  Problem unter WindowsNT: Hier st”rt nur SCANDISK(?)
  Deshalb: Codeseite konstant lassen und in Deckung mit Windows bringen!
  DOSLFN hat seit 01/03 volle DBCS-Untersttzung (chinesisch, japanisch u.a.).
  Neunzehn šbersetzungs-Tabellen sind DOSLFN beigefgt.
  Beim Wechsel der Codeseite l„dt DOSLFN "im Hintergrund"
  die richtige Tabelle nach.

l Sprache setzen: sollte nicht weiter erkl„rungsbedrftig sein...
  Ist DOSLFN resident, merkt es sich die Einstellung bis zum Herauswurf.

m Heap-Gr”áe setzen; dieser wird fr FindFirst/FindNext, die CD-Link-Tabelle
  und sp„ter fr Sektor-Puffer ben”tigt.

TZ Zeitzonen-Variable: Unter UNIX und NT gang und g„be, aber unter DOS und 95
  scheint sie niemand zu kennen, obwohl viele (C-)Programme diese ebenfalls
  implizit brauchen! Der Aufbau ist schlicht, dass nach 3 x-beliebigen
  Buchstaben, die den Namen der Zeitzone angeben, eine vorzeichenbehaftete
  Gleitkommazahl folgt, die die Verschiebung in Stunden zur UTC (oder GMT?)
  angibt. Danach k”nnen drei weitere Buchstaben zur Festlegung der Sommerzeit-
  Regel folgen. Da diese sowieso sich st„ndig „ndert und in der Standard-
  Implementierung mit regelm„áiger Bosheit immer wieder nur fr Amerika
  gemacht wird (kotz!), ist von dieser Angabe abzuraten, sodass im Sommer
  "TZ=MET-2" und im Winter "TZ=MET-1" (in Mitteleuropa) angegeben werden
  [Genau genommen arbeitet die Angabe yyy=DST (daylight savings time
  =Sommerzeit) schlieálich mit der Angabe xxx zusammen, um festzustellen,
  ob gerade Sommerzeit ist oder nicht. Ansonsten ist xxx belanglos.
  Nichtsdestotrotz bleibt uneindeutig, ob 2.30 Uhr in der bewussten Herbstnacht
  in Sommerzeit oder Winterzeit gemeint ist, sodass man diese Angabe eigentlich
  in einem solchen Fall immer dazuschreiben msste, etwa 2.30 Uhr MESZ!
  Auf der Festplatte jedenfalls steht diese Angabe nicht; auch die Zeitzone
  des Ortes des Speicherns der Datei fehlt.] DOSLFN verwendet TZ (noch) nicht.

³Funktioniert nicht oder noch nicht:
* Uhrzeitangaben in Windows-NT-Zeit (100-ns-Schritte seit 1.1.1601),
  die FAT-Dateizeiten werden jedoch in eine stetig wachsende Zahl konvertiert.
  Praktisch jedes Programm verwendet diese NT-Zeit nicht, und l„sst sie
  sp„ter in die DOS-Zeit umrechnen.
  Fhrt zu sichtbarem Fehler, wenn NTFSDOS nachgeladen wird.
* Funktion auf geJOINten Laufwerken (geSUBSTet funktioniert seit 12/02)
* Funktion auf ASSIGNeten Laufwerken (ungetestet)
* Unter Windows 3.11 mit eingeschaltetem 32-Bit-Dateizugriff arbeitet
  DOSLFN auf Festplatte im Rckfall-Modus (ohne LFN), weil Windows (VCACHE.386)
  den direkten Zugriff per Int25/26 sowie Int21/AH=32 verweigert.
  Schalten Sie den 32-Bit-Dateizugriff aus.
  (Der 32-Bit-Laufwerkszugriff kann eingeschaltet bleiben.)
Noch schlimmer:
* Erweitertes L”schen mit Platzhalterzeichen auf Nicht-FAT-Laufwerken
* Umbenennen mit (eigentlich) gleichem kurzen Dateinamen 
  -> da entsteht leider ein anderer kurzer Name

Untersttzt die Int21/AH=71-Schnittstelle gem„á Ralf-Brown-Liste, auáer
folgende Punkte:
* Funktionen mit SUBST, AL=AAh		("SUBST-Abfrage" ist OK)
* Datei-Erstellung vom Server, AL=A9h
* Handle-Information holen, AL=A6h
* Laufwerk rcksetzen, AL=0Dh

Unl”sbares(?) Kompatibilit„tsproblem:
Bei Int21/AX=7141h (lfn_unlink) mit Platzhalterzeichen kann das L”schen
auch teilweise versagen.
In jedem Fall werden alle l”schbaren Dateien gel”scht.
Win95 (1. Ausgabe) meldet Fehler, wenn ALLE Dateien nicht l”schbar waren
Win98 (1. Ausgabe) meldet Fehler, wenn EINE Datei nicht l”schbar war.

MK_TABLE konvertiert eine Unicode-Tabelle in ASCII-Form, wie man sie
bei herunterladen kann, in die Volkov-Commander-Form um.

MKLINK (Name kann sich in Zukunft „ndern) generiert eine sog.
"Joliet-Verzeichnis-Verbindungs-Tabelle" (Joliet Directory Link Table)
fr jede gefundene Joliet-CD.
Dazu durchsucht es s„mtliche Laufwerke, und erstellt diese Tabelle nach
einem mittelm„áig komplexen, rekursiven Verfahren, ber das ich bei der
Entwicklung lange gegrbelt habe. Als Dateinamen w„hlt es die Datentr„ger-
Bezeichnung (Volume Label) mit der Endung .JLT.
So kann man seine CD-Sammlung nacheinander einlesen und Tabellen generieren
Die so gewonnenen kleinen .JLT-Dateien werden bei Bedarf von
DOSLFN eingelesen, um auch bei nicht mit WinOnCD erstellten Medien
lange Dateinamen zu nutzen.

Auf der Kommandozeile kann man die Laufwerkssuche einschr„nken (besonders
ntzlich bei CD-Wechsellaufwerken), und es gibt folgende Schalter:
 /b	* "Stapelbetrieb" zum interaktiven Einlesen einer ganzen CD-Sammlung
 /f	* CD auch dann einlesen, wenn Zieldatei bereits existiert
	* CD auch dann einlesen, wenn sie eine CeQuadrat-WinOnCD-Tabelle hat
 /v	* Einlese-Operation mehrzeilig (als Tabelle) anzeigen (empfehlenswert)
 /v-	* Einlese-Operation nicht anzeigen
 /c	* Vergleich der Reihenfolge im ISO- und Joliet-Baum
 /h	* Hilfe (in englisch) anzeigen
Die Angabe von zu durchsuchenden Laufwerken erfolgt durch einzelnstehende



| DOSLFN - A Real-mode driver for Long File Names missed in DOS |
|	   With full Unicode and DBCS support!			|


Of course I needed such a program since 1996, but in mind that such a tool
is useful for everybody, I thought someone would write it. And so I was
idle and waiting, and last year I found some tools, e.g. LFNDOS.EXE,
written 1998, not so old as expected.

This program was written for functionality with Win9x COMMAND.COM,
and doesn't work with my favourite file manager, Volkov Commander.
(You cannot go into directories with a long name.) And that TSR is so
S_L_O_W, and, on the other hand, consumes 64 KB of memory, too much!
This program cannot create files and directories with lower case letters
(Why??), there is no way to go away from snakes (tildes, according to
the registry key NameNumericTail=0), and, last not least, it doesn't
supports umlauts correctly.


Of course, such a program must be written in assembly language.
With the nice Turbo Assembler I used the not-so-commonly used IDEAL mode
to enable local structure components, among other advantages (e.g. speed).
This program is dedicated to not to have the bugs found in the ones as
stated above. And I would support long names on CD (Joliet), very useful
for restoring backups under plain DOS. A reasonable good tool for this is
ODI's LFN tools, but that's not a driver.

Important at least to me is usefulness in conjunction with Volkov Commander,
the best Norton Commander clone I think. Among it supports long filenames,
it is much smaller and faster than the original, and has some nice features.
(Unfortunately, there are some disadvantages, like missing hotkeys for
 directory sorting, or a computer link feature.)

While programming I must state that's not so easy to write a bullet-proof
driver with at most full functionality as I'm thougt at a glance.
No wonder that I found such one not earlier - and so hard to program.

At first, an objective was to consume as least as possible memory, around
4 KB. Now, I'm far, far away from this goal, and I'm happy with less than
12 KB. Compared with 64K this is good enough.

Another hurdle was understanding Windows9x long filename semantics. What
"cd .." should be, is commonly known, "cd ..." is new with 9x and changes
two directory levels up, "cd ...." three and so forth. (I was familiar with
the fact that the directory entries "." and ".." are not directly used by
DOS.) Or the way pattern matching with long filenames is done: some is
known from UNIX (like *1 matches all files ending with "1"), some is Win32
specific, like "*." that matches all files WITHOUT an extension.
And, an extension is defined as the part after the LAST dot not in a
chain of first dots. Or that's possible to create files with leading
spaces and/or dots, but trailing spaces and/or dots were truncated.
With "*." in mind, this is necessary, because there is no way to find files
with a dot at end. Therefore, filenames with spaces and dots alone are not
allowed, with the virtual exception of useless "." and ".." directory entries.
COMMAND.COM uses the DOS function Get Extended Error Information, and so I
had to use the unhandy complementary function to set this error code, to
put COMMAND.COM to work correctly.


~ (tilde usage): By default, Win9x adds a "~1" designator to the alias of
  any long file name, "~2" if there is a clash, and so on.
  Therefore, these long file names in plain DOS cannot address the alias.
  This behaviour seems to be built in due to erraneous behaviour of
  some tested software. (I guess, it was some old Microsoft software.)

  For normal DOS & Win users, this is impractical. Plain DOS is able to
  "support" long names by automatically truncating them to 8.3 form.
  Unless name contains spaces or multiple dots, the same long name can
  address a file both with and without available LFNs. Users can maintain
  compatibility for some program configuration independently whether running
  {Win9x or DOSLFN} or not.

  You can switch off tilde usage in Win9x by adding following binary key:
  Then you have to restart Windows. (Dont't forget to hold down the "shift"
  key when you confirm selecting "restart"; it is not necessary to reboot.)
  You may also refer the WWW with keyword "NameNumericTail".

t (tunnel effect): This feature, built in Win9x file system, help long
  file names to survive when modifying files with a conventional (8.3)
  text editor or compareable tool. They replace files as follows:
  * delete a file <alias>.bak (if any)
  * rename the original file <alias>.txt to <alias>.bak
  * create a new file <alias>.txt

  With this sequence, the long file name will be lost forever.
  But with "tunnel effect" active, Win9x and DOSLFN will watch for
  delete-rename-create (DRC) sequences and "automagically" attach previously
  deleted long file name entries to newly created names, if the <alias>
  is the same.
  The DRC sequence above may also be truncated to DR, DC, RR, or RC,
  and works for directories too.
  As documented in MSDN CD, Win9x internal "tunnel info" is kept 15 seconds,
  however, I can't find any obliviousness. Also, tunneling in Win9x works
  in both "directions", it remembers the alias if an LFN aware program
  does the same procedure. Therefore, you cannot get rid of "~" in "PROGRA~1"
  if you just rename "Program Files" to "Programs" and back.
  (You can restart Windows between two renamings to get desired effect.)

  Furthermore, as required in a multi-tasked OS, Win9x has more than one
  "tunnel info", allowing two or more processes (Win16 or DOS programs)
  make such DRC sequences at the same time or interleaved in one process.
  For simplicity, DOSLFN will only support one "tunnel info".

c (Checksum link): You should let this switch ON. With OFF, DOSLFN may
  be able to read a little damaged disk (e.g. with a Disk Editor),
  but it's outside of any specification. DOSLFN doesn't try to repair
  defective links. (Later, it may be possible to give a complete different
  short name for a long name, but SCANDISK finds that incorrect.)

a Because Microsoft hates programmers, they doesn't had added support
  for long names on classic APIs like "open" (AH=3Dh), "creat" (AH=3Ch)
  and so forth. (Of course, support for FindFirst/FindNext isn't possible
  because programs expect max. 12-character file names. Similar GetCurDir,
  where programs expect max. 64 characters.)
  In a future version of DOSLFN, it will be supported (except someone
  replies this is not necessary)
c (CDROM support): Enables CDROM support, i.e. DOSLFN uses much more memory
  to keep code for CDROM initialization, CDROM access, and buffers for
  keeping one .JLT file and (at least) two CDROM sectors
  This switch defaults to the state whether MSCDEX is loaded or not.
  You must include a c+ switch if you load DOSLFN before MSCDEX, and you
  want long file names on CDROM!

i (InDOS flag usage): For supporting TSR programs that use LFNs, they need
  to know whether DOSLFN is still working or not. Even worse, working with
  short file names can lead to data trash if DOSLFN removes unused LFNs
  or adds LFNs by tunneling (see -t switch).
  The odds of InDOS flag usage are that while DOSLFN calls OldInt21,
  the InDOS flag rises to 2. I don't know better bullet-proof solution to
  keep InDOS flag nonzero _and_ call DOS.
  If you get in trouble, you may switch it off. On is the default.

z DOSLFN must convert Unicode to local code page, and this is locale
  dependent. Because DOS (or NLSFUNC) has no such a table built-in,
  this table must be delivered to DOSLFN.
  Nineteen Unicode translation tables, e.g. for 437 (Standard IBM, for
  resetting purpose), 850 (Western Europe), 852 (Eastern Europe), 866
  (cyrillic), and two for Greek are now bundled with DOSLFN.
  A code page can be loaded/changed even while DOSLFN is resident.
  Most European users use umlauts very seldom (due to known problems
  with bad-coded software[*] around the world), therefore, a forgotten
  code table load is not critical. But if you see filenames with
  unexpected underlines, you should load the code table.
  (DOSLFN does simply convert non-convertible unicodes to "_", without
   any notification on now equal file names.)
  Hint: DOSLFN loads the "right" unicode table automatically on startup,
  therefore, you don't need this switch even in east european countries.
  Furthermore, DOSLFN loads a table automatically if you change the code
  page using DOS' nlsfunc, but you may have to reserve extra heap
  (Japanese DOS must include /m18000 if they load DOSLFN while in US mode).

  [*] Often, it is wicked Unix software (e.g. "tar") that kills umlauts.
  Unix is internally more a 7 bit OS rather than 32 bit, and this limitation
  is spreaded into world until recent (brain-dead UTF-7, MIME codings...)

m DOSLFN needs an internal heap for storing data; mostly, for Find Handles.
  The size of this data area defaults to 1000 Bytes, with CDROM to 2000.
  Smaller values reduce the memory consumption of resident DOSLFN.
  This switch cannot be given while DOSLFN is resident; the memory may be
  in use.

l DOSLFN is bilingual. If it detects a locale of Austria, Switzerland,
  or Germany, it defaults to German language, English otherwise.
  To override language defaulting, use "ld" for German or "le" for English.
  e.g. get english help in Austria with "doslfn -le -h" or "doslfn leh"
  (As you see, DOSLFN ignores switch prefixes and spaces.
   A trailing whitespace is only necessary for the z command.)
  While DOSLFN is resident, the language override is permanent.

TZ This environment variable will be used later - to convert FAT time
  stamp to Win32 time format (an Int64 in 100ns steps past 1.1.1601).
  It must match to a scanf() template like "%c%c%c%g", meaning three
  (unused) letters, a float number (not in exponential form), and optional
  trailing letters. The float number expresses distance in hours from
  GMT (Greenwich). A daylight savings time (DST) cannot be used because
  of unknown calculation method for so many countries. If wanted so, DOSLFN
  must have knowledge for all DST rules in the past (and future) for
  given country, to convert file times according to its dates, not to
  current date (most programs seems to have this bug). Using American
  DST rule is not applicable, although most programs do so.
  Therefore, I suggest that users should set the TZ variable, e.g. for
  Central Europe:
	set TZ=MET-1		in winter
	set TZ=MET-2		in summer
  not using any DST info - but they have to change their AUTOEXEC.BAT
  twice a year.

  TZ is not necessary for converting CDFS to Win32 time format
  because dates on it contain information about time zone distance
  (a byte in 15min steps) for the country where the CD is created.
  However, to maintain equal world time, converting CDFS times to
  FAT time (as return value for almost all time functions), both
  TZ and CDFS time zone info must be put together to calculate correct
  FAT (=always local) time - so it's better to step internally through
  Win32 time format.


Action letters must stay at the end of a command line, because command line
parsing ends there.

The default action is to load DOSLFN or to activate and show a short message,
saying that DOSLFN is already loaded and active.

Unloading DOSLFN may fail if there is a TSR hooking Int21 or 2F above DOSLFN.
If so, DOSLFN disables itself, but remains in memory until another
action (like unloading or re-enabling). You have to unload this (or these)
above TSR(s) first. If that's impossible (mostly: Microsoft shit),
you have to "simply reboot your system".


A big trouble to me is safe support for long names on CD. Because I want
to build on top of MSCDEX, I have to make bridges between Joliet and ISO,
and I found, there are no safe bridges! (WinOnCD burns such a Link Table,
it's nice to me, but that isn't a standard.)
Windows 9x and NT "invent" new short file names and don't use the ISO part
of Joliet CDs at all, furthermore, these two systems have different rules.
So, if you put a CD with long file names into a drive and look on it with
an old DOS program, you'll find up to three different short names for a
long name under bare DOS, Windows9x and WindowsNT.
As ODI's LFN tools doesn't require MSCDEX (except for reading sectors),
it has no problem with it, a driver should deliver right short names
for the long ones, because MSCDEX should handle the short ones.

The recent solution uses Link Tables on disk (e.g. hard disk), and a program
that builds the list for each CD. Making this list is time-consuming,
Maybe, a better program doesn't spend so much time, but reading of all
directories IS time-consuming and a bad action for DOSLFN.
DOSLFN would check the CD and load the appropriate table, or the user
has to load the table as with Unicode conversion table.

Another trouble are Write accesses and the consistency of sector buffers:
I want to cache data, but a ShortName API may change disk content;
so I have to discard all caches, at least for this drive, at every
DOS directory write access, even the old FCB ones.
This degrades DOSLFN's performance.
To support as many DOS versions as possible (not only MS), I don't want
to use undocumented internal DOS structures.


* MS Windows NT 4 DOS-Box, FAT12 and FAT16 drives
  (but you should take NTLFN package, also nice open-source Freeware)
* MS-DOS 6.2
* MS-DOS 7.10, FAT32
* DR-DOS 7, with a magneto-optical drive


* true Windows NT time format (but a conversion forth and back is built-in).
  All Programs I've seen don't use this NT time directly, but call DOSLFN
  to convert this NT time to DOS time (e.g. DOS7 COMMAND.COM's DIR command)
  Leads to visible error when NTFSDOS is loaded after DOSLFN
* JOINed drives (but SUBSTed drives work)
* ASSIGNed drives (not tested, because similar to SUBST it should work later)
* Windows 3.11 with enabled 32 bit file access forces DOSLFN to its FallBack
  mode for your hard disk(s) because VCACHE.386 prevents direct disk access
  via Int25/26 and Int21/AH=32. Please disable the "32 bit file access".
  (You can leave the "32 bit disk access" on.)
* Extended Delete sub-function with wildcards on non-FAT drives
* REName with same short file name -> creates a new short file name


* functions around SUBST, AL=AAh	("query subst" is available)
* file creation from server, AL=A9h
* retrieve handle information, AL=A6h
* reset drive, AL=0Dh

HINT FOR DBCS (Chinese, Japanese, Korean, =CJK) USERS:

Simply load DOSLFN as a western user - but DOSLFN consumes much more
memory to hold the larger DBCS<->Unicode table.

When booting from an Win9x/Me Emergency Disk, DOS reports a code page of 932,
936, 949, or 950, but the display font is yet the BIOS' 437.
Furthermore, the DOS internal DBCS Lead Byte table is not yet activated.
Therefore, you see garbage when you list file names containing Chinese
Characters, regardless of using DOSLFN.
After starting PDOS95.BAT, I suppose, the display is switched to a 40x24
full-width (square shaped) Chinese character graphics mode (with half-width
katakana between if you use CP932=Japanese Shift-JIS). The 25. line is for the
Input Method Editor (IME), merely a Romaji/Pinyin input and Kanji/Kanxi
selection line. (Selection is necessary due to the fact that more characters
with different meanings exist for one spelling, especially in Japanese.)
Furthermore, the DOS internal DBCS Lead Byte table is activated, and DOSLFN
should then convert all Unicodes in LFNs to DBCS and vice versa when writing.
Due to availability of a Mainland Chinese user (and I who understand Japanese),
future testings are limited to CP932 and CP936. (CP950 reportedly works yet.)
Note that there are much better replacement tools for the PDOS95.BAT,
I had the "TechWay SCS V3.2" program/driver available (thanks 2 wengier),
which runs under German DOS6 too. One of its advantage is automatic
detection of widely-used box drawing symbols and not to interpret them
as Chinese characters (as PDOS95.BAT will do). Therefore, I could run
my favorite file manager (, editor (turbo.exe) and debugger (td.exe)
with almost no annoyances.


MK_TABLE converts a Unicode table (ASCII form), downloadable at, into binary Volkov Commander form used by DOSLFN.

MKLINK (name may change in future) creates "Joliet Directory Link Tables"
for each Joliet CD found.
By default, it scans all CD drives, and creates this table using a rather
complex, recursive processing. MKLINK chooses file names derivated from
CD's Volume Label, and appends .JLT, for each CD processed.
Therefore one can scan in his CD collection and create tables for all.
These tables will be used by DOSLFN to gain access
to long file names on media not created by WinOnCD.

MKLINK accepts some command line parameters. There are following options:
 /b	* interactive batch processing of a whole CD collection
 /f	* force reading CD even when link table file is already present
	* force reading CD ignoring CeQuadrat WinOnCD Table
 /v	* show reading process in multiple lines (as a table, recommended)
 /v-	* don't show reading process
 /c	* compare order of ISO and Joliet tree
 /h	* show help
Selecting drives is done by typing single drive letter(s).

You should let MKLINK drop its .JLT files to the working directory of DOSLFN,
this is the default when you leave MKLINK beside DOSLFN.
It is not a good idea to burn a .JLT file on its CDROM in a multi-session
because burning another session skews all directory sectors.


Change.LOG: (+ added, - bug-fixed * changed)

Version 0.30 (01/01)
  Initial version

Version 0.31 (04/01)
+ better support for Windows NT (now useless)
+ timeout solution for keeping data for removable media
+ Automatically locking volumes on DOS7 before Write access
* twiddeling with PKZIP 2.50 support - no final solution
* ISR terminates with IRET instead of RETF 2, for work with single-stepping

Version 0.32 (09/01)
- works with internal devices like NUL,CON,LPT...
* source code has option for setting InDOS flag
+ variable heap size supported; memory consumption of DOSLFN is up to user
+ built-in PRINTF-alike function (transient code part only)
* changed output style for "Status" action
+ four code translation tables included with ZIP package
- A little-bit deflamed readme file

Version 0.32a (10/01)
- erraneous root directory of some FAT32 drives
  (this bug was constantly reported but doesn't occur at me until now)
- misbehaviour when DOSLFN started from FAT32 drive
  (this bug was programmed in at Version 0.32)
+ all available code translation tables included with ZIP package
+ MK_TABLE.C enhanced (was made at 0.32) and included
* Version numbering with "a" indicates that there is another version 0.33
  currently in development. This is more a bugfix release.

Version 0.32b (10/01)
- invalid AX on INT21/4E&4F, reported by
  (Behaviour was not documented in Ralf Brown list 03/99)
- some english text missing in DOSLFN.TXT (time zone, test conditions)
  reported by Wu Yongwei <>
- CP850UNI.TBL was wrong, copied to CP858UNI.TBL (this was one containing the
  Euro sign, CP850 does not contain Euro. (by <>)
+ MKLINK is added, although output link table file is useless yet

Version 0.32c (11/01)
- in some occations, *. doesn't work (e.g. failure on "copy *. tmp")
- FindFirst of character devices does return error but should not
  (failure on "copy con xx"), both reported by
* reduced default heap size, CD sectors are not yet inside
* size for internal Link Table expanded to 32 bits

Version 0.32d (06/02)
- complete failure on SUBSTed drives modified to no-lfn-support
- right-align of numeric tail inserting underlines was erraneous (caillet)
* MKLINK modified to check validity of CeQuadrat link table
- MKLINK can now handle multi-session and EasyCdCreator disks

Version 0.32e (06/02)
* re-arranged source, more english in declaration area
+ use of InDOS flag (user-presettable)
- VolumeStart delivered by MSCDEX was wrong, IOCTL-based routine inserted
* removed "checksum linkage" and "LoSA" switch, "LoSA" will be moved into VxD
- LFN GetFAttr of root dir on a CDROM
* changed default settings (tilde usage set to ON)
+ DOSLFN can now load MKLINK-generated files (i.e. support all Joliet CDROMs)
+ LastError report feature
- minor bugfix in MKLINK (InSTab comparred LowWord instead of LongInt)
* (known) root directory link included in *.JLT, MKLINK changed again
* MKLINK changed internally, using an object, added "tree order check"

Version 0.32fà (09/02)
- return value CX at LFN_FindFirst/FindNext
* internal call of Extended Open/Create(6C) instead of Creat(3C)
- recognize bootable CDs too (MKLINK not yet)
* preparing of tunnel effect
Version 0.32fá (10/02)
- extended open/create (bug since 0.32fà)
- LFN_DirEnt remove for lfn_rmdir (bug was always present)
* no more recursive Int21 calls (except for .JLT access)
* no recursion to sfn_unlink for lfn_unlink (faster)
+ delete with wildcards (not tested; not yet for FALLBACK mode)
Version 0.32fâ (11/02)
- interpreting volume label as path component
Version 0.32fã (12/02)
- most (hopefully all) EDIT.COM bugs removed
- ugly write-to-wrong-segment removed (introduced in version 0.32e)
Version 0.32fä (12/02)
+ Delete with wildcards now implemented, at least for FAT drives
Version 0.32f (12/02) - last "f" version
- creating already existing directory returns "file not found" [wengier]
- rename command sometimes forget or destroy another LFN (two bugs)

Version 0.32g (12/02)
- VC Alt+F7 bug (trailing backslash on lfn_name call were stripped)
- VC recursive delete and PKZIP recursive create bug (FastOpenCache bug)
* development of Version 0.33 stopped

Version 0.32h (12/02)
- Access SFN with spaces (surprisingly, this fix reduces code size)
- Minor fixes in MKLINK: verbosity switch, table arrangement
+ MKLINK creates a link table if CeQuadrat LT is not at first session
+ MKLINK got a built-in code page 437 (for verbose output)
- root directory of CDROM shows . and .. entries
- "cd" command with trailing backslash was disabled by VC Alt+F7 bugfix

Version 0.32i (12/02)
- crash starting DOSLFN with CDROM as current drive
- incorrrect handling and uselessness of /p switch
- taking wrong directory for auto-loading Unicode table

Version 0.32j (12/02 - Xmas)
+ wrote LFNXLAT.386 - a protected mode API for Windows and its DOS boxes
+ Int2F interface for loading that VxD (Win3) or disabling itself (Win95+)
+ DOS and Windows version checking, refusing while DOS<4 or Win9x is running
+ automatic codepage change notification over Int2F (not yet tested)
+ LastError report feature now functional with five messages
+ automatic heap size calculation based on largest .JLT file
+ functional /c switch
+ shrinked memory consumption in FAT-ONLY mode (ie. no CDROM support)
- loading CeQuadrat LT from CDROM if multi-session
- at least three bugs around directory enlargement
- you could create a file name containing wildcards in its long name
+ full support for SUBSTed drives
- Long ISO names crash DOSLFN - now simply truncated to 12 characters
- renaming fails when changing case only
* setjmp/longjmp or Catch/Throw alike error handling simplifies source
+ tunnel effect (preserves long name for old editors etc.)
- cannot create file/directory with same name as volume label
- incompatible acception of trailing backslash tends to failure of PKUNZIP
+ functional /t switch - now all switches are functional
- bug in Joliet CDROM listing on root directory (files become directories)
+ DBCS support prepared

Version 0.32k (01/03)
- "dir makefile" doesn't show the makefile
  (this small bug required rewriting of large amount of DOSLFN)
* Without any .TBL, DOSLFN now defaults to ISO-Latin1 instead of CP437.
  This is due to internal changes for DBCS support.
- can't handle files that have 0xE5 as first byte (DOS TRUENAME "bug" @0.32j)
+ DBCS .TBL file format now declared, see TBL.TXT
+ Three new code page tables added: Japanese (Shift-JIS),
  Simplified Chinese (GB2312, subset of GBK), Traditional Chinese (BIG5)
+ Added full DBCS support, but impossible to test for me
  CHINESE OR JAPANESE USERS must include /m18000 or similar to give more heap
  (This switch will be automated in a later version.)
- after accessing devices, data corruption may occur
- when working with different versions of DOSLFN, wrong strings may occur
- /z switch doesn't work  since 0.32j

Version 0.32l (01/03)
- DBCS support doesn't work at all (multiple bugs), checked with TechWay SCS
- erraneous messages when loading DBCS without CDROM support
- partially overwritten DBCS table
* more strict "critical initialization code" section
+ automatic heap size calculation extended to include .TBL file
  CJK users need no switch anymore

Version 0.32m (01/03)
- query help with /? or -h crashes DOS  since 0.32l  (oops!)
- erraneous return value for DEL command  since 0.32fá
* slightly improved performance for creating short-name, all-uppercase files
- CP950UNI.TBL was in wrong (outdated) format
+ fourth DBCS Unicode table, CP949UNI (Korean) added, but I need feedback!

Version 0.32n (01/03)
+ fifth CP936UNI.GBK is a Unicode table for full-range Simplified Chinese
- fails to auto-load unicode table on CHCP command
- command line overwrite error (couldn't enter longer paths),
  variable area re-arranged completely
+ handling UNC names as FallBack mode (not throrougly tested)
- truename error on SUBSTed drives
- file/directory creation error in FallBack mode
+ checking for ";?" (?=1..9) at end of ISO/Joliet file names rather than
  strip two characters, since NERO can generate such non-ISO CDROMs
* VCACHE.386 problem detected, no fix except not using 32bit file access
+ simple heap walker detects size and free areas
+ FMLFN.DRV, a very beta Long Filename provider for Windows File Manager
+ DOSLFN should be available on SimTel (
+ MKLINK has now Unicode and DBCS support too (for its screen output)
- multiple links in .JLT file generated by MKLINK
- directory sizes not modulo 2048 can crash MKLINK (no ISO standard)

Version 0.32o (05/03)
- option /? crash system once again
+ Russian text strings available but not yet implemented
 Following changes and bugfixes are inspired by but
 he has much more done:
* minor code optimizations
- setting ReadOnly attribute when creating SFN file with Tunnel effect
* Sector access goes through (undocumented) SmartDrive cache, improves
  performance like shown when copying some files from C:
  without DOSLFN	25 s copy to A:		7 s delete from A:
  with DOSLFN 0.32n	78 s copy to A:		12 s delete from A:
  with DOSLFN 0.32o	43 s copy to A:		7 s delete from A:
* MKLINK can now handle directories larger than 64KB (rare, not tested)
* MKLINK.PAS can compile to a DPMI version for more memory usage (tested)

Remaining known bugs:
- no setting/updating "last access" date
- no setting/removing LFN DirEnts when calling FCB functions
- wildcard search on CDROM does not scan ISO entries (since 0.32e?)
- RENAME bug (always change short name when renaming)
- VCACHE.386 bug, you must disable 32bit file access in Windows 3.11
- FILETIME bug when NTFSDOS is loaded after DOSLFN (DIR shows wrong times)
- LFN DRIVER LOAD ORDER bug - NTFSDOS must be loaded after DOSLFN
- no VERSION CHECK - strange behaviour when using different DOSLFN versions
- TRUENAME doesn't handle devices correctly

Detected encoding: UTF-80