gpt4 book ai didi

c++ - 需要说明将路径转换为长 Unicode 路径或以\\?\开头的路径

转载 作者:可可西里 更新时间:2023-11-01 12:39:43 27 4
gpt4 key购买 nike

首先,让我问一个修辞问题 -- 微软,为什么让我们在路径前添加 \\?\ 以允许它们的长度为 32,767 个字符?为什么不按原样使用它们并扩展 API 上的内部缓冲区的大小?对不起,我只是发泄我的不满......

好的,现在我的实际问题是,如果我有一个路径,我如何将它转换为接受 32,767 个字符长度的格式?请注意,我对该路径一无所知——它可以是相对路径、绝对本地路径、网络共享等。换句话说,它可以是 Microsoft 发明的众多路径格式中的任何一种。

乍一看,在开头添加 \\?\ 似乎是一个简单的提议,对吧?那么,如果该路径已经转换为扩展格式怎么办?我试过 reading this从该页面的大小和底部的评论数量,您可以看出事情并不像看起来那么简单。

最佳答案

好的。事实证明这并不像听起来那么简单。绊脚石(除了模糊的文档和无数的路径格式之外)是一些 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

关于c++ - 需要说明将路径转换为长 Unicode 路径或以\\?\开头的路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18580945/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com