2003-10-27 16:27:27 UTC
Here's my C++ implementation that seems to work okay with limited
testing. Feedback and corrections welcome.
char *ConvertFilespecToCorrectCase(char *aFullFileSpec)
// aFullFileSpec must be a modifiable string
// since it will be converted to proper case.
// Returns aFullFileSpec, the contents of which
// have been converted to the case used by the
// file system. Note: The trick of changing
// the current directory to be that of
// aFullFileSpec and then calling GetFullPathName()
// doesn't always work. So perhaps the
// only easy way is to call FindFirstFile() on each
// directory that composes aFullFileSpec, which
// is what is done here.
// Longer in case of UNCs and such,
// which might be longer than MAX_PATH:
#define WORK_AREA_SIZE (MAX_PATH * 2)
if (!aFullFileSpec || !*aFullFileSpec) return aFullFileSpec;
size_t length = strlen(aFullFileSpec);
if (length < 2 || length >= WORK_AREA_SIZE) return aFullFileSpec;
// Start with something easy, the drive letter:
if (aFullFileSpec == ':')
aFullFileSpec = toupper(aFullFileSpec);
// else it might be a UNC that has no drive letter.
char built_filespec[WORK_AREA_SIZE], *dir_start, *dir_end;
if (dir_start = strchr(aFullFileSpec, ':'))
// Skip over 1st backslash that goes with drive letter.
dir_start += 2;
else // it's probably a UNC (handling of UNCs hasn't been tested)
if (strncmp(aFullFileSpec, "\\\\", 2))
// Doesn't appear to be a UNC, so don't try:
// I think MS says you can't use FindFirstFile() directly
// on a share name, so we want to omit that from consideration
// (i.e. we don't attempt to find its proper case):
dir_start = aFullFileSpec + 2;
// Init the new string (the filespec we're building),
// e.g. copy just the "c:\\" part.
int chars_to_copy = dir_start - aFullFileSpec;
memcpy(built_filespec, aFullFileSpec, chars_to_copy);
built_filespec[chars_to_copy] = '\0';
for (dir_end = dir_start; dir_end = strchr(dir_end, '\\'); ++dir_end)
*dir_end = '\0'; // Temporarily terminate.
file_search = FindFirstFile(aFullFileSpec, &found_file);
*dir_end = '\\'; // Restore it before we do anything else.
if (file_search == INVALID_HANDLE_VALUE)
// Append the case-corrected version of this directory name:
// Now do the filename itself:
if ( (file_search = FindFirstFile(aFullFileSpec, &found_file))
== INVALID_HANDLE_VALUE )
// It might be possible for the new one to be longer than the old,
// e.g. if some 8.3 short names were converted to long names by the
// process. Thus, the caller should ensure that aFullFileSpec is
// large enough:
Hopefully this will be of help to someone.
- Chris Mallett
Key words: name correct case convert findfirstfile pathname filename