Get the DLL-file for a COM-Object without using CLSID and registry in c++

一世执手 提交于 2019-12-23 18:14:51

问题


Is it possible to get the DLL-filename for a loaded COM-Object without using the CLSID and a registry lookup?

I have an IUnknown or in my case an IBaseFilter interface pointer and now I want to get the DLL-filename who created this COM-Object. Can I use the object point adress to reverse lookup the loaded module where it was created? And then get the HMODULE to use it in GetModuleFileName.


回答1:


Only using some hacks, naturally. The object itself is on the heap, which is shared, but you could see where the its virtual table resides - it should be almost universally in the read-only data section of the creator's binary.

So load the first pointer in the object, as that's where virtual table pointers reside in Windows COM ABI:

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

Then I originally suggested to do some circus with EnumProcessModules() like e.g. here, call GetModuleInformation() on each module and check if the vtbl pointer falls into its memory ranges. Stupid me, I forgot about VirtualQueryEx(), so better do it as Roman described in his answer.

Of course, all this can work only for in-process COM objects and where there are no proxies involved. I assume it can still be useful in your DirectShow case though.

Also see the comment about using IPersist::GetClassId() and registry lookup, it should apply nicely to most DirectShow filters.




回答2:


Yirkha's answer is in good standing and I have two notes to add:

  1. DirectShow filters are typically old school C++ COM objects with virtual method table residing in code segment, with no proxy/stub code as long as we are inside single process. That is, the hacks of resolving module from interface pointer do work well.

  2. There is an easier replacement for EnumProcessModules/GetModuleInformation walk along module list. VirtualQueryEx can locate the base address of the DLL directly:

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. This is something we also do in both DirectShowSpy here , and also in GraphStudioNext.



来源:https://stackoverflow.com/questions/23505194/get-the-dll-file-for-a-com-object-without-using-clsid-and-registry-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!