获取COM-Object的DLL文件,而不使用c ++中的CLSID和注册表

时间:2014-05-06 21:54:41

标签: c++ dll com directshow

是否可以在不使用CLSID和注册表查找的情况下获取加载的COM-Object的DLL-filename?

我有IUnknown或者我的情况是IBaseFilter接口指针,现在我想获取创建此COM-Object的DLL-filename。我可以使用对象点地址反向查找已创建它的已加载模块吗?然后让HMODULEGetModuleFileName中使用它。

2 个答案:

答案 0 :(得分:3)

Yirkha的回答是良好的,我有两个补充说明:

  1. DirectShow过滤器通常是旧式C ++ COM对象,虚拟方法表驻留在代码段中,只要我们在单个进程内,就没有代理/存根代码。也就是说,从接口指针解析模块的hack确实运行良好。

  2. EnumProcessModules / GetModuleInformation可以更轻松地替换模块列表。 VirtualQueryEx可以直接找到DLL的基地址:

  3. const VOID* pvVirtualTable = *((const VOID**) pBaseFilter);
    MEMORY_BASIC_INFORMATION Information;
    if(VirtualQueryEx(GetCurrentProcess(), pvVirtualTable, &Information,
      sizeof Information))
    {
      TCHAR pszPath[MAX_PATH] = { 0 };
      if(GetModuleFileName((HMODULE) Information.AllocationBase, pszPath,
        _countof(pszPath)))
      {
    

    P.S。我们也在DirectShowSpy here以及GraphStudioNext中执行此操作。

答案 1 :(得分:2)

自然只使用一些黑客攻击。对象本身位于堆上,它是共享的,但是你可以看到它的虚拟表所在的位置 - 它应该几乎普遍存在于创建者二进制文件的只读数据部分。

所以加载对象中的第一个指针,就像虚拟表指针驻留在Windows COM ABI中一样:

IBaseFilter* pFilter = ...;
char* vtbl = *reinterpret_cast<char**>(pFilter);

然后我最初建议用EnumProcessModules()做一些马戏团,例如here,在每个模块上调用GetModuleInformation()并检查vtbl指针是否落入其内存范围。愚蠢的我,我忘记了VirtualQueryEx(),所以罗马在他的回答中所描述的更好。

当然,所有这些只能用于进程内COM对象,并且不涉及代理。我认为它在你的DirectShow案例中仍然有用。

另请参阅有关使用IPersist::GetClassId()和注册表查找的注释,它应该适用于大多数DirectShow过滤器。