News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

COM Events

Started by mabdelouahab, April 16, 2015, 05:50:24 PM

Previous topic - Next topic

mabdelouahab

First: I make the very simplest server software does not contain only 1 function and 1 event
Open VB New Project an Select DLL ActiveX , In Class1 add:

Public Event EventForTest()
Public Sub MethodForTest()
    MsgBox "Hi Is Me ..."       ' invoke MessageBox ...
    RaiseEvent EventForTest   ' FireEvents EventForTest   
End Sub

Rename Class1 to ClsForTest and rename Project1 to DllForTest
In FILE Menu select "Create DllForTest.DLL" and save it

VB will automatically made Active X Dll contains the following:_ClsForTest Dispatsh ;__ClsForTest (Event Dispatsh ) ; Inc file is as follows (Generate by me):
.data
CLSID_ClsForTest  GUID <0B6E21F7Ch,0AC81h,040EDh,<089h,0F7h,0D9h,034h,05Fh,027h,051h,066h>>
IID__ClsForTest    GUID <06B81DDC9h,0881Bh,0486Fh,<087h,08Bh,03Ch,0BCh,0A3h,005h,09Dh,090h>>

Inst__ClsForTest dd 0

_ClsForTest struct
    QueryInterface dd 0
    AddRef dd 0
    Release dd 0
    GetTypeInfoCount dd 0
    GetTypeInfo dd 0
    GetIDsOfNames dd 0
    _Invoke dd 0
MethodForTest dd 0
_ClsForTest ends

.code
_ClsForTest@Release proc
        MOV EDX, Inst__ClsForTest
        PUSH EDX   
        MOV EDX,[EDX]   
        CALL DWORD PTR [EDX+8] ;Call ClsForTest.Release
ret
_ClsForTest@Release endp
_ClsForTest@MethodForTest proc
        MOV EDX, Inst__ClsForTest
        PUSH EDX   
        MOV EDX,[EDX]   
        CALL DWORD PTR [EDX+28] ;Call ClsForTest.MethodForTest
ret
_ClsForTest@MethodForTest endp

_ClsForTest@CreateClass Proc
LOCAL __IUnknown
    invoke CoCreateInstance,addr CLSID_ClsForTest,NULL,CLSCTX_ALL,addr IID_IUnknown,addr __IUnknown
        .if eax == S_OK
LEA ECX, Inst__ClsForTest
PUSH ECX
lea eax ,IID__ClsForTest
        PUSH EAX
        MOV EDX,__IUnknown
        PUSH EDX
        MOV EDX,[EDX]
        CALL DWORD PTR [EDX] ;QueryInterface
.if !eax
        invoke crt_wprintf,cfm$("\n CreateClass _ClsForTest OK ")
            MOV EAX,TRUE
.else
        invoke crt_wprintf,cfm$("\n CreateClass _ClsForTest  fail ")
            MOV EAX,FALSE
.endif
        .else
        MOV EAX,FALSE
        .endif
ret
_ClsForTest@CreateClass endp

Go back to Masm, make the following
create New Consol :
__UNICODE__ equ 1
include \masm32\include\masm32rt.inc
.data
IID_IUnknown GUID <000000000H,00000H,00000H,<0C0H,000H,000H,000H,000H,000H,000H,046H>>

include Cls_ClsForTest.inc
.code
Start:
invoke CoInitializeEx, NULL,COINIT_MULTITHREADED    ;COINIT_APARTMENTTHREADED ;
.if rv( _ClsForTest@CreateClass); Create New ClsForTest
invoke _ClsForTest@MethodForTest ;ClsForTest.MethodForTest
invoke _ClsForTest@Release ; ClsForTest.Release
.endif
invoke CoUninitialize
exit
End Start

add the INC file of DllFor test to Proj, Must register DllForTest.dll "  REGSVR32 "DllForTest.dll"  "
Run and I will complete

mabdelouahab

at here I work without EVENT
if I want to work with events we must create an interface at my application then advise it to the Server DLL

I generate Inc File for the Event Clss (__ClsForTest)  , add it to the project
.data

IID___ClsForTest  GUID <03D369F24h,0B1BFh,04816h,<0BEh,0A2h,0B1h,0AFh,0A2h,0FFh,098h,053h>>

Inst__ClsForTest dd 0
___ClsForTest@RefCount dd 0

__ClsForTest struct ;;;;;;;; Events
    QueryInterface dd 0
    AddRef dd 0
    Release dd 0
    GetTypeInfoCount dd 0
    GetTypeInfo dd 0
    GetIDsOfNames dd 0
    _Invoke dd 0
EventForTest dd 0
__ClsForTest ends

.code

    __ClsForTest@QueryInterface proc    lpME:dword ,riid:DWORD,ppvObj:DWORD
invoke crt_wprintf,cfm$("\n __ClsForTest@QueryInterface")
        .if rv(IsEqualGUID,addr IID_IUnknown ,riid)
        mov eax,lpME
    mov ecx,ppvObj
    mov dword ptr [ecx],eax
    mov eax,S_OK
    jmp __ClsForTest@QueryInterfaceExit
        .endif
        .if  rv(IsEqualGUID,addr IID___ClsForTest,riid)
        mov eax,lpME
    mov ecx,ppvObj
    mov dword ptr [ecx],eax
    mov eax,S_OK
    jmp __ClsForTest@QueryInterfaceExit
        .endif
        mov eax,E_NOINTERFACE
    __ClsForTest@QueryInterfaceExit:
    ret
    __ClsForTest@QueryInterface endp
__ClsForTest@AddRef proc lpME:dword
invoke crt_wprintf,cfm$("\n __ClsForTest@AddRef")
inc ___ClsForTest@RefCount
mov eax,___ClsForTest@RefCount
ret
__ClsForTest@AddRef endp
__ClsForTest@Release proc lpME:dword
invoke crt_wprintf,cfm$("\n __ClsForTest@Release")
dec ___ClsForTest@RefCount
mov eax,___ClsForTest@RefCount
ret
__ClsForTest@Release endp
__ClsForTest@GetTypeInfoCount proc lpME:dword ,pctinfo:DWORD
invoke crt_wprintf,cfm$("\n __ClsForTest@GetTypeInfoCount")
mov eax,E_NOTIMPL
ret
__ClsForTest@GetTypeInfoCount endp
__ClsForTest@GetTypeInfo proc lpME:dword ,itinfo:DWORD,lcid:DWORD,pptinfo:DWORD
invoke crt_wprintf,cfm$("\n __ClsForTest@GetTypeInfo")
mov eax,E_NOTIMPL
ret
__ClsForTest@GetTypeInfo endp
__ClsForTest@GetIDsOfNames proc lpME:dword ,riid:DWORD,rgszNames:DWORD,cNames:DWORD,lcid:DWORD,rgdispid:DWORD
invoke crt_wprintf,cfm$("\n __ClsForTest@GetIDsOfNames")
mov eax,E_NOTIMPL
ret
__ClsForTest@GetIDsOfNames endp
__ClsForTest@_Invoke proc lpME:dword ,dispidMember:SDWORD,riid:DWORD,lcid:DWORD,wFlags:WORD,pdispparams:DWORD,pvarResult:DWORD,pexcepinfo:DWORD,puArgErr:DWORD
invoke crt_wprintf,cfm$("\n __ClsForTest@_Invoke %d ") ,dispidMember
mov ecx,dispidMember
cmp ecx,1
jne @F
push lpME
call __ClsForTest@MethodForTest
jmp __ClsForTest@_InvokeExit
@@: ;cmp ecx,2
;jne @F
; push lpME
; call __ClsForTest@MethodForTest
; jmp __ClsForTest@_InvokeExit...............
__ClsForTest@_InvokeExit:
xor eax,eax
ret
__ClsForTest@_Invoke endp
__ClsForTest@MethodForTest proc lpME:dword
invoke crt_wprintf,cfm$("\n __ClsForTest@MethodForTest")
invoke MessageBox,0,chr$(" __ClsForTest@MethodForTest Event Fired OK"),0,0
ret
__ClsForTest@MethodForTest endp

__ClsForTest@CreateInterface proc
invoke LocalAlloc,LMEM_FIXED or LMEM_ZEROINIT ,sizeof __ClsForTest
mov edi,eax
mov dword ptr [edi] ,OFFSET __ClsForTest@QueryInterface
add edi,4
mov dword ptr [edi] ,OFFSET __ClsForTest@AddRef
add edi,4
mov dword ptr [edi] ,OFFSET __ClsForTest@Release
add edi,4
mov dword ptr [edi] ,OFFSET __ClsForTest@GetTypeInfoCount
add edi,4
mov dword ptr [edi] ,OFFSET __ClsForTest@GetTypeInfo
add edi,4
mov dword ptr [edi] ,OFFSET __ClsForTest@GetIDsOfNames
add edi,4
mov dword ptr [edi] ,OFFSET __ClsForTest@_Invoke
add edi,4
mov dword ptr [edi] ,OFFSET __ClsForTest@MethodForTest
ret
__ClsForTest@CreateInterface endp
__ClsForTest@Advise  proc PUBLIC
LOCAL pIConnectionPointContainer,m_pIConnectionPoint,m_dwCookie,dwRegister
xor ecx,ecx
mov pIConnectionPointContainer,ecx
mov m_pIConnectionPoint,ecx
mov m_dwCookie,ecx
.if !Inst__ClsForTest
mov Inst__ClsForTest,rv(__ClsForTest@CreateInterface)
.endif
;------------------------------------------ Class.QueryInterface IConnectionPointContainer
LEA ECX, pIConnectionPointContainer
PUSH ECX
lea eax ,IID_IConnectionPointContainer
    PUSH EAX
    MOV EDX,Inst_ClsForTest
    PUSH EDX
    MOV EDX,[EDX]
    CALL DWORD PTR [EDX];QueryInterface
   
        .if pIConnectionPointContainer
        invoke crt_wprintf,cfm$("\n QueryInterface IConnectionPointContainer OK ")
;------------------------------------------ IConnectionPointContainer.FindConnectionPoint
LEA ECX, m_pIConnectionPoint
PUSH ECX
lea eax ,IID___ClsForTest
    PUSH EAX
    MOV EDX,pIConnectionPointContainer
    PUSH EDX
    MOV EDX,[EDX]
    CALL DWORD PTR [EDX+16];FindConnectionPoint
.if m_pIConnectionPoint
    MOV EDX,pIConnectionPointContainer
    PUSH EDX
    MOV EDX,[EDX]
    CALL DWORD PTR [EDX+8];release
        invoke crt_wprintf,cfm$("\n FindConnectionPoint OK")
;------------------------------------------ FindConnectionPoint.Advise
LEA ECX, m_dwCookie
PUSH ECX
lea ecx,Inst__ClsForTest
    PUSH ecx 
    MOV EDX,m_pIConnectionPoint
    PUSH EDX
    MOV EDX,[EDX]
    CALL DWORD PTR [EDX+20];Advise
    .if eax == S_OK
        invoke crt_wprintf,cfm$("\n Advise OK ")
.else
        invoke crt_wprintf,cfm$("\n Advise Failer eax:=0x%Xh"),eax
    .endif
.else
        invoke crt_wprintf,cfm$("\n FindConnectionPoint Failer")
.endif
        .else
        invoke crt_wprintf,cfm$("\n IConnectionPointContainer Failer")
        .endif
ret
__ClsForTest@Advise endp

and after invoke _ClsForTest@MethodForTest : add
invoke __ClsForTest@Advise


then add another  invoke _ClsForTest@MethodForTest for test if the event is fired
The final code as follows: __UNICODE__ equ 1
include \masm32\include\masm32rt.inc
.data
IID_IUnknown GUID <000000000H,00000H,00000H,<0C0H,000H,000H,000H,000H,000H,000H,046H>>
IID_IConnectionPointContainer GUID <0B196B284h,0BAB4h,0101Ah,<0B6h,09Ch,000h,0AAh,000h,034h,01Dh,007h>>

include Ev_ClsForTest.inc
include Cls_ClsForTest.inc
.code
Start:
invoke CoInitializeEx, NULL,COINIT_MULTITHREADED    ;COINIT_APARTMENTTHREADED ;
.if rv( _ClsForTest@CreateClass); Create New ClsForTest
invoke _ClsForTest@MethodForTest ;ClsForTest.MethodForTest
invoke __ClsForTest@Advise
invoke _ClsForTest@MethodForTest ;ClsForTest.MethodForTest
invoke _ClsForTest@Release ; ClsForTest.Release
.endif
invoke CoUninitialize
inkey
exit
End Start


Switch between COINIT_MULTITHREADED   and COINIT_APARTMENTTHREADED at CoInitializeEx; then tell me what's going on

mabdelouahab

At here everything is working fine; We have succeeded in working with InprocServer DLL
So
I created the same ٍVB project, But this time with EXE Active X
Alert: I added event 2
Public Event EventForTest()
Public Event EventForTest2()

Public Sub MethodForTest()
    MsgBox "Hi Is Me ..."
    RaiseEvent EventForTest2
    RaiseEvent EventForTest
End Sub

And I created a second Masm project for working with the new VB project , But the strange thing this time everything well
Quote
CreateClass _ClsForTest OK
QueryInterface IConnectionPointContainer OK
FindConnectionPoint OK
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@AddRef
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@Release
__ClsForTest@QueryInterface
__ClsForTest@AddRef
Advise OK
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@Release
__ClsForTest@AddRef
__ClsForTest@_Invoke 2
__ClsForTest@MethodForTest
__ClsForTest@_Invoke 1
__ClsForTest@MethodForTest
__ClsForTest@Release
__ClsForTest@Release
__ClsForTest@Release
__ClsForTest@QueryInterface
__ClsForTest@QueryInterface
__ClsForTest@ReleasePress any key to continue ...
Don't forget Reg.Bat to register exe server

mabdelouahab

What happens to me
This time everything worked
Everything went correctly
What we neglect in the past  :redface:

mabdelouahab

Dave , Zen ,adeyblue ,jj2007 , Biterider ,Gunther .. Thank you all  :t, Forum members, Thank everyone

Gunther

Hi mabdelouahab,

Quote from: mabdelouahab on April 26, 2015, 04:53:20 AM
Dave , Zen ,adeyblue ,jj2007 , Biterider ,Gunther .. Thank you all  :t, Forum members, Thank everyone

it was our pleasure to help you.

Gunther
You have to know the facts before you can distort them.