MORE INFORMATION
The following file is available for download from the Microsoft Download Center:
For additional information about how to download Microsoft Support files, click the following article number to view the article in the Microsoft Knowledge Base:
119591 How to Obtain Microsoft Support Files from Online Services
Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help to prevent any unauthorized changes to the file.
After downloading the file, run it in an empty directory with the -d
switch to set up the directory structure:
This sample provides helper functions that allow easy implementation of
event-handling support in a COM server that fires events. A COM server must
implement the following interfaces to fire events:
IConnectionPointContainer
IConnectionPoint
EnumConnectionPoints
EnumConnections
This sample provides a function called CreateStdCPContainer() that
implements the above interfaces and a function called FireEvent() that
the server can use to fire events to all clients who have connected to a
connection point. The helper functions can be found in the Event.cpp and
Event.h files and can be used by 32-bit applications only. These files
are self-contained and can be added to any 32-bit project.
This sample also provides a COM server that uses the helper functions to
implement event-handling support and a COM client that uses the server.
The COM server is the HELLO automation server sample that ships with the
Win32 SDK with added event-handling support. The COM client is the
HELCTRL automation client sample that ships with the Win32 SDK with
added event-handling support.
To implement event-handling support in a COM server, the server must
aggregate with the IConnectionPointContainer implementation provided by the
helper function, CreateStdCPContainer. Following is the documentation of
this function:
HRESULT CreateStdCPContainer(
IUnknown* punkController,
ITypeInfo* aptinfo[],
ULONG cTypeInfos,
DWORD dwFlags,
IUnknown** ppunkCPC)
The function creates a connection-point container object with connection
points corresponding to the array of typeinfos passed in. The newly created
object, which supports IConnectionPointContainer, is aggregated with
punkController. The implementation uses SAFEARRAYs as the data structure to
store the connection-point objects and the event sink pointers provided by
the COM clients.
Parameters
punkController
[in] Points to the server's IUnknown. The connection-point container
created by this function aggregates with this IUnknown.
aptinfo
[in] Array of pointers to typeinfos. Each one corresponds to an event
interface/dispinterface that the object supports. Typically, an object has
only one event interface/dispinterface.
cTypeInfos
[in] Size of aptinfo array. This is typically 1, unless the object has
multiple event interfaces.
dwFlags
[in] Indicates the type of connection-point container to create. The two
values allowed are CPTYPEFLAG_MULTICAST and CPTYPEFLAG_SINGLECAST.
CPTYPEFLAG_MULTICAST indicates that multiple clients can connect their
sinks to each connection point and the event will be fired to all those
clients. CPTYPEFLAG_SINGLECAST indicates that only one client can connect
its sink to each connection point and the event will be fired only to that
client. These constants are defined in Event.h in this sample.
ppunkCPC
[out] Returns IUnknown* of the created connection-point container object.
(This is the private unknown of the aggregate.)
Return Value
S_OK Success.
E_INVALIDARG Invalid argument.
E_OUTOFMEMORY Memory allocation failed.
Example
In this code example, ptinfo is the typeinfo of the event interface
(obtained from the type library) and riidEvents is the GUID of that
interface. The COM server should call this code in its creation routine.
This server has one event interface. It saves the returned pointer to the
IUnknown* of the connection-point container object in the m_punkCPContainer
data member. It also saves the pointer to the connection point in the m_pcp
data member:
CreateStdCPContainer(this, &ptinfo, 1, CPTYPEFLAG_MULTICAST,
&m_punkCPContainer);
m_punkCPContainer->QueryInterface(IID_IConnectionPointContainer,
(void**)&pcpc);
pcpc->;FindConnectionPoint(riidEvents, &m_pcp);
The COM server should implement its IUnknown::QueryInterface. Following is
an example of how to handle a request for IID_IConnectionPointContainer:
if (iid == IID_IConnectionPointContainer)
return m_punkCPContainer->QueryInterface(iid, ppv);
After the server has aggregated with the connection-point container object
provided by CreateStdCPContainer, it can use the FireEvent() helper
function to fire events to the clients who have connected to a connection
point. Following is the documentation of FireEvent():
STDAPI FireEvent(IConnectionPoint FAR *pcp,
DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pdispparams,
VARIANT FAR* pvarResult,
EXCEPINFO FAR* pexcepinfo,
UINT FAR* puArgErr)
This fires the event specified by dispidMember to all sinks connected to
the pcp connection point. IDispatch::Invoke fires the event. Consequently,
the event sink in the client must implement IDispatch for this function to
work. If you do not want to use IDispatch to fire events, you must rewrite
this function but you can still use CreateStdCPContainer(). This function
does not stop firing events if the call to a specific event sink fails.
Parameters
pcp
[in] The connection point for which events are going to be fired. This
connection point must be obtained from the connection-point container
created by CreateStdCPContainer().
The other parameters are the same as the IDispatch::Invoke parameters
and include the DISPID of the event to be fired and the parameters of
the event.
Return Value
S_OK Success
E_OUTOFMEMORY Memory Allocation failure
Errors returned by failure of SafeArrayCopy and SafeArrayAccessData.
Example
In the following example, m_pcp is the variable referenced in the example
section of the CreateStdCPContainer documentation:
FireEvent(m_pcp, dispid, IID_NULL, LOCALE_USER_DEFAULT,
DISPATCH_METHOD, &dispparamsNoArgs, NULL, NULL, NULL);
To Compile the Samples
To compile an ANSI-debug version of the sample for Windows NT and
Windows 95, use the following command:
To compile a Unicode-debug version of the sample for Windows NT only, use
the following command:
See the makefile header comments for other make options.
Compile the HELLO sample before compiling the HELCTRL sample because
HELCTRL uses HELLO's Tlb.h file. In this sample, the HELCTRL client
application uses the server's type library to implement the IDispatch
interface of the event sink. Note that the client can also use its own type
library for this purpose.
To Run the Samples
Change Hello.reg to provide the full path of Hello.exe and Hello.tlb.
Register Hello.reg in the registration database by double-clicking it in
Explorer. Run Helctrl.exe and use its menu to control the HELLO server. You
can use CreateHello to create a new instance of HELLO. You can use GetHello
to bind to a running instance of HELLO. Use the Visible menu item to make
the server visible if required. Use InvokeSayHello to invoke the SayHello
method. The server fires the SaidHello event when SayHello is invoked. The
client displays a message box indicating that it received the fired event.
Windows NT 4.0 and Windows 95 with DCOM have system-provided marshaling
code for the event interfaces (IConnectionPointContainer, IConnectionPoint,
EnumConnectionPoints and EnumConnections). Without DCOM, Windows NT 3.51
and Windows 95 do not have system-provided marshaling code for these
interfaces. If you want to run these samples on Windows 95 without DCOM and
Windows NT 3.51, install the marshaling code provided in the following
sample from the Microsoft Knowledge Base. Make sure that you carefully read
the installation instructions in the sample before installing the
marshaling code:
149231 Marshaling Code for Connection Point Interfaces
If you would like to run the server on a remote computer and you want to
gain access to it from the client using DOCM, read the following article in
the Microsoft Knowledge Base. If you do this, make sure that the client
application provides access permission to the user on the server computer,
which is where the server application runs. Otherwise, the server
application cannot fire events to the client application.
158582 Configuring a non-DCOM server and client to use DCOM