• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-341  評論-2670  文章-0  trackbacks-0
                GacUI到了撰寫文檔的時候了。雖然GacUI本身的功能還沒有全部完成,但是發布一個alpha版還是可以的。因此GacUI需要一份文檔。自從.net語言支持XML注釋生成文檔之后,Visual Studio的本地C++也支持使用XML注釋了。只要打開了[工程屬性 -> C/C++ -> Output Files -> Generate XML Documentation Files]之后,Visual Studio會在編譯本地C++工程之后,將所有的XML注釋收集起來,放在和可執行文件同一個目錄下的<ProjectName.xml>里面。然后我就嘗試bing了一下有沒有從C++的XML文檔生成可讀文檔的工具,結果發現只有.net才支持。

                后來我稍微研究了一下(詳細內容將會在下一篇博客透露),發現之所以沒人寫這個工具,是因為只有.net的可執行文件才包含足夠多的元數據,而且這些元數據是必須的,否則無法生成一個完整的文檔。舉個例子,雖然<ProjectName.xml>包含了xml注釋和該注釋所在的符號,但是卻沒有包含該符號的結構信息。結果你試圖生成一個函數的文檔的時候,發現你獲取不到它的返回類型!不過這也是情有可原的,因為本地C++程序根本就沒有元數據。

                由此我聯想到了之前寫程序讀pdb的時候的一些內容,我想到pdb生成的那份xml顯然是可以當成元數據的。而且我找到了一個方法,讓你在使用Visual Studio2010的PDB API msdia100.dll的時候,可以不需要安裝Visual Studio 2010了。下面就來介紹PDB Dumper的代碼。

                首先是main函數。main函數做的工作跟之前的這篇博客說的一樣,當然還是要創建一個IDiaSymbol的COM對象。一般來說,COM對象是需要被注冊到windows里面(基本上都在注冊表里)才能使用CoCreateInstance來創建。但是后來我發現msdia100.dll十分良心,還提供了一個NoRegCoCreate函數,可以在你只有msdia100.dll但卻沒有注冊它的COM對象的情況下創建該對象:
            #include <Windows.h>
            #include 
            <iostream>
            #include 
            <string>
            #include 
            "dia2.h"
            #include 
            "diacreate.h"

            #pragma comment(lib, 
            "diaguids.lib")

            namespace dumppdb
            {
                
            extern void DumpPdbToXml(IDiaSymbol* exeSymbol, const wchar_t* xml);
            }

            IDiaSymbol
            * CreateDiaSymbol(const wchar_t* pdbPath)
            {
                IDiaDataSource
            * pSource=0;
                IDiaSession
            * pSession=0;
                IDiaSymbol
            * pSymbol=0;
                CoInitialize(NULL);
                
            //HRESULT hr = CoCreateInstance(
                
            //    CLSID_DiaSource,
                
            //    NULL,
                
            //    CLSCTX_INPROC_SERVER,
                
            //    IID_IDiaDataSource,
                
            //    (void**) &pSource
                
            //    );
                HRESULT hr = NoRegCoCreate(
                    L
            "msdia100.dll",
                    CLSID_DiaSource,
                    IID_IDiaDataSource,
                    (
            void**&pSource
                    );
                
            if(SUCCEEDED(hr))
                
            if(SUCCEEDED(pSource->loadDataFromPdb(pdbPath)))
                
            if(SUCCEEDED(pSource->openSession(&pSession)))
                
            if(SUCCEEDED(pSession->get_globalScope(&pSymbol)))
                {
                    
            return pSymbol;
                }
                
            return 0;
            }

            int wmain(int argc, wchar_t* argv[])
            {
                
            if(argc==3)
                {
                    std::wcout
            <<L"importing "<<argv[1]<<std::endl;
                    IDiaSymbol
            * exeSymbol=CreateDiaSymbol(argv[1]);
                    
            if(exeSymbol)
                    {
                        std::wcout
            <<L"exporting "<<argv[2]<<std::endl;
                        dumppdb::DumpPdbToXml(exeSymbol, argv[
            2]);
                        std::wcout
            <<L"exported "<<argv[2]<<std::endl;
                    }
                    
            else
                    {
                        std::wcout
            <<L"Failed to read pdb("<<argv[1]<<L")"<<std::endl;
                    }
                }
                
            else
                {
                    std::wcout
            <<L"Pdb2Xml.exe <pdb-path> <xml-path>"<<std::endl;
                }
                
            return 0;
            }

                這里的dia2.h、diacreate.h、diaguids.lib和msdia100.dll都可以在C:\Program Files (x86)\Microsoft Visual Studio 10.0\DIA SDK下找到。我們需要做的就是將這些文件都復制到我們的工程目錄下面。至于如何讀取IDiaSymbol的內容,各位就自己查MSDN了。下面貼出我使用IDiaSymbol將PDB的關鍵內容輸出成xml的函數,也就是上面的代碼提到的DumpPdbToXml函數了:

            #include "Dia2.h"
            #include 
            "..\..\..\..\..\Library\Stream\Accessor.h"
            #include 
            "..\..\..\..\..\Library\Stream\CharFormat.h"
            #include 
            "..\..\..\..\..\Library\Stream\FileStream.h"
            #include 
            "..\..\..\..\..\Library\Stream\CacheStream.h"
            #include 
            "..\..\..\..\..\Library\Collections\Dictionary.h"

            using namespace vl;
            using namespace vl::collections;
            using namespace vl::stream;

            namespace dumppdb
            {

                
            //--------------------------------------------------------------------

                
            void PrintString(TextWriter& file, const wchar_t* text, int len=-1)
                {
                    
            if(len==-1) len=(int)wcslen(text);
                    file.WriteString(text, len);
                }

                
            void PrintSpaces(TextWriter& file, int level)
                {
                    
            for(int i=0;i<level;i++) PrintString(file, L"  ");
                }

                
            void PrintEscapedName(TextWriter& file, const wchar_t* name)
                {
                    
            const wchar_t* head=name;
                    
            const wchar_t* reading=head;
                    
            while(*reading)
                    {
                        
            switch(*reading)
                        {
                        
            case L'<':
                            PrintString(file, head, reading
            -head);
                            PrintString(file, L
            "&lt;");
                            head
            =reading+1;
                            reading
            =head;
                            
            break;
                        
            case L'>':
                            PrintString(file, head, reading
            -head);
                            PrintString(file, L
            "&gt;");
                            head
            =reading+1;
                            reading
            =head;
                            
            break;
                        
            case L'&':
                            PrintString(file, head, reading
            -head);
                            PrintString(file, L
            "&amp;");
                            head
            =reading+1;
                            reading
            =head;
                            
            break;
                        
            case L'\"':
                            PrintString(file, head, reading
            -head);
                            PrintString(file, L
            "&quot;");
                            head
            =reading+1;
                            reading
            =head;
                            
            break;
                        
            default:
                            reading
            ++;
                        }
                    }
                    PrintString(file, head, reading
            -head);
                }

                
            void PrintXMLOpen(
                    TextWriter
            & file, int level, const wchar_t* tagName, const wchar_t* symbolName
                    ,
            const wchar_t* a1=0const wchar_t* v1=0
                    ,
            const wchar_t* a2=0const wchar_t* v2=0
                    ,
            const wchar_t* a3=0const wchar_t* v3=0
                    )
                {
                    PrintSpaces(file, level);
                    PrintString(file, L
            "<");
                    PrintString(file, tagName);
                    
            if(symbolName)
                    {
                        PrintString(file, L
            " name=\"");
                        PrintEscapedName(file, symbolName);
                        PrintString(file, L
            "\"");
                    }
                    
            if(a1)
                    {
                        PrintString(file, L
            " ");
                        PrintString(file, a1);
                        PrintString(file, L
            "=\"");
                        PrintEscapedName(file, v1);
                        PrintString(file, L
            "\"");
                    }
                    
            if(a2)
                    {
                        PrintString(file, L
            " ");
                        PrintString(file, a2);
                        PrintString(file, L
            "=\"");
                        PrintEscapedName(file, v2);
                        PrintString(file, L
            "\"");
                    }
                    
            if(a3)
                    {
                        PrintString(file, L
            " ");
                        PrintString(file, a3);
                        PrintString(file, L
            "=\"");
                        PrintEscapedName(file, v3);
                        PrintString(file, L
            "\"");
                    }
                    PrintString(file, L
            " >\r\n");
                }

                
            void PrintXMLClose(TextWriter& file, int level, const wchar_t* tagName)
                {
                    PrintSpaces(file, level);
                    PrintString(file, L
            "</");
                    PrintString(file, tagName);
                    PrintString(file, L
            ">\r\n");
                }

                
            //--------------------------------------------------------------------

                Dictionary
            <WString, IDiaSymbol*> udtSymbols;
                Dictionary
            <WString, IDiaSymbol*> funcSymbols;

                
            void AddOrRelease(Dictionary<WString, IDiaSymbol*>& symbols, IDiaSymbol* symbol)
                {
                    
            // get name
                    BSTR nameBSTR=0;
                    
            if(SUCCEEDED(symbol->get_name(&nameBSTR)) && nameBSTR)
                    {
                        WString name
            =nameBSTR;
                        
            if(!symbols.Keys().Contains(name))
                        {
                            
            // record class symbol
                            symbols.Add(name, symbol);
                            symbol
            =0;
                        }
                    }
                    
            if(symbol) symbol->Release();
                }

                
            void AddUdtOrRelease(IDiaSymbol* udtType)
                {
                    AddOrRelease(udtSymbols, udtType);
                }

                
            void AddFuncOrRelease(IDiaSymbol* funcSymbol)
                {
                    AddOrRelease(funcSymbols, funcSymbol);
                }

                
            void FindClasses(IDiaSymbol* exeSymbol)
                {
                    {
                        
            // enumerate classes
                        IDiaEnumSymbols* udtEnum=0;
                        
            if(SUCCEEDED(exeSymbol->findChildren(SymTagUDT, NULL, nsNone, &udtEnum)))
                        {
                            DWORD udtCelt
            =0;
                            IDiaSymbol
            * udtSymbol=0;
                            
            while(SUCCEEDED(udtEnum->Next(1&udtSymbol, &udtCelt)) && udtSymbol && udtCelt)
                            {
                                AddUdtOrRelease(udtSymbol);
                            }
                        }
                    }
                    {
                        
            // enumerate enums
                        IDiaEnumSymbols* enumEnum=0;
                        
            if(SUCCEEDED(exeSymbol->findChildren(SymTagEnum, NULL, nsNone, &enumEnum)))
                        {
                            DWORD enumCelt
            =0;
                            IDiaSymbol
            * enumSymbol=0;
                            
            while(SUCCEEDED(enumEnum->Next(1&enumSymbol, &enumCelt)) && enumSymbol && enumCelt)
                            {
                                AddUdtOrRelease(enumSymbol);
                            }
                        }
                    }
                    {
                        
            // enumerate compilands
                        IDiaEnumSymbols* compilandEnum=0;
                        
            if(SUCCEEDED(exeSymbol->findChildren(SymTagCompiland, NULL, nsNone, &compilandEnum)))
                        {
                            DWORD compilandCelt
            =0;
                            IDiaSymbol
            * compilandSymbol=0;
                            
            while(SUCCEEDED(compilandEnum->Next(1&compilandSymbol, &compilandCelt)) && compilandSymbol && compilandCelt)
                            {
                                
            // enumerate functions
                                IDiaEnumSymbols* functionEnum=0;
                                
            if(SUCCEEDED(compilandSymbol->findChildren(SymTagFunction, NULL, nsNone, &functionEnum)))
                                {
                                    DWORD functionCelt
            =0;
                                    IDiaSymbol
            * functionSymbol=0;
                                    
            while(SUCCEEDED(functionEnum->Next(1&functionSymbol, &functionCelt)) && functionSymbol && functionCelt)
                                    {
                                        IDiaSymbol
            * udtType=0;
                                        
            if(SUCCEEDED(functionSymbol->get_classParent(&udtType)) && udtType)
                                        {
                                            AddUdtOrRelease(udtType);
                                            functionSymbol
            ->Release();
                                        }
                                        
            else
                                        {
                                            AddFuncOrRelease(functionSymbol);
                                        }
                                    }
                                    functionEnum
            ->Release();
                                }
                                compilandSymbol
            ->Release();
                            }
                            compilandEnum
            ->Release();
                        }
                    }
                }

                
            //--------------------------------------------------------------------

                
            const wchar_t* GetAccessName(enum CV_access_e access)
                {
                    
            switch(access)
                    {
                    
            case CV_private: return L"private";
                    
            case CV_protected: return L"protected";
                    
            case CV_public: return L"public";
                    
            defaultreturn L"";
                    }
                }

                
            const wchar_t* GetCallingConversionName(enum CV_call_e callconv)
                {
                    
            switch(callconv)
                    {
                    
            case CV_CALL_NEAR_C: return L"cdecl";
                    
            case CV_CALL_NEAR_FAST: return L"fastcall";
                    
            case CV_CALL_NEAR_STD: return L"stdcall";
                    
            case CV_CALL_NEAR_SYS: return L"syscall";
                    
            case CV_CALL_THISCALL: return L"thiscall";
                    
            case CV_CALL_CLRCALL: return L"clrcall";
                    
            defaultreturn L"";
                    }
                }

                
            const wchar_t* GetBasicTypeName(enum BasicType type, int length)
                {
                    
            switch(type)
                    {
                    
            case btVoid:        return L"void";
                    
            case btChar:        return L"char";
                    
            case btWChar:        return L"wchar_t";
                    
            case btInt:
                    
            case btLong:        return length==1?L"signed __int8":length==2?L"signed __int16":length==4?L"signed __int32":length==8?L"signed __int64":L"[UnknownSInt]";
                    
            case btUInt:
                    
            case btULong:        return length==1?L"unsigned __int8":length==2?L"unsigned __int16":length==4?L"unsigned __int32":length==8?L"unsigned __int64":L"[UnknownUInt]";
                    
            case btFloat:        return length==4?L"float":length==8?L"double":L"[UnknownFloat]";
                    
            case btBool:        return L"bool";

                    
            case btBCD:            return L"[BCD]";
                    
            case btCurrency:    return L"[Currency]";
                    
            case btDate:        return L"[Date]";
                    
            case btVariant:        return L"[Variant]";
                    
            case btComplex:        return L"[Complex]";
                    
            case btBit:            return L"[Bit]";
                    
            case btBSTR:        return L"[BSTR]";
                    
            case btHresult:        return L"[HRESULT]";
                    
            default:            return L"[NoType]";
                    }
                }

                
            //--------------------------------------------------------------------

                
            extern void DumpType(TextWriter& file, IDiaSymbol* typeSymbol, int level);

                
            void DumpTypeHelper(TextWriter& file, IDiaSymbol* typeSymbol, int level, const wchar_t* tagName, const wchar_t* symbolName, bool close=true)
                {
                    BOOL constType
            =FALSE, volatileType=FALSE;
                    typeSymbol
            ->get_constType(&constType);
                    typeSymbol
            ->get_volatileType(&volatileType);
                    PrintXMLOpen(file, level, tagName, symbolName, L
            "const", (constType?L"true":L"false"), L"volatile", (volatileType?L"true":L"false"));
                    
            if(close)
                    {
                        PrintXMLClose(file, level, tagName);
                    }
                }

                
            void DumpFunctionType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
                {
                    DumpTypeHelper(file, typeSymbol, level, L
            "function", NULL, false);
                    {
                        CV_call_e callconv;
                        typeSymbol
            ->get_callingConvention((DWORD*)&callconv);
                        PrintXMLOpen(file, level
            +1, L"callconv", NULL, L"value", GetCallingConversionName(callconv));
                        PrintXMLClose(file, level
            +1, L"callconv");
                        PrintXMLOpen(file, level
            +1, L"arguments", NULL);
                        {
                            IDiaEnumSymbols
            * argumentEnum=0;
                            
            if(SUCCEEDED(typeSymbol->findChildren(SymTagFunctionArgType, NULL, nsNone, &argumentEnum)) && argumentEnum)
                            {
                                DWORD argumentCelt
            =0;
                                IDiaSymbol
            * argumentSymbol=0;
                                
            while(SUCCEEDED(argumentEnum->Next(1&argumentSymbol, &argumentCelt)) && argumentSymbol && argumentCelt)
                                {
                                    IDiaSymbol
            * argumentType=0;
                                    
            if(SUCCEEDED(argumentSymbol->get_type(&argumentType)))
                                    {
                                        PrintXMLOpen(file, level
            +2, L"argument", NULL);
                                        DumpType(file, argumentType, level
            +3);
                                        PrintXMLClose(file, level
            +2, L"argument");
                                        argumentType
            ->Release();
                                    }
                                    argumentSymbol
            ->Release();
                                }
                                argumentEnum
            ->Release();
                            }
                        }
                        PrintXMLClose(file, level
            +1, L"arguments");
                    }
                    IDiaSymbol
            * returnTypeSymbol=0;
                    
            if(SUCCEEDED(typeSymbol->get_type(&returnTypeSymbol)) && returnTypeSymbol)
                    {
                        PrintXMLOpen(file, level
            +1, L"return", NULL);
                        DumpType(file, returnTypeSymbol, level
            +2);
                        PrintXMLClose(file, level
            +1, L"return");
                        returnTypeSymbol
            ->Release();
                    }
                    PrintXMLClose(file, level, L
            "function");
                }

                
            void DumpPointerType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
                {
                    IDiaSymbol
            * elementTypeSymbol=0;
                    
            if(SUCCEEDED(typeSymbol->get_type(&elementTypeSymbol)) && elementTypeSymbol)
                    {
                        BOOL lref
            =FALSE;
                        BOOL rref
            =FALSE;
                        typeSymbol
            ->get_reference(&lref);
                        typeSymbol
            ->get_RValueReference(&rref);
                        
            if(lref)
                        {
                            DumpTypeHelper(file, typeSymbol, level, L
            "reference", NULL, false);
                            DumpType(file, elementTypeSymbol, level
            +1);
                            PrintXMLClose(file, level, L
            "reference");
                        }
                        
            else if(rref)
                        {
                            DumpTypeHelper(file, typeSymbol, level, L
            "rightValueReference", NULL, false);
                            DumpType(file, elementTypeSymbol, level
            +1);
                            PrintXMLClose(file, level, L
            "rightValueReference");
                        }
                        
            else
                        {
                            DumpTypeHelper(file, typeSymbol, level, L
            "pointer", NULL, false);
                            DumpType(file, elementTypeSymbol, level
            +1);
                            PrintXMLClose(file, level, L
            "pointer");
                        }
                        elementTypeSymbol
            ->Release();
                    }
                }

                
            void DumpArrayType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
                {
                    IDiaSymbol
            * indexTypeSymbol=0;
                    IDiaSymbol
            * elementTypeSymbol=0;
                    
            if(SUCCEEDED(typeSymbol->get_type(&elementTypeSymbol)) && elementTypeSymbol)
                    {
                        ULONGLONG arraySize
            =0, elementSize=0;
                        typeSymbol
            ->get_length(&arraySize);
                        elementTypeSymbol
            ->get_length(&elementSize);
                        
            int elementCount=arraySize?(int)(arraySize/elementSize):0;
                        wchar_t elementCountBuffer[
            20];
                        _itow_s(elementCount, elementCountBuffer, 
            10);
                        
                        DumpTypeHelper(file, typeSymbol, level, L
            "array", NULL, false);
                        PrintXMLOpen(file, level
            +1, L"count", NULL, L"value", elementCountBuffer);
                        PrintXMLClose(file, level
            +1, L"count");
                        
            if(SUCCEEDED(typeSymbol->get_arrayIndexType(&indexTypeSymbol)) && indexTypeSymbol)
                        {
                            PrintXMLOpen(file, level
            +1, L"index", NULL);
                            DumpType(file, indexTypeSymbol, level
            +2);
                            PrintXMLClose(file, level
            +1, L"index");
                            indexTypeSymbol
            ->Release();
                        }
                        PrintXMLOpen(file, level
            +1, L"element", NULL);
                        DumpType(file, elementTypeSymbol, level
            +2);
                        PrintXMLClose(file, level
            +1, L"element");
                        PrintXMLClose(file, level, L
            "array");
                        elementTypeSymbol
            ->Release();
                    }
                }

                
            void DumpBaseType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
                {
                    
            enum BasicType basicType=btNoType;
                    ULONGLONG length
            =0;
                    
            if(SUCCEEDED(typeSymbol->get_baseType((DWORD*)&basicType)) && SUCCEEDED(typeSymbol->get_length(&length)))
                    {
                        DumpTypeHelper(file, typeSymbol, level, L
            "primitive", GetBasicTypeName(basicType, (int)length));
                    }
                }

                
            void DumpEnumType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
                {
                    BSTR nameBSTR
            =0;
                    
            if(SUCCEEDED(typeSymbol->get_name(&nameBSTR)) && nameBSTR)
                    {
                        DumpTypeHelper(file, typeSymbol, level, L
            "enumType", nameBSTR);
                    }
                }

                
            void DumpUserType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
                {
                    BSTR nameBSTR
            =0;
                    
            if(SUCCEEDED(typeSymbol->get_name(&nameBSTR)) && nameBSTR)
                    {
                        DumpTypeHelper(file, typeSymbol, level, L
            "classType", nameBSTR);
                    }
                }

                
            void DumpType(TextWriter& file, IDiaSymbol* typeSymbol, int level)
                {
                    
            enum SymTagEnum symTag=SymTagNull;
                    typeSymbol
            ->get_symTag((DWORD*)&symTag);
                    
            switch(symTag)
                    {
                    
            case SymTagFunctionType:
                        
            return DumpFunctionType(file, typeSymbol, level);
                    
            case SymTagPointerType:
                        
            return DumpPointerType(file, typeSymbol, level);
                    
            case SymTagArrayType:
                        
            return DumpArrayType(file, typeSymbol, level);
                    
            case SymTagBaseType:
                        
            return DumpBaseType(file, typeSymbol, level);
                    
            case SymTagEnum:
                        
            return DumpUserType(file, typeSymbol, level);
                    
            case SymTagUDT:
                        
            return DumpUserType(file, typeSymbol, level);
                    }
                }

                
            void DumpSymbolType(TextWriter& file, IDiaSymbol* symbolWithType, int symbolLevel)
                {
                    IDiaSymbol
            * typeSymbol=0;
                    
            if(SUCCEEDED(symbolWithType->get_type(&typeSymbol)) && typeSymbol)
                    {
                        PrintXMLOpen(file, symbolLevel
            +1, L"type", NULL);
                        DumpType(file, typeSymbol, symbolLevel
            +2);
                        PrintXMLClose(file, symbolLevel
            +1, L"type");
                        typeSymbol
            ->Release();
                    }
                }

                
            //--------------------------------------------------------------------

                
            void DumpBaseClasses(TextWriter& file, IDiaSymbol* udtSymbol)
                {
                    PrintXMLOpen(file, 
            2, L"baseClasses", NULL, false);
                    IDiaEnumSymbols
            * baseClassEnum=0;
                    
            if(SUCCEEDED(udtSymbol->findChildren(SymTagBaseClass, NULL, nsNone, &baseClassEnum)) && baseClassEnum)
                    {
                        DWORD baseClassCelt
            =0;
                        IDiaSymbol
            * baseClassSymbol=0;
                        
            while(SUCCEEDED(baseClassEnum->Next(1&baseClassSymbol, &baseClassCelt)) && baseClassSymbol && baseClassCelt)
                        {
                            CV_access_e access
            =CV_public;
                            baseClassSymbol
            ->get_access((DWORD*)&access);

                            BSTR nameBSTR
            =0;
                            
            if(SUCCEEDED(baseClassSymbol->get_name(&nameBSTR)) && nameBSTR)
                            {
                                PrintXMLOpen(file, 
            3, L"baseClass", nameBSTR, L"access", GetAccessName(access));
                                PrintXMLClose(file, 
            3, L"baseClass");
                            }
                            baseClassSymbol
            ->Release();
                        }
                        baseClassEnum
            ->Release();
                    }
                    PrintXMLClose(file, 
            2, L"baseClasses");
                }

                
            void DumpNestedClasses(TextWriter& file, IDiaSymbol* udtSymbol)
                {
                    PrintXMLOpen(file, 
            2, L"nestedClasses", NULL, false);
                    IDiaEnumSymbols
            * nestedClassEnum=0;
                    
            if(SUCCEEDED(udtSymbol->findChildren(SymTagUDT, NULL, nsNone, &nestedClassEnum)) && nestedClassEnum)
                    {
                        DWORD nestedClassCelt
            =0;
                        IDiaSymbol
            * nestedClassSymbol=0;
                        
            while(SUCCEEDED(nestedClassEnum->Next(1&nestedClassSymbol, &nestedClassCelt)) && nestedClassSymbol && nestedClassCelt)
                        {
                            BSTR nameBSTR
            =0;
                            
            if(SUCCEEDED(nestedClassSymbol->get_name(&nameBSTR)) && nameBSTR)
                            {
                                PrintXMLOpen(file, 
            3, L"nestedClass", nameBSTR);
                                PrintXMLClose(file, 
            3, L"nestedClass");
                            }
                            nestedClassSymbol
            ->Release();
                        }
                        nestedClassEnum
            ->Release();
                    }
                    PrintXMLClose(file, 
            2, L"nestedClasses");
                }

                
            void DumpTypedefs(TextWriter& file, IDiaSymbol* udtSymbol)
                {
                    PrintXMLOpen(file, 
            2, L"typedefs", NULL, false);
                    IDiaEnumSymbols
            * typedefEnum=0;
                    
            if(SUCCEEDED(udtSymbol->findChildren(SymTagTypedef, NULL, nsNone, &typedefEnum)) && typedefEnum)
                    {
                        DWORD typedefCelt
            =0;
                        IDiaSymbol
            * typedefSymbol=0;
                        
            while(SUCCEEDED(typedefEnum->Next(1&typedefSymbol, &typedefCelt)) && typedefSymbol && typedefCelt)
                        {
                            BSTR nameBSTR
            =0;
                            
            if(SUCCEEDED(typedefSymbol->get_name(&nameBSTR)) && nameBSTR)
                            {
                                PrintXMLOpen(file, 
            3, L"typedef", nameBSTR);
                                DumpSymbolType(file, typedefSymbol, 
            3);
                                PrintXMLClose(file, 
            3, L"typedef");
                            }
                            typedefSymbol
            ->Release();
                        }
                        typedefEnum
            ->Release();
                    }
                    PrintXMLClose(file, 
            2, L"typedefs");
                }

                
            void DumpFields(TextWriter& file, IDiaSymbol* udtSymbol)
                {
                    PrintXMLOpen(file, 
            2, L"fields", NULL);
                    IDiaEnumSymbols
            * fieldEnum=0;
                    
            if(SUCCEEDED(udtSymbol->findChildren(SymTagData, NULL, nsNone, &fieldEnum)) && fieldEnum)
                    {
                        DWORD fieldCelt
            =0;
                        IDiaSymbol
            * fieldSymbol=0;
                        
            while(SUCCEEDED(fieldEnum->Next(1&fieldSymbol, &fieldCelt)) && fieldSymbol && fieldCelt)
                        {
                            
            enum DataKind dataKind;
                            
            if(SUCCEEDED(fieldSymbol->get_dataKind((DWORD*)&dataKind)) && (dataKind==DataIsMember || dataKind==DataIsStaticMember || dataKind==DataIsConstant))
                            {
                                
            enum CV_access_e access;
                                fieldSymbol
            ->get_access((DWORD*)&access);
                                BSTR nameBSTR
            =0;
                                
            if(SUCCEEDED(fieldSymbol->get_name(&nameBSTR)) && nameBSTR)
                                {
                                    
            if(dataKind==DataIsMember)
                                    {
                                        PrintXMLOpen(file, 
            3, L"field", nameBSTR, L"access", GetAccessName(access));
                                        DumpSymbolType(file, fieldSymbol, 
            3);
                                        PrintXMLClose(file, 
            3, L"field");
                                    }
                                    
            else if(dataKind==DataIsStaticMember)
                                    {
                                        PrintXMLOpen(file, 
            3, L"staticField", nameBSTR, L"access", GetAccessName(access));
                                        DumpSymbolType(file, fieldSymbol, 
            3);
                                        PrintXMLClose(file, 
            3, L"staticField");
                                    }
                                    
            else if(dataKind==DataIsConstant)
                                    {
                                        PrintXMLOpen(file, 
            3, L"const", nameBSTR, L"access", GetAccessName(access));
                                        DumpSymbolType(file, fieldSymbol, 
            3);
                                        {
                                            VARIANT value;
                                            value.vt 
            = VT_EMPTY;
                                            
            if (fieldSymbol->get_value(&value) == S_OK)
                                            {
                                                signed __int64 ivalue
            =0;
                                                
            switch(value.vt)
                                                {
                                                
            case VT_I1:
                                                    ivalue
            =value.cVal;
                                                    
            goto PROCESS_INTEGER;
                                                
            case VT_I2:
                                                    ivalue
            =value.iVal;
                                                    
            goto PROCESS_INTEGER;
                                                
            case VT_I4:
                                                    ivalue
            =value.lVal;
                                                    
            goto PROCESS_INTEGER;
                                                
            case VT_UI1:
                                                    ivalue
            =value.bVal;
                                                    
            goto PROCESS_INTEGER;
                                                
            case VT_UI2:
                                                    ivalue
            =value.uiVal;
                                                    
            goto PROCESS_INTEGER;
                                                
            case VT_UI4:
                                                    ivalue
            =value.ulVal;
                                                    
            goto PROCESS_INTEGER;
                                                PROCESS_INTEGER:
                                                    wchar_t valueBuffer[
            100];
                                                    _i64tow_s(ivalue, valueBuffer, 
            10010);
                                                    PrintXMLOpen(file, 
            4, L"intValue", NULL, L"value", valueBuffer);
                                                    PrintXMLClose(file, 
            4, L"intValue");
                                                    
            break;
                                                }
                                            }
                                        }
                                        PrintXMLClose(file, 
            3, L"const");
                                    }
                                }
                            }
                            fieldSymbol
            ->Release();
                        }
                        fieldEnum
            ->Release();
                    }
                    PrintXMLClose(file, 
            2, L"fields");
                }

                
            void DumpMethodArguments(TextWriter& file, IDiaSymbol* methodSymbol)
                {
                    PrintXMLOpen(file, 
            4, L"arguments", NULL);
                    IDiaEnumSymbols
            * argumentEnum=0;
                    
            if(SUCCEEDED(methodSymbol->findChildren(SymTagData, NULL, nsNone, &argumentEnum)) && argumentEnum)
                    {
                        DWORD argumentCelt
            =0;
                        IDiaSymbol
            * argumentSymbol=0;
                        
            while(SUCCEEDED(argumentEnum->Next(1&argumentSymbol, &argumentCelt)) && argumentSymbol && argumentCelt)
                        {
                            
            enum DataKind dataKind;
                            
            if(SUCCEEDED(argumentSymbol->get_dataKind((DWORD*)&dataKind)) && dataKind==DataIsParam)
                            {
                                BSTR nameBSTR
            =0;
                                
            if(SUCCEEDED(argumentSymbol->get_name(&nameBSTR)) && nameBSTR)
                                {
                                    PrintXMLOpen(file, 
            5, L"argument", nameBSTR);
                                    DumpSymbolType(file, argumentSymbol, 
            5);
                                    PrintXMLClose(file, 
            5, L"argument");
                                }
                            }
                            argumentSymbol
            ->Release();
                        }
                        argumentEnum
            ->Release();
                    }
                    PrintXMLClose(file, 
            4, L"arguments");
                }

                
            void DumpMethod(TextWriter& file, IDiaSymbol* methodSymbol)
                {
                    
            enum CV_access_e access;
                    methodSymbol
            ->get_access((DWORD*)&access);
                    BOOL staticMethod
            =FALSE;
                    methodSymbol
            ->get_isStatic(&staticMethod);
                    BSTR nameBSTR
            =0;

                    
            const wchar_t* virtualValue=L"normal";
                    BOOL virtualBool
            =FALSE;
                    
            if(SUCCEEDED(methodSymbol->get_pure(&virtualBool)) && virtualBool)
                    {
                        virtualValue
            =L"pure";
                    }
                    
            else if(SUCCEEDED(methodSymbol->get_virtual(&virtualBool)) && virtualBool)
                    {
                        virtualValue
            =L"virtual";
                    }
                    
            if(SUCCEEDED(methodSymbol->get_name(&nameBSTR)) && nameBSTR)
                    {
                        
            if(staticMethod)
                        {
                            PrintXMLOpen(file, 
            3, L"staticMethod", nameBSTR, L"access", GetAccessName(access), L"virtual", virtualValue);
                            DumpMethodArguments(file, methodSymbol);
                            DumpSymbolType(file, methodSymbol, 
            3);
                            PrintXMLClose(file, 
            3, L"staticMethod");
                        }
                        
            else
                        {
                            PrintXMLOpen(file, 
            3, L"method", nameBSTR, L"access", GetAccessName(access), L"virtual", virtualValue);
                            DumpMethodArguments(file, methodSymbol);
                            DumpSymbolType(file, methodSymbol, 
            3);
                            PrintXMLClose(file, 
            3, L"method");
                        }
                    }
                }

                
            void DumpMethods(TextWriter& file, IDiaSymbol* udtSymbol)
                {
                    PrintXMLOpen(file, 
            2, L"methods", NULL);
                    IDiaEnumSymbols
            * methodEnum=0;
                    
            if(SUCCEEDED(udtSymbol->findChildren(SymTagFunction, NULL, nsNone, &methodEnum)) && methodEnum)
                    {
                        DWORD methodCelt
            =0;
                        IDiaSymbol
            * methodSymbol=0;
                        
            while(SUCCEEDED(methodEnum->Next(1&methodSymbol, &methodCelt)) && methodSymbol && methodCelt)
                        {
                            DumpMethod(file, methodSymbol);
                            methodSymbol
            ->Release();
                        }
                        methodEnum
            ->Release();
                    }
                    PrintXMLClose(file, 
            2, L"methods");
                }

                
            void Dump(TextWriter& file, IDiaSymbol* exeSymbol)
                {
                    FindClasses(exeSymbol);

                    
            for(int i=0;i<udtSymbols.Count();i++)
                    {
                        WString className
            =udtSymbols.Keys()[i];
                        IDiaSymbol
            * classSymbol=udtSymbols.Values()[i];
                        
            enum SymTagEnum symTag=SymTagNull;
                        classSymbol
            ->get_symTag((DWORD*)&symTag);
                        
            if(symTag==SymTagUDT)
                        {
                            PrintXMLOpen(file, 
            1, L"class", className.Buffer());
                            DumpBaseClasses(file, classSymbol);
                            DumpNestedClasses(file, classSymbol);
                            DumpTypedefs(file, classSymbol);
                            DumpFields(file, classSymbol);
                            DumpMethods(file, classSymbol);
                            PrintXMLClose(file, 
            1, L"class");
                        }
                        
            else if(symTag==SymTagEnum)
                        {
                            PrintXMLOpen(file, 
            1, L"enum", className.Buffer());
                            DumpFields(file, classSymbol);
                            PrintXMLClose(file, 
            1, L"enum");
                        }
                    }
                    
            for(int i=0;i<udtSymbols.Count();i++)
                    {
                        udtSymbols.Values()[i]
            ->Release();
                    }
                    udtSymbols.Clear();

                    PrintXMLOpen(file, 
            1, L"functions", NULL);
                    
            for(int i=0;i<funcSymbols.Count();i++)
                    {
                        WString funcName
            =funcSymbols.Keys()[i];
                        IDiaSymbol
            * funcSymbol=funcSymbols.Values()[i];
                        DumpMethod(file, funcSymbol);
                    }
                    PrintXMLClose(file, 
            1, L"functions");
                    
            for(int i=0;i<funcSymbols.Count();i++)
                    {
                        funcSymbols.Values()[i]
            ->Release();
                    }
                    funcSymbols.Clear();
                }

                
            void DumpPdbToXml(IDiaSymbol* exeSymbol, const wchar_t* xml)
                {
                    FileStream fileStream(xml, FileStream::WriteOnly);
                    CacheStream cacheStream(fileStream, 
            1048576);
                    BomEncoder encoder(BomEncoder::Utf16);
                    EncoderStream encoderStream(cacheStream, encoder);
                    StreamWriter file(encoderStream);
                    PrintString(file, L
            "<?xml version=\"1.0\" encoding=\"utf-16\" ?>\r\n");
                    PrintXMLOpen(file, 
            0, L"pdb", NULL);
                    Dump(file, exeSymbol);
                    PrintXMLClose(file, 
            0, L"pdb");
                }
            }

                下一篇文章將講到我如何使用上面的程序產生的xml和Visual Studio的本地C++編譯器生成的XML文檔,來合并成一個完整的XML描述的文檔。
            posted on 2012-03-09 14:43 陳梓瀚(vczh) 閱讀(7034) 評論(0)  編輯 收藏 引用 所屬分類: C++GacUI
            久久国产欧美日韩精品| 久久综合丁香激情久久| 亚洲狠狠婷婷综合久久久久| 亚洲精品乱码久久久久久蜜桃图片 | 久久婷婷五月综合国产尤物app | 亚洲精品国产自在久久| 久久精品国产乱子伦| 香蕉久久夜色精品国产小说| 亚洲精品tv久久久久| 国产精品久久久天天影视| 欧美粉嫩小泬久久久久久久 | 亚洲天堂久久精品| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 国产91色综合久久免费| 国产精品久久久香蕉| 久久香蕉一级毛片| 久久精品国产亚洲AV不卡| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 麻豆一区二区99久久久久| 久久国产精品免费一区| av无码久久久久不卡免费网站 | 思思久久精品在热线热| 国产农村妇女毛片精品久久| 久久久久AV综合网成人| 四虎国产精品成人免费久久| 久久99精品久久久久久噜噜| 999久久久免费精品国产| 中文国产成人精品久久不卡| 久久人人爽人爽人人爽av| 久久免费高清视频| 91精品国产色综合久久| 无码国产69精品久久久久网站| 伊人热热久久原色播放www| 精品无码久久久久久国产| 伊人久久大香线焦综合四虎| 国内精品久久久久影院日本| 性欧美丰满熟妇XXXX性久久久 | 久久青青草原亚洲av无码app| 久久精品桃花综合| 影音先锋女人AV鲁色资源网久久| 久久久久久久久波多野高潮|