【问题标题】:How recognize Symbolic link files?如何识别符号链接文件?
【发布时间】:2020-07-18 05:47:50
【问题描述】:

我总是使用this solution 递归地枚举文件和文件夹。该代码工作得很好,向所有找到的人显示正确的文件/文件夹名称。但是存在识别symbolic link文件相关的问题,导致链接解决方案失败,例如:

如上图所示,这 3 个文件是指向某个地方的 dll 文件的符号链接文件。然后,执行上面提到的代码将打印:

  • api-ms-win-core-console-l1-1-0.dll

而不是

  • api-ms-win-core-console-l1-1-0.symlink

另一个类似的案例,使用了IoCreateFile() 函数。如果这接收到错误的文件名或对象属性(仍然是指链接答案的代码),也会失败并出现 ntstatus 错误 STATUS_OBJECT_PATH_NOT_FOUND 或与此问题相关的其他一些问题。

那么我的问题是:

是否有一些解决方案来识别我使用的链接代码可以工作的符号链接文件(以及为什么没有像ZwOpenFile 等任何其他功能)?

提前感谢您的任何建议。

版本:

这是一个代码,当符号链接作为文件名传递时,IoCreateFile() 函数失败:

#include <ntifs.h>
#include <ntddk.h>

HANDLE
MyIoOpenFile(
        IN PCWSTR FileName,
        IN ACCESS_MASK DesiredAccess,
        IN ULONG ShareAccess)
{
        NTSTATUS ntStatus;
        UNICODE_STRING uniFileName;
        OBJECT_ATTRIBUTES objectAttributes;
        HANDLE ntFileHandle;
        IO_STATUS_BLOCK ioStatus;
        
        if (KeGetCurrentIrql() > PASSIVE_LEVEL) {
            DbgPrint("KeGetCurrentIrql() > PASSIVE_LEVEL\n");
            return 0;
        }

        RtlInitUnicodeString(&uniFileName, FileName);
        InitializeObjectAttributes(&objectAttributes, &uniFileName,
                OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);

        ntStatus = IoCreateFile(&ntFileHandle,
                DesiredAccess,
                &objectAttributes,
                &ioStatus,
                0,
                FILE_ATTRIBUTE_NORMAL,
                ShareAccess,
                FILE_OPEN,
                0,
                NULL,
                0,
                0,
                NULL,
                IO_NO_PARAMETER_CHECKING);

        if (!NT_SUCCESS(ntStatus)) {
                DbgPrint("IoCreateFile() error - 0x%X \n", ntStatus);
                return 0;
        }

        return ntFileHandle;
}

//---------------------------------------------------------------------------

HANDLE hFileHandle = MyIoOpenFile(L"\\??\\C:\\Full-Path-FileName-Here",
                FILE_READ_ATTRIBUTES,
                FILE_SHARE_READ);
               
if (hFileHandle != 0) {
    DbgPrint("hFileHandle: %08X\n", hFileHandle);
    ZwClose(hFileHandle);
}

【问题讨论】:

  • 代码打印正确的文件名 api-ms-win-core-console-l1-1-0.dll 并在代码中检查符号链接/重解析点 - FILE_ATTRIBUTE_REPARSE_POINT
  • .symlink - 这不是扩展名,也不是文件名的一部分。这是在 Type 列内 - 文件类型的简单描述。 api-ms-win-core-console-l1-1-0.symlink - 这是错误的名称 - 不存在这样的文件。真正的文件名是 api-ms-win-core-console-l1-1-0.dll 你得到的(你在系统上测试选项不显示已知文件扩展名,如 . dll 开启)
  • @RbMm,那么不存在操纵符号链接(这些快捷方式:D)文件的解决方案,例如删除(之前将您的句柄作为参考)-IoCreateFile/ZwOpenFile?已经知道它总是指向不存在的“api-ms-win-core-console-l1-1-0.dll”(STATUS_OBJECT_PATH_NOT_FOUND)。
  • 您需要使用FILE_OPEN_REPARSE_POINT 选项。猜你不使用它。如果你想删除这个文件 - 用FILE_OPEN_REPARSE_POINT|FILE_DELETE_ON_CLOSE打开它
  • 你的代码当然是错的——没有FILE_OPEN_REPARSE_POINT选项

标签: c++ windows filesystems driver kernel-mode


【解决方案1】:

来自微软文档:

FILE_ATTRIBUTE_REPARSE_POINT - 具有关联重分析点的文件或目录,或者是符号链接的文件。

所以你可以使用GetFileAttributes 来检测符号链接:

LPCWSTR lpszFileName = /* get file name */;

if (GetFileAttributes(lpszFileName) & FILE_ATTRIBUTE_REPARSE_POINT)
{
    // Symbolic link
}

有关错误检查和内核模式 API 的更多信息,请参阅 cmets

【讨论】:

  • (GetFileAttributes(lpszFileName) == FILE_ATTRIBUTE_REPARSE_POINT) 是错误检查。可以是文件上的多个属性。必须是GetFileAttributes(lpszFileName) &amp; FILE_ATTRIBUTE_REPARSE_POINT(并单独检查没有返回INVALID_FILE_ATTRIBUTES。内核中也不存在此api。如果我们还没有FileAttributes,则需要调用ZwQueryFullAttributesFile
  • @RbMm 我忘了,GetFileAttributes 返回位掩码 - 已修复
  • 符号链接是数十种重解析点中的一种。一类称为“名称代理”(即IsReparseTagNameSurrogate)的重解析点具有符号链接行为(即“文件或目录代表系统中的另一个命名实体”),例如IO_REPARSE_TAG_SYMLINK 和IO_REPARSE_TAG_MOUNT_POINT。但请注意,在重新解析相对符号链接(IO_REPARSE_TAG_SYMLINK 使用相对目标路径重新解析点)或在远程路径中访问时,这两个具有不同的行为,并且不应盲目地将挂载点视为等同于符号链接。
猜你喜欢
  • 2012-03-13
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多