Microsoft KB Archive/179689

= How to hook into the IUnknown members of a COM object in MFC =

Article ID: 179689

Article Last Modified on 11/21/2006

-

APPLIES TO

 Microsoft Foundation Class Library 4.2, when used with:  Microsoft Visual C++ 5.0 Enterprise Edition

 Microsoft Visual C++ 6.0 Enterprise Edition

 Microsoft Visual C++ 5.0 Professional Edition

 Microsoft Visual C++ 6.0 Professional Edition</li></ul>

 Microsoft Visual C++ 6.0 Standard Edition</li></ul>

 Microsoft Visual C++ 2005 Express Edition</li></ul>

 Microsoft Visual C++ .NET 2003 Standard Edition</li></ul>

 Microsoft Visual C++ .NET 2002 Standard Edition</li></ul> </li></ul>

-

<div class="notice_section">

This article was previously published under Q179689

<div class="notice_section">

Note Microsoft Visual C++ .NET 2002 and Microsoft Visual C++ .NET 2003 support both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code. Microsoft Visual C++ 2005 supports both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model.

<div class="summary_section">

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.

<div class="moreinformation_section">

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.

<div class="references_section">