News:

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

Main Menu

COM Events

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

Previous topic - Next topic

mabdelouahab

    QueryInterface proc    lpME:dword ,riid:DWORD,ppvObj:DWORD
    LOCAL ff
        invoke crt_wprintf,cfm$("\n QueryInterface   iidClass  :\n   ")
        invoke PrintGUID,riid
        .if rv(IsEqualGUID,addr IID_IUnknown ,riid)
        invoke crt_wprintf,cfm$("_QIf2")
        mov eax,lpME
    mov ecx,ppvObj
    mov dword ptr [ecx],eax
    mov eax,S_OK
    jmp exQI
        .endif
        .if  rv(IsEqualGUID,addr IID_IDispatch,riid)
        invoke crt_wprintf,cfm$("_QIf3")
        mov eax,lpME
    mov ecx,ppvObj
    mov dword ptr [ecx],eax
    mov eax,S_OK
    jmp exQI
        .endif
        .if  rv(IsEqualGUID,addr IID___Class1,riid)
        invoke crt_wprintf,cfm$("_QIf4")
        mov eax,lpME
    mov ecx,ppvObj
    mov dword ptr [ecx],eax
    mov eax,S_OK
    jmp exQI
        .endif
        .if  rv(IsEqualGUID,addr IID_IMarshal,riid)
        invoke crt_wprintf,cfm$("QIf5")
        .if !Inst_InterfaceIMarshal
        mov ecx,rv(CreateInterface@IMarshal)
        mov Inst_InterfaceIMarshal,ecx
        .endif
        lea eax,Inst_InterfaceIMarshal
    mov ecx,ppvObj
    mov [ecx],eax
    mov eax,S_OK
    jmp exQI
        .endif
;         .if  rv(IsEqualGUID,addr IID_INoMarshal,riid)
;         invoke crt_wprintf,cfm$("QIf7")
;         lea eax,Inst_ICF ; IClassFactory
;     mov ecx,ppvObj
;     mov dword ptr [ecx],eax
;     mov eax,S_OK
;     jmp exQI
;         .endif
        mov eax,E_NOINTERFACE
    exQI:
    ret
    QueryInterface endp

IMarshal_QIP typedef proto IMarshal_QIP :DWORD,:DWORD,:DWORD
IMarshal_QRP typedef proto IMarshal_QRP :DWORD
IMarshal_RLP typedef proto IMarshal_RLP :DWORD

IMarshal_GetUnmarshalClassProto typedef proto IMarshal_GetUnmarshalClassProto :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
IMarshal_GetMarshalSizeMaxProto typedef proto IMarshal_GetMarshalSizeMaxProto :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
IMarshal_MarshalInterfaceProto typedef proto IMarshal_MarshalInterfaceProto :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
IMarshal_UnmarshalInterfaceProto typedef proto IMarshal_UnmarshalInterfaceProto :DWORD,:DWORD,:DWORD,:DWORD
IMarshal_ReleaseMarshalDataProto typedef proto IMarshal_ReleaseMarshalDataProto :DWORD,:DWORD
IMarshal_DisconnectObjectProto typedef proto IMarshal_DisconnectObjectProto :DWORD,:DWORD

IMarshal_QIPP typedef ptr  IMarshal_QIP 
IMarshal_QRPP typedef ptr  IMarshal_QRP 
IMarshal_RLPP typedef ptr  IMarshal_RLP 
IMarshal_GetUnmarshalClassVal typedef ptr IMarshal_GetUnmarshalClassProto
IMarshal_GetMarshalSizeMaxVal typedef ptr IMarshal_GetMarshalSizeMaxProto
IMarshal_MarshalInterfaceVal typedef ptr IMarshal_MarshalInterfaceProto
IMarshal_UnmarshalInterfaceVal typedef ptr IMarshal_UnmarshalInterfaceProto
IMarshal_ReleaseMarshalDataVal typedef ptr IMarshal_ReleaseMarshalDataProto
IMarshal_DisconnectObjectVal typedef ptr IMarshal_DisconnectObjectProto

IMarshal            STRUCT
    QueryInterface IMarshal_QIPP 0
    AddRef IMarshal_QRPP 0
    Release IMarshal_RLPP 0
GetUnmarshalClass    IMarshal_GetUnmarshalClassVal 0
GetMarshalSizeMax    IMarshal_GetMarshalSizeMaxVal 0
MarshalInterface IMarshal_MarshalInterfaceVal 0
UnmarshalInterface    IMarshal_UnmarshalInterfaceVal 0
ReleaseMarshalData    IMarshal_ReleaseMarshalDataVal 0
DisconnectObject    IMarshal_DisconnectObjectVal 0
IMarshal            ENDS
.data

pMarshal dd 0

.code
    IMarshal@QueryInterface proc    lpME:dword ,riid:DWORD,ppvObj:DWORD
        invoke crt_wprintf,cfm$("\n ICP_QIf")
        invoke PrintGUID,riid
        mov eax,lpME
    mov ecx,ppvObj
    mov dword ptr [ecx],eax
    mov eax,S_OK
    ret
    IMarshal@QueryInterface endp

IMarshal@AddRef proc lpME:dword
invoke crt_wprintf,cfm$("\n IMarshal@AddRef ")
inc RefCount
mov eax,RefCount
ret
IMarshal@AddRef endp
IMarshal@Release proc lpME:dword
invoke crt_wprintf,cfm$("\n IMarshal@Release")
dec RefCount
mov eax,RefCount
ret
IMarshal@Release endp
IMarshal@GetUnmarshalClass proc lpME :DWORD,riid:DWORD,pv:DWORD,dwDestContext:DWORD,pvDestContext:DWORD,mshlflags:DWORD,pClsid:DWORD
LOCAL dwRegister
LOCAL dd__
;jmp stest2
        lea eax,pclsismarsh
    mov ecx,pClsid
    m2m dword ptr [ecx],dword ptr [eax]
    m2m dword ptr [ecx+4],dword ptr [eax+4]
    m2m dword ptr [ecx+8],dword ptr [eax+8]
    m2m dword ptr [ecx+12],dword ptr [eax+12]
    invoke crt_wprintf,cfm$("\n IMarshal@GetUnmarshalClass   iidClass  :\n   ")
invoke PrintGUID,riid
jmp IMarshal@GetUnmarshalClassexit
;************************************************************** 1 test
stest2:
mov pMarshal,0
        invoke CoGetStandardMarshal,addr IID___Class1,NULL, dwDestContext,pvDestContext, mshlflags,addr pMarshal
        .if pMarshal
        invoke crt_wprintf,cfm$("\n    CoGetStandardMarshal OK ")
mov ecx,pMarshal
mov edx,ecx
mov ecx,[ecx]
invoke [ECX].IMarshal.GetUnmarshalClass,edx,addr IID___Class1, NULL, dwDestContext, pvDestContext, mshlflags, pClsid
.if !eax
invoke crt_wprintf,cfm$("\n     GetUnmarshalClass OK ")
.endif
mov ecx,pMarshal
mov edx,ecx
mov ecx,[ecx]
invoke [ECX].IMarshal.Release,edx
.else
invoke crt_wprintf,cfm$("\n CoGetStandardMarshal ___________ Fail ")       
        .endif
IMarshal@GetUnmarshalClassexit:
ret
IMarshal@GetUnmarshalClass endp
.data
h dd 0
m_spIStream dd 0
cbMax dq 0
        iLNull  dq  0
        uLLen  dq  0
        spIPersistStm dd 0
.code

IMarshal@GetMarshalSizeMax proc lpME:DWORD,riid:DWORD,pv:DWORD,dwDestContext:DWORD,pvDestContext:DWORD,mshlflags:DWORD,pSize:DWORD
LOCAL lff
local ulSize,hGlobal,ppStreamReceiver_
mov lff,0
invoke crt_wprintf,cfm$("\n IMarshal@GetMarshalSizeMax iidClass: \n     ")
invoke PrintGUID,riid
invoke crt_wprintf,cfm$("\n")
        invoke CoGetStandardMarshal,addr IID___Class1,NULL, dwDestContext,pvDestContext, mshlflags,addr pMarshal
        .if pMarshal
        invoke crt_wprintf,cfm$("\n    CoGetStandardMarshal  OK ")
mov ecx,pMarshal
mov edx,ecx
mov ecx,[ecx]
invoke [ECX].IMarshal.GetMarshalSizeMax,edx,addr IID___Class1, pv, dwDestContext, pvDestContext, mshlflags, pSize
.if !eax
mov eax,pSize
mov edx,[eax]
invoke crt_wprintf,cfm$("\n     IMarshal.GetMarshalSizeMax pSize= %d "),edx
.endif
.else
invoke crt_wprintf,cfm$("\n    CoGetStandardMarshal  Fail ")       
        .endif
IMarshal@GetMarshalSizeMaxexit:
mov eax,S_OK ;E_FAIL
ret
IMarshal@GetMarshalSizeMax endp
IMarshal@MarshalInterface proc  lpME:DWORD,pStm:DWORD,riid:DWORD,pv:DWORD,dwDestContext:DWORD,pvDestContext:DWORD,mshlflags:DWORD


invoke crt_wprintf,cfm$("\n\n IMarshal@MarshalInterface ")
ret
IMarshal@MarshalInterface endp
IMarshal@UnmarshalInterface proc  lpME:DWORD,pStm:DWORD,riid:DWORD,ppv:DWORD

invoke crt_wprintf,cfm$("\n IMarshal@UnmarshalInterface")
mov eax,E_NOTIMPL
ret
IMarshal@UnmarshalInterface endp

IMarshal@ReleaseMarshalData proc lpME:dword ,pStm:DWORD
invoke crt_wprintf,cfm$("\n\n IMarshal@ReleaseMarshalData ")
ret
IMarshal@ReleaseMarshalData endp
IMarshal@DisconnectObject proc lpME:dword ,dwReserved:DWORD
invoke crt_wprintf,cfm$("\n\n IMarshal@DisconnectObject")
ret
IMarshal@DisconnectObject endp

CreateInterface@IMarshal proc
invoke LocalAlloc,LMEM_FIXED or LMEM_ZEROINIT ,sizeof IMarshal
mov edi,eax
mov dword ptr [edi] ,OFFSET IMarshal@QueryInterface
add edi,4
mov dword ptr [edi] ,OFFSET IMarshal@AddRef
add edi,4
mov dword ptr [edi] ,OFFSET IMarshal@Release
add edi,4
mov dword ptr [edi] ,OFFSET IMarshal@GetUnmarshalClass
add edi,4
mov dword ptr [edi] ,OFFSET IMarshal@GetMarshalSizeMax
add edi,4
mov dword ptr [edi] ,OFFSET IMarshal@MarshalInterface
add edi,4
mov dword ptr [edi] ,OFFSET IMarshal@UnmarshalInterface
add edi,4
mov dword ptr [edi] ,OFFSET IMarshal@ReleaseMarshalData
add edi,4
mov dword ptr [edi] ,OFFSET IMarshal@DisconnectObject
ret
CreateInterface@IMarshal endp


mabdelouahab

For illustration
I added to the QueryInterface:

        .if  rv(IsEqualGUID,addr IID_IMarshal,riid)
        invoke crt_wprintf,cfm$("QIf5")
        .if !Inst_InterfaceIMarshal
        mov ecx,rv(CreateInterface@IMarshal)
        mov Inst_InterfaceIMarshal,ecx
        .endif
        lea eax,Inst_InterfaceIMarshal
    mov ecx,ppvObj
    mov [ecx],eax
    mov eax,S_OK
    jmp exQI
        .endif

With the addition of IMarshal inc

Zen

MABDELOUAHAB,
Can you post your current source (and maybe a compiled executable) for your client ???
...So, that we can understand what you've got that actually WORKS ???
Zen

mabdelouahab

OK Zen
dont forget \vbexmple\REG.bat

Gunther

Hi mabdelouahab,

is a VB installation necessary for your example?

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

mabdelouahab

I Add masm server example, Choose which Server you want to , and If you choose masm server , run "\AsmEvent\REG.bat"

Gunther

That's fine. Thank you.

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

Zen

#37
MABDELOUAHAB,
I was looking at your server code (which presumably compiles into AsmEvent.dll, located in the AsmEvent directory), including the DEF file:
; MyCom2.def : Declares the module parameters.

LIBRARY      "AsmEvent.DLL"

EXPORTS
DllCanUnloadNow        @1 PRIVATE
DllGetClassObject      @2 PRIVATE
DllRegisterServer      @3 PRIVATE
DllUnregisterServer    @4 PRIVATE



I ran the DUMPBIN utility on the AsmEvent DLL with the /EXPORTS option, and, yes, it told me that AsmEvent.dll does export  DllGetClassObject (also, DllRegisterServer, DllUnregisterServer, and DllCanUnloadNow). I'm assuming that AsmEvent.dll is an In-Proc server, because it's a DLL (In-Proc servers must be DLLs). But, without the implementation of DllRegisterServer, I can't be sure.

...Anyway, I couldn't find the implementation of these exported functions.
If DLL doesn't export DllGetClassObject, all activation calls will fail.

This quote is from: The Rules of the Component Object Model, MSDN
QuoteServer Rules
In-process servers must export DllGetClassObject and DllCanUnloadNow.
In-process servers must support COM self-registration.
In-process and local servers should put an OLESelfReg string in their file version information.
In-process servers should export DllRegisterServer and DllUnRegisterServer.
Local servers should support the /RegServer and /UnRegServer command-line switches.

This quote is from: Introduction to COM Part II - Behind the Scenes of a COM Server

Quote from: Introduction to COM Part II - Behind the Scenes of a COM ServerAn in-proc server must meet two criteria before it can be used by the COM library:
It must be registered properly under the HKEY_CLASSES_ROOT\CLSID key.
It must export a function called DllGetClassObject().

Here is a good description of: How Does COM Activation Work Anyway?, Larry Osterman's Blog (The article's hyperlinks are dead, but, you can Google them.)

DllGetClassObject Entry Point, MSDN

Create Class (which is in the client code directory, TestEvents.inc, looks like this)
CreateClass Proc

    invoke CoCreateInstance,addr sCLSID_Class1,NULL,CLSCTX_LOCAL_SERVER,addr IID_IUnknown,addr Inst_IUnknown
        .if eax == S_OK
LEA ECX, Inst_Class1
PUSH ECX
lea eax ,IID__Class1
        PUSH EAX
        MOV EDX,Inst_IUnknown
        PUSH EDX
        MOV EDX,[EDX]
        CALL DWORD PTR [EDX]
.if !eax
        invoke crt_wprintf,cfm$("\n CreateClass OK ")
            MOV EAX,TRUE
.else
        invoke crt_wprintf,cfm$("\n CreateClass fail ")
            MOV EAX,FALSE
.endif
        .else
        MOV EAX,FALSE
        .endif
ret
CreateClass endp


This routine is called in TestEvent.asm. Presumably, TestEvent.asm will be compiled into the client exe.
You know, it's confusing,...all these directories have files with the same names (yes, I know, the paths are different).
Zen

Zen

#38
MABDELOUAHAB,
You will notice in the above call to CoCreateInstance, that the CLSCTX_LOCAL_SERVER member of the CLSCTX Enumeration is specified, indicating that the server is: an Out-Of-Process Server (The EXE code that creates and manages objects of this class runs on same machine but is loaded in a separate process space.)

The following is from: COM Clients and Servers, MSDN
QuoteThere are two main types of servers, in-process and out-of-process. In-process servers are implemented in a dynamic linked library (DLL), and out-of-process servers are implemented in an executable file (EXE). Out-of-process servers can reside either on the local computer or on a remote computer.

Informative reading: COM Server Responsibilities, MSDN

...So,...what is it ??? An In-Proc Server or an Out-Of-Process Server ??? I think that neglecting these kinds of critically important details in your current project, is why MASM Forum members are reluctant to provide suggestions and help for your 'problem',...
If you don't know, just ask,...there a number of extremely-knowledgeable, World-Class COM programmers that belong to this Forum,...
...Heck,...even DAVE knows quite a bit about COM,...:icon_eek:

...Here's how Japheth implements DllGetClassObject (from, SimpleServer.asm, in the zip file, Simple Server Example, Japheth.zip):
;--------------------------------------------------------------
;--- DllGetClassObject: scans object table to see if requested
;--- CLSID is in there. If yes, creates an IClassFactory object
;--------------------------------------------------------------

DllGetClassObject PROC public uses esi rclsid:ptr CLSID,riid:ptr IID,ppReturn:ptr LPCLASSFACTORY

mov eax, ppReturn
mov DWORD PTR [eax], 0

mov esi, offset ObjectMap
mov ecx, OBJECTMAPITEMS
.while (ecx)
push ecx
invoke IsEqualGUID, rclsid, [esi].ObjectEntry.pClsId
pop ecx
.break .if (eax)
add esi, sizeof ObjectEntry
dec ecx
.endw
.if (!ecx)
mov eax, CLASS_E_CLASSNOTAVAILABLE
jmp done
.endif

invoke Create@CClassFactory, esi
.if (eax == NULL)
mov eax, E_OUTOFMEMORY
jmp done
.endif
mov esi,eax

invoke vf(esi,IClassFactory,QueryInterface),riid,ppReturn
push eax
invoke vf(esi,IClassFactory,Release)
pop eax
done:
ret

DllGetClassObject ENDP


...That file also has example implementations of: DllRegisterServer, DllUnregisterServer, and, DllCanUnloadNow.

...Here are some interesting blog articles from Raymond Chen:
How Can I Tell Whether a DLL Has Been Registered?
Registration-Free COM the Old-Fashioned Way

...And, you should probably read these too (from Larry Osterman's Blog):
So What Exactly IS COM Anyway ?, Larry Osterman
Minimal COM Object Registration, Larry Osterman
What Registry Entries Are Needed To Register a COM Object ?, Larry Osterman
COM Registration If You Need a Typelib, Larry Osterman
What Are These "Threading Models" and Why Do I Care?, Larry Osterman
COM Registration for Cross Process Access, Larry Osterman
When Do You Need an APPID in your COM Registration ?, Larry Osterman

...OK,...sorry,...that last section is just overkill,...
Zen

mabdelouahab

#39
Hi Zen
I thank you for helping me,
Just for clarification, I found that information available, clear, but there is always an error.
I focused on errors only, in order to know the real problem
Before speaking to the real problem, I want to point out what I have learned
When the Client forwards request to the server to associate a connection point, The server sends the request to the proxy, either iid of custom interface or iid_IMarshal ,
* iid of custom interface In the case of single Thread,
* IID_IMarshal In the case of Multi-Thread,In this case the system intervenes by COMBASE.DLL to solve the problem between disputants
The Client must send our Instance of IMarshal, then COM sends 3 consecutive requests
1.IMarshal::GetUnmarshalClass is called to obtain the CLSID of the proxy object.
2.IMarshal::GetMarshalSizeMax is called to determine the size of the marshaling packet that the interface needs.
The system allocates the memory and then creates a stream object that wraps the memory buffer.
3.IMarshal::MarshalInterface is called to tell the object to marshal the interface pointer into the stream.

Here detailing locations Will That Be Custom or Standard Marshaling? or How to marshal interfaces across apartments in Visual C++(for more information)
I go back to my problem
I used VS2012 Debuger to access error, I discovered that ...(Focused with me please)
Error in which debt program stops Is that the Parametre sent to the function overlap, Sometimes at the programme ، and Sometimes at the COMBASE.DLL



this is mov edx,pSize
mov dword ptr [edx],255

In
IMarshal@GetMarshalSizeMax   proc     lpME:DWORD, riid:DWORD,pv:DWORD,dwDestContext:DWORD,pvDestContext:DWORD,mshlflags:DWORD,pSize:DWORD
The procedure receives the value of pSize 0


this is IStream::Write
but pStream = addr of IID_INoMarshal
I think that the Align

mabdelouahab

I've translated the proceedings being conducted by the COMBASE.DLL in the BackGround:
PMarshal proc pUnknown,riid,  dwDestContext, pvDestContext, dwFlags

; AddRef the incoming pointer to verify that it is safe.
;******************* pUnknown::AddRef
        MOV EDX, pUnknown
        PUSH EDX   
        MOV EDX,[EDX]   
        CALL DWORD PTR [EDX+4] ; pUnknown::AddRef

; Do you support custom marshaling?
;******************* pUnknown::QueryInterface
        PUSH OFFSET pMarshal_   
        PUSH OFFSET IID_IMarshal   
        MOV EDX, pUnknown
        PUSH EDX   
        MOV EDX,[EDX]   
        CALL DWORD PTR [EDX] ; pUnknown::QueryInterface
; I guess not, so we'll use standard marshaling.
.if eax == E_NOINTERFACE
invoke CoGetStandardMarshal,riid, pUnknown, dwDestContext, pvDestContext, dwFlags, addr pMarshal_
.endif
; OK, what's the CLSID of your proxy?
mov ecx,pMarshal_
mov edx,ecx
mov ecx,[ecx]
invoke [ECX].IMarshal.GetUnmarshalClass,edx,riid, pUnknown, dwDestContext, pvDestContext, dwFlags,addr clsid
; How much space do you need?
mov ecx,pMarshal_
mov edx,ecx
mov ecx,[ecx]
invoke [ECX].IMarshal.GetMarshalSizeMax,edx,riid, pUnknown, dwDestContext, pvDestContext, dwFlags,addr packetSize
; Allocate that memory.
mov ecx,packetSize
add ecx,sizeof CLSID
mov pMem ,rv(GlobalAlloc,GHND, ecx );
; Turn it into a stream object.
invoke CreateStreamOnHGlobal,pMem, FALSE, addr pStream_
.if !eax
invoke crt_wprintf,cfm$("\n .... CreateStreamOnHGlobal OK \n")
.endif
; Write the CLSID of the proxy into the stream.
invoke WriteClassStm,pStream_,addr clsid
.if !eax
invoke crt_wprintf,cfm$("\n .... WriteClassStm OK \n")
.endif
; Marshal that interface into the stream.
mov ecx,pMarshal_
mov edx,ecx
mov ecx,[ecx]
invoke [ECX].IMarshal.MarshalInterface,edx,pStream_,riid, pUnknown, dwDestContext, pvDestContext, dwFlags

push eax

; Release everything in sight.
        MOV EDX, pStream_
        PUSH EDX   
        MOV EDX,[EDX]   
        CALL DWORD PTR [EDX+8] ; pStream::Release

        MOV EDX, pMarshal_
        PUSH EDX   
        MOV EDX,[EDX]   
        CALL DWORD PTR [EDX+8] ; pMarshal::Release

        MOV EDX, pUnknown
        PUSH EDX   
        MOV EDX,[EDX]   
        CALL DWORD PTR [EDX+8] ; pUnknown::Release

pop eax

ret
PMarshal endp

mabdelouahab

Without the use of any communication with the server
And without any new CoCreateInstanceof objects
When you create new interface and use CoMarshalInterface the com is the same with you and produce the same errors

invoke CoInitializeEx, NULL,COINIT_MULTITHREADED    ;COINIT_APARTMENTTHREADED ;
invoke CoCreateGuid,addr pclsismarsh
mov Inst_InterfaceMASM,rv(CreateInterfaceMASM)
mov Inst_ICF,rv(CreateInterface@IClassFactory)
invoke CoRegisterClassObject,addr pclsismarsh,addr  Inst_ICF ,CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE,addr dwReg__
  invoke GlobalAlloc,GMEM_MOVEABLE,ecx
  mov hGlobal,eax
  invoke  CreateStreamOnHGlobal, hGlobal, TRUE,addr ppStreamReceiver_
  invoke CoMarshalInterface ,ppStreamReceiver_, addr IID___Class1, addr Inst_Interface, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL

mabdelouahab

Quote from: Zen on April 24, 2015, 06:33:20 AM
MABDELOUAHAB,
I was looking at your server code (which presumably compiles into AsmEvent.dll, located in the AsmEvent directory), including the DEF file:
; MyCom2.def : Declares the module parameters.

LIBRARY      "AsmEvent.DLL"

EXPORTS
DllCanUnloadNow        @1 PRIVATE
DllGetClassObject      @2 PRIVATE
DllRegisterServer      @3 PRIVATE
DllUnregisterServer    @4 PRIVATE



I ran the DUMPBIN utility on the AsmEvent DLL with the /EXPORTS option, and, yes, it told me that AsmEvent.dll does export  DllGetClassObject (also, DllRegisterServer, DllUnregisterServer, and DllCanUnloadNow). I'm assuming that AsmEvent.dll is an In-Proc server, because it's a DLL (In-Proc servers must be DLLs). But, without the implementation of DllRegisterServer, I can't be sure.
....
Not important, because CoCreateInstanceEx locate COM component DLL (From registry) then load it into memory using LoadLibrary, then locate DllGetClassObject function exported from the DLL using GetProcAddress Win32 API, Call DllGetClassObject and obtain IClassFactory interface of your component class factory

mabdelouahab

Quote from: Zen on April 25, 2015, 03:29:30 AM
MABDELOUAHAB,
You will notice in the above call to CoCreateInstance, that the CLSCTX_LOCAL_SERVER member of the CLSCTX Enumeration is specified, indicating that the server is: an Out-Of-Process Server (The EXE code that creates and manages objects of this class runs on same machine but is loaded in a separate process space.)

The following is from: COM Clients and Servers, MSDN
QuoteThere are two main types of servers, in-process and out-of-process. In-process servers are implemented in a dynamic linked library (DLL), and out-of-process servers are implemented in an executable file (EXE). Out-of-process servers can reside either on the local computer or on a remote computer.

Informative reading: COM Server Responsibilities, MSDN

...So,...what is it ??? An In-Proc Server or an Out-Of-Process Server ??? I think that neglecting these kinds of critically important details in your current project ...
Zen
I haven't neglected this, and explained that if case single Thread the QueryInterface will receive IID of EventClass, and in the case of multiple thread
The QueryInterface  receives IID_IMarshal Because the program required that Marshal our Interface to send it
And Excuse me for my english

mabdelouahab

Quote from: Zen on April 25, 2015, 03:29:30 AM
..., is why MASM Forum members are reluctant to provide suggestions and help for your 'problem',...
If you don't know, just ask,...there a number of extremely-knowledgeable, World-Class COM programmers that belong to this Forum,...
...Heck,...even DAVE knows quite a bit about COM,...

Always I'm getting help from Forum members, Thank everyone of course  :biggrin:
If someone can continue with me, I suggested that I restored from zero, and does not add anything to the project until I explained