A customer had an app with a plugin model based on vendor-supplied COM objects that are loaded into the process via CoCreateInstance.Main processEngine↓PluginThese COM objects run in-process, but the customer realized that these plugins were a potential source of instability, and they saw that you can instruct COM to load the plugin into a sacrificial process so that if the plugin crashes, the main program is unaffected.What they want is something like this:Main process Surrogate processEngine→PluginBut how do you opt a third-party component into the COM Surrogate? The third party component comes with its own registration, and it would be rude to alter that registration so that it runs in a COM Surrogate. Besides, a COM Surrogate requires an AppId, and the plugin might not have one.The answer is simple: Create your own object that is registered to run in the COM Surrogate. Define an interface for that custom object, say, ISurrogateHost and give that interface a method like LoadPlugin(REFCLSID pluginClsid, REFIID iid, void** result) which calls CoCreateInstance on the plugin CLSID and requests the specified interface pointer from it. (If you want to support aggregation, you can add a punkOuter parameter.)Main process Surrogate processEngine → Host↓PluginThe LoadPlugin method runs inside the surrogate, so when the plugin loads in-process, it loads into the surrogate process.The host can return a reference to the plugin directly to the main app engine, so it steps out of the way once the two sides are connected. The purpose of the host is to set up a new process.In fact, you don't even need to invent that special surrogate interface. There is already a standard COM interface that does this already: ICreateObject. It has a single method, uncreatively named CreateObject that takes exactly the parameters we want, including the punkOuter.Your surrogate host object would go like this, using (rolls dice) the WRL template library.struct SurrogateHost : Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::ClassicCom | Microsoft::WRL::RuntimeClassType::InhibitWeakReference>, ICreateObject, Microsoft::WRL::FtmBase>{ STDMETHOD(CreateObject)( REFCLSID clsid, IUnknown* outer, REFIID iid, void** result) { return CoCreateInstance(clsid, outer, CLSCTX_INPROC_SERVER, riid, result); }};In the engine, where you would normally dohr = CoCreateInstance(pluginClsid, outer, CLSCTX_INPROC_SERVER, riid, result);you instead create a surrogate host:Microsoft::WRL::ComPtr host;hr = CoCreateInstance(CLSID_SurrogateHost, nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&host));and then each time you need an object, you ask the surrogate host to do it:hr = host->CreateObject(pluginClsid, outer, riid, result);You can even get fancy and decide that some plugins are sus and should run in a surrogate, whereas others are trustworthy and may run inside the main process.if (is_trustworthy(pluginClsid)) { // Let this one load into the main process hr = CoCreateInstance(pluginClsid, outer, CLSCTX_INPROC_SERVER, riid, result);} else { // Boot this one to the surrogate process hr = host->CreateObject(pluginClsid, outer, riid, result);}Reusing the host object means that a single surrogate process is used for all plugins. If you want each plugin running in a separate surrogate, then create a separate host for each one.