From 1136044e5d6bb0b3b4540a857b913dfa0504fae8 Mon Sep 17 00:00:00 2001 From: NextTurn <45985406+NextTurn@users.noreply.github.com> Date: Sun, 9 Dec 2018 00:00:00 +0800 Subject: [PATCH] Fix broken links to Windows docs --- docs/atl/iunknown.md | 2 +- docs/atl/queryinterface.md | 2 +- docs/atl/reference/ccomptrbase-class.md | 2 +- .../tn038-mfc-ole-iunknown-implementation.md | 28 +++++++++---------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/atl/iunknown.md b/docs/atl/iunknown.md index 584b104e37d..19cbfe61eba 100644 --- a/docs/atl/iunknown.md +++ b/docs/atl/iunknown.md @@ -7,7 +7,7 @@ ms.assetid: e6b85472-e54b-4b8c-b19f-4454d6c05a8f --- # IUnknown -[IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) is the base interface of every other COM interface. This interface defines three methods: [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)), [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), and [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release). [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) allows an interface user to ask the object for a pointer to another of its interfaces. [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref) and [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release) implement reference counting on the interface. +[IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) is the base interface of every other COM interface. This interface defines three methods: [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)), [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), and [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release). [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) allows an interface user to ask the object for a pointer to another of its interfaces. [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref) and [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release) implement reference counting on the interface. ## See also diff --git a/docs/atl/queryinterface.md b/docs/atl/queryinterface.md index a202592219b..1a9387bfd78 100644 --- a/docs/atl/queryinterface.md +++ b/docs/atl/queryinterface.md @@ -7,7 +7,7 @@ ms.assetid: 62fce95e-aafa-4187-b50b-e6611b74c3b3 --- # QueryInterface -Although there are mechanisms by which an object can express the functionality it provides statically (before it is instantiated), the fundamental COM mechanism is to use the `IUnknown` method called [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)). +Although there are mechanisms by which an object can express the functionality it provides statically (before it is instantiated), the fundamental COM mechanism is to use the `IUnknown` method called [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)). Every interface is derived from `IUnknown`, so every interface has an implementation of `QueryInterface`. Regardless of implementation, this method queries an object using the IID of the interface to which the caller wants a pointer. If the object supports that interface, `QueryInterface` retrieves a pointer to the interface, while also calling `AddRef`. Otherwise, it returns the E_NOINTERFACE error code. diff --git a/docs/atl/reference/ccomptrbase-class.md b/docs/atl/reference/ccomptrbase-class.md index 252a171bc93..7449aea8973 100644 --- a/docs/atl/reference/ccomptrbase-class.md +++ b/docs/atl/reference/ccomptrbase-class.md @@ -359,7 +359,7 @@ Returns S_OK on success, or E_NOINTERFACE on failure. ### Remarks -This method calls [IUnknown::QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)). +This method calls [IUnknown::QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)). In debug builds, an assertion error will occur if *pp* is not equal to NULL. diff --git a/docs/mfc/tn038-mfc-ole-iunknown-implementation.md b/docs/mfc/tn038-mfc-ole-iunknown-implementation.md index 9b1ee42f821..ae6ea1d8996 100644 --- a/docs/mfc/tn038-mfc-ole-iunknown-implementation.md +++ b/docs/mfc/tn038-mfc-ole-iunknown-implementation.md @@ -49,7 +49,7 @@ ULONG CMyObj::Release() } ``` -The [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) member function is a little more interesting. It is not very interesting to have an object whose only member functions are [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref) and [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release) — it would be nice to tell the object to do more things than [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) provides. This is where [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) is useful. It allows you to obtain a different "interface" on the same object. These interfaces are usually derived from [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) and add additional functionality by adding new member functions. COM interfaces never have member variables declared in the interface, and all member functions are declared as pure-virtual. For example, +The [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) member function is a little more interesting. It is not very interesting to have an object whose only member functions are [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref) and [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release) — it would be nice to tell the object to do more things than [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) provides. This is where [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) is useful. It allows you to obtain a different "interface" on the same object. These interfaces are usually derived from [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) and add additional functionality by adding new member functions. COM interfaces never have member variables declared in the interface, and all member functions are declared as pure-virtual. For example, ```cpp class IPrintInterface : public IUnknown @@ -59,7 +59,7 @@ public: }; ``` -To get an IPrintInterface if you only have an [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown), call [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) using the `IID` of the `IPrintInterface`. An `IID` is a 128-bit number that uniquely identifies the interface. There is an `IID` for each interface that either you or OLE define. If *pUnk* is a pointer to an [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) object, the code to retrieve an IPrintInterface from it might be: +To get an IPrintInterface if you only have an [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown), call [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) using the `IID` of the `IPrintInterface`. An `IID` is a 128-bit number that uniquely identifies the interface. There is an `IID` for each interface that either you or OLE define. If *pUnk* is a pointer to an [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) object, the code to retrieve an IPrintInterface from it might be: ```cpp IPrintInterface* pPrint = NULL; @@ -98,7 +98,7 @@ HRESULT CPrintObj::QueryInterface(REFIID iid, void FAR* FAR* ppvObj) } ``` -As you can see, if the interface identifier (IID) is recognized, a pointer is returned to your object; otherwise an error occurs. Also note that a successful [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) results in an implied [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref). Of course, you'd also have to implement CEditObj::Print. That is simple because the IPrintInterface was directly derived from the [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) interface. However, if you wanted to support two different interfaces, both derived from [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown), consider the following: +As you can see, if the interface identifier (IID) is recognized, a pointer is returned to your object; otherwise an error occurs. Also note that a successful [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) results in an implied [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref). Of course, you'd also have to implement CEditObj::Print. That is simple because the IPrintInterface was directly derived from the [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) interface. However, if you wanted to support two different interfaces, both derived from [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown), consider the following: ```cpp class IEditInterface : public IUnkown @@ -213,7 +213,7 @@ HRESULT CEditPrintObj::CPrintObj::QueryInterface(REFIID iid, void** ppvObj) } ``` -Notice that most of the [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) implementation is placed into the CEditPrintObj class rather than duplicating the code in CEditPrintObj::CEditObj and CEditPrintObj::CPrintObj. This reduces the amount of code and avoids bugs. The key point here is that from the IUnknown interface it is possible to call [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) to retrieve any interface the object might support, and from each of those interfaces it is possible to do the same. This means that all [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) functions available from each interface must behave exactly the same way. In order for these embedded objects to call the implementation in the "outer object", a back-pointer is used (m_pParent). The m_pParent pointer is initialized during the CEditPrintObj constructor. Then you would implement CEditPrintObj::CPrintObj::PrintObject and CEditPrintObj::CEditObj::EditObject as well. Quite a bit of code was added to add one feature — the ability to edit the object. Fortunately, it is quite uncommon for interfaces to have only a single member function (although it does happen) and in this case, EditObject and PrintObject would usually be combined into a single interface. +Notice that most of the [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) implementation is placed into the CEditPrintObj class rather than duplicating the code in CEditPrintObj::CEditObj and CEditPrintObj::CPrintObj. This reduces the amount of code and avoids bugs. The key point here is that from the IUnknown interface it is possible to call [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) to retrieve any interface the object might support, and from each of those interfaces it is possible to do the same. This means that all [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) functions available from each interface must behave exactly the same way. In order for these embedded objects to call the implementation in the "outer object", a back-pointer is used (m_pParent). The m_pParent pointer is initialized during the CEditPrintObj constructor. Then you would implement CEditPrintObj::CPrintObj::PrintObject and CEditPrintObj::CEditObj::EditObject as well. Quite a bit of code was added to add one feature — the ability to edit the object. Fortunately, it is quite uncommon for interfaces to have only a single member function (although it does happen) and in this case, EditObject and PrintObject would usually be combined into a single interface. That's a lot of explanation and a lot of code for such a simple scenario. The MFC/OLE classes provide a simpler alternative. The MFC implementation uses a technique similar to the way Windows messages are wrapped with Message Maps. This facility is called *Interface Maps* and is discussed in the next section. @@ -225,7 +225,7 @@ MFC/OLE includes an implementation of "Interface Maps" similar to MFC's "Message - Maintenance of the reference count, modified by [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref) and [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release) -- Data driven implementation of [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) +- Data driven implementation of [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) In addition, interface maps support the following advanced features: @@ -257,7 +257,7 @@ MFC's interface map support is rooted in the `CCmdTarget` class. `CCmdTarget` "* 7. Use the METHOD_PROLOGUE macro to access the parent, `CCmdTarget`-derived object. -8. [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) can delegate to the `CCmdTarget` implementation of these functions (`ExternalAddRef`, `ExternalRelease`, and `ExternalQueryInterface`). +8. [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) can delegate to the `CCmdTarget` implementation of these functions (`ExternalAddRef`, `ExternalRelease`, and `ExternalQueryInterface`). The CPrintEditObj example above could be implemented as follows: @@ -281,7 +281,7 @@ protected: }; ``` -The above declaration creates a class derived from `CCmdTarget`. The DECLARE_INTERFACE_MAP macro tells the framework that this class will have a custom interface map. In addition, the BEGIN_INTERFACE_PART and END_INTERFACE_PART macros define nested classes, in this case with names CEditObj and CPrintObj (the X is used only to differentiate the nested classes from global classes which start with "C" and interface classes which start with "I"). Two nested members of these classes are created: m_CEditObj, and m_CPrintObj, respectively. The macros automatically declare the [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) functions; therefore you only declare the functions specific to this interface: EditObject and PrintObject (the OLE macro STDMETHOD is used so that **_stdcall** and virtual keywords are provided as appropriate for the target platform). +The above declaration creates a class derived from `CCmdTarget`. The DECLARE_INTERFACE_MAP macro tells the framework that this class will have a custom interface map. In addition, the BEGIN_INTERFACE_PART and END_INTERFACE_PART macros define nested classes, in this case with names CEditObj and CPrintObj (the X is used only to differentiate the nested classes from global classes which start with "C" and interface classes which start with "I"). Two nested members of these classes are created: m_CEditObj, and m_CPrintObj, respectively. The macros automatically declare the [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) functions; therefore you only declare the functions specific to this interface: EditObject and PrintObject (the OLE macro STDMETHOD is used so that **_stdcall** and virtual keywords are provided as appropriate for the target platform). To implement the interface map for this class: @@ -292,9 +292,9 @@ BEGIN_INTERFACE_MAP(CPrintEditObj, CCmdTarget) END_INTERFACE_MAP() ``` -This connects the IID_IPrintInterface IID with m_CPrintObj and IID_IEditInterface with m_CEditObj respectively. The `CCmdTarget` implementation of [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) (`CCmdTarget::ExternalQueryInterface`) uses this map to return pointers to m_CPrintObj and m_CEditObj when requested. It is not necessary to include an entry for `IID_IUnknown`; the framework will use the first interface in the map (in this case, m_CPrintObj) when `IID_IUnknown` is requested. +This connects the IID_IPrintInterface IID with m_CPrintObj and IID_IEditInterface with m_CEditObj respectively. The `CCmdTarget` implementation of [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) (`CCmdTarget::ExternalQueryInterface`) uses this map to return pointers to m_CPrintObj and m_CEditObj when requested. It is not necessary to include an entry for `IID_IUnknown`; the framework will use the first interface in the map (in this case, m_CPrintObj) when `IID_IUnknown` is requested. -Even though the BEGIN_INTERFACE_PART macro automatically declared the [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release) and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) functions for you, you still need to implement them: +Even though the BEGIN_INTERFACE_PART macro automatically declared the [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release) and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) functions for you, you still need to implement them: ```cpp ULONG FAR EXPORT CEditPrintObj::XEditObj::AddRef() @@ -350,7 +350,7 @@ There are two ways to use aggregation: (1) using a COM object that supports aggr ### Using an Aggregate Object -To use an aggregate object, there needs to be some way to tie the aggregate into the QueryInterface mechanism. In other words, the aggregate object must behave as though it is a native part of your object. So how does this tie into MFC's interface map mechanism In addition to the INTERFACE_PART macro, where a nested object is mapped to an IID, you can also declare an aggregate object as part of your `CCmdTarget` derived class. To do so, the INTERFACE_AGGREGATE macro is used. This allows you to specify a member variable (which must be a pointer to an [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) or derived class), which is to be integrated into the interface map mechanism. If the pointer is not NULL when `CCmdTarget::ExternalQueryInterface` is called, the framework will automatically call the aggregate object's [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) member function, if the `IID` requested is not one of the native `IID`s supported by the `CCmdTarget` object itself. +To use an aggregate object, there needs to be some way to tie the aggregate into the QueryInterface mechanism. In other words, the aggregate object must behave as though it is a native part of your object. So how does this tie into MFC's interface map mechanism In addition to the INTERFACE_PART macro, where a nested object is mapped to an IID, you can also declare an aggregate object as part of your `CCmdTarget` derived class. To do so, the INTERFACE_AGGREGATE macro is used. This allows you to specify a member variable (which must be a pointer to an [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) or derived class), which is to be integrated into the interface map mechanism. If the pointer is not NULL when `CCmdTarget::ExternalQueryInterface` is called, the framework will automatically call the aggregate object's [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) member function, if the `IID` requested is not one of the native `IID`s supported by the `CCmdTarget` object itself. #### To use the INTERFACE_AGGREGATE macro @@ -400,13 +400,13 @@ BEGIN_INTERFACE_MAP(CAggrExample, CCmdTarget) END_INTERFACE_MAP() ``` -The m_lpAggrInner variable is initialized in the constructor to NULL. The framework ignores a NULL member variable in the default implementation of [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)). `OnCreateAggregates` is a good place to actually create your aggregate objects. You'll have to call it explicitly if you are creating the object outside of the MFC implementation of `COleObjectFactory`. The reason for creating aggregates in `CCmdTarget::OnCreateAggregates` as well as the usage of `CCmdTarget::GetControllingUnknown` will become apparent when creating aggregatable objects is discussed. +The m_lpAggrInner variable is initialized in the constructor to NULL. The framework ignores a NULL member variable in the default implementation of [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)). `OnCreateAggregates` is a good place to actually create your aggregate objects. You'll have to call it explicitly if you are creating the object outside of the MFC implementation of `COleObjectFactory`. The reason for creating aggregates in `CCmdTarget::OnCreateAggregates` as well as the usage of `CCmdTarget::GetControllingUnknown` will become apparent when creating aggregatable objects is discussed. -This technique will give your object all of the interfaces that the aggregate object supports plus its native interfaces. If you only want a subset of the interfaces that the aggregate supports, you can override `CCmdTarget::GetInterfaceHook`. This allows you very low-level hookability, similar to [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)). Usually, you want all the interfaces that the aggregate supports. +This technique will give your object all of the interfaces that the aggregate object supports plus its native interfaces. If you only want a subset of the interfaces that the aggregate supports, you can override `CCmdTarget::GetInterfaceHook`. This allows you very low-level hookability, similar to [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)). Usually, you want all the interfaces that the aggregate supports. ### Making an Object Implementation Aggregatable -For an object to be aggregatable, the implementation of [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) must delegate to a "controlling unknown." In other words, for it to be part of the object, it must delegate [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) to a different object, also derived from [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown). This "controlling unknown" is provided to the object when it is created, that is, it is provided to the implementation of `COleObjectFactory`. Implementing this carries a small amount of overhead, and in some cases is not desirable, so MFC makes this optional. To enable an object to be aggregatable, you call `CCmdTarget::EnableAggregation` from the object's constructor. +For an object to be aggregatable, the implementation of [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) must delegate to a "controlling unknown." In other words, for it to be part of the object, it must delegate [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) to a different object, also derived from [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown). This "controlling unknown" is provided to the object when it is created, that is, it is provided to the implementation of `COleObjectFactory`. Implementing this carries a small amount of overhead, and in some cases is not desirable, so MFC makes this optional. To enable an object to be aggregatable, you call `CCmdTarget::EnableAggregation` from the object's constructor. If the object also uses aggregates, you must also be sure to pass the correct "controlling unknown" to the aggregate objects. Usually this [IUnknown](/windows/win32/api/unknwn/nn-unknwn-iunknown) pointer is passed to the object when the aggregate is created. For example, the pUnkOuter parameter is the "controlling unknown" for objects created with `CoCreateInstance`. The correct "controlling unknown" pointer can be retrieved by calling `CCmdTarget::GetControllingUnknown`. The value returned from that function, however, is not valid during the constructor. For this reason, it is suggested that you create your aggregates only in an override of `CCmdTarget::OnCreateAggregates`, where the return value from `GetControllingUnknown` is reliable, even if created from the `COleObjectFactory` implementation. @@ -496,7 +496,7 @@ The name of the interface that this class implements #### Remarks -For each interface that your class will implement, you need to have a BEGIN_INTERFACE_PART and END_INTERFACE_PART pair. These macros define a local class derived from the OLE interface that you define as well as an embedded member variable of that class. The [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q_)) members are declared automatically. You must include the declarations for the other member functions that are part of the interface being implemented (those declarations are placed between the BEGIN_INTERFACE_PART and END_INTERFACE_PART macros). +For each interface that your class will implement, you need to have a BEGIN_INTERFACE_PART and END_INTERFACE_PART pair. These macros define a local class derived from the OLE interface that you define as well as an embedded member variable of that class. The [AddRef](/windows/win32/api/unknwn/nf-unknwn-iunknown-addref), [Release](/windows/win32/api/unknwn/nf-unknwn-iunknown-release), and [QueryInterface](/windows/win32/api/unknwn/nf-unknwn-iunknown-queryinterface(q)) members are declared automatically. You must include the declarations for the other member functions that are part of the interface being implemented (those declarations are placed between the BEGIN_INTERFACE_PART and END_INTERFACE_PART macros). The *iface* argument is the OLE interface that you wish to implement, such as `IAdviseSink`, or `IPersistStorage` (or your own custom interface).