Connection point interface failing miserably
Magnus Werner <[email protected]> Thu, 20 Feb 2003 07:08:28 -0800
| Newsgroups | gmane.comp.windows.devel.vbcom |
|---|---|
| Message-ID | <VBCOM%[email protected]> |
I've implemented a simple ActiveX COM server using ATL. It implements a
connection point interface that will be used to call back to a VB client.
For some reason (that I'd very much like to know) there is a catastrophic
failure when firing the event. The pDispatch->Invoke causes an Access
violation in VB6. Why is that? I'd be most grateful for any suggestions how
to solve this.
Regards,
Magnus Werner
// IDLTest.idl : IDL source for IDLTest.dll
//
// This file will be processed by the MIDL tool to
// produce the type library (IDLTest.tlb) and marshalling code.
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(80C10722-4741-4EEC-A1C8-8DC4A97159EF),
dual,
helpstring("IExpImp Interface"),
pointer_default(unique)
]
interface IExpImp : IDispatch
{
[id(1), helpstring("method Export")] HRESULT Export([in]
short Delay);
[id(2), helpstring("method Cancel")] HRESULT Cancel();
};
[
uuid(152812E3-0A28-42DB-8F22-1A5C75CF01CB),
version(1.0),
helpstring("IDLTest 1.0 Type Library")
]
library IDLTESTLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(A006CA98-3C7D-441A-865E-F64C42B4B0A6),
helpstring("IExpImpEvents Interface")
]
dispinterface IExpImpEvents
{
properties:
methods:
[id(1), helpstring("method OnProgress")] HRESULT OnProgress
([in] long Progress);
[id(2), helpstring("method OnComplete")] HRESULT OnComplete
();
[id(3), helpstring("method OnCancel")] HRESULT OnCancel();
};
[
uuid(1EE8B0E4-C43F-45C7-BD94-D50809E47BB9),
helpstring("ExpImp Class")
]
coclass ExpImp
{
[default] interface IExpImp;
[default, source] dispinterface IExpImpEvents;
};
};
============================================================================
// ExpImp.h : Declaration of the CExpImp
#ifndef __EXPIMP_H_
#define __EXPIMP_H_
#include "resource.h" // main symbols
#include "IDLTestCP.h"
////////////////////////////////////////////////////////////////////////////
/
// CExpImp
class ATL_NO_VTABLE CExpImp :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CExpImp, &CLSID_ExpImp>,
public ISupportErrorInfo,
public IConnectionPointContainerImpl<CExpImp>,
public IDispatchImpl<IExpImp, &IID_IExpImp, &LIBID_IDLTESTLib>,
public CProxy_IExpImpEvents< CExpImp >,
public IProvideClassInfo2Impl< &CLSID_ExpImp, &DIID_IExpImpEvents,
&LIBID_IDLTESTLib, 1, 0 >
{
public:
CExpImp()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_EXPIMP)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CExpImp)
COM_INTERFACE_ENTRY(IExpImp)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
COM_INTERFACE_ENTRY(IProvideClassInfo2)
COM_INTERFACE_ENTRY(IProvideClassInfo)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CExpImp)
CONNECTION_POINT_ENTRY(DIID_IExpImpEvents)
END_CONNECTION_POINT_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
// IExpImp
public:
STDMETHOD(Cancel)();
STDMETHOD(Export)(/*[in]*/ short Delay);
void run();
private:
short m_sDelay;
HANDLE m_hThread;
DWORD m_dwThreadId;
bool m_bCanceled;
};
#endif //__EXPIMP_H_
============================================================================
// ExpImp.cpp : Implementation of CExpImp
#include "stdafx.h"
#include "IDLTest.h"
#include "ExpImp.h"
DWORD WINAPI ThreadProc(
LPVOID lpParameter // thread data
)
{
CExpImp *pCExpImp = static_cast<CExpImp*>(lpParameter);
pCExpImp->run();
return 0; // Thread exit code
}
////////////////////////////////////////////////////////////////////////////
/
// CExpImp
STDMETHODIMP CExpImp::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IExpImp
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP CExpImp::Export(short Delay)
{
m_bCanceled = false;
m_hThread = ::CreateThread(NULL,
// Default security descriptor
0,
// Default stack size
&ThreadProc, // Thread start routing
static_cast<LPVOID>(this), // Arguments to start routine
0,
// Creation flags
&m_dwThreadId);
if (m_hThread == NULL)
return HRESULT_FROM_WIN32(GetLastError());
return S_OK;
}
void CExpImp::run()
{
CoInitialize(0);
for (int i=0; i<101; i++)
{
if (m_bCanceled)
{
HRESULT hr = Fire_OnCancel();
CoUninitialize();
::ExitThread(1);
}
HRESULT hr = Fire_OnProgress(i);
}
HRESULT hr = Fire_OnComplete();
CoUninitialize();
}
STDMETHODIMP CExpImp::Cancel()
{
m_bCanceled = true;
return S_OK;
}
============================================================================
Private WithEvents ProgressHandler As IDLTESTLib.ExpImp
Private Sub CancelButton_Click()
ProgressHandler.Cancel
End Sub
Private Sub Form_Load()
On Error GoTo error
Set ProgressHandler = New ExpImp
Exit Sub
error:
MsgBox Err.Description
End Sub
Private Sub OKButton_Click()
ProgressHandler.Export 2
'For i = 1 To 100
' ProgressBar1.Value = i
'Next
End Sub
Private Sub ProgressHandler_OnCancel()
'TBD
End Sub
Private Sub ProgressHandler_OnComplete()
'TBD
End Sub
Private Sub ProgressHandler_OnProgress(ByVal Progress As Long)
ProgressBar1.Value = Progress
End Sub
You can read messages from the VBCOM archive, unsubscribe from VBCOM, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.