Raymond Chen continues his series on creating a fake agile wrapper for non-marshalable COM objects by wrapping them in a marshalable object, enabling registration in the global interface table while preserving undefined-behavior-free failures in other apartments.
<p>Last time, we tried to execute on <a title="Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 2" href="https://devblogs.microsoft.com/oldnewthing/20260804-00/?p=112586"> our plan to use the global interface table to hold hold a reference to an object in another apartment that automatically expires when the apartment runs down</a>. But it broke down because objects that are marked <code>INoMarshal</code> can’t go into the global interface table.</p>
<p>So we will just force the square peg into the round hole: We can put the non-marshalable object inside an object that <i>is</i> marshalable.</p>
<pre>template<typename Smart>
struct force_marshal :
winrt::implements<force_marshal<Smart>, ::IUnknown, winrt::non_agile>
{
force_marshal(Smart const& p) : m_p(p) {}
Smart m_p;
};
</pre>
<p>The <code>force_marshal<Smart></code> object babysits a non-marshalable smart pointer to a COM object and exposes a marshalable wrapper around it. Since the wrapped object is not agile, the wrapper cannot be either. (If the wrapper were agile, then we’d be back where we started: How do we ensure that the <code>m_p</code> is destructed in the correct apartment?)¹</p>
<p>We can put the unmarshalable object inside the wrapper, and then put the wrapper in the global interface table.</p>
<pre>template<typename T>
struct fake_agile_ref
{
⟦ ... ⟧
fake_agile_ref(Smart const& p) : m_raw(winrt::get_abi(p))
{
if (m_raw) {
m_context = winrt::capture<IContextCallback>(CoGetObjectContext);
m_token = get_context_token();
m_git = winrt::create_instance<IGlobalInterfaceTable>(CLSID_StdGlobalInterfaceTable);
winrt::check_hresult(m_git->RegisterInterfaceInGlobal(
<span style="border: solid 1px currentcolor;">winrt::make<force_marshal<Smart>>(p).get()</span>,
__uuidof(IUnknown), &m_cookie));
}
}
⟦ ... ⟧
};
template<typename T> fake_agile_ref(winrt::com_ptr<T> const&)
-> fake_agile_ref<T>;
template<typename T> fake_agile_ref(T const&)
-> fake_agile_ref<T>;
</pre>
<p>Okay, so now we have managed to create an agile wrapper around an unmarshalable object. This agile wrapper is agile on paper: You can use it from any thread. However, it is not agile in practice: If you try to use it from the wrong apartment, it throws an exception. But at least the behavior when used from the wrong apartment is <i>well-defined</i>, as opposed to the case of directly using an unmarshalable object from the wrong apartment, which is <i>undefined</i>.</p>
<p>Next time, we’ll do some fine tuning.</p>
<p><b>Bonus chatter</b>: Of course, now that we have a marshalable wrapper, we <i>could</i> use that wrapper to call the original non-marshalable object.</p>
<table class="cp3" style="border-collapse: collapse; text-align: center;" border="0" cellspacing="0" cellpadding="3">
<tbody>
<tr>
<td>Original apartment</td>
<td style="border-right: dashed currentcolor 1px;"> </td>
<td> </td>
<td>Other apartment</td>
</tr>
<tr>
<td style="border: solid currentcolor 1px;">Wrapper</td>
<td style="border-right: dashed currentcolor 1px;">←</td>
<td>←</td>
<td style="border: solid currentcolor 1px;">Caller</td>
</tr>
<tr>
<td>↓</td>
<td style="border-right: dashed currentcolor 1px;"> </td>
<td> </td>
</tr>
<tr>
<td style="border: solid currentcolor 1px;">Non-marshalable</td>
<td style="border-right: dashed currentcolor 1px;"> </td>
<td> </td>
</tr>
</tbody>
</table>
<p>The non-marshalable object does not allow any arrows to come in from other apartments, but the wrapper lives in the same apartment as the non-marshalable object, so <i>its</i> arrow is coming from within the same apartment.</p>
<p>You can think of the wrapper as a VPN into the original apartment, allowing calls to come in from the outside, but to appear to the non-marshalable object as if they came from within the same apartment.</p>
<p>Now, you <i>could</i> do that, but I’m not going to. The original object presumably went out of its way to declare itself non-marshalable for a reason, so we honor that preference and not play funny games to trick it into doing something it said that it didn’t want to do.</p>
<p>¹ Two commenters fell into this trap by suggesting that we wrap the non-marshalable object inside an object that implements <code>IMarshal</code>. If you implement <code>IMarshal</code>, then you are saying, “I’m way cooler than a standard non-agile object. I’m going to do fancy stuff (like being agile).” But we <i>want</i> to be a boring non-agile object, so that COM will do standard marshaling for us.</p>
<p>The post <a href="https://devblogs.microsoft.com/oldnewthing/20260805-00/?p=112591">Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 3</a> appeared first on <a href="https://devblogs.microsoft.com/oldnewthing">The Old New Thing</a>.</p>
# Creating a fake agile wrapper that is technically agile but is not useful outside its home apartment, part 3 - The Old New Thing
Source: [https://devblogs.microsoft.com/oldnewthing/20260805-00?p=112591](https://devblogs.microsoft.com/oldnewthing/20260805-00?p=112591)
Last time, we tried to execute on[our plan to use the global interface table to hold hold a reference to an object in another apartment that automatically expires when the apartment runs down](https://devblogs.microsoft.com/oldnewthing/20260804-00/?p=112586)\. But it broke down because objects that are marked`INoMarshal`can’t go into the global interface table\.
So we will just force the square peg into the round hole: We can put the non\-marshalable object inside an object that*is*marshalable\.
```
template<typename Smart>
struct force_marshal :
winrt::implements<force_marshal<Smart>, ::IUnknown, winrt::non_agile>
{
force_marshal(Smart const& p) : m_p(p) {}
Smart m_p;
};
```
The`force\_marshal<Smart\>`object babysits a non\-marshalable smart pointer to a COM object and exposes a marshalable wrapper around it\. Since the wrapped object is not agile, the wrapper cannot be either\. \(If the wrapper were agile, then we’d be back where we started: How do we ensure that the`m\_p`is destructed in the correct apartment?\)¹
We can put the unmarshalable object inside the wrapper, and then put the wrapper in the global interface table\.
```
template<typename T>
struct fake_agile_ref
{
⟦ ... ⟧
fake_agile_ref(Smart const& p) : m_raw(winrt::get_abi(p))
{
if (m_raw) {
m_context = winrt::capture<IContextCallback>(CoGetObjectContext);
m_token = get_context_token();
m_git = winrt::create_instance<IGlobalInterfaceTable>(CLSID_StdGlobalInterfaceTable);
winrt::check_hresult(m_git->RegisterInterfaceInGlobal(
winrt::make<force_marshal<Smart>>(p).get(),
__uuidof(IUnknown), &m_cookie));
}
}
⟦ ... ⟧
};
template<typename T> fake_agile_ref(winrt::com_ptr<T> const&)
-> fake_agile_ref<T>;
template<typename T> fake_agile_ref(T const&)
-> fake_agile_ref<T>;
```
Okay, so now we have managed to create an agile wrapper around an unmarshalable object\. This agile wrapper is agile on paper: You can use it from any thread\. However, it is not agile in practice: If you try to use it from the wrong apartment, it throws an exception\. But at least the behavior when used from the wrong apartment is*well\-defined*, as opposed to the case of directly using an unmarshalable object from the wrong apartment, which is*undefined*\.
Next time, we’ll do some fine tuning\.
**Bonus chatter**: Of course, now that we have a marshalable wrapper, we*could*use that wrapper to call the original non\-marshalable object\.
Original apartmentOther apartmentWrapper←←Caller↓Non\-marshalableThe non\-marshalable object does not allow any arrows to come in from other apartments, but the wrapper lives in the same apartment as the non\-marshalable object, so*its*arrow is coming from within the same apartment\.
You can think of the wrapper as a VPN into the original apartment, allowing calls to come in from the outside, but to appear to the non\-marshalable object as if they came from within the same apartment\.
Now, you*could*do that, but I’m not going to\. The original object presumably went out of its way to declare itself non\-marshalable for a reason, so we honor that preference and not play funny games to trick it into doing something it said that it didn’t want to do\.
¹ Two commenters fell into this trap by suggesting that we wrap the non\-marshalable object inside an object that implements`IMarshal`\. If you implement`IMarshal`, then you are saying, “I’m way cooler than a standard non\-agile object\. I’m going to do fancy stuff \(like being agile\)\.” But we*want*to be a boring non\-agile object, so that COM will do standard marshaling for us\.
### Category
### Topics
## Author

Raymond has been involved in the evolution of Windows for more than 30 years\. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie\-jeebies\. The Web site spawned a book, coincidentally also titled The Old New Thing \(Addison Wesley 2007\)\. He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information\.
Raymond Chen describes a technique for creating a fake agile wrapper in COM that uses the Global Interface Table to automatically release an object when its source apartment shuts down, addressing a problem with context callback failures.
Raymond Chen continues his series on creating a fake agile wrapper in COM, explaining how to move non-marshalable objects by forwarding references into the force_marshal wrapper and discussing C++/WinRT deduction guides.
Raymond Chen explains how to use std::unique_ptr to manage a registration cookie in a fake agile wrapper, discussing integer-to-pointer round-tripping and the wil::unique_any alternative.
Raymond Chen continues his series on building an agile Windows Runtime delegate in C++/WinRT, comparing how C++/WinRT, C++/CX, and WRL handle non-marshalable delegates and agile reference creation.
This blog post discusses handling Windows Runtime delegates that implement the INoMarshal interface in C++/WinRT, providing an agile delegate wrapper that checks the calling context to avoid marshaling errors.