The DOS Long-Filename INT 21h API: Capability Checks, Search Handles, and Fallbacks
Use DOS INT 21h 71xx services safely by probing per-volume support, closing search handles, preserving aliases, and designing an 8.3 fallback.
The DOS long-filename (LFN) interface is an optional extension family, not a property that every INT 21h implementation provides. Windows 95 introduced the AX=71xxh services for DOS and Win16 applications; FreeDOS installations can obtain similar behavior from an external driver such as DOSLFN. The important engineering question is therefore not “what version string did DOS return?” but “does the active provider support this service on this volume, and what will the application do if it does not?”
LFN-aware code still has to coexist with classic 8.3 programs and filesystems. A careful caller probes capability, checks carry and error codes on each operation, closes search state, handles Unicode/OEM conversion, and keeps a tested fallback path. This guide covers the interface boundary rather than the installation steps, which are covered separately in the DOSLFN setup and troubleshooting guides.
What the 71xx family changes
Traditional DOS file calls accept paths through interfaces designed around the 8.3 namespace. The LFN family adds operations for longer names, volume information, long-name searches, extended open/create behavior, and path conversion. Examples include AX=7139h for creating a directory, 713Bh for changing directory, 7141h for deletion, 7143h for attributes, 714Eh/714Fh for search, 7156h for rename, 7160h for name conversion, 716Ch for extended open/create, and 71A0h for volume information. The precise registers and structures vary by subfunction; use the matching reference for each call rather than assuming that changing AH on an old DOS function is sufficient.
The LFN call prefix does not itself guarantee Unicode end-to-end. A real-mode DOS program often exchanges bytes in the active OEM code page, while the directory’s long-name representation uses Unicode. DOSLFN documents conversion tables and code-page interactions; unrepresentable characters may be replaced or otherwise constrained by the provider. Applications should preserve the name returned by the API and avoid round-tripping through a lossy OEM conversion when the original Unicode spelling matters.
Capability is per volume and per implementation
The documented 71A0h Get Volume Information call is a practical capability test. It accepts a root path and a buffer for the filesystem name, and returns flags and limits such as maximum filename and path sizes when supported. A system that lacks the extension reports the documented unsupported-function result (AX=7100h with carry set in the Windows 95 interface). Do not infer support only from INT 21h/AH=30h; a compatible version number does not establish that an LFN handler is installed, enabled, or functional for a particular drive.
Probe the volume that the operation will use, not just the boot drive. A local FAT volume, an optical disc, a network redirector, and an emulated drive can expose different capabilities. Treat returned maximum lengths as bounds for the operation, allocate buffers with space for the terminating NUL, and still check the actual result of each request. A successful volume query does not imply that every optional subfunction is implemented by every driver.
For FreeDOS specifically, the kernel’s call-support document says LFN behavior can be supplied by a separate driver that hooks INT 21h; its support table is version-stamped, so do not treat it as a guarantee for every custom or future kernel build. DOSLFN is an independent resident component, so load order, configuration, memory, redirector support, and safe unloading are part of the operational contract. Avoid writing code that silently assumes an LFN TSR is always present.
Search calls create resources that must be closed
The LFN search pair is not interchangeable with classic 4Eh/4Fh. 714Eh returns a search record and a handle used by 714Fh for continuation. Microsoft’s Windows 95 programming reference describes the result as including both a long filename and its short alias where one exists. 71A1h Find Close ends the search and frees the provider’s search storage. A program that abandons a search after one result but never closes it can leak scarce resident-driver heap.
The lifecycle should be explicit:
probe the target volume with 71A0h
call 714Eh and save the returned search handle
process the result, including both long name and alias
call 714Fh until the provider reports no more matches
call 71A1h on every path that obtained a search handle
This is deliberately pseudocode: WIN32_FIND_DATA layout, date conversion selector, attribute masks, segment registers, and return conventions belong to the exact DOS LFN specification/provider. In assembly or C, put cleanup in a single exit path so an early error cannot skip 71A1h. Do not reuse a handle from classic AH=4Eh search state; those calls use the DTA continuation format and different process state.
LFN wildcard matching can consider both the long spelling and generated 8.3 aliases. A pattern that appears to match only a short alias may also select a long-name entry. If the operation must affect one specific file, compare the returned long and short names and verify the attributes before opening, deleting, or renaming it. Enumeration is not a stable snapshot: another process or redirector can change the directory between calls.
Treat the search result as a provider-owned record, not a persistent pointer. Copy fields the application needs into its own storage before the next call, since the provider may reuse an output buffer or search structure. For a search that finds no entries, report that separately from an unsupported-function result: the former is a normal query outcome, while the latter means the application must switch providers or take its fallback path. On every exit, preserve enough context to close the handle even if formatting or application-level processing fails.
Open, rename, and conversion need deliberate policy
Extended open/create (716Ch) can express disposition and attributes beyond classic 3Ch/3Dh; it is not a drop-in replacement with identical flag layouts. Define whether an existing file should be opened, truncated, or rejected, and check the return code before writing. When the application needs to preserve both names, retain the long name for display and the short alias for compatibility; do not synthesize a ~1 alias yourself because alias assignment is provider- and directory-dependent.
7160h supports name conversion operations, but normalization should not be mistaken for durable identity. A short-name result is useful to pass into a legacy program, yet the target may change or be unavailable after a rename, media swap, or remote redirector update. A full path string returned by a DOS service is still subject to time-of-check/time-of-use races. Open the intended object and keep the returned handle for subsequent I/O instead of repeatedly resolving its name.
A compatibility fallback that does not corrupt data
When LFN support is absent, the safest fallback is not to truncate blindly. Reject names that cannot be represented in the application’s supported 8.3 subset, or ask the user to choose an explicit alias. Truncating quarterly-report-final.txt to a guessed QUARTE~1.TXT can select a different file or collide with another generated alias. If the program can enumerate the directory using the short-name API, present the actual aliases and let an operator resolve ambiguity.
Design the fallback per operation. Read-only display may degrade gracefully to the returned short name; creating a file may require refusal if the long spelling is semantically important; a destructive delete must never proceed based on an approximate alias. If an LFN call returns 7100h, fall back only when the legacy path is unambiguously valid and the application’s data-integrity policy permits it. Other errors - access denied, path not found, media not ready, or network failure - are not evidence that the extension is missing.
Validation matrix for an LFN-aware program
Test on at least two environments: a plain DOS/FreeDOS boot without DOSLFN and a boot with the intended LFN provider. Include a local FAT volume, a directory containing mixed-case and space-containing names, and a volume with no long names. Confirm the 71A0h probe’s unsupported path, then verify the application’s chosen fallback.
Exercise long-name search with several results and early termination; confirm every allocated search handle is closed. Test duplicate aliases, wildcard matches against long and short spellings, rename across directories, open dispositions for existing and missing files, and code-page changes. Preserve a disk-image snapshot and compare directory listings and file hashes before and after destructive test cases. Reboot after a controlled crash test to detect orphaned or malformed LFN entries.
Record the kernel version, LFN driver name/version, load order, filesystem and volume, active code page, API return registers, and the exact path bytes. That record matters because two DOS-compatible systems with the same nominal API can route a request through different drivers. A reliable LFN implementation is capability-aware, cleans up its resources, preserves aliases, and fails closed when a destructive operation cannot be represented safely.
Related:
- How to Set Up Long Filename Support on FreeDOS with DOSLFN
- Fixing DOSLFN Long Filename Problems on FreeDOS
Sources: