Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

MSDIA - How to Initialize a non registered interface

Started by guga, July 22, 2014, 08:21:41 PM

Previous topic - Next topic


This is a small piece of code to initialize a non registered interface. In this example, the focus is msdia120.dll

Example of usage and how to call the interface

Although it seems to be not mandatory that you call the dll using a UNICODE path to msdia library, i posted as unicode on this example, because it is mandatory to use it UNICODE path whenever you wants to load your pdb file. So, to make it easier to understand, i maintained the same unicode version and not a mix between unicode and ascii

To maintain things simple. It is wise to load the dll name in the same path as your main app. This is why it is used here simple as "U$ "msdia120.dll" and not "U$ "c:\temp\msdia120.dll" or "mypath\U$ "msdia120.dll" etc

[g_pDiaDataSource: D$ 0]

    call InitializeDiaInterface {U$ "msdia120.dll" 0}, CLSID_DiaSourceAlt, IID_IDiaDataSource, g_pDiaDataSource
    If eax <> &S_OK ; If eax is not S_OK, do error case
        xor eax eax ; exit false on error cases

Main code Initialization

The function DllGetClassObject inside msdia is the same one as when you call IClassFactory interface. So, the documentation can be seeing here

; Initialize an object not registered

Proc InitializeDiaInterface:
    Arguments @lpLibFileName, @pClsid, @pIID, @pOut
    Local @hpfDllGetClassObject, @ppv
    Uses esi, edi, ecx, ebx, edx

    call 'KERNEL32.LoadLibraryExW' D@lpLibFileName, 0, &LOAD_WITH_ALTERED_SEARCH_PATH
    .If eax = 0
        call ReportWinError {'LoadLibraryExW' 0} ; show cause of failure
        mov eax &E_FAIL

    call 'KERNEL32.GetProcAddress' eax, {B$ "DllGetClassObject", 0}
    .If eax = 0
        call ReportWinError {'msdia120.dll' 0} ; show cause of failure
        mov eax &E_FAIL
    mov D@hpfDllGetClassObject eax

    lea ecx D@ppv
    call D@hpfDllGetClassObject D@pClsid, IID_IClassFactory, ecx
    mov esi eax
    .If eax = &S_OK ; points to CreateInstance
        icall ICLASS_FACTORY_CREATE_INSTANCE D@ppv, 0, D@pIID, D@pOut
        mov esi eax
        icall IUNKNOWN_RELEASE D@ppv

    mov eax esi


IClassFactory Interface

    EXTERN_C const IID IID_IClassFactory; 
    #if defined(__cplusplus) && !defined(CINTERFACE) 
        IClassFactory : public IUnknown 
            virtual /* [local] */ HRESULT STDMETHODCALLTYPE CreateInstance(   
                /* [unique][in] */ IUnknown __RPC_FAR *pUnkOuter, 
                /* [in] */ REFIID riid, 
                /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) = 0; 
            virtual /* [local] */ HRESULT STDMETHODCALLTYPE LockServer(   
                /* [in] */ BOOL fLock) = 0; 
    #else   /* C style interface */ 
        typedef struct IClassFactoryVtbl 
            HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(   
                IClassFactory __RPC_FAR * This, 
                /* [in] */ REFIID riid, 
                /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); 
            ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(   
                IClassFactory __RPC_FAR * This); 
            ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(   
                IClassFactory __RPC_FAR * This); 
            /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateInstance )(   
                IClassFactory __RPC_FAR * This, 
                /* [unique][in] */ IUnknown __RPC_FAR *pUnkOuter, 
                /* [in] */ REFIID riid, 
                /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject); 
            /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LockServer )(   
                IClassFactory __RPC_FAR * This, 
                /* [in] */ BOOL fLock); 
        } IClassFactoryVtbl; 
        interface IClassFactory 
            CONST_VTBL struct IClassFactoryVtbl __RPC_FAR *lpVtbl; 

IID_IClassFactory.Data1: D$ 1
IID_IClassFactory.Data2: W$ 0
IID_IClassFactory.Data3: W$ 0
IID_IClassFactory.Data4: B$ 0C0, 0, 0, 0, 0, 0, 0, 046]

; Vtable from IID_IClassFactory


; General usage Vtable for adding, releasing, querying

; Vtable Displacements

Simple windows error managment for HResult conversion


Proc ReportWinError:
    Arguments @Caption
    Local @String, @ErrCode
    Structure @StringtoAdd 64, @StringtoAdd_DataDis 0
    Uses ebx, ecx, edx

    call 'Kernel32.GetLastError' | mov D@ErrCode eax

    mov edx (&SUBLANG_DEFAULT shl 16 or &LANG_NEUTRAL) ; to retrieve potential HRESULT error, it is necessary to set FORMAT_MESSAGE_IGNORE_INSERTS equate
    lea ecx D@String
    ...If eax <> 0
        call 'User32.MessageBoxA' &NULL, D@String, D@Caption, &MB_ICONERROR
        call 'Kernel32.LocalFree' D@String
        ; release message, even in cases of failure
        call 'Kernel32.LocalFree' D@String
        call HRESULTtoWCode D@ErrCode
        ..If eax = 0
            lea ebx D@ErrCode
            C_call 'msvcrt.vsprintf' D@StringtoAdd, {B$ "Unknown Error code value =  0x%08X", 0}, ebx
            call 'User32.MessageBoxA' &NULL, D@StringtoAdd, D@Caption, &MB_ICONERROR
            mov edx (&SUBLANG_DEFAULT shl 16 or &LANG_NEUTRAL)
            lea ecx D@String
            call 'User32.MessageBoxA' &NULL, D@String, D@Caption, &MB_ICONERROR
            call 'Kernel32.LocalFree' D@String



[MAKE_HRESULT_IMM | ( (#1 shl 31) or (#2 shl 16) or #3)]

Proc HRESULTtoWCode:
    Arguments @ErrorCode

    mov eax D@ErrorCode
        movzx eax ax
        mov eax 0 ; no message found to be converted


MSDia 120 Interfaces

IID_IDiaLoadCallback.Data1: D$ 0C32ADB82
IID_IDiaLoadCallback.Data2: W$ 073F4
IID_IDiaLoadCallback.Data3: W$ 0421B
IID_IDiaLoadCallback.Data4: B$ 095, 0D5, 0A4, 070, 06E, 0DF, 05D, 0BE]

IID_IDiaLoadCallback2.Data1: D$ 04688A074
IID_IDiaLoadCallback2.Data2: W$ 05A4D
IID_IDiaLoadCallback2.Data3: W$ 04486
IID_IDiaLoadCallback2.Data4: B$ 0AE, 0A8, 07B, 090, 071, 01D, 09F, 07C]

IID_IDiaReadExeAtOffsetCallback.Data1: D$ 0587A461C
IID_IDiaReadExeAtOffsetCallback.Data2: W$ 0B80B
IID_IDiaReadExeAtOffsetCallback.Data3: W$ 04F54
IID_IDiaReadExeAtOffsetCallback.Data4: B$ 091, 094, 050, 032, 058, 09A, 063, 019]

IID_IDiaReadExeAtRVACallback.Data1: D$ 08E3F80CA
IID_IDiaReadExeAtRVACallback.Data2: W$ 07517
IID_IDiaReadExeAtRVACallback.Data3: W$ 0432A
IID_IDiaReadExeAtRVACallback.Data4: B$ 0BA, 07, 028, 051, 034, 0AA, 0EA, 08E]

IID_IDiaDataSource.Data1: D$ 079F1BB5F
IID_IDiaDataSource.Data2: W$ 0B66E
IID_IDiaDataSource.Data3: W$ 048E5
IID_IDiaDataSource.Data4: B$ 0B6, 0A9, 015, 045, 0C3, 023, 0CA, 03D]

IID_IDiaEnumSymbols.Data1: D$ 0CAB72C48
IID_IDiaEnumSymbols.Data2: W$ 0443B
IID_IDiaEnumSymbols.Data3: W$ 048F5
IID_IDiaEnumSymbols.Data4: B$ 09B, 0B, 042, 0F0, 082, 0A, 0B2, 09A]

IID_IDiaEnumSymbolsByAddr.Data1: D$ 0624B7D9C
IID_IDiaEnumSymbolsByAddr.Data2: W$ 024EA
IID_IDiaEnumSymbolsByAddr.Data3: W$ 04421
IID_IDiaEnumSymbolsByAddr.Data4: B$ 09D, 06, 03B, 057, 074, 071, 0C1, 0FA]

IID_IDiaEnumSourceFiles.Data1: D$ 010F3DBD9
IID_IDiaEnumSourceFiles.Data2: W$ 0664F
IID_IDiaEnumSourceFiles.Data3: W$ 04469
IID_IDiaEnumSourceFiles.Data4: B$ 0B8, 08, 094, 071, 0C7, 0A5, 05, 038]

IID_IDiaEnumInputAssemblyFiles.Data1: D$ 01C7FF653
IID_IDiaEnumInputAssemblyFiles.Data2: W$ 051F7
IID_IDiaEnumInputAssemblyFiles.Data3: W$ 0457E
IID_IDiaEnumInputAssemblyFiles.Data4: B$ 084, 019, 0B2, 0F, 057, 0EF, 07E, 04D]

IID_IDiaEnumLineNumbers.Data1: D$ 0FE30E878
IID_IDiaEnumLineNumbers.Data2: W$ 054AC
IID_IDiaEnumLineNumbers.Data3: W$ 044F1
IID_IDiaEnumLineNumbers.Data4: B$ 081, 0BA, 039, 0DE, 094, 0F, 060, 052]

IID_IDiaEnumInjectedSources.Data1: D$ 0D5612573
IID_IDiaEnumInjectedSources.Data2: W$ 06925
IID_IDiaEnumInjectedSources.Data3: W$ 04468
IID_IDiaEnumInjectedSources.Data4: B$ 088, 083, 098, 0CD, 0EC, 08C, 038, 04A]

IID_IDiaEnumSegments.Data1: D$ 0E8368CA9
IID_IDiaEnumSegments.Data2: W$ 01D1
IID_IDiaEnumSegments.Data3: W$ 0419D
IID_IDiaEnumSegments.Data4: B$ 0AC, 0C, 0E3, 012, 035, 0DB, 0DA, 09F]

IID_IDiaEnumSectionContribs.Data1: D$ 01994DEB2
IID_IDiaEnumSectionContribs.Data2: W$ 02C82
IID_IDiaEnumSectionContribs.Data3: W$ 04B1D
IID_IDiaEnumSectionContribs.Data4: B$ 0A5, 07F, 0AF, 0F4, 024, 0D5, 04A, 068]

IID_IDiaEnumFrameData.Data1: D$ 09FC77A4B
IID_IDiaEnumFrameData.Data2: W$ 03C1C
IID_IDiaEnumFrameData.Data3: W$ 044ED
IID_IDiaEnumFrameData.Data4: B$ 0A7, 098, 06C, 01D, 0EE, 0A5, 03E, 01F]

IID_IDiaEnumDebugStreamData.Data1: D$ 0486943E8
IID_IDiaEnumDebugStreamData.Data2: W$ 0D187
IID_IDiaEnumDebugStreamData.Data3: W$ 04A6B
IID_IDiaEnumDebugStreamData.Data4: B$ 0A3, 0C4, 029, 012, 059, 0FF, 0F6, 0D]

IID_IDiaEnumDebugStreams.Data1: D$ 08CBB41E
IID_IDiaEnumDebugStreams.Data2: W$ 047A6
IID_IDiaEnumDebugStreams.Data3: W$ 04F87
IID_IDiaEnumDebugStreams.Data4: B$ 092, 0F1, 01C, 09C, 087, 0CE, 0D0, 044]

IID_IDiaAddressMap.Data1: D$ 0B62A2E7A
IID_IDiaAddressMap.Data2: W$ 067A
IID_IDiaAddressMap.Data3: W$ 04EA3
IID_IDiaAddressMap.Data4: B$ 0B5, 098, 04, 0C0, 097, 017, 050, 02C]

IID_IDiaSession.Data1: D$ 06FC5D63F
IID_IDiaSession.Data2: W$ 011E
IID_IDiaSession.Data3: W$ 040C2
IID_IDiaSession.Data4: B$ 08D, 0D2, 0E6, 048, 06E, 09D, 06B, 068]

IID_IDiaSymbol.Data1: D$ 0CB787B2F
IID_IDiaSymbol.Data2: W$ 0BD6C
IID_IDiaSymbol.Data3: W$ 04635
IID_IDiaSymbol.Data4: B$ 0BA, 052, 093, 031, 026, 0BD, 02D, 0CD]

IID_IDiaSourceFile.Data1: D$ 0A2EF5353
IID_IDiaSourceFile.Data2: W$ 0F5A8
IID_IDiaSourceFile.Data3: W$ 04EB3
IID_IDiaSourceFile.Data4: B$ 090, 0D2, 0CB, 052, 06A, 0CB, 03C, 0DD]

IID_IDiaInputAssemblyFile.Data1: D$ 03BFE56B0
IID_IDiaInputAssemblyFile.Data2: W$ 0390C
IID_IDiaInputAssemblyFile.Data3: W$ 04863
IID_IDiaInputAssemblyFile.Data4: B$ 094, 030, 01F, 03D, 08, 03B, 076, 084]

IID_IDiaLineNumber.Data1: D$ 0B388EB14
IID_IDiaLineNumber.Data2: W$ 0BE4D
IID_IDiaLineNumber.Data3: W$ 0421D
IID_IDiaLineNumber.Data4: B$ 0A8, 0A1, 06C, 0F7, 0AB, 05, 070, 086]

IID_IDiaSectionContrib.Data1: D$ 0CF4B60E
IID_IDiaSectionContrib.Data2: W$ 035B1
IID_IDiaSectionContrib.Data3: W$ 04C6C
IID_IDiaSectionContrib.Data4: B$ 0BD, 0D8, 085, 04B, 09C, 08E, 038, 057]

IID_IDiaSegment.Data1: D$ 0775B784
IID_IDiaSegment.Data2: W$ 0C75B
IID_IDiaSegment.Data3: W$ 04449
IID_IDiaSegment.Data4: B$ 084, 08B, 0B7, 0BD, 031, 059, 054, 05B]

IID_IDiaInjectedSource.Data1: D$ 0AE605CDC
IID_IDiaInjectedSource.Data2: W$ 08105
IID_IDiaInjectedSource.Data3: W$ 04A23
IID_IDiaInjectedSource.Data4: B$ 0B7, 010, 032, 059, 0F1, 0E2, 061, 012]

IID_IDiaStackWalkFrame.Data1: D$ 07C590C1
IID_IDiaStackWalkFrame.Data2: W$ 0438D
IID_IDiaStackWalkFrame.Data3: W$ 04F47
IID_IDiaStackWalkFrame.Data4: B$ 0BD, 0CD, 043, 097, 0BC, 081, 0AD, 075]

IID_IDiaFrameData.Data1: D$ 0A39184B7
IID_IDiaFrameData.Data2: W$ 06A36
IID_IDiaFrameData.Data3: W$ 042DE
IID_IDiaFrameData.Data4: B$ 08E, 0EC, 07D, 0F9, 0F3, 0F5, 09F, 033]

IID_IDiaImageData.Data1: D$ 0C8E40ED2
IID_IDiaImageData.Data2: W$ 0A1D9
IID_IDiaImageData.Data3: W$ 04221
IID_IDiaImageData.Data4: B$ 086, 092, 03C, 0E6, 061, 018, 04B, 044]

IID_IDiaTable.Data1: D$ 04A59FB77
IID_IDiaTable.Data2: W$ 0ABAC
IID_IDiaTable.Data3: W$ 0469B
IID_IDiaTable.Data4: B$ 0A3, 0B, 09E, 0CC, 085, 0BF, 0EF, 014]

IID_IDiaEnumTables.Data1: D$ 0C65C2B0A
IID_IDiaEnumTables.Data2: W$ 01150
IID_IDiaEnumTables.Data3: W$ 04D7A
IID_IDiaEnumTables.Data4: B$ 0AF, 0CC, 0E0, 05B, 0F3, 0DE, 0E8, 01E]

LIBID_Dia2Lib.Data1: D$ 0106173A0
LIBID_Dia2Lib.Data2: W$ 0173
LIBID_Dia2Lib.Data3: W$ 04E5C
LIBID_Dia2Lib.Data4: B$ 084, 0E7, 0E9, 015, 042, 02B, 0E9, 097]

CLSID_DiaSource.Data1: D$ 03BFCEA48
CLSID_DiaSource.Data2: W$ 0620F
CLSID_DiaSource.Data3: W$ 04B6B
CLSID_DiaSource.Data4: B$ 081, 0F7, 0B9, 0AF, 075, 045, 04C, 07D]

CLSID_DiaSourceAlt.Data1: D$ 083AB22C8
CLSID_DiaSourceAlt.Data2: W$ 0993A
CLSID_DiaSourceAlt.Data3: W$ 04D14
CLSID_DiaSourceAlt.Data4: B$ 0A0, 0E0, 037, 0BC, 0A, 0AE, 0A7, 093]

CLSID_DiaStackWalker.Data1: D$ 020CEA761
CLSID_DiaStackWalker.Data2: W$ 083C2
CLSID_DiaStackWalker.Data3: W$ 044F4
CLSID_DiaStackWalker.Data4: B$ 0A6, 0F7, 05C, 0C4, 057, 071, 098, 0CA]

IID_IDiaPropertyStorage.Data1: D$ 09D416F9C
IID_IDiaPropertyStorage.Data2: W$ 0E184
IID_IDiaPropertyStorage.Data3: W$ 045B2
IID_IDiaPropertyStorage.Data4: B$ 0A4, 0F0, 0CE, 051, 07F, 071, 09E, 09B]

IID_IDiaStackFrame.Data1: D$ 05EDBC96D
IID_IDiaStackFrame.Data2: W$ 0CDD6
IID_IDiaStackFrame.Data3: W$ 04792
IID_IDiaStackFrame.Data4: B$ 0AF, 0BE, 0CC, 089, 0, 07D, 096, 010]

IID_IDiaEnumStackFrames.Data1: D$ 0EC9D461D
IID_IDiaEnumStackFrames.Data2: W$ 0CE74
IID_IDiaEnumStackFrames.Data3: W$ 04711
IID_IDiaEnumStackFrames.Data4: B$ 0A0, 020, 07D, 08F, 09A, 01D, 0D2, 055]

IID_IDiaStackWalkHelper.Data1: D$ 021F81B1B
IID_IDiaStackWalkHelper.Data2: W$ 0C5BB
IID_IDiaStackWalkHelper.Data3: W$ 042A3
IID_IDiaStackWalkHelper.Data4: B$ 0BC, 04F, 0CC, 0BA, 0A7, 05B, 09F, 019]

IID_IDiaStackWalker.Data1: D$ 05485216B
IID_IDiaStackWalker.Data2: W$ 0A54C
IID_IDiaStackWalker.Data3: W$ 0469F
IID_IDiaStackWalker.Data4: B$ 096, 070, 052, 0B2, 04D, 052, 029, 0BB]

IID_IDiaStackWalkHelper2.Data1: D$ 08222C490
IID_IDiaStackWalkHelper2.Data2: W$ 0507B
IID_IDiaStackWalkHelper2.Data3: W$ 04BEF
IID_IDiaStackWalkHelper2.Data4: B$ 0B3, 0BD, 041, 0DC, 0A7, 0B5, 093, 04C]

IID_IDiaStackWalker2.Data1: D$ 07C185885
IID_IDiaStackWalker2.Data2: W$ 0A015
IID_IDiaStackWalker2.Data3: W$ 04CAC
IID_IDiaStackWalker2.Data4: B$ 094, 011, 0F, 04F, 0B3, 09B, 01F, 03A]

IID_IDiaDataSource2.Data1: D$ 06D31CB3B
IID_IDiaDataSource2.Data2: W$ 0EDD4
IID_IDiaDataSource2.Data3: W$ 04C3E
IID_IDiaDataSource2.Data4: B$ 0AB, 044, 012, 0B9, 0F7, 0A3, 082, 08E]

IID_IDiaDataSource3.Data1: D$ 065A23C15
IID_IDiaDataSource3.Data2: W$ 0BAB3
IID_IDiaDataSource3.Data3: W$ 045DA
IID_IDiaDataSource3.Data4: B$ 086, 039, 0F0, 06D, 0E8, 06B, 09E, 0A8]

IID_IDiaDataSource4.Data1: D$ 027B468A6
IID_IDiaDataSource4.Data2: W$ 0229C
IID_IDiaDataSource4.Data3: W$ 04248
IID_IDiaDataSource4.Data4: B$ 08F, 05E, 0F3, 026, 0E7, 0C6, 02B, 0A4]

The icall macro

; Example :  iCall Lock D$BackSurfacePtr &NULL DDSURFACEDESC DDLOCK_WAIT &NULL
[iCall | mov edx #2 | mov edx D$edx | push #L>3 | push #2 | call D$edx+#1 ]

The icall macro is the way to call some Com Interfaces containing the STDMETHOD. It simply used edx register to gain access to the internal table pointers of the interface that calls the different functions.


is unrolled as:

    mov edx D@ppv ; This is the proper way to go inside the Com interface.
    mov edx D$edx ; the address of the table inside com

    push D@pOut  ; 3rd parameter of the Com function
    push D@pIID  ; 2nd parameter of the Com function
    push 0 ; 1st parameter of the Com function

    push D@ppv ; The 1st push is always the one that will be used internally on the interface object. It works more like a handle to the proper Com functions to be called internally
    call D$edx+ICLASS_FACTORY_CREATE_INSTANCE ; value of this equate is 12. Now we are going to the proper address of the table located in the 12th byte. It then calls the function "CreateInstance" of the interface

Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites: