FILE: Hooking into the IUnknown of a COM Object in MFC
ID: Q179689
|
The information in this article applies to:
-
The Microsoft Foundation Classes (MFC), included with:
-
Microsoft Visual C++, 32-bit Editions, versions 5.0, 6.0
SUMMARY
This sample provides a generic technique to hook into:
- 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, useful debug
information, such as the current reference of the object when it changes,
and the symbolic names of the object's interfaces that are queried for, can
be determined. Also, the hook gives the flexibility to control what
interfaces of an object can be made available to other applications. The
more information section details the use of this functionality with an
example.
This sample applies the hooking technique to an OLE control generated using
ControlWizard. However, note that the same hooking technique could be
applied to any CCmdTarget-derived COM object that provides one or more
interface implementation(s).
MORE INFORMATION
The following file is available for download from the Microsoft Software
Library:
Hookctrl.exe
For more information about downloading files from the Microsoft Software
Library, please see the following article in the Microsoft Knowledge Base:
Q119591 How to Obtain Microsoft Support Files from Online Services
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.
REFERENCES
For additional information on the topics discussed above, please refer to
the following:
- MFC Technical Note #38, "MFC/OLE IUnknown implementation".
- Chapter-2 in "Inside OLE", Second Edition, by Kraig Brockschmidt.
Additional query words:
kbvc500 kbvc600
Keywords : kbfile kbole kbMFC kbVC
Version : WINNT:5.0,6.0
Platform : winnt
Issue type : kbhowto
Last Reviewed: August 8, 1999