In a recent 10-Minute Solution, I pointed out that when a user drops a filename on your application's icon, the system passes the short path name to your application's command line. The system does this, presumably, because it is not able to tell whether your application will correctly handle long filenames. Surprisingly, MFC does not convert the path name to the long path name. This can make your applications look rather unprofessional when they display the short version of a file's name.
At that time, I presented code to convert a filename on the command line to the long version. This month, I'd like to expand on this topic and address a limitation of the code I presented at that time. Although my previous code worked, the routine I presented only extracted the long version of the filename, and not the entire path. So I'm presenting a more generic routine that converts any existing pathname to its long version.
The technique I used was to call FindFirstFile with a given filename. FindFirstFile returns the long version of an existing filename or directory. Because FindFirstFile only returns the long version of the file or subdirectory name (not the entire path), the code below parses out each directory or file name, converting them to the long versions one at a time.
As I did before, I'll point out that the API does provide a GetLongPathName that does what the code below does. However, that routine is only available in Windows 98 or Windows NT 2000 or later. If you want your code to work on all Win32 operating systems, you'll need to avoid the API routine.
#define PATH_DELIMITER '\\'
//
BOOL MyGetLongPathName(LPTSTR lpszShortPath, LPTSTR lpszLongPath)
{
TCHAR *p, *pStart;
TCHAR buff[MAX_PATH];
WIN32_FIND_DATA wfd;
HANDLE handle;
int i;
// Keep strings null-terminated
*buff = '\0';
*lpszLongPath = '\0';
//
p = lpszShortPath;
while (p != NULL) {
// Find next
p = strchr(pStart = p, PATH_DELIMITER);
// See if a token was found
if (p != pStart) {
i = strlen(buff);
// Append token to temp buffer
if (p == NULL)
strcpy(buff + i, pStart);
else {
*p = '\0';
strcpy(buff + i, pStart);
*p = PATH_DELIMITER;
}
// Copy token unmodified if drive specifier
if (strchr(buff + i, ':') != NULL)
strcat(lpszLongPath, buff + i);
else {
// Convert token to long name
handle = FindFirstFile(buff, &wfd);
if (handle == INVALID_HANDLE_VALUE)
return FALSE;
strcat(lpszLongPath, wfd.cFileName);
FindClose(handle);
}
}
// Copy terminator
if (p != NULL) {
buff[i = strlen(buff)] = *p;
buff[i + 1] = '\0';
lpszLongPath[i = strlen(lpszLongPath)] = *p;
lpszLongPath[i + 1] = '\0';
}
// Bump pointer
if (p) p++;
}
return TRUE;
}