You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Minifilter获取文件打开路径异常:NTFS Junction场景不符合预期

问题根源分析

你遇到的问题核心在于FLT_FILE_NAME_ALLOW_QUERY_ON_REPARSE这个标志的作用——当你设置它时,FltGetFileNameInformation会等待系统完成重解析点的处理后再查询文件名,因此返回的是解析后的真实路径,而非用户最初打开文件时使用的原始路径。这和你依赖FLT_FILE_NAME_OPENED获取"打开时名称"的预期直接冲突了。

另外,NTFS junction的处理逻辑是:系统会先接收用户的原始打开请求(比如\Device\HarddiskVolume2\a\b\b.txt),处理重解析点后发起内部请求打开真实路径(\Device\HarddiskVolume2\b\b.txt),你的Post-Create回调实际触发的是这个内部请求,默认情况下拿到的自然是真实路径。

解决方案:获取重解析前的原始路径

要获取用户最初使用的打开路径,你需要使用FLT_FILE_NAME_REPARSE_ORIGINAL这个文件名类型标志,它专门用于获取重解析处理前的原始请求路径。结合回退逻辑处理非重解析场景,修改后的代码如下:

PFLT_FILE_NAME_INFORMATION pFNI = NULL;
NTSTATUS Status;

// 优先尝试获取重解析前的原始路径
Status = FltGetFileNameInformation(
    Data,
    FLT_FILE_NAME_REPARSE_ORIGINAL | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
    &pFNI
);
if (NT_SUCCESS(Status)) {
    DBG_PRINT_INFO("Original opened path: '%wZ'", pFNI->Name);
    // 这里可以提取父目录路径用于查找配置文件
    FltReleaseFileNameInformation(pFNI);
    pFNI = NULL;
} else {
    // 非重解析场景,回退到常规的FLT_FILE_NAME_OPENED
    Status = FltGetFileNameInformation(
        Data,
        FLT_FILE_NAME_OPENED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP,
        &pFNI
    );
    if (NT_SUCCESS(Status)) {
        DBG_PRINT_INFO("Opened path: '%wZ'", pFNI->Name);
        FltReleaseFileNameInformation(pFNI);
        pFNI = NULL;
    } else {
        DBG_PRINT_ERROR("FltGetFileNameInformation failed: %#x", Status);
        __leave;
    }
}
关键注意事项
  1. 移除FLT_FILE_NAME_ALLOW_QUERY_ON_REPARSE:这个标志会强制等待重解析完成,导致你无法拿到原始路径,必须从标志组合中移除。
  2. 释放文件名信息:每次调用FltGetFileNameInformation成功后,务必调用FltReleaseFileNameInformation释放资源,避免内存泄漏(你原来的代码缺少这一步,需要补上)。
  3. 回退逻辑的必要性FLT_FILE_NAME_REPARSE_ORIGINAL仅在请求经过重解析处理时有效,非重解析场景下会返回失败,因此必须回退到FLT_FILE_NAME_OPENED保证兼容性。

这样修改后,当用户通过junction打开文件时,你就能拿到\Device\HarddiskVolume2\a\b\b.txt这个原始路径,进而正确找到父目录下的配置文件了。

内容的提问来源于stack exchange,提问作者Wade Brainerd

火山引擎 最新活动