![]() |
China DOS Union-- Unite DOS · Advance DOS · Grow DOS --Union site: www.cn-dos.net Forum site: www.cn-dos.net/forum |
| Guest | Log in | Register | Members | Search | China DOS Union |
|
中国DOS联盟论坛 The time now is 2026-09-15 05:37 |
47,812 topics / 349,917 posts / today 0 new / 48,268 members |
| DOS开发编程 & 发展交流 (开发室) » [Original] Detailed Explanation of Handling Windows 95 Long Filename Interrupts |
| Printable Version 1,437 / 9 |
| Floor1 lemonhall | Posted 2003-08-07 00:00 |
| 高级用户 Posts 183 Credits 639 | |
|
Detailed Explanation of Handling Windows 95 Long Filename Interrupts
Many friends have written programs in the DOS environment, and quite a few of them are related to file handling. As everyone knows, under DOS filenames use the 8.3 format, while Windows 95 started using the long filename format. Programs written for the old DOS environment could only handle these long filenames in 8.3 format. When reading file or directory names that was still acceptable, at worst it just looked a bit awkward (they all turned into filenames like PROGRA~1 and MYPROD~3.EXE). But when creating new directories and files it became troublesome, because the old DOS development environments (such as Tubro C 2.0, Borland C++ 3.1, Turbo Pascal, etc.) had no functions for handling long filenames. All long filenames were truncated by the old functions. I looked up some materials and found that Windows 95 provides interrupts for handling long filenames, so I translated and organized them into this article, hoping it will be of some help to everyone. All the functions introduced in this article are called through INT 21H. Windows 95 handles long filenames through subfunction 71H of interrupt 21H, as follows: AL value Function ===== ========================================== 0DH Reset drive 39H Create subdirectory 3AH Delete subdirectory 3BH Change current directory 41H Delete file 43H Read/set file attributes 47H Get current directory 4EH Find first matching file (findfirst) 4FH Find next matching file (findnext) 56H Move (rename) file 60H TRUENAME 6CH Create/open file A0H Read volume information A1H End file search (findfirst/findnext) A6H Read file information A7H Time conversion A8H Generate short filename (8.3 format) A9H Server create/open file AAH Start/end SUBST After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Note: If the returned error code is 7100H, it means this function is not supported, and the old-style interrupt will be called. For compatibility with older DOS versions (before 7.0), set CF before calling to confirm that it is set on return. There are also several undocumented functions: AL=A2H, A3H, A4H, A5H. Among them, the function of AL=A2H is known and is similar to AL=4FH. These functions are used internally by Windows and will not be introduced in this article. 1. Reset drive Entry: AX = 710DH CX = 0000H Actually write the file system buffer to disk and reset the drive 0001H Actually write the file system buffer and cache to disk, and reset the drive 0002H Remount DriveSpace volume DX = Drive number (00H = A:, 01H = B:, etc.) Exit: CF clear Corresponding old-style call: AH=0DH 2. Create subdirectory Entry: AX = 7139H DS X -> long directory name (ASCIZ string)Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Corresponding old-style call: AH=39H 3. Delete subdirectory Entry: AX = 713AH DS X -> long directory name to delete (ASCIZ string)Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Corresponding old-style call: AH=3AH 4. Change current directory Entry: AX = 713BH DS X -> long directory name (ASCIZ string) to set as the current directoryExit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Corresponding old-style call: AH=3BH 5. Delete file Entry: AX = 7141H DS X -> long filename of the file to delete (ASCIZ string)SI = Wildcard and attribute flags 0000H Wildcards not supported, search attributes are ignored 0001H Wildcards supported, only names and attributes that match will be deleted CL = Search attributes CH = Must-match attributes Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Corresponding old-style call: AH=41H 6. Read/set file attributes Entry: AX = 7143H DS X -> filename (ASCIZ string)BL = 00H Read attributes Return: CX = file attributes 01H Set attributes CX = file attributes 02H Read physical size of compressed file Return: DX:AX = actual disk space used by the file in bytes 03H Set last write date/time DI = new last write date CX = new last write time 04H Read last write date/time Return: DI = last write date CX = last write time 05H Set last access date DI = new last access date 06H Read last access date Return: DI = last access date 07H Set creation date/time DI = new creation date CX = new creation time SI = hundredths of a second 08h Read creation date/time Return: DI = creation date CX = creation time SI = hundredths of a second Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. For return values on success, see the "Entry" section of this subsection. Corresponding old-style call: AH=43H Please refer to: Appendix 1, Appendix 2, Appendix 3 7. Get current directory Entry: AX = 7147H DL = Drive number (00H = current drive, 01H = A:, etc.) DS:SI -> memory area used to store the directory name (ASCIZ string) Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. The directory name will be stored in the memory area pointed to by DS:SI. Note: The returned directory name does not include the drive letter, colon, or leading backslash, and it is not necessarily a long filename. What this function returns is the path used to change to this directory, and it may contain a string mixed with long and short filenames. The minimum size of the memory area provided (pointed to by DS:SI) should be determined by function AX=71A0H. Corresponding old-style call: AH=47H 8. Find first matching file Entry: AX = 714EH CL = Allowed attributes (bit 0 and bit 5 ignored) CH = Required attributes SI = 0000h Use Windows 95 64-bit file time format 0001h Use MS-DOS date/time values, with the date in the high word and the time in the low word DS X -> filename with wildcards ("*" and "*.*" both match all files)ES I -> space used to store the FindData structureExit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. On success, return: AX = filefind handle (used to continue the search) CX = Unicode conversion flags Bit 0: the returned long filename contains Unicode characters that could not be converted and were replaced with underscores Bit 1: the returned short filename contains Unicode characters that could not be converted and were replaced with underscores Note: This function only works when IFSMgr is running, not in DOS 7.0 pure DOS mode. The application should call function AX=71A1H to end the search immediately after the search is complete. Corresponding old-style call: AH=4EH Please refer to: Appendix 1, Appendix 2, Appendix 3, Appendix 4 9. Find next matching file Entry: AX = 714FH BX = filefind handle (from function AX=714EH) SI = 0000h Use Windows 95 64-bit file time format 0001h Use MS-DOS date/time values, with the date in the high word and the time in the low word ES I -> space used to store the FindData structureExit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. On success, return: CX = Unicode conversion flags Bit 0: the returned long filename contains Unicode characters that could not be converted and were replaced with underscores Bit 1: the returned short filename contains Unicode characters that could not be converted and were replaced with underscores Note: This function only works when IFSMgr is running, not in DOS 7.0 pure DOS mode. Corresponding old-style call: AH=4FH Please refer to: Appendix 2, Appendix 3, Appendix 4 10. Move (rename) file Entry: AX = 7156H DS X -> old filename (ASCIZ)ES I -> new filename (ASCIZ)Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Note: A file can be renamed into a different directory, but it must be on the same drive. Corresponding old-style call: AH=56H 11. TRUENAME Entry: AX = 7160H CL = 00H Get canonical path 01H Get short filename 02H Get canonical long filename or path CH = SUBST extension flag 00H The returned path is the real path without the SUBST drive letter 80H The returned path may contain the SUBST drive letter DS:SI -> file or pathname (ASCIZ string), either long or short ES I -> 261-byte buffer used to store the canonical path or long filename(CL=00H or 02H) or a 67-byte (possibly 128-byte) buffer used to store the short filename (CL=00H or 02H) Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Error codes: 02H File (directory) not found in the directory, or only a drive letter was specified 03H Invalid path or invalid drive letter On success, the buffer pointed to by ES I is written with the returned path or filename.Corresponding old-style call: AH=60H 12. Create/open file Entry: AX = 716CH BX = access mode and sharing flags (Appendix 5) CX = attributes DX = open mode (Appendix 6) DS:SI -> filename (ASCIZ string) DI = alias hint (the digit in short filenames used to remove ambiguity) Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. On success: AX = file handle CX = 0001H file opened 0002H file created 0003H file replaced Corresponding old-style call: AH=6CH Please refer to: Appendix 1, Appendix 5, Appendix 6 13. Read volume information Entry: AX = 71A0H DS X -> root directory name (ASCIZ string), such as "C:\”"ES I -> memory area for storing the file system name (usually 32 bytes is enough)CX = size of the memory area pointed to by ES IExit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. On success: BX = file system flags CX = maximum filename length (usually 255) DX = maximum pathname length (usually 260) The memory area pointed to by ES I is filled with "FAT", "NTFS","CDFS", etc. BUG: In Windows 95 SP1 this function returns DX=0000H for CD-ROMs Corresponding old-style call: none Please refer to: Appendix 7 14. End file search Entry: AX = 71A1H BX = filefind handle (from function AX=714EH) Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Note: After beginning a file search with function AX=714EH, this function must be called to release the filefind hadle This function only works when IFSMgr is running, not in DOS 7.0 pure DOS mode. Corresponding old-style call: none 15. Read file information Entry: AX = 71A6H BX = file handle DS X -> memory area used to store file informationCF set Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. On success, the memory area pointed to by DS X is written with file information.Corresponding old-style call: none Please refer to: Appendix 8 16. Time conversion Entry: AX = 71A7H DS:SI -> QWORD-format file time BL = 00H File time to DOS time Return: CX = DOS time DX = DOS date BH = hundredths of a second 01H DOS time to file time CX = DOS time DX = DOS date BH = hundredths of a second Return: the memory area pointed to by DS:SI is filled Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. For the remaining return data on success, see the "Entry" section. Note: When BL=00H, it fails if the file time is not between 01/01/1980 and 12/31/2107. Corresponding old-style call: none Please refer to: Appendix 8 17. Generate short filename (8.3 format) Entry: AX = 71A8H DS:SI -> long filename (ASCIZ string), path not required ES I -> memory area used to store the short filename (ASCIZ string)DH = short filename format 00H 11-character / FCB filename format 01H DOS 8.3 DL = character set Bits 7-4: character set of the short filename Bits 3-0: character set of the long filename 00h Windows ANSI 01h current OEM character set 02h Unicode Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Corresponding old-style call: none 18. Server create/open file Entry: AX = 71A9H BX = access mode and sharing flags (Appendix 5) CX = attributes DX = open mode (Appendix 6) DS:SI -> filename (ASCIZ string) DI = alias hint (the digit in short filenames used to remove ambiguity) Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. On success: AX = global file handle CX = 0001H file opened 0002H file created 0003H file replaced Note: Only for real-mode servers Corresponding old-style call: none Please refer to: Appendix 1, Appendix 5, Appendix 6 19. Start/end SUBST Entry: AX = 71AAH BH = 00H Start SUBST The memory area pointed to by DS X is used for input01H End SUBST No need to specify DS X02H Query SUBST The memory area pointed to by DS X is used for outputBL = drive number (00H=default, 01H=A:, etc.) DS X -> pathname associated with the drive (ASCIZ string)Exit: After the interrupt call, CF set indicates an error (AX stores the error code), and CF clear indicates success. Note: BL may be 00H only when BH=00H Corresponding old-style call: none 20. Final remarks The original material for this article came from Ralf Brown's Interrupt List (English edition). This interrupt collection contains quite a lot of rich content, and is truly a very good programming reference. Because of my limited level and the rush of time, the translation and organization are not very good, and there are surely places that are unsatisfactory. Please be forgiving. If there is anything incorrect, please point it out. Everyone may freely distribute this article, so that it can serve more friends, but I respectfully ask that when spreading this article, you be sure to keep it complete. Many thanks. After some time I may write some example routines using these interrupt calls as a supplement to this article. When they are finished, I will publish them through the mailing list geprogram (Golden Eagle's Programmer World). Friends who are interested can join this mailing list in the following way: 1. Send a blank email to sml-geprogram-subscribe@mylist.soim.com 2. Reply to a confirmation letter you receive To contact me, please Email: goldeagle@cmmail.com or: pengyin@yeah.net Gold Eagle Nov.26,1999 in Dongguan, Guangdong Appendix 1: Meaning of each file attribute bit: Bit Description ==== ================================= 7-8 Reserved (used in Novell Netware) 6 Unused 5 Archive (A) 4 Directory (D) 3 Volume label 2 System (S) 1 Hidden (H) 0 Read-only (R) Appendix 2: File date format Bit Description ==== ================================= 15-9 Year minus 1980 8-5 Month 4-0 Day Appendix 3: File time format Bit Description ===== ================================= 15-11 Hours (0-23) 10-5 Minutes 4-0 Seconds/2 Appendix 4: Windows 95 long filename FindData structure Offset Length Description ==== ====== ============================ 00H DWORD File attributes Bits 0-6 are standard file attributes Bit 8: temporary file 04H QWORD File creation time (100ns units starting from 1/1/1601) 0CH QWORD Last access time 14H QWORD Last modification time 1CH DWORD File length (high 32 bits) 20H DWORD File length (high 32 bits) 24H 8 BYTEs Reserved (apparently unused) 2CH 260 BYTEs Long filename (ASCIZ string) 130H 14 BYTEs Short filename for backward compatibility (ASCIZ string) Note: In Windows95B, if the directory structure does not contain long filename information, the returned short filename is empty. For this reason, please use the long filename (offset 2CH). Appendix 5. Windows 95 access/sharing modes Bit Description ==== ================================= 2-0 File access mode 000 read-only 001 write-only 010 read/write 100 read-only, and do not change the file's last access time 6-4 File sharing mode 7 Non-inheritance flag 8 Do not cache data (requires all reads and writes to match physical sectors exactly) 9 Do not compress file, even if this volume normally compresses files 10 Use the number specified in DI as the tail number of the alias 12-11 Unused??? (0) 13 When opening a file, on critical errors return an error code without calling INT 24H 14 Commit the file on every write operation Appendix 6. Windows 95 long filename file open modes Bit Description ==== ================================= 0 Open file (fail if the file does not exist) 1 Truncate if file exists (fail if the file does not exist) 4 Create new file if file does not exist (fail if the file exists) Note: Bit 0 and bit 1 cannot be set at the same time Appendix 7. Long filename volume information flags Bit Description ==== ================================= 0 Case-sensitive during search 1 Case information is stored in the directory 2 Unicode characters may be used in file and directory names 3-13 Reserved (0) 14 Supports DOS long filename functions 15 Volume is compressed Appendix 8. Windows 95 file information structure Offset Length Description ==== ====== ============================ 00H DWORD File attributes 04H QWORD Creation time (0 = not supported) 0CH QWORD Last access time (0 = not supported) 14H QWORD Last write time 1CH DWORD Volume serial number 20H DWORD File length (high 32 bits) 24H DWORD File length (low 32 bits) 28H DWORD Number of file links (link) 2CH DWORD Unique file identifier (high 32 bits) 30H DWORD Unique file identifier (low 32 bits) Note: When the file is opened, the file identifier together with the volume serial number uniquely identifies a file. This identifier may change when the system is rebooted or when the file is first opened. |
|
| Floor2 bird | Posted 2003-10-15 00:00 |
| 初级用户 Posts 4 Credits 126 | |
|
Salute to the expert.
|
|
| Floor3 qb45 | Posted 2003-10-15 00:00 |
| 高级用户 Posts 194 Credits 677 | |
|
You've worked hard, really hard, support!
|
|
| Floor4 Wengier | Posted 2003-10-15 00:00 |
| 系统支持 Posts 10,521 Credits 27,736 | |
|
The following passage is nonsense:
"As everyone knows, under DOS filenames use the 8.3 format, while Windows 95 started using the long filename format. Programs written for the old DOS environment could only handle these long filenames in 8.3 format. When reading file or directory names that was still acceptable, Who says programs under DOS can only handle long filenames in 8.3 format??? Don't "Super MS-DOS 7.10 Boot Disk", "MS-DOS 7.10 Full Installation Edition", ROM-DOS 7.10, etc. all support long filenames natively? DOS that does not support long filenames refers only to old versions of DOS, right... As for DOS development environments, can't DJGPP directly use long filenames under pure DOS when there is an LFN API??? |
|
| Floor5 lemonhall | Posted 2003-10-16 00:00 |
| 高级用户 Posts 183 Credits 639 | |
|
This is a reposted article, sorry about that. I'm not an expert either......
I was quite surprised by the webmaster's rebuttal. Actually even by MS-DOS 7.1 it still doesn't support long filenames. Only after adding extras such as DOSLFN can pure DOS support long filenames. DJGPP does indeed support long filenames. But several conditions are required. (DJGPP) DOS7.1+DOSLFN, with LFN=Y, can use long filenames. DOS7.1 without DOSLFN cannot use long filenames. The WIN95 DOS BOX uses 128-character long filenames, and has no 3 timestamps. DJGPP can't get around that either. The WIN98 DOS BOX uses 256-character long filenames, 3 timestamps (requires FAT32). Finally, what needs to be stated is that DJGPP merely wraps the calls mentioned in the material above. Its C standard functions call a non-ANSI standard _open function, and then the _open function calls a DPMI protected-mode INT call to access the LFN API. And when DOSLFN is not loaded (that is, the 71H subfunction of INT 21H mentioned earlier in the article), DJGPP will automatically determine that LFN=N (LFN is an environment variable of the DJGPP runtime; every program compiled with DJGPP will automatically check the value of this environment variable), and then call a special subroutine to do the "truncation" work. This truncation work is the same as mentioned above, and also the same as one QB45 long filename implementation (that implementation is awful; it throws errors on many QB compilers, and it is aimed at WIN95 long filename implementation. It merely truncates the filename, and the source program is full of calls to the external command "DIR".... dizzy.) When opening a file, DJGPP will automatically truncate the long filename you provide into an 8.3 filename, and then open it. But unfortunately, DJGPP still cannot create long-filename files when the LFN API is not loaded. All this is based on my experience using DJGPP for programming and referring to its standard C library. If there is anything wrong, please point it out. ================================== What I mean by providing this material is to encourage ASM experts to write some libraries, so that for old compilers such as QB4.5 and TC2.0 new calling functions can be written (after looking at DJGPP's implementation I still couldn't write one myself, what a shame, because it really uses too much DPMI and too many header files, it made my head spin!!) Also, DJGPP's approach can be borrowed. If no LFN API is detected as loaded, at least a compromise truncation scheme can be provided, offering a high degree of compatibility. =================================================== Finally, another phenomenon I found is this. Many programs written in the early DJGPP days (actually specifically DJGPP2.01+WIN95) show a lot of strange behavior when handling long filenames. At first, I guessed that WIN95 and later WIN98 and DOSLFN might provide somewhat different LFN APIs. After looking at the source code from that period and DJGPP's implementation of long filenames, I found there was no difference at all!!!!!! But programs from that era all had one extra function for detecting whether the LFN API exists, and this function seems unable to detect the existence of DOSLFN. This is most obvious in TEDIT. In the end I deleted all calls to this function and forcibly used ASSERT to assume LFN=Y. Only then did the program work normally under DJGPP2.03 (before that it could not access the parent directory, and could only open files in the current directory...) This phenomenon is very strange, but I did not continue researching it.... too bad. |
|
| Floor6 lemonhall | Posted 2003-10-16 00:00 |
| 高级用户 Posts 183 Credits 639 | |
|
The webmaster's DOS absolutely supports long filenames.
What doesn't support long filenames are old compiler systems. Their FOPEN() or OPEN commands, when opening long filenames, either do nothing or simply report an error saying the file does not exist. Very frustrating. The DIR command in DOS7.1 is a very good implementation of long filenames. With DOSLFN, WIN95, or WIN98, it all handles things correctly. When there is an LFN API, it displays two columns of filenames. One column is 8.3, one column is the long filename. Without it, its display is the same as the DIR command in DOS6.22. A model of high compatibility!! |
|
| Floor7 qb45 | Posted 2003-10-16 00:00 |
| 高级用户 Posts 194 Credits 677 | |
|
If someone is willing to use QB (4.0, 4.5, 7.1) for programming (for example, to make some tool or something), I'm willing to write a library based on your technical documentation!
|
|
| Floor8 lemonhall | Posted 2003-10-16 00:00 |
| 高级用户 Posts 183 Credits 639 | |
|
If you're willing, write one first!!!!
Because QB45+ALLEGRO+this library can achieve a very good installation interface. Taking a step back, it could also be made to work for QB7.1 (because these compiler systems are not protected mode, they're now most suitable for interface work, but in actual work I found that their functions don't support long filenames, very frustrating. Actually QB45, I was fascinated with QB for a while too, ![]() Actually, developing a library is itself a process of making a tool! If you finish writing it, I'm willing to use it to develop something practical. |
|
| Floor9 Wengier | Posted 2003-10-17 00:00 |
| 系统支持 Posts 10,521 Credits 27,736 | |
|
MS-DOS 7.x actually itself knows how to use long filenames, but to really use long filenames it needs a driver called an LFN API provider, namely DOSLFN. MS-DOS 6.x is different; since it itself does not support long filenames, even having an LFN API would be useless. Similarly, taking XMS as an example, DOS itself knows how to use XMS memory, but to really use XMS memory, there must be an XMS API provider, namely HIMEM.SYS. So MS-DOS 7.x is absolutely a DOS that supports long filenames; as long as there is an LFN API, it can really use them.
By comparison, ROM-DOS 7.10 includes the LFN API in the DOS kernel, so once it starts it can natively support long filenames, without loading some other LFN API provider such as DOSLFN. |
|
| Floor10 lemonhall | Posted 2003-10-18 00:00 |
| 高级用户 Posts 183 Credits 639 | |
|
Actually the key is not whether DOS recognizes LFN, because even DOS6.22+DOSLFN+LFNDIR, this kind of special-purpose
package, still works fine, doesn't it? The key is whether the tools being used support LFN. Even if DOS recognizes LFN, if basic tools like EDIT do not recognize LFN, it is still very inconvenient to use. So developing an LFN library for old compiler tools is still very meaningful. Also, recently I found a GNU tool that is very useful, and I recommend it to everyone. GRCODE, it has very good support for various character sets. UTF-8 and so on. At the same time it is also a programming library. |
|
|
[ Contact the Union admin team -
中国DOS联盟 -
Standard version ] Sponsored by ifanr Inc | © 2001–2023 |