65.9K
CodeProject is changing. Read more.
Home

Dump full interfaces information of an object

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (4 votes)

May 17, 2004

1 min read

viewsIcon

29965

downloadIcon

422

How to understand more about certain objects' implementation details

Introduction

When you get an interface pointer, you may want to know a little more about it. Then you can make full use of it. The following class will dump all other interfaces sit in the same object instance.

Using the code

You just need to declare an instance of the IFDump class in your control class or any other place where you can get an interface pointer. This class will get and cache all registered interfaces into a list in its ctor. Soon after, you can call DumpIF to dump all interfaces for you.

If you think an unregistered typelib which may involve with this interface, you can use GetEntriesFromRegistry to add it, then IFDump class will dump it with a known name, or it will be invisible in the output report.

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;
    }
};

The last step is, call DumpIF like the following:

    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;
    }

History

If you have any other requirements about this class, and you don't want to do it yourself, please drop me a line, I will do my best. Or if you find out any masterpiece which was done by Don Box, Keith Brown or Chris sells, just do the same thing, please let me know. Thanks for your time!