;*** interfaces IConnectionPointContainer, IEnumConnectionPoints,
;*** IConnectionPoint

	.386
	.model flat, stdcall
	option casemap:none ; case sensitive
	option proc:private

	.nolist
	.nocref
	include windows.inc
	include unknwn.inc
	include objidl.inc
	include oleidl.inc
	include olectl.inc
	include oaidl.inc
	include ocidl.inc
	include CatProp.inc

	include macros.inc
	include debugout.inc
	.list
	.cref

	include control.inc

CEnumConnectionPoints struct
m_IEnumConnectionPoints IEnumConnectionPoints <>
m_ObjRefCount		DWORD	?
m_pObject			DWORD	?
m_dwIndex			DWORD	?
CEnumConnectionPoints ends


Create@CEnumConnectionPoints proto :ptr CAsmCtrl
Create@CConnectionPoint proto :ptr CConnectionPoint, :ptr CAsmCtrl, :ptr IID


	.const

CConnectionPointContainerVtbl IConnectionPointContainerVtbl {\
	QueryInterface_, AddRef_, Release_,\
	EnumConnectionPoints, FindConnectionPoint}
	
CEnumConnectionPointsVtbl IEnumConnectionPointsVtbl {\
	QueryInterface@CEnumConnectionPoints, AddRef@CEnumConnectionPoints, Release@CEnumConnectionPoints,\
	Next, Skip, Reset, Clone}

CConnectionPointVtbl IConnectionPointVtbl {\
	QueryInterface@CConnectionPoint, AddRef@CConnectionPoint, Release@CConnectionPoint,\
	GetConnectionInterface, GetConnectionPointContainer, \
	Advise, Unadvise, EnumConnections}

	.code

;--------------------------------------------------------------------------
;IConnectionPointContainer interface
;--------------------------------------------------------------------------

CastOffset textequ <offset CAsmCtrl.m_IConnectionPointContainer>

	@MakeIUnknownStubs CastOffset

InitCP proc uses ebx edi this_:ptr CAsmCtrl

	mov ebx,this_
	assume ebx:ptr CAsmCtrl
	lea edi,[ebx].m_CPArray

	.if ([edi].CConnectionPoint.m_refIID == NULL)
		invoke Create@CConnectionPoint, edi, ebx, addr IID__AsmCtrlEvent
	.endif
	add edi,sizeof CConnectionPoint
;------------------ add other connectionpoints here!
;	.if ([edi].CConnectionPoint.m_refIID == NULL)
;		invoke Create@CConnectionPoint, edi, ebx, addr IID__AsmCtrlEventXXX
;	.endif
	ret
	align 4

InitCP endp



EnumConnectionPoints proc this_:ptr CAsmCtrl, ppIEnumConnectionPoints:ptr ptr

	@AdjustThis

	DebugOut "IConnectionPointContainer::EnumConnectionPoints"
	.if (ppIEnumConnectionPoints == NULL)
		return E_POINTER
	.endif

	invoke InitCP, this_

	invoke Create@CEnumConnectionPoints, this_

	mov ecx,ppIEnumConnectionPoints
	mov [ecx],eax
	.if (eax)
		return S_OK
	.else
		return E_OUTOFMEMORY
	.endif
	align 4

EnumConnectionPoints endp

;--------------------------------------------------------------------------

FindConnectionPoint proc uses ebx esi edi this_:ptr CAsmCtrl, pRefIID: ptr IID, ppIConnectionPoint:ptr ptr

	@AdjustThis

	mov ebx,this_
	assume ebx:ptr CAsmCtrl

	DebugOut "IConnectionPointContainer::FindConnectionPoint"

	mov eax,ppIConnectionPoint
	.if (eax == NULL)
		return E_POINTER
	.endif
	mov dword ptr [eax],NULL

	invoke InitCP, ebx

	lea esi,[ebx].m_CPArray
	mov edi,sizeof CPArray / sizeof CConnectionPoint

	.while (edi)
		invoke IsEqualGUID, [esi].CConnectionPoint.m_refIID, pRefIID
		.if (eax)
			invoke ComPtrAssign, ppIConnectionPoint, esi
			return S_OK
		.endif
		dec edi
		add esi,sizeof CConnectionPoint
	.endw
	
	return CONNECT_E_NOCONNECTION
	assume ebx:nothing
	align 4

FindConnectionPoint endp

;--------------------------------------------------------------------------
;IEnumConnectionPoints interface
;--------------------------------------------------------------------------

Create@CEnumConnectionPoints proc uses ebx pObject:ptr CAsmCtrl

	DebugOut "Create@CEnumConnectionPoints"

	invoke LocalAlloc,LMEM_FIXED,sizeof CEnumConnectionPoints
	.if (eax == NULL)
		ret
	.endif
	mov ebx,eax
	assume ebx:ptr CEnumConnectionPoints

	mov [ebx].m_IEnumConnectionPoints,offset CEnumConnectionPointsVtbl
	mov [ebx].m_ObjRefCount,1
	mov eax,pObject
	mov [ebx].m_pObject,eax
	invoke vf(eax, IUnknown, AddRef)
	mov [ebx].m_dwIndex,0

	inc g_DllRefCount

	return ebx
	assume ebx:nothing
	align 4

Create@CEnumConnectionPoints endp


?CEnumConnectionPoints proc uses ebx this_:ptr CEnumConnectionPoints

	DebugOut "?CEnumConnectionPoints"

	mov eax,this_
	invoke vf([eax].CEnumConnectionPoints.m_pObject, IUnknown, Release)
	invoke LocalFree,this_
	dec g_DllRefCount
	ret
	align 4

?CEnumConnectionPoints endp

	.const

supInterfaces label dword
	dd offset IID_IUnknown,0
	dd offset IID_IEnumConnectionPoints,0
IFTABSIZE equ ($ - supInterfaces)/ (2 * sizeof dword)

	.code

QueryInterface@CEnumConnectionPoints proc this_:ptr CEnumConnectionPoints,riid:ptr IID,ppReturn:ptr
	invoke IsInterfaceSupported, riid, offset supInterfaces, IFTABSIZE,  this_, ppReturn
	ret
	align 4
QueryInterface@CEnumConnectionPoints endp


AddRef@CEnumConnectionPoints proc this_:ptr CEnumConnectionPoints

	mov eax,this_
	assume eax:ptr CEnumConnectionPoints

	inc [eax].m_ObjRefCount
	mov eax, [eax].m_ObjRefCount
	ret
	assume eax:nothing
	align 4

AddRef@CEnumConnectionPoints endp


Release@CEnumConnectionPoints proc this_:ptr CEnumConnectionPoints

	mov eax,this_
	assume eax:ptr CEnumConnectionPoints

	dec [eax].m_ObjRefCount
	mov eax,[eax].m_ObjRefCount
	.if (eax == 0)
		invoke ?CEnumConnectionPoints,this_
		xor eax,eax
	.endif
	ret
	assume eax:nothing
	align 4

Release@CEnumConnectionPoints endp


Next proc uses ebx esi edi this_:ptr CEnumConnectionPoints, dwElements:dword, ppICP:ptr LPCONNECTIONPOINT, pdwFetched:ptr dword

local	dwReturn:dword

	DebugOut "IEnumConnectionPoints::Next"

	mov ebx,this_
	assume ebx: ptr CEnumConnectionPoints

	.if (dwElements > 1 && !pdwFetched)
		return E_INVALIDARG
	.endif

	mov edi,ppICP
	.if (!edi)
		return E_POINTER
	.endif

	mov dwReturn,0

	mov esi,[ebx].m_pObject
	lea esi,[esi].CAsmCtrl.m_CPArray	;cannot be NULL here
	mov ecx,[ebx].m_dwIndex
	imul ecx,sizeof CConnectionPoint
	add esi,ecx

	.while (1)
		.break .if (ecx >= sizeof CPArray)
		.break .if (dwElements == 0)
		mov dword ptr [edi], NULL
		push ecx
		invoke ComPtrAssign, edi, esi
		pop ecx
		add edi, sizeof LPCONNECTIONPOINT
		add esi, sizeof CConnectionPoint
		add ecx, sizeof CConnectionPoint
		dec dwElements
		inc [ebx].m_dwIndex
		inc dwReturn
	.endw

	mov eax,pdwFetched
	.if (eax)
		mov ecx,dwReturn
		mov [eax],ecx
	.endif

	.if (dwElements == 0)
		mov eax,S_OK
	.else
		mov eax,S_FALSE
	.endif
	ret
	assume ebx:nothing
	align 4

Next endp


;--------------------------------------------------------------------------

Skip proc this_:ptr CEnumConnectionPoints, cConn:dword
	DebugOut "IEnumConnectionPoints::Skip"
	return E_FAIL
	align 4
Skip endp

;--------------------------------------------------------------------------

Reset proc this_:ptr CEnumConnectionPoints

	DebugOut "IEnumConnectionPoints::Reset"
	mov ecx,this_
	mov [ecx].CEnumConnectionPoints.m_dwIndex,0
	return S_OK
	align 4
Reset endp

;--------------------------------------------------------------------------

Clone proc this_:ptr CEnumConnectionPoints, ppIECP:ptr LPENUMCONNECTIONPOINTS
	mov ecx, ppIECP
	mov dword ptr [ecx], NULL
	return E_FAIL
	align 4
Clone endp


;--------------------------------------------------------------------------
;IConnectionPoint interface
;--------------------------------------------------------------------------

Create@CConnectionPoint proc uses ebx this_:ptr CConnectionPoint, pObject:ptr CAsmCtrl, riid:ptr IID

	DebugOut "Create@CConnectionPoint"

	mov ebx,this_
	assume ebx: ptr CConnectionPoint

	mov [ebx].m_IConnectionPoint,offset CConnectionPointVtbl
	mov [ebx].m_ObjRefCount,1
	mov eax,pObject
	mov [ebx].m_pObject,eax
	mov eax,riid
	mov [ebx].m_refIID,eax
	mov [ebx].m_pFirstSink,NULL

	return ebx
	align 4

Create@CConnectionPoint endp

?CConnectionPoint proc uses ebx this_:ptr CConnectionPoint

	DebugOut "?CConnectionPoint"

	mov ebx,this_
	assume ebx:ptr CConnectionPoint
;	mov [ebx].CConnectionPoint.m_refIID,NULL

	mov eax, [ebx].m_pFirstSink
	assume eax:ptr CEventSink
	mov [ebx].m_pFirstSink, NULL

	.while (eax)
		push [eax].m_pNext
		invoke LocalFree, eax
		pop eax
	.endw
	ret
	align 4
	assume ebx:nothing
	assume eax:nothing

?CConnectionPoint endp

	.const

supInterfaces2 label dword
	dd offset IID_IUnknown,0
	dd offset IID_IConnectionPoint,0
IFTABSIZE2 equ ($ - supInterfaces2)/ (2 * sizeof dword)

	.code

QueryInterface@CConnectionPoint proc this_:ptr CConnectionPoint,riid:ptr IID,ppReturn:ptr

	invoke IsInterfaceSupported, riid, offset supInterfaces2, IFTABSIZE2,  this_, ppReturn
	ret
	align 4

QueryInterface@CConnectionPoint endp


AddRef@CConnectionPoint proc this_:ptr CConnectionPoints


	mov eax,this_
	assume eax:ptr CConnectionPoint

	inc [eax].m_ObjRefCount

	DebugOut "IConnectionPoint::AddRef() [cnt=%u]", [eax].m_ObjRefCount

	mov eax, [eax].m_ObjRefCount
	ret
	assume eax:nothing
	align 4

AddRef@CConnectionPoint endp


Release@CConnectionPoint proc this_:ptr CConnectionPoint

	mov eax,this_
	assume eax:ptr CConnectionPoint

	dec [eax].m_ObjRefCount

	DebugOut "IConnectionPoint::Release() [cnt=%u]", [eax].m_ObjRefCount

	mov eax,[eax].m_ObjRefCount
	.if (eax == 0)
		invoke ?CConnectionPoint,this_
		xor eax,eax
	.endif
	ret
	assume eax:nothing
	align 4

Release@CConnectionPoint endp


GetConnectionInterface proc uses esi edi this_:ptr CConnectionPoint, pIID:ptr IID

	DebugOut "IConnectionPoint::GetConnectionInterface( %X )", pIID

	mov edi, pIID
	.if (edi == NULL)
		return E_POINTER
	.endif
	mov esi,offset IID__AsmCtrlEvent
	movsd
	movsd
	movsd
	movsd
	return S_OK
	align 4

GetConnectionInterface endp

;--------------------------------------------------------------------------

GetConnectionPointContainer proc this_:ptr CConnectionPoint, ppCPContainer:ptr IConnectionPointContainer

	DebugOut "IConnectionPoint::GetConnectionPointContainer( %X )", ppCPContainer

	mov ecx,this_
	mov ecx,[ecx].CConnectionPoint.m_pObject
	lea edx,[ecx].CAsmCtrl.m_IConnectionPointContainer
	mov eax,ppCPContainer
	.if (eax == NULL)
		return E_POINTER
	.endif
	mov [eax],edx
	invoke vf(edx, IUnknown, AddRef)

	return S_OK
	align 4

GetConnectionPointContainer endp

;--------------------------------------------------------------------------


Advise proc uses ebx esi this_:ptr CConnectionPoint, pUnknown:ptr IUnknown, pdwCookie:ptr dword

	DebugOut "IConnectionPoint::Advise( %X, %X )", pUnknown, pdwCookie

	mov eax,pdwCookie
	.if (eax == 0)
		return E_POINTER
	.endif
	mov dword ptr [eax],0

	mov ebx,this_
	assume ebx:ptr CConnectionPoint

if 0
;--- if only 1 sink for connection point is to be allowed
	.if ([ebx].m_pEvent)
		DebugOut "IConnectionPoint::Advise failed with CONNECT_E_ADVISELIMIT"
		return CONNECT_E_ADVISELIMIT
	.endif
endif

	invoke LocalAlloc, LMEM_FIXED or LMEM_ZEROINIT, sizeof CEventSink
	.if (eax == NULL)
		return E_OUTOFMEMORY
	.endif
	mov esi,eax
	assume esi:ptr CEventSink
	invoke vf( pUnknown, IUnknown, QueryInterface ), addr IID__AsmCtrlEvent, addr [esi].m_pEvent

	.if (eax != S_OK)
		invoke LocalFree, esi
		DebugOut "IConnectionPoint::Advise failed with CONNECT_E_CANNOTCONNECT"
		return CONNECT_E_CANNOTCONNECT
	.endif
	lea eax,[ebx].m_pFirstSink
	.while ([eax].CEventSink.m_pNext)
		mov eax, [eax].CEventSink.m_pNext
	.endw
	mov [eax].CEventSink.m_pNext, esi
	mov eax, pdwCookie
	mov [eax],esi
	return S_OK
	assume ebx:nothing
	align 4

Advise endp

;--------------------------------------------------------------------------

Unadvise proc uses ebx esi this_:ptr CConnectionPoint, dwCookie:dword

	DebugOut "IConnectionPoint::Unadvise(%X)", dwCookie

	mov ebx,this_
	assume ebx:ptr CConnectionPoint

	lea esi, [ebx].m_pFirstSink
	assume esi:ptr CEventSink

	.while ([esi].m_pNext)
		mov eax,[esi].m_pNext
		.if (eax == dwCookie)
			invoke vf([eax].CEventSink.m_pEvent, IUnknown, Release)
			mov eax,[esi].m_pNext
			push [eax].CEventSink.m_pNext
			invoke LocalFree, eax
			pop [esi].m_pNext
			return S_OK
		.endif
		mov esi,[esi].m_pNext
	.endw

	return CONNECT_E_NOCONNECTION
	align 4

	assume ebx:nothing
	assume esi:nothing

Unadvise endp

;--------------------------------------------------------------------------

EnumConnections proc this_:ptr CConnectionPoint, ppEnumConnections:ptr IEnumConnections

	DebugOut "IConnectionPoint::EnumConnections( %X )", ppEnumConnections

;--- to do: enum the current connections
	mov ecx, ppEnumConnections
	mov dword ptr [ecx],0
	return E_FAIL
	align 4

EnumConnections endp

	end