Source code : Transforming 8.3 path into Windoze-style long filename (long file name) and back. © 1991-2001, Chad Mulligan.
Use this code freely.
Back to Ze Freeware
Thanks to Ben Lunt, Robert Mashlan and Florent Ramière.
Complete Zip file (more up-to-date)
/* 
comLFN.c 
Some C source code to detect whether 
Windows long file names are supported 
and convert full paths to and from Old DOS format (8.3) 
Works under True DOS and Windows 95 and Windows NT, 
but not (yet) in a Windows NT console. 
For 16-bit compilation use only the Large model. 
For 32-bit compilation, do not run under DOS4G/W, but works fine with PMode/W. 
Lame, but does the job. 
All errors are mine. 
*/ 
#include <conio.h> 
#include <dos.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include "common.h" /* not necessary */ 
#ifdef TARGET_Win 
#include <windows.h> 
#endif 
#define COM_USE_LONG_FILENAMES 
#define xSHOW_LONG_FILENAMES 
#define xSHOW_8dot3_to_LFN 
/* for stand_alone linking 
#ifndef com_message 
#define com_message puts 
#endif 
#define COM_USE_EXTENDED_REGS_NAMES // if 32-bit 
#define COM_LG_MAX_PATH_SYSTEM 444 
#define TARGET_DOS // console executable 
//#define TARGET_Win // Windows executable 
*/ 
int com_LFN_check_for_longfilenames ( void ) ; 
void com_test_LFNs ( void ) ; 
int com_path_8dot3_to_LFN ( char *buf_8dot3, char *buf_LFN ) ; 
int com_path_LFN_to_8dot3 ( char *buf_LFN, char *buf_8dot3 ) ; 
int com_LFN_8dot3_to_LFN_Win ( char *buf_8dot3, char *buf_LFN ) ; 
int com_LFN_8dot3_to_LFN_asm ( char *buf_8dot3, char *buf_LFN ) ; 
int com_LFN_LFN_to_8dot3_asm ( char *buf_LFN, char *buf_8dot3 ) ; 
int com_local_long_filenames_ok_p = 0 ; 
/*      Zero if LFN not handled at all (Old DOS, NT console) 
1 : Use interrupt 0x7160 
2 Use Windoze functions 
*/ 
int com_LFN_check_for_longfilenames ( void ) { 
int ret = 1 ; 
#ifdef SHOW_LONG_FILENAMES 
char  message[400] = "" ; 
#endif 
#ifdef COM_USE_LONG_FILENAMES 
#ifdef TARGET_DOS 
static char Buffer[COM_LG_MAX_PATH_SYSTEM+1] = "" ; 
union REGS inr ; 
union REGS outr ; 
struct SREGS sregs ; 
#endif 
#ifdef TARGET_Win 
com_local_long_filenames_ok_p = 2 ; 
#endif 
#ifdef TARGET_DOS 
memset( &sregs, 0, sizeof(struct SREGS) ) ; 
memset( &inr, 0, sizeof(union REGS) ) ; 
memset( &outr, 0, sizeof(union REGS) ) ; 
#ifdef COM_USE_EXTENDED_REGS_NAMES 
inr.x.eax = 0x71A0 ; 
#else 
inr.x.ax = 0x71A0 ; 
#endif 
int86 ( 0x21, &inr, &outr ) ; 
ret = (int) outr.h.al; 
#ifdef SHOW_LONG_FILENAMES 
sprintf ( message, "Code retour de Int. 0x71A0=%u (nonzéro attendu)", (unsigned int) ret ) ; 
com_message (  "lfn", message ) ; 
#endif 
if ( ret ) 
com_local_long_filenames_ok_p = 1 ; 
#endif 
#ifdef SHOW_LONG_FILENAMES 
if ( com_local_long_filenames_ok_p ) { 
sprintf ( message, "Long file names are supported (mode %d).", com_local_long_filenames_ok_p ) ; 
com_message (  "lfn", message ) ; 
} 
else { 
com_message ("Aaargh ! Long file names are NOT supported.") ; 
} 
#endif 
#ifdef TARGET_DOS 
#ifdef SHOW_LONG_FILENAMES 
/* get current directory */ 
mptr = Buffer; /* NMP avec Buffer direct !!! */ 
SegBuffer = FP_SEG(mptr) ; 
OffBuffer = FP_OFF(mptr) ; 
memset( &sregs, 0, sizeof(struct SREGS) ) ; 
memset( &inr, 0, sizeof(union REGS) ) ; 
memset( &outr, 0, sizeof(union REGS) ) ; 
segread ( &sregs ) ; 
#ifdef COM_USE_EXTENDED_REGS_NAMES 
inr.x.eax = 0x7147 ; 
inr.x.esi = OffBuffer ; 
inr.x.esi = (unsigned) Buffer ; 
#else 
inr.x.ax = 0x7147 ; 
inr.x.si = OffBuffer ; 
#endif 
inr.h.dl = 0 ; 
sregs.ds = SegBuffer ; 
int86 ( 0x21, &inr, &outr ) ; 
ret = outr.h.al ; 
ret = outr.x.cflag ; 
#ifdef SHOW_LONG_FILENAMES 
sprintf ( message, 
"Code retour de Int. 0x7147 : outr.h.al=%u outr.x.cflag=%u (zéro attendu),\n\t Buffer=%s.", 
(unsigned int) outr.h.al, (unsigned int) outr.x.cflag, Buffer ) ; 
com_message (  "lfn", message ) ; 
if ( getch ( ) == 27 ) 
exit ( 0 ) ; 
#endif 
#endif 
#endif 
#endif 
return com_local_long_filenames_ok_p ; 
} 
int com_path_8dot3_to_LFN ( char *buf_8dot3, char *buf_LFN ) { 
int  ok_p = 0 ; 
switch ( com_local_long_filenames_ok_p ) { 
case 0 : 
break ; 
case 1 : 
#ifdef TARGET_DOS 
ok_p = com_LFN_8dot3_to_LFN_asm ( buf_8dot3, buf_LFN ) ; 
#endif 
break ; 
case 2 : 
#ifdef TARGET_Win 
/* [ Only defined from Win98 and Win2000… a**holes… 
GetLongPathName ( buf_8dot3, buf_LFN, COM_LG_MAX_PATH_SYSTEM ) ; 
*/ 
ok_p = com_LFN_8dot3_to_LFN_Win ( buf_8dot3, buf_LFN ) ; 
#endif 
break ; 
} ; 
if ( !ok_p ) 
strcpy ( buf_LFN, buf_8dot3 ) ; 
return ok_p ; 
} 
int com_path_LFN_to_8dot3 ( char *buf_LFN, char *buf_8dot3 ) { 
int  ok_p = 0 ; 
switch ( com_local_long_filenames_ok_p ) { 
case 0 : 
break ; 
case 1 : 
#ifdef TARGET_DOS 
ok_p = com_LFN_LFN_to_8dot3_asm ( buf_LFN, buf_8dot3 ) ; 
#endif 
break ; 
case 2 : 
#ifdef TARGET_Win 
ok_p = GetShortPathName ( buf_LFN, buf_8dot3, COM_LG_MAX_PATH_SYSTEM ) ; 
#endif 
break ; 
} ; 
if ( !ok_p ) 
strcpy ( buf_8dot3, buf_LFN ) ; 
return ok_p ; 
} 
#ifdef TARGET_Win 
int com_LFN_8dot3_to_LFN_Win ( char *buf_8dot3, char *buf_LFN ) { 
/* Crée directory et tous les dirs intermédiaires nécessaires 
p = strrchr ( buf_8dot3 
ok_p = SHGetFileInfo ( buf_8dot3, 0, &sh, sizeof ( sh ), SHGFI_DISPLAYNAME ) ; 
if ( ok_p ) 
strcpy ( buf_LFN, sh.szDisplayName ) ; 
*/ 
SHFILEINFO sh ; 
int ok_p ; 
char path2[COM_LG_MAX_PATH_SYSTEM], *path, *p, *next_p ; 
ok_p = GetFullPathName ( buf_8dot3, COM_LG_MAX_PATH_SYSTEM, path2, NULL ) ; 
path = path2 ; 
#ifdef SHOW_8dot3_to_LFN 
fprintf ( stderr, "com_LFN_8dot3_to_LFN_Win:créer \"%s\".\n", path ) ; 
#endif 
p = next_p = strchr ( path, '\\' ) ; 
if ( !p ) { 
#ifdef SHOW_8dot3_to_LFN 
fprintf ( stderr, "com_LFN_8dot3_to_LFN_Win:retour 1.\n" ) ; 
#endif 
return 1 ; 
} ; 
*buf_LFN = 0 ; 
if ( path[1] == ':' ) { 
strncpy ( buf_LFN, path, 2 ) ; 
buf_LFN[2] = 0 ; 
if ( path[2] == '\\' || path[2] == '/' ) { 
strcat ( buf_LFN, "\\" ) ; 
} ; 
} 
else { 
if ( path[0] == '\\' || path[0] == '/' ) { 
strcat ( buf_LFN, "\\" ) ; 
} ; 
} ; 
p = next_p = strchr ( path, '\\' ) ; 
do { 
p = next_p ; 
if ( p ) 
*p = 0 ; 
ok_p = 0 ; 
if ( *path ) 
ok_p = SHGetFileInfo ( path, 0, &sh, sizeof ( sh ), SHGFI_DISPLAYNAME ) ; 
if ( ok_p ) { 
strcat ( buf_LFN, sh.szDisplayName ) ; 
if ( p ) 
strcat ( buf_LFN, "\\" ) ; 
} ; 
if ( p ) { 
*p = '\\' ; 
next_p = strchr ( p+1, '\\' ) ; 
} ; 
} while ( p ) ; 
#ifdef SHOW_8dot3_to_LFN 
fprintf ( stderr, "com_LFN_8dot3_to_LFN_Win:\"%s\"  OK.\n", buf_LFN ) ; 
#endif 
return 1 ; 
} 
#endif 
#ifdef TARGET_DOS 
#ifdef COM_USE_EXTENDED_REGS_NAMES 
#define ax eax 
#define cx ecx 
#define di edi 
#define si esi 
#endif 
/* Stolen from Robert Mashlan, whose code in WDJ is more elegant 
than my own clumsy attempts */ 
static int DoDosCall( unsigned func, union REGS *r, struct SREGS *s ) 
/* helper function to call DOS interrupt*/ 
{ 
r->x.ax = func; 
int86x ( 0x21, r,r,s); 
if(r->x.cflag) { 
_doserrno = r->x.ax; 
/*perror ( "Pas bon" ) ;*/ 
} 
else 
_doserrno = 0; 
return r->x.cflag; 
} 
#define SETPTR(seg,off,ptr) s.seg = FP_SEG((ptr)), r.x.off = FP_OFF((ptr)) 
int com_LFN_LFN_to_8dot3_asm ( char *buf_LFN, char *buf_8dot3 ) { 
union REGS r; struct SREGS s; 
memset(&s,0,sizeof(struct SREGS)); 
SETPTR(ds,si,buf_LFN); 
SETPTR(es,di,buf_8dot3); 
r.x.cx = 1; 
if(DoDosCall(0x7160,&r,&s)) 
return 0; 
return strlen(buf_8dot3); 
} 
int com_LFN_8dot3_to_LFN_asm ( char *buf_8dot3, char *buf_LFN ) { 
union REGS r; struct SREGS s; 
memset(&s,0,sizeof(struct SREGS)); 
SETPTR(ds,si,buf_8dot3); 
SETPTR(es,di,buf_LFN); 
r.x.cx = 2; 
if(DoDosCall(0x7160,&r,&s)) 
return 0; 
return strlen(buf_LFN); 
} 
#endif 
/* Test function ---------------------------------------------- */ 
void com_test_LFNs ( void ) { 
int res = 0 ; 
char  message[2*COM_LG_MAX_PATH_SYSTEM+1] = "" ; 
unsigned char  buf_LFN[COM_LG_MAX_PATH_SYSTEM+1] = 
"c:\\J'aimerais bien\\sucer un petit\\clito.txt" ; 
/* such a file must exist */ 
unsigned char  buf_8dot3[COM_LG_MAX_PATH_SYSTEM+1] = "" ; 
res = com_LFN_check_for_longfilenames ( ) ; 
/* LFN -> 8.3 */ 
strcpy ( buf_LFN, "d:\\tmp" ) ; 
strcpy ( buf_8dot3, "" ) ; 
res = com_path_LFN_to_8dot3 ( buf_LFN, buf_8dot3 ) ; 
sprintf(message, "LFN_to_8dot3 1: %s -> %s, ret=%d.\n", buf_LFN, buf_8dot3, res ) ; 
com_message (  "lfn", message ) ; 
/* 8.3 -> LFN */ 
strcpy ( buf_LFN, "" ) ; 
strcpy ( buf_8dot3, "d:\\tmp\\" ) ; 
res = com_path_8dot3_to_LFN ( buf_8dot3, buf_LFN ) ; 
sprintf(message, "8dot3_to_LFN 2: %s -> %s, ret=%d.\n", buf_8dot3, buf_LFN, res ) ; 
com_message (  "lfn", message ) ; 
/* 8.3 -> LFN */ 
strcpy ( buf_LFN, "" ) ; 
strcpy ( buf_8dot3, "d:\\tmp" ) ; 
res = com_path_8dot3_to_LFN ( buf_8dot3, buf_LFN ) ; 
sprintf(message, "8dot3_to_LFN 2: %s -> %s, ret=%d.\n", buf_8dot3, buf_LFN, res ) ; 
com_message (  "lfn", message ) ; 
/* 8.3 -> LFN */ 
strcpy ( buf_LFN, "" ) ; 
strcpy ( buf_8dot3, "d:\\j'aime~1" ) ; 
res = com_path_8dot3_to_LFN ( buf_8dot3, buf_LFN ) ; 
sprintf(message, "8dot3_to_LFN 2: %s -> %s, ret=%d.\n", buf_8dot3, buf_LFN, res ) ; 
com_message (  "lfn", message ) ; 
/* 8.3 -> LFN */ 
strcpy ( buf_LFN, "" ) ; 
strcpy ( buf_8dot3, "\\j'aime~1" ) ; 
res = com_path_8dot3_to_LFN ( buf_8dot3, buf_LFN ) ; 
sprintf(message, "8dot3_to_LFN 2: %s -> %s, ret=%d.\n", buf_8dot3, buf_LFN, res ) ; 
com_message (  "lfn", message ) ; 
/* LFN -> 8.3 */ 
strcpy ( buf_LFN, "c:\\J'aimerais bien\\sucer un petit\\clito.txt" ) ; 
strcpy ( buf_8dot3, "" ) ; 
res = com_path_LFN_to_8dot3 ( buf_LFN, buf_8dot3 ) ; 
sprintf(message, "LFN_to_8dot3 3: %s -> %s, ret=%d.\n", buf_LFN, buf_8dot3, res ) ; 
com_message (  "lfn", message ) ; 
/* 8.3 -> LFN */ 
strcpy ( buf_LFN, "" ) ; 
res = com_path_8dot3_to_LFN ( buf_8dot3, buf_LFN ) ; 
sprintf(message, "8dot3_to_LFN 6: %s -> %s, ret=%d.\n", buf_8dot3, buf_LFN, res ) ; 
com_message (  "lfn", message ) ; 
/* LFN -> 8.3 */ 
strcpy ( buf_LFN, "c:\\J'aimerais bien\\sucer deux petits\\clitos.txt" ) ; 
strcpy ( buf_8dot3, "" ) ; 
res = com_path_LFN_to_8dot3 ( buf_LFN, buf_8dot3 ) ; 
sprintf(message, "LFN_to_8dot3 7: %s -> %s, ret=%d.\n", buf_LFN, buf_8dot3, res ) ; 
com_message (  "lfn", message ) ; 
if ( getch ( ) == 27 ) 
exit ( 0 ) ; 
}