SUMMARY
This sample provides a generic technique to hook into the
following:
- The IUnknown members of the interfaces implemented by a CCmdTarget- derived
COM object that is not an aggregate.
- The members of the inner IUnknown of a CCmdTarget-derived COM object that is created as an
aggregated object.
By hooking into the
IUnknown members of a COM object, you can determine the following useful
debug information:
- The current reference of the object when it
changes.
- The symbolic names of the interfaces of the object for
which you have queried.
Also, the hook gives you flexibility to control what interfaces
of an object can be made available to other applications. For more information
about using this functionality with an example, see the "More Information"
section.
This sample applies the hooking technique to an OLE control
that is generated by using ControlWizard. However, note that the same hooking
technique may be applied to any CCmdTarget-derived COM object that provides one
or more interface implementations.
MORE INFORMATION
The
following files are available for download from the Microsoft Download
Center:
Visual C++ 6.0
Download
the Hookctrl.exe package now. For more 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 prevent
any unauthorized changes to the file.
Visual C++ .NET
Download
the Hookctrlvcnet.exe package
now. Release Date: June 25,
2002
For more 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 prevent
any unauthorized changes to the file.
In MFC, when a COM object instance is created in the
implementation of
IClassFactory::CreateInstance, the component pieces (that is, the aggregates) of this object,
if any, are created by calling the virtual function
CCmdTarget::OnCreateAggregates. The default implementation of
OnCreateAggregates provided in
CCmdTarget does nothing by returning TRUE.
In COM, an object that
is aggregated to an outer object stores the latter's
IUnknown, which is called as the outer unknown or the controlling unknown.
This is done so that the inner object can delegate all the
IUnknown calls from its own interfaces to this outer unknown. MFC stores
this controlling unknown for an object in a public member variable of
CCmdTarget called "m_pOuterUnknown".
An object that is not
aggregated by any other outer object has the above variable set to NULL,
implying that the controlling unknown for this object is the same as its own
IUnknown. This concept of outer unknowns being NULL for an object that
isn't aggregated can be used to hook in to its
IUnknown functions. This can be accomplished by replacing the object's
IUnknown implementation with a custom implementation. This custom
implementation (for example,
IUnknownHook) can be made to provide more debug information by displaying the
object's current reference count whenever it changes, by displaying the
symbolic names of the object's interfaces that are queried for, and so on. In
addition, the
IUnknown hook can be used to control what interfaces of an object are
accessible from other applications.
This sample illustrates the above
hooking technique by applying it to an OLE control generated using the
ControlWizard. Installing the hook to an OLE control gives access to the
IUnknown implementation for all of its interfaces when it is not created
as an aggregate, and to the control's inner
IUnknown implementation when it is created as an aggregate.
The
sample retrieves the symbolic name of the control's interfaces by calling
AfxGetIIDString, which is an undocumented MFC function. Also, the sample replaces
CInnerUnknown, which provides the implementation for the inner
IUnknown when an object is created as an aggregate, with
CMyInnerUnknown in order to gain access to the inner
IUnknown implementation.
Finally, the sample also demonstrates
the use of this hook to control interfaces that are not accessible from outside
by returning E_NOINTERFACE from
IUnknownHook::QueryInterface. For example, if an OLE control wants to use
IPersistStorage for storing its persistence information, it can choose not to
expose
IPersistStreamInit and
IPersistMemory by returning E_NOINTERFACE for the latter two interfaces. Note
that the above example assumes that control container uses one of these
interfaces for storing the control's persistence information:
IPersistMemory,
IPersistStreamInit, or
IPersistStorage.