首先,让我问一个修辞问题 - 微软,为什么要让我们在\\?\
前面添加路径以允许它们长达32,767个字符?为什么不直接使用它们并扩展API上内部缓冲区的大小?对不起,我只是在发泄我的沮丧......
好的,现在我的实际问题,如果我有一条路径,如何将其转换为接受32,767个字符长度的格式?请注意,我对该路径一无所知 - 它可以是相对路径,绝对本地路径,网络共享等。换句话说,它可以是Microsoft发明的那些路径格式中的任何一种。
起初看起来似乎是在开头添加\\?\
的直截了当的主张,对吧?那么,如果该路径已经转换为扩展格式怎么办?我尝试了reading this,根据该页面的大小和底部的评论数量,您可以看到事情并不像看起来那么简单。
答案 0 :(得分:4)
行。结果并不像听起来那么简单。绊脚石(除了模糊的文档和无数的路径格式)是一些API甚至不像所有版本的操作系统所宣传的那样工作。
无论如何,这是我提出的,似乎适用于XP SP3,Vista,Windows 7和8.有点大,也是为MFC编写的,但这只适用于字符串管理。我没时间调整它:
enum PATH_PREFIX_TYPE
{
PPT_UNKNOWN,
PPT_ABSOLUTE, //Found absolute path that is none of the other types
PPT_UNC, //Found \\server\share\ prefix
PPT_LONG_UNICODE, //Found \\?\ prefix
PPT_LONG_UNICODE_UNC, //Found \\?\UNC\ prefix
};
CString MakeUnicodeLargePath(LPCTSTR pPath)
{
//Convert path from 'pPath' into a larger Unicode path, that allows up to 32,767 character length
//RETURN:
// = Resulting path
CString strPath;
if(pPath &&
pPath[0] != 0)
{
//Determine the type of the existing prefix
PATH_PREFIX_TYPE ppt;
GetOffsetAfterPathRoot(pPath, &ppt);
//Assume path to be without change
strPath = pPath;
switch(ppt)
{
case PPT_ABSOLUTE:
{
//First we need to check if its an absolute path relative to the root
BOOL bOK2AddPrefix = TRUE;
if(strPath.GetLength() >= 1 &&
(strPath[0] == L'\\' || strPath[0] == L'/'))
{
bOK2AddPrefix = FALSE;
//Get current root path
TCHAR chDummy[1];
DWORD dwLnSz = GetCurrentDirectory(0, chDummy);
if(dwLnSz)
{
TCHAR* pBuff = new (std::nothrow) TCHAR[dwLnSz];
if(pBuff)
{
if(GetCurrentDirectory(dwLnSz, pBuff) == dwLnSz - 1)
{
int nIndFollowing = GetOffsetAfterPathRoot(pBuff);
if(nIndFollowing > 0)
{
bOK2AddPrefix = TRUE;
CString strRoot = pBuff;
strPath = strRoot.Left(nIndFollowing) + strPath.Right(strPath.GetLength() - 1);
}
}
delete[] pBuff;
pBuff = NULL;
}
}
}
if(bOK2AddPrefix)
{
//Add \\?\ prefix
strPath = L"\\\\?\\" + strPath;
}
}
break;
case PPT_UNC:
{
//First we need to remove the opening slashes for UNC share
if(strPath.GetLength() >= 2 &&
(strPath[0] == L'\\' || strPath[0] == L'/') &&
(strPath[1] == L'\\' || strPath[1] == L'/')
)
{
strPath = strPath.Right(strPath.GetLength() - 2);
}
//Add \\?\UNC\ prefix
strPath = L"\\\\?\\UNC\\" + strPath;
}
break;
}
}
return strPath;
}
LPCTSTR PathSkipRoot_CorrectedForMicrosoftStupidity(LPCTSTR pszPath)
{
//Correction for PathSkipRoot API
CString strPath = pszPath;
//Replace all /'s with \'s because PathSkipRoot can't handle /'s
strPath.Replace(L'/', L'\\');
//Now call the API
LPCTSTR pResBuff = PathSkipRoot(strPath.GetString());
return pResBuff ? pszPath + (UINT)(pResBuff - strPath.GetString()) : NULL;
}
BOOL PathIsRelative_CorrectedForMicrosoftStupidity(LPCTSTR pszPath)
{
//Correction for PathIsRelative API
CString strPath = pszPath;
//Replace all /'s with \'s because PathIsRelative can't handle /'s
strPath.Replace(L'/', L'\\');
//Now call the API
return PathIsRelative(strPath);
}
int GetOffsetAfterPathRoot(LPCTSTR pPath, PATH_PREFIX_TYPE* pOutPrefixType)
{
//Checks if 'pPath' begins with the drive, share, prefix, etc
//EXAMPLES:
// Path Return: Points at: PrefixType:
// Relative\Folder\File.txt 0 Relative\Folder\File.txt PPT_UNKNOWN
// \RelativeToRoot\Folder 1 RelativeToRoot\Folder PPT_ABSOLUTE
// C:\Windows\Folder 3 Windows\Folder PPT_ABSOLUTE
// \\server\share\Desktop 15 Desktop PPT_UNC
// \\?\C:\Windows\Folder 7 Windows\Folder PPT_LONG_UNICODE
// \\?\UNC\server\share\Desktop 21 Desktop PPT_LONG_UNICODE_UNC
//RETURN:
// = Index in 'pPath' after the root, or
// = 0 if no root was found
int nRetInd = 0;
PATH_PREFIX_TYPE ppt = PPT_UNKNOWN;
if(pPath &&
pPath[0] != 0)
{
int nLen = lstrlen(pPath);
//Determine version of Windows
OSVERSIONINFO osi;
osi.dwOSVersionInfoSize = sizeof(osi);
BOOL bWinXPOnly = GetVersionEx(&osi) && osi.dwMajorVersion <= 5;
//The PathSkipRoot() API doesn't work correctly on Windows XP
if(!bWinXPOnly)
{
//Works since Vista and up, but still needs correction :)
LPCTSTR pPath2 = PathSkipRoot_CorrectedForMicrosoftStupidity(pPath);
if(pPath2 &&
pPath2 >= pPath)
{
nRetInd = pPath2 - pPath;
}
}
//Now determine the type of prefix
int nIndCheckUNC = -1;
if(nLen >= 8 &&
(pPath[0] == L'\\' || pPath[0] == L'/') &&
(pPath[1] == L'\\' || pPath[1] == L'/') &&
pPath[2] == L'?' &&
(pPath[3] == L'\\' || pPath[3] == L'/') &&
(pPath[4] == L'U' || pPath[4] == L'u') &&
(pPath[5] == L'N' || pPath[5] == L'n') &&
(pPath[6] == L'C' || pPath[6] == L'c') &&
(pPath[7] == L'\\' || pPath[7] == L'/')
)
{
//Found \\?\UNC\ prefix
ppt = PPT_LONG_UNICODE_UNC;
if(bWinXPOnly)
{
//For older OS
nRetInd += 8;
}
//Check for UNC share later
nIndCheckUNC = 8;
}
else if(nLen >= 4 &&
(pPath[0] == L'\\' || pPath[0] == L'/') &&
(pPath[1] == L'\\' || pPath[1] == L'/') &&
pPath[2] == L'?' &&
(pPath[3] == L'\\' || pPath[3] == L'/')
)
{
//Found \\?\ prefix
ppt = PPT_LONG_UNICODE;
if(bWinXPOnly)
{
//For older OS
nRetInd += 4;
}
}
else if(nLen >= 2 &&
(pPath[0] == L'\\' || pPath[0] == L'/') &&
(pPath[1] == L'\\' || pPath[1] == L'/')
)
{
//Check for UNC share later
nIndCheckUNC = 2;
}
if(nIndCheckUNC >= 0)
{
//Check for UNC, i.e. \\server\share\ part
int i = nIndCheckUNC;
for(int nSkipSlashes = 2; nSkipSlashes > 0; nSkipSlashes--)
{
for(; i < nLen; i++)
{
TCHAR z = pPath[i];
if(z == L'\\' ||
z == L'/' ||
i + 1 >= nLen)
{
i++;
if(nSkipSlashes == 1)
{
if(ppt == PPT_UNKNOWN)
ppt = PPT_UNC;
if(bWinXPOnly)
{
//For older OS
nRetInd = i;
}
}
break;
}
}
}
}
if(bWinXPOnly)
{
//Only if we didn't determine any other type
if(ppt == PPT_UNKNOWN)
{
if(!PathIsRelative_CorrectedForMicrosoftStupidity(pPath + nRetInd))
{
ppt = PPT_ABSOLUTE;
}
}
//For older OS only
LPCTSTR pPath2 = PathSkipRoot_CorrectedForMicrosoftStupidity(pPath + nRetInd);
if(pPath2 &&
pPath2 >= pPath)
{
nRetInd = pPath2 - pPath;
}
}
else
{
//Only if we didn't determine any other type
if(ppt == PPT_UNKNOWN)
{
if(!PathIsRelative_CorrectedForMicrosoftStupidity(pPath))
{
ppt = PPT_ABSOLUTE;
}
}
}
}
if(pOutPrefixType)
*pOutPrefixType = ppt;
return nRetInd;
}
以下是我测试的方法:
_tprintf(MakeUnicodeLargePath(L""));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"C:\\Ba*d\\P|a?t<h>\\Windows\\Folder"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"Relative\\Folder\\File.txt"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"C:\\Windows\\Folder"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"\\\\?\\C:\\Windows\\Folder"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"\\\\?\\UNC\\server\\share\\Desktop"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"\\\\?\\unC\\server\\share\\Desktop\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"\\\\server\\share\\Desktop\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"C:\\Desktop\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"\\AbsoluteToRoot\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path\\Very Long path"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"\\\\server\\share\\Desktop"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"\\\\?\\UNC\\\\share\\folder\\Desktop"));
_tprintf(L"\n");
_tprintf(MakeUnicodeLargePath(L"\\\\server\\share"));
_tprintf(L"\n");
这是我得到的输出:
\\?\C:\Ba*d\P|a?t<h>\Windows\Folder
Relative\Folder\File.txt
\\?\C:\Windows\Folder
\\?\C:\Windows\Folder
\\?\UNC\server\share\Desktop
\\?\unC\server\share\Desktop\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path
\\?\UNC\server\share\Desktop\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path
\\?\C:\Desktop\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path
\\?\C:\AbsoluteToRoot\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path
\\?\UNC\server\share\Desktop
\\?\UNC\\share\folder\Desktop
\\?\UNC\server\share
答案 1 :(得分:2)
今天是你的幸运日,因为我正在为自己的计划解决问题。解决方案很简单:PathCchCanonicalizeEx函数将添加&#34; \?\&#34;如果需要的话。但是这个功能有一些缺点,因为它需要使用Windows 8作为目标平台,这不是一个交易。这就是我自己的功能,接受了一个&#34;异常&#34;路径字符串作为输入并输出准备好超过MAX_PATH限制的规范化字符串。它使用Win8 SDK中的新定义:
// max # of characters we support using the "\\?\" syntax
// (0x7FFF + 1 for NULL terminator)
#define PATHCCH_MAX_CCH 0x8000
函数声明如下(不是它需要CString定义并且它使用SAL注释):
//Normalize path and prepend "\\?\" if it exceeds the MAX_PATH limit
_Success_(return != false) //If the path was normalized and it exist (if bValidate == true) the return value is true and the normalized path is assigned to the sPath param
bool NormalizePath(_Inout_ CString & sPath, //Set to the abnormal path (relative, UNC, absolute), it is also used to store the normal path
_In_ const CString sCurrentDir, //Set to the currend directory that will be used to resolve relative paths (used for security as GetCurrentDirectory function is thread-unsafe)
_Out_opt_ bool *bDir = NULL, //Set to a bool pointer that will be set to true if the path points to a directory
_In_ bool bValidate = false //If set the path existence is checked and the bDir argument is used
);
定义(没有很多评论):
// max # of characters we support using the "\\?\" syntax
// (0x7FFF + 1 for NULL terminator)
#define PATHCCH_MAX_CCH 0x8000
#define LONG_PATH_ID L"\\\\?\\"
#define UNC_PREFIX "\\\\"
#define UNC_LONG_ID L"\\\\?\\UNC\\"
#define CUR_DIR_REL_PATH_ID ".\\"
#define WILDCAR_CHAR_ASTER '*'
#define WILDCAR_CHAR_QUEMARK '?'
#define DIR_DOWN ".."
#define DIR_UP "."
//Verify that a path exists and set bDir to true if the path points to an directory
bool ValidatePath(_In_ const TCHAR *sPath, _Out_ bool & bDir)
{
//If the path contains a wildcards search test only the parent directory
const TCHAR * sLastElement = _tcsrchr(sPath, _T('\\')); //The last component in the path
bool bFoundWildCard = false;
if(sLastElement)
{
++sLastElement;
if(_tcsrchr(sLastElement, _T(WILDCAR_CHAR_ASTER)) || _tcsrchr(sLastElement, _T(WILDCAR_CHAR_QUEMARK))) //If wilcard characters are contained in the last path component
{
bFoundWildCard = true;
--sLastElement;
const_cast<TCHAR *>(sLastElement)[0] = _T('\0');
}
}
DWORD dwPathAttr = GetFileAttributes(sPath);
if(dwPathAttr == INVALID_FILE_ATTRIBUTES)
{
_com_error sErrorMsg(GetLastError());
//CProgramError.Set(sErrorMsg.ErrorMessage());
return false;
}
bDir = dwPathAttr & FILE_ATTRIBUTE_DIRECTORY;
if(bFoundWildCard)
{
const_cast<TCHAR *>(sLastElement)[0] = _T('\\');
}
return true;
}
void RespondPathComponent(_In_ const TCHAR *pComponent, _Out_ std::vector<CString> & vPathComponents)
{
const TCHAR *pComponentLimiterR = _tcschr(pComponent, _T('\\'));
const TCHAR *pComponentLimiterL = _tcschr(pComponent, _T('/'));
const TCHAR *pComponentLimiter = NULL;
if(pComponentLimiterR && pComponentLimiterL)
pComponentLimiter = (pComponentLimiterR > pComponentLimiterL ? pComponentLimiterL : pComponentLimiterR);
else
pComponentLimiter = (pComponentLimiterR ? pComponentLimiterR : pComponentLimiterL);
if(pComponentLimiter)
{
size_t szComponent = pComponentLimiter - pComponent;
if(szComponent)
{
CString sTemp;
sTemp.SetString(pComponent, szComponent);
vPathComponents.push_back(sTemp);
}
++pComponentLimiter;
RespondPathComponent(pComponentLimiter, vPathComponents);
}
else
{
size_t szLastComp = _tcslen(pComponent);
if(szLastComp)
{
CString sTemp;
sTemp.SetString(pComponent, szLastComp);
vPathComponents.push_back(sTemp);
}
}
}
size_t FixUpPathComponents(_Out_ std::vector<CString> & vPathComponents, _In_ const TCHAR *pPathComponents)
{
RespondPathComponent(pPathComponents, vPathComponents);
size_t szNumComponents = vPathComponents.size();
for(size_t i(0); i < szNumComponents; ++i) //Check path components for special meanings
{
if(vPathComponents[i] == _T(DIR_DOWN))
{
vPathComponents.erase(vPathComponents.begin() + i); //Remove the current component
--szNumComponents;
if(i > 0)
{
vPathComponents.erase(vPathComponents.begin() + i - 1);
--szNumComponents;
}
}
else if(vPathComponents[i] == _T(DIR_UP))
{
if( (i + 1) < szNumComponents )
{
vPathComponents.erase(vPathComponents.begin() + i + 1);
--szNumComponents;
}
vPathComponents.erase(vPathComponents.begin() + i); //Remove the current component
--szNumComponents;
}
}
return szNumComponents;
}
//Note that sCurrentDir is appended to all relative paths (nomatter the drive letter) - it needs to be a full path, not ending with '\\'
bool ExpandAndFixUpPath(_Inout_ CString & sPath, _In_opt_ const CString sCurrentDir)
{
const size_t InPathStrSz = sPath.GetLength();
if(!InPathStrSz) //Invalid path
return false;
//sPath.LockBuffer(); //Lock character buffer
const TCHAR *PathBuffer = sPath.GetString(); //Retrieve the buffer
if(InPathStrSz > 1) //To suppose the path is full it needs to have at lease 2 characters
{
if(_tcsstr(PathBuffer, _T(UNC_PREFIX)) == PathBuffer) //If the path begin with UNC_PREFIX
{
std::vector<CString> vPathComponents;
size_t nComponents;
if((nComponents = FixUpPathComponents(vPathComponents, &PathBuffer[2])) < 2) //A UNC path needs at leas two elements
return false;
sPath = _T('\\');
for(size_t i(0); i < nComponents; ++i)
{
sPath += _T('\\');
sPath += vPathComponents[i];
}
return true;
}
else if(PathBuffer[1] == _T(':')) //If the path begin with a disk designator
{
std::vector<CString> vPathComponents;
if(FixUpPathComponents(vPathComponents, &PathBuffer[2]))
{
if(PathBuffer[2] == _T('\\') || PathBuffer[2] == _T('/'))
{
sPath.SetString(PathBuffer, 2);
for(size_t i(0); i < vPathComponents.size(); ++i)
{
sPath += _T('\\');
sPath += vPathComponents[i];
}
}
else
{
sPath = sCurrentDir;
for(size_t i(0); i < vPathComponents.size(); ++i)
{
sPath += _T('\\');
sPath += vPathComponents[i];
}
}
}
else
{
sPath.SetString(PathBuffer, 2);
sPath += _T('\\');
}
return true;
}
}
std::vector<CString> vPathComponents;
const TCHAR *pComponentsBegin = (_tcsstr(PathBuffer, _T(CUR_DIR_REL_PATH_ID)) == PathBuffer ? &PathBuffer[((sizeof(_T(CUR_DIR_REL_PATH_ID)) / sizeof(TCHAR)) - 1)] : PathBuffer);
FixUpPathComponents(vPathComponents, pComponentsBegin);
sPath = sCurrentDir;
for(size_t i(0); i < vPathComponents.size(); ++i)
{
sPath += _T('\\');
sPath += vPathComponents[i];
}
return true;
}
bool NormalizePath(_Inout_ CString & sPath, _In_ const CString sCurrentDir, _Out_opt_ bool *bDir = NULL, _In_ bool bValidate = false)
{
if(!ExpandAndFixUpPath(sPath, sCurrentDir)) //Extend the path to it's full form
return false;
size_t LongPathLen = sPath.GetLength();
const TCHAR *pPathBuf = sPath.GetString();
#ifdef _UNICODE
if(LongPathLen <= (MAX_PATH - 1)) //If the path is longer in the range of MAX_PATH return it directly
{
if(bValidate)
if(!ValidatePath(pPathBuf, *bDir)) //Validate path before returning it
return false;
return true;
}
bool bIsUNCPath = _tcsstr(pPathBuf, _T(UNC_PREFIX)) == pPathBuf;
if(!bIsUNCPath)
{
if(LongPathLen > (PATHCCH_MAX_CCH - 1 - ((sizeof(LONG_PATH_ID) / sizeof(WCHAR)) - 1))) //If have no space to store the prefix fail
{
//CProgramError.Set(_T("Path too long!"));
return false;
}
CString sPathTmp = LONG_PATH_ID;
sPathTmp += pPathBuf;
if(bValidate)
if(!ValidatePath(sPathTmp.GetString(), *bDir)) //Validate path before returning it
return false;
sPath = sPathTmp;
return true;
}
else
{
if( LongPathLen > ( PATHCCH_MAX_CCH - 1 - ((sizeof(UNC_LONG_ID) / sizeof(WCHAR)) - 1) + ((sizeof(_T(UNC_PREFIX)) / sizeof(WCHAR)) - 1) ) ) //If have no space to store the prefix fail
{
//CProgramError.Set(_T("Path too long!"));
return false;
}
CString sPathTmp = UNC_LONG_ID;
sPathTmp += &pPathBuf[2];
if(bValidate)
if(!ValidatePath(sPathTmp.GetString(), *bDir)) //Validate path before returning it
return false;
sPath = sPathTmp;
return true;
}
#else
if(bValidate)
if(!ValidatePath(pPathBuf, *bDir)) //Validate path before returning it
return false;
return true;
#endif
}
答案 2 :(得分:0)
这是一个从我的一些旧.NET代码转换为未经测试的C ++代码的示例。
#include <iostream>
#include <string>
// For PathIsRelative() & PathCombine()
#include "Shlwapi.h"
#pragma comment(lib, "Shlwapi.lib")
// For _wgetcwd()
#include <direct.h>
std::wstring ConvertToWin32Path(std::wstring &filepath);
std::wstring MakePathAbsolute(std::wstring &filepath);
int main()
{
std::wstring filepath;
std::wcout << L"Enter absolute file path (ex. \"c:\\temp\\myfile.txt\"):";
std::wcin >> filepath;
std::wcout << L"Converted file path: " << ConvertToWin32Path(filepath);
return 0;
}
// If file path is disk file path then prepend it with \\?\
// if file path is UNC prepend it with \\?\UNC\ and remove \\ prefix in unc path.
std::wstring ConvertToWin32Path(std::wstring &filepath)
{
if (filepath.compare(0, 2, L"\\\\"))
{
// If the path is relative then we need to convert it to a absolute path
if (PathIsRelative(filepath.c_str()))
filepath = MakePathAbsolute(filepath);
filepath = std::wstring(L"\\\\?\\") + filepath;
}
else
{
// Is the path already converted, if so then return the same filepath
if (filepath.compare(0, 3, L"\\\\?"))
filepath = std::wstring(L"\\\\?\\UNC\\") + filepath.substr(2, filepath.length() - 2);
}
return filepath;
}
// Converts a relative path to a absolute one by adding the path of the executable
std::wstring MakePathAbsolute(std::wstring &filepath)
{
// Convert from a relative to an absolute file path
const size_t maxCurrDirLen = 256;
wchar_t currentDir[maxCurrDirLen];
_wgetcwd(currentDir, maxCurrDirLen - 1);
const size_t maxPathLen = 32767;
wchar_t fullPath[maxPathLen];
PathCombine(fullPath, currentDir, filepath.c_str());
return std::wstring(fullPath);
}
<强>更新强>
在结束
之前,您是否测试过我的代码?“感谢您的努力,但对不起,这并不是那么简单。”
?我用我的新帖子的输入路径添加了代码的输出;你能说出我的代码失败的地方吗?据我所知,我的代码输出比(更复杂的代码)更准确。我能看到的唯一问题是UNC共享路径应该是\\share\folder\Desktop
而不是\\?\UNC\\share\folder\Desktop
,但这很容易解决 - 但是你自己的代码又有同样的错误......
\\?\c:\dev\UNC_path_test \\?\C:\Ba*d\P|a?t<h>\Windows\Folder \\?\c:\dev\UNC_path_test\Relative\Folder\File.txt \\?\C:\Windows\Folder \\?\C:\Windows\Folder \\?\UNC\server\share\Desktop \\?\unC\server\share\Desktop\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\V ery Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\V ery Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\V ery Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\V ery Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path \\?\UNC\server\share\Desktop\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\V ery Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\V ery Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\V ery Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\V ery Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very L ong path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long p ath\Very Long path\Very Long path\Very Long path \\?\C:\Desktop\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\ Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\ Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\ Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\ Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path \\?\\AbsoluteToRoot\Very Long path\Very Long path\Very Long path\Very Long path\ Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\ Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\ Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\ Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\ Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path\Very Long path \\?\UNC\server\share\Desktop \\?\UNC\\share\folder\Desktop \\?\UNC\server\share