【问题标题】:Can I Initialize a IThumbnailProvider Object with a File?我可以用文件初始化 IThumbnailProvider 对象吗?
【发布时间】:2019-12-01 18:15:56
【问题描述】:

我正在编写一个实现IInitializeWithFile 的缩略图提供程序,但是传递给初始化方法的文件路径无效。

  • 我在HKCR\CLSID\{CLSID of my thumbnail provider} 的注册表中创建了"DisableProcessIsolation" 值,以退出进程隔离,以便能够使用IInitializeWithFile/IInitializeWithItem 而不是IInitializeWithStream
  • 我用IInitializeWithStream 测试了我的代码,效果很好。 从带有SHCreateStreamOnFile() 的文件路径中检索IStream 对象失败。
  • 传递的文件路径无效(PathFileExistsW(FilePath) 返回 false)。
  • 缩略图提供程序已正确注册(注册表项均已正确设置,并且在改用IInitializeWithStream 时工作正常)。

我不能使用IInitializeWithStream的原因是我需要文件的路径才能返回正确的缩略图。

IFACEMETHODIMP RecipeThumbnailProvider::Initialize(LPCWSTR FilePath, DWORD Mode){
    std::wofstream *FileStream1 = new std::wofstream("D:\\test1.txt");

    if(!PathFileExistsW(FilePath)){//check if the passed path is valid
        (*FileStream1)<< L"path invalid";
    }else{
        (*FileStream1)<<L"path valid" << FilePath;
    }
    (*FileStream1).close();

    // A handler instance should be initialized only once in its lifetime. 
    HRESULT hr = ERROR_ALREADY_INITIALIZED;
    if (m_pStream == NULL)
    {
        hr = SHCreateStreamOnFileW(FilePath, Mode, &m_pStream);//get IStream from file path
    }
    return hr;
}

【问题讨论】:

  • 这个无效路径是什么样的?
  • 传递的路径长3个字符,看起来像“F0_”
  • 我只能建议您调试调用 Initialize 的代码。如果这是 32 位,您应该能够看到 pushcall 之前的路径地址(3 个推送中的第 2 个)。
  • 只知道文件名OK还是需要完整路径?
  • 我需要路径,因为实际缩略图存储在父文件夹中的某个位置。

标签: c++ winapi com thumbnails


【解决方案1】:

您似乎只能在 Windows Vista 中使用IInitializeWithStream

我在这里做了一些广泛的测试(参见this pull requestthis pull request。测试表明Initialize 方法是调用的,除非服务器实现IInitializeWithStream

最新的 MSDN 文档位于:

https://docs.microsoft.com/en-us/windows/win32/api/thumbcache/nn-thumbcache-ithumbnailprovider

似乎也暗示了这一点:

Shell 使用项目的流调用 IInitializeWithStream::Initialize,并且 IInitializeWithStream 是在进程外加载 IThumbnailProvider 实例时使用的唯一初始化接口(用于隔离目的)。这是所有 IThumbnailCache 代码路径的 Windows 主代码路径。

当第 3 方不使用 IThumbnailCache API 请求处理程序时,可以使用 IInitializeWithItem 或 IInitializeWithFile 初始化缩略图实现,但这并不常见。如果您实现 IInitializeWithItem,Shell 将使用项目的 IShellItem 表示调用 IInitializeWithItem::Initialize。如果您实现 IInitializeWithFile,Shell 会使用文件的路径调用 IInitializeWithFile::Initialize。

我相信由于here提到的安全问题,微软可能已经确保shell只会使用IInitializeWithStream

我仍在调查是否有一些迂回的方式从IStream 获取路径 - 到目前为止我只能获得显示名称。但是,如果 IStream 的对象还实现了其他一些接口,则可能可以查询它的路径,如果我发现方法,我会更新这个答案。

【讨论】:

  • IInitializeWithStream 是首选的接口,但它不是唯一的接口。这个界面的问题是你对文件的来源视而不见。如果这是您需要的,那么应该使用 IInitializeWithFile 或 Item。他们更喜欢 Stream iface,但众所周知,MS 并不反对任何东西。我认为这种方法中最好的防御是保护自己免受输入的影响。我看到它向我发送数字(一个 int64 0x100)...而不是指针。
  • Lompican 所以你能够成功地实现 IInitializeWithFile 并且 Initialize 被调用了?我尝试修改 RecipeThumbnailHandler 示例以使用 IInitializeWithFile 但从未调用 Initialize。您有机会发布一些示例代码吗?实际上,我一开始忘记更新 QueryInterface,虽然它仍然引用了 IInitilizeWithStream Initialize,但实际上被调用了,但我得到了文件路径的垃圾。
猜你喜欢
  • 2011-10-07
  • 1970-01-01
  • 1970-01-01
  • 2019-01-24
  • 1970-01-01
  • 2020-01-04
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多