MSDN文档命名文件,路径和命名空间讨论\\?\
前缀.报价:
对于文件I/O,路径字符串的"\?\"前缀告诉Windows API禁用所有字符串解析并将其后面的字符串直接发送到文件系统.
实验表明,\??\
前缀具有相同的效果,禁用路径解析(..
处理)和启用路径的时间长于MAX_PATH
.
MSDN \\?
称为"Win32文件命名空间",它是纯粹由Win32用户模式API知道并转换为\??
NT命名空间吗?无论如何,通过Winobj,我GLOBAL??
在NT命名空间中看到,而不是??
.
Jon*_*ter 11
您的问题的答案是,是的,传递\\?\
和\??\
用户模式功能之间存在差异.
在内部,NT始终表示带有\??\
前缀的路径.通常,当您CreateDirectoryW
使用普通路径调用用户模式函数(例如)时C:\foo
,用户模式函数会调用一个名为的内部函数RtlDosPathNameToNtPathName_U
,该函数将其转换为前缀为NT的NT样式路径\??\
.这种转换是使用固定大小的静态缓冲区完成的,这是着名的MAX_PATH
限制来源.
当你调用一个用户模式功能指定\\?\
前缀(注意,只有一个?
),RtlDosPathNameToNtPathName_U
是不是叫.相反,第二个反斜杠变成了?字符和路径是逐字使用的.当他们谈论\\?\
关闭"...自动扩展路径字符串" 时,这就是文档的意思.
但是,当您使用\??\
前缀调用用户模式函数时,该前缀记住是内部NT前缀,此扩展仍然完成.
用户模式功能专门用于\\?\
禁用自动扩展过程,并且由于您没有提供它,因此您的路径被视为非前缀路径并被馈送到RtlDosPathNameToNtPathName_U
.此功能足够智能,不会\??\
在路径的开头添加额外的前缀,但仍使用固定大小的静态缓冲区.
这是关键的区别.当您\??\
作为前缀传递时,您的路径仍受MAX_PATH
长度限制.
以下示例程序演示了这一点.该TestNestedDir
函数只是尝试创建(然后删除)MAX_PATH
长度大于字符的路径,一次一个级别.如果运行此代码,您将看到的结果是:
CreateDir, no prefix = 0
CreateDir, prefix \\?\ = 1
CreateDir, prefix \??\ = 0
Run Code Online (Sandbox Code Playgroud)
只有使用\\?\
前缀完成的创建才会成功.
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <assert.h>
#include <Windows.h>
const wchar_t* pszLongPath =
L"C:\\"
L"12345678901234567890123456789012345678901234567890\\"
L"12345678901234567890123456789012345678901234567890\\"
L"12345678901234567890123456789012345678901234567890\\"
L"12345678901234567890123456789012345678901234567890\\"
L"12345678901234567890123456789012345678901234567890\\"
L"12345678901234567890123456789012345678901234567890";
bool TestCreateNestedDir(LPCWSTR pszPath)
{
std::wstring strPath = pszPath;
std::wstring::size_type pos = 0, first = std::wstring::npos;
bool fDirs = false, fResult = false;
// step through each level in the path, but only try to start creating directories
// after seeing a : character
while ((pos = strPath.find_first_of(L'\\', pos)) != std::wstring::npos)
{
if (fDirs)
{
// get a substring for this level of the path
std::wstring strSub = strPath.substr(0, pos);
// check if the level already exists for some reason
DWORD dwAttr = ::GetFileAttributesW(strSub.c_str());
if (dwAttr != -1 && (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
{
++pos;
continue;
}
// try to make the dir. if it exists, remember the first one we successfully made for later cleanup
if (!::CreateDirectoryW(strSub.c_str(), nullptr))
break;
if (first == std::wstring::npos) first = pos;
}
else
if (pos > 0 && strPath[pos - 1] == L':')
fDirs = true;
++pos;
}
if (pos == std::wstring::npos)
{
// try to create the last level of the path (we assume this one doesn't exist)
if (::CreateDirectoryW(pszPath, nullptr))
{
fResult = true;
::RemoveDirectoryW(pszPath);
}
}
else
--pos;
// now delete any dirs we successfully made
while ((pos = strPath.find_last_of(L'\\', pos)) != std::wstring::npos)
{
::RemoveDirectoryW(strPath.substr(0, pos).c_str());
if (pos == first) break;
--pos;
}
return fResult;
}
int _tmain(int argc, _TCHAR* argv[])
{
assert(wcslen(pszLongPath) > MAX_PATH);
printf("CreateDir, no prefix = %ld\n", TestCreateNestedDir(pszLongPath));
std::wstring strPrefix = L"\\\\?\\" + std::wstring(pszLongPath);
printf("CreateDir, prefix \\\\?\\ = %ld\n", TestCreateNestedDir(strPrefix.c_str()));
strPrefix[1] = L'?';
printf("CreateDir, prefix \\??\\ = %ld\n", TestCreateNestedDir(strPrefix.c_str()));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
849 次 |
最近记录: |