Author Topic: MSDIA - How to Initialize a non registered interface  (Read 4701 times)


  • Moderator
  • Member
  • *****
  • Posts: 1196
  • Assembly is a state of art.
    • RosAsm
MSDIA - How to Initialize a non registered interface
« on: July 22, 2014, 08:21:41 PM »
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

Code: [Select]

[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
Code: [Select]

; 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

Code: [Select]
    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

Code: [Select]

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

Code: [Select]

 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

Code: [Select]
; 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.

Code: [Select]
is unrolled as:
Code: [Select]

    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
« Last Edit: July 22, 2014, 09:25:00 PM by guga »
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: