如何以编程方式检查当前进程在Windows上是否具有长路径感知功能?


Windows 10版本1607中,进程现在可以使用清单属性选择长路径感知(
https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath)

如何以编程方式检查调用进程是否具有长路径感知功能?请注意,仅检查操作系统版本或注册表项的值是不够的,因为Windows版本≥1607的情况下,系统范围内禁用长路径,并且长路径不显示该过程.

最佳答案 ntdll(在win10 1607中)导出下一个API BOOLEAN NTAPI RtlAreLongPathsEnabled(); – 所以你可以打电话给这个.如果LongPaths Enabled,则返回TRUE

这里代码spinet – 如果RtlAreLongPathsEnabled返回false – 返回STATUS_NAME_TOO_LONG(c0000106)

《如何以编程方式检查当前进程在Windows上是否具有长路径感知功能?》

系统需要将Win32路径转换为NT路径,然后才能在任何调用内核的文件函数中使用它.这是通过调用RtlDosPathNameTo * NtPathName *来完成的.这个函数,如果看到该路径超过MAX_PATH(〜) – 称为RtlAreLongPathsEnabled()并且仅在函数返回TRUE时继续工作.如果错误 – STATUS_NAME_TOO_LONG返回.

RtlAreLongPathsEnabled的代码很简单 – 当第一次调用时 – 它检查注册表(并且只有注册表)并保存结果.根本不寻求表现.这里确切的功能代码:

BOOLEAN RtlAreLongPathsEnabled()
{
    static BOOLEAN init;
    static BOOLEAN elp;
    if (!init)
    {
        init = true;
        HANDLE hKey;
        KEY_VALUE_PARTIAL_INFORMATION kvpi;
        STATIC_OBJECT_ATTRIBUTES(FileSystemRegKeyName, "\\registry\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\FileSystem");
        if (0 <= ZwOpenKey(&hKey, KEY_READ, &FileSystemRegKeyName))
        {
            STATIC_UNICODE_STRING(LongPathRegKeyValue, "LongPathsEnabled");
            if (0 <= ZwQueryValueKey(hKey, &LongPathRegKeyValue, KeyValuePartialInformation, &kvpi, sizeof(kvpi), &kvpi.TitleIndex) &&
                kvpi.Type == REG_DWORD && kvpi.DataLength == sizeof(DWORD))
            {
                elp = *(DWORD*)kvpi.Data != 0;
            }
            ZwClose(hKey);
        }
    }
    return elp;
}

所以我的结论 – 在当前构建的长路径行为仅依赖于注册表设置,绝对不依赖于应用程序清单,尽管MSDN.

对于下来的选票 – 对我来说简直有趣 – 有人来自你构建测试应用程序(有和没有清单)并自己测试,或者你只能阅读文档?

对于那些发现自己很困难,或者懒得自己编写代码的人.你可以用这段代码测试:

BOOL CreateFolder(LPCWSTR lpPathName)
{
    return CreateDirectoryW(lpPathName, 0) || GetLastError() == ERROR_ALREADY_EXISTS;
}

void LPT()
{
    WCHAR name[128], path[0x8000], *c;

    if (!SHGetFolderPath(0, CSIDL_PROFILE , 0, 0, path))
    {
        *name = '\\';
        __stosw((PUSHORT)name + 1, '3', RTL_NUMBER_OF(name) - 2);
        name[RTL_NUMBER_OF(name) - 1] = 0;

        c = path + wcslen(path);

        int n = 4;
        do 
        {
            memcpy(c, name, sizeof(name));
            c += RTL_NUMBER_OF(name) - 1;

            if (!CreateFolder(path))
            {
                break;
            }

        } while (--n);

        if (!n)
        {
            wcscpy(c, L"\\1.txt");

            HANDLE hFile = CreateFileW(path, FILE_GENERIC_WRITE, FILE_SHARE_VALID_FLAGS, 0, OPEN_ALWAYS, 0, 0);

            if (hFile != INVALID_HANDLE_VALUE)
            {
                CloseHandle(hFile);
                return ;
            }
        }
    }

    GetLastError();
}

并使用< ws2:longPathAware> true< / ws2:longPathAware>进行测试在清单中,LongPathsEnabled == 0在注册表中.它失败了?然后测试它没有清单但在注册表中使用LongPathsEnabled == 1.工作?

如果是这样我在Windows 10上测试.版本1607. build 14393.0

在win10 1709实现改变了:现在RtlAreLongPathsEnabled非常简单:

《如何以编程方式检查当前进程在Windows上是否具有长路径感知功能?》

BOOLEAN RtlAreLongPathsEnabled()
{
    return NtCurrentTeb()->ProcessEnvironmentBlock->IsLongPathAwareProcess;
}

在以前的版本中是:

《如何以编程方式检查当前进程在Windows上是否具有长路径感知功能?》

点赞