65.9K
CodeProject 正在变化。 阅读更多。
Home

转储对象的完整接口信息

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (4投票s)

2004年5月17日

1分钟阅读

viewsIcon

30305

downloadIcon

422

如何更好地了解某些对象的实现细节。

引言

当你获得一个接口指针时,你可能想了解更多关于它的信息。这样你才能充分利用它。下面的类将会转储同一个对象实例中的所有其他接口。

使用代码

你只需要在你的控件类或者任何可以获得接口指针的地方声明一个 IFDump 类的实例。这个类会在它的 ctor 中获取并缓存所有注册的接口到一个列表中。之后,你可以调用 DumpIF 来转储所有接口。

如果你认为有一个未注册的 typelib 可能与这个接口相关,你可以使用 GetEntriesFromRegistry 来添加它,然后 IFDump 类将会以已知的名称转储它,否则它将在输出报告中不可见。

typedef struct IFPoint
{
    CComBSTR    key;
    ULONG**    addr;
    int    ikind;
    CSimpleArray<MEMORY_BASIC_INFORMATION> mia;
} *pIFPoint;

class IFDump
{
public:
    IFDump()
    {
        GetSystemInfo(&sysinfo);
        limit = sysinfo.lpMinimumApplicationAddress;
        GetEntriesFromRegistry();
    }

    ~IFDump()
    {
        Reset();
        ikeys.RemoveAll();
    }
    CAtlMap<IID,CComBSTR> ikeys;

private:
    CAtlList<IFPoint*>    lstIF;
    SYSTEM_INFO sysinfo;
    LPVOID limit;

    BOOL GetEntriesFromRegistry()
    {
        BOOL Result= FALSE;
        HKEY        hKey1, hKey2;

        ULONG        index1 = 0;
        DWORD        cbName = MAX_PATH;
        TCHAR        tszClsid[MAX_PATH];
        TCHAR        tszSrcName[MAX_PATH];
        DWORD        cbValue = MAX_PATH;

        if (RegOpenKeyEx(HKEY_CLASSES_ROOT, _T("Interface"), 
              0, KEY_READ, &hKey1) == ERROR_SUCCESS)
        {
            while(RegEnumKeyEx(hKey1, index1++, tszClsid, &cbName, 
                      NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
            {
                cbName=MAX_PATH;
                if (RegOpenKeyEx(hKey1, tszClsid, 0, 
                    KEY_READ, &hKey2) == ERROR_SUCCESS)
                {
                    tszSrcName[0] = _T('\0');
                    RegQueryValueEx(hKey2,_T(""),NULL,NULL,
                                  (LPBYTE)tszSrcName,&cbValue);
                    IID iid;
                    CComBSTR bstrInterface(tszClsid);
                    IIDFromString(bstrInterface,&iid);
                    CComBSTR bstrkey(tszSrcName);
                    ikeys.SetAt(iid,bstrkey);
                    cbValue = MAX_PATH;
                    RegCloseKey(hKey2);
                }
                else
                    Result = FALSE;
            }

            RegCloseKey(hKey1);
        }

        return FALSE;
    }

    void QueryMem(ULONG* start,CSimpleArray<MEMORY_BASIC_INFORMATION>& array)
    {
        MEMORY_BASIC_INFORMATION buf;
        SIZE_T result;
        ULONG* p;
        LPVOID q;

        p = (ULONG*)((ULONG)start & ~(sysinfo.dwPageSize - 1));
        for (;;) {
            q = (LPVOID)(p - sysinfo.dwPageSize);
            if ((ULONG*)q > (ULONG*)p || q < limit) 
                break;
            result = VirtualQuery(q, &buf, sizeof(buf));

            if (result != sizeof(buf) || buf.AllocationBase == 0) 
                break;

            array.Add(buf);
            p = (ULONG*)(buf.AllocationBase);
        }
    }

public:
    BOOL Reset()
    {
        POSITION pos1 = lstIF.GetTailPosition();
        while(pos1!=NULL)
        {
            IFPoint* itmIF = lstIF.GetAt(pos1);
            delete itmIF;
            lstIF.GetPrev(pos1);
        }
        lstIF.RemoveAll();
        return TRUE;
    }

    BOOL OutPutResult()
    {
        TCHAR sz[0x1000];
        CComBSTR output;

        POSITION pos1 = lstIF.GetTailPosition();
        ULONG paddr0 = 0;
        while(pos1!=NULL)
        {
            IFPoint* itmIF = lstIF.GetAt(pos1);
            ULONG paddr = (ULONG)itmIF->addr;

            MEMORY_BASIC_INFORMATION buf;
            int icount = itmIF->mia.GetSize();
            if(icount>0)
            {
                buf = itmIF->mia[0];

                ATLTRACE("%08x %08x ",buf.BaseAddress,
                  (ULONG)buf.BaseAddress+(ULONG)buf.RegionSize);
            }
            ATLTRACE("\t");

            wsprintf(sz,_T("%d\t%08x\t%08x\t%s\r\n"),itmIF->ikind,
              itmIF->addr,*itmIF->addr,itmIF->key);
            OutputDebugString(sz);
            lstIF.GetPrev(pos1);
            paddr0 = paddr;
        }
        return TRUE;
    }

    BOOL AddEntriesFromTypeLib(LPOLESTR szFile)
    {
        HRESULT hr = S_FALSE;
        CComPtr<ITypeLib>  ptlib;
        hr = LoadTypeLibEx(szFile, REGKIND_NONE, &ptlib);
        if(FAILED(hr))    return FALSE;

        UINT uicount = ptlib->GetTypeInfoCount();
        for(UINT i=0;i<uicount;i++)
        {
            CComPtr<ITypeInfo> pti;
            hr = ptlib->GetTypeInfo(i,&pti);
            if(FAILED(hr))    break;    
        
            TYPEATTR* pTypeAttr;
            hr = pti->GetTypeAttr(&pTypeAttr);
            if(FAILED(hr))    break;    

            if(pTypeAttr->typekind==TKIND_INTERFACE||
                    pTypeAttr->typekind==TKIND_DISPATCH)
            {
                CComBSTR bstrName;
                hr = pti->GetDocumentation(-1, &bstrName, NULL, NULL, NULL);
                if(SUCCEEDED(hr))    
                    ikeys.SetAt(pTypeAttr->guid,bstrName);
            }

            pti->ReleaseTypeAttr(pTypeAttr);
        }
        return TRUE;
    }

    HRESULT DumpIF(CComPtr<IUnknown> spunk,int kind=0)
    {
        if(!spunk) return S_FALSE;
        HRESULT hr = S_FALSE;

        POSITION pos = ikeys.GetStartPosition();
        while(pos!=NULL)
        {
            CComPtr<IUnknown> xxx;
            hr =spunk->QueryInterface(ikeys.GetKeyAt(pos),(void**)&xxx);
            if(hr==S_OK)
            {
                IFPoint* itmIF    = new IFPoint;
                itmIF->addr        = (ULONG**)((INT_PTR)xxx.p);
                itmIF->ikind    = kind;
                itmIF->key        = ikeys.GetValueAt(pos);
                QueryMem((ULONG*)(xxx.p),itmIF->mia);

                POSITION pos1 = lstIF.GetTailPosition();
                if(pos1==NULL)
                    lstIF.AddTail(itmIF);
                else
                {
                    bool badded = false;
                    while(pos1!=NULL)
                    {
                        IFPoint* curIF = lstIF.GetAt(pos1);

                        if((ULONG)(itmIF->addr)<(ULONG)(curIF->addr))
                        {
                            lstIF.InsertAfter(pos1,itmIF);
                            badded = true;
                            break;
                        }
                        if((ULONG)(itmIF->addr)==(ULONG)(curIF->addr))
                        {
                            curIF->key += _T(" ");
                            curIF->key += ikeys.GetValueAt(pos);
                            lstIF.SetAt(pos1,curIF);
                            badded = true;
                            break;
                        }
                        lstIF.GetPrev(pos1);
                    }
                    if(!badded)
                        lstIF.AddHead(itmIF);
                }
            }
            if(xxx)
            {
                xxx.Release();
                xxx = NULL;
            }
            ikeys.GetNext(pos);
        }
        return hr;
    }
};

最后一步是,像下面这样调用 DumpIF

    IFDump ifd;

    HRESULT InPlaceActivate(LONG iVerb, const RECT* /*prcPosRect*/)
    {
        HRESULT hr = CComControl<CProber>::InPlaceActivate(iVerb);

        ifd.Reset();
        ifd.DumpIF(GetUnknown(),0);
        ifd.DumpIF(m_spClientSite.p,1);
        ifd.OutPutResult();
        return S_OK;
    }

历史

如果你对这个类有任何其他需求,并且不想自己动手实现,请与我联系,我会尽力而为。或者如果你发现了 Don Box、Keith Brown 或 Chris Sells 的任何杰作,请做同样的事情,并告诉我。感谢你的时间!

© . All rights reserved.