c00*_*0fd 11 c++ windows unicode winapi path
首先,让我问一个修辞问题 - 微软,为什么\\?\要让我们在前面添加路径以允许它们长达32,767个字符?为什么不直接使用它们并扩展API上内部缓冲区的大小?对不起,我只是在发泄我的沮丧......
好的,现在我的实际问题,如果我有一条路径,如何将其转换为接受32,767个字符长度的格式?请注意,我对该路径一无所知 - 它可以是相对路径,绝对本地路径,网络共享等.换句话说,它可以是Microsoft发明的众多路径格式中的任何一种.
起初,它似乎是一个直接的命题,\\?\在开头添加,对吧?那么,如果该路径已经转换为扩展格式怎么办?我尝试阅读这个,从该页面的大小和底部的评论数量,你可以看到事情并不像看起来那么简单.
好的。事实证明这并不像听起来那么简单。绊脚石(除了模糊的文档和无数的路径格式)是,某些 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;
}
Run Code Online (Sandbox Code Playgroud)
这是我测试它的方法:
_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");
Run Code Online (Sandbox Code Playgroud)
这是我得到的输出:
\\?\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
Run Code Online (Sandbox Code Playgroud)