Nov 012011
If you need to create or open a file that is in a really deeply nested path structure in Windows you can’t use a typical file path. File paths are good up to MAX_PATH (260) characters. If the name of the folders or number of folders deep takes it beyond that restriction you have to add characters to the beginning of the path to tell Windows it’s OK to access. These functions will help you manage those types of paths.
One of the functions listed below uses the IsPathUNC() function that is part of the SHLWAPI API. To include it simply add the include file “shlwapi.h” and add the library “shlwapi.lib” to your linked libraries for your project.
#include "shlwapi.h"
#define LONGPATH_UNC _T("\\\\?\\UNC")
#define LONGPATH_DRIVE _T("\\\\?\")
// See if Unicode path already added
bool IsUNCPathUnicode(CString path)
{
CString DRIVEVersion = LONGPATH_DRIVE;
return path.Left(DRIVEVersion.GetLength()) == LONGPATH_DRIVE;
}
// Remove Unicode
CStringW RemoveUNCPathUnicode(CString path)
{
CString UNCVersion = LONGPATH_UNC;
CString DRIVEVersion = LONGPATH_DRIVE;
bool bIsUNC = false;
CString header = _T("");
if(path.Left(UNCVersion.GetLength()) == LONGPATH_UNC) {
header = UNCVersion;
bIsUNC = true;
}
else if(path.Left(DRIVEVersion.GetLength()) == LONGPATH_DRIVE)
header = DRIVEVersion;
else
return path; // Already done
path = path.Mid(header.GetLength());
if(bIsUNC)
path = _T("\") + path; // Add back UNC part
return CString(path);
}
//
// Return a Unicode name suitable for win32 really long filepaths.
// If the name is a UNC then it adds \\?\UNC to the start of the path.
// In any case the path is changed to Unicode.
//
CStringW MakeUNCPathUnicode(CString path)
{
if(IsUNCPathUnicode(path)) // Already done
return path;
CStringW csw;
// allow really long names, add \\?\ for drive letter and \\?\UNC\ for UNC paths
if (path.GetLength()) {
path = RemoveUNCPathUnicode(path); // In case it has one already
if (PathIsUNC(path))
path = LONGPATH_UNC + path.Mid(1);
else
path = LONGPATH_DRIVE + path;
csw = CStringW(path);
}
return csw;
}
#define LONGPATH_UNC _T("\\\\?\\UNC")
#define LONGPATH_DRIVE _T("\\\\?\")
// See if Unicode path already added
bool IsUNCPathUnicode(CString path)
{
CString DRIVEVersion = LONGPATH_DRIVE;
return path.Left(DRIVEVersion.GetLength()) == LONGPATH_DRIVE;
}
// Remove Unicode
CStringW RemoveUNCPathUnicode(CString path)
{
CString UNCVersion = LONGPATH_UNC;
CString DRIVEVersion = LONGPATH_DRIVE;
bool bIsUNC = false;
CString header = _T("");
if(path.Left(UNCVersion.GetLength()) == LONGPATH_UNC) {
header = UNCVersion;
bIsUNC = true;
}
else if(path.Left(DRIVEVersion.GetLength()) == LONGPATH_DRIVE)
header = DRIVEVersion;
else
return path; // Already done
path = path.Mid(header.GetLength());
if(bIsUNC)
path = _T("\") + path; // Add back UNC part
return CString(path);
}
//
// Return a Unicode name suitable for win32 really long filepaths.
// If the name is a UNC then it adds \\?\UNC to the start of the path.
// In any case the path is changed to Unicode.
//
CStringW MakeUNCPathUnicode(CString path)
{
if(IsUNCPathUnicode(path)) // Already done
return path;
CStringW csw;
// allow really long names, add \\?\ for drive letter and \\?\UNC\ for UNC paths
if (path.GetLength()) {
path = RemoveUNCPathUnicode(path); // In case it has one already
if (PathIsUNC(path))
path = LONGPATH_UNC + path.Mid(1);
else
path = LONGPATH_DRIVE + path;
csw = CStringW(path);
}
return csw;
}
I hope this helps someone else use this kind of obscure functionality.