Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
9 lines (8 sloc) 2.83 KB
---
layout: post
title: "End-run around registration-free COM"
date: 2009-04-23
comments: false
---
<div class='post'>
With the introduction of registration-free COM, Windows now allows you to create COM objects without registering their DLLs in the registry. This means that you can include your COM DLLs with your application files and run the application without being an administrator and mucking with regsvr32. Instead you include (or embed in your executable/DLL) a manifest which specifies the location of the COM DLL relative to your application. <br /><br />This "new" (it was introduced with Windows XP, I believe) approach is not flexible enough for Titanium, which doesn't know until after run-time which WebKit DLL it will be using. Writing this manifest file into the application directory and restarting or copying the DLLs into the application directory is a less than ideal solution. While the copy may work in Vista because of the wonky UAC virtualization of write permissions (that's an entirely different rant), copying an entire DLL and its dependencies at startup is expensive and defeats the purpose of DLLs.<br /><br />This situation bothered me until I stumbled upon <a href="http://blogs.msdn.com/gpalem/archive/2007/03/26/avoid-registration-free-com-manifest-problems-with-activation-context-api.aspx">this blog post </a>in the murky underbelly of the interblogs. It basically describes an approach using the somewhat thinly documented (perhaps intentionally) <a href="http://msdn.microsoft.com/en-us/library/aa375134.aspx">activation context API</a>.<br /><br />This Windows nightmare has a happy ending in that we were able to simply point an activation context at the WebKit DLL's manifest path. Here's what it looks like (this is originally from Gopalakrishna's blog which I linked to above):<br /><br /><pre><code><br />// This is a normal CoCreateInstance -- done as if the COM DLL<br />// was actually registered with the system -- it will fail<br />IMyComponent* pObj = NULL;<br />HRESULT hr = CoCreateInstance(<br /> CLSID_MyComponent, <br /> NULL, <br /> CLSCTX_INPROC_SERVER, <br /> IID_IMyComponent,<br /> (void**)&pObj);<br /><br />ACTCTX actctx;<br />ZeroMemory(&actctx, sizeof(actctx));<br />actctx.cbSize = sizeof(actctx);<br />actctx.lpSource = "C:\Path\To\My\Manifest.manifest";<br />HANDLE pActCtx = CreateActCtx(&actctx);<br />ULONG_PTR lpCookie;<br /><br />if(pActCtx != INVALID_HANDLE_VALUE)<br />{<br /> if (ActivateActCtx(pActCtx, &lpCookie))<br /> {<br /> // CoCreateInstance should succeed now. <br /> HRESULT hr = CoCreateInstance(<br /> CLSID_MyComponent, <br /> NULL, <br /> CLSCTX_INPROC_SERVER, <br /> IID_IMyComponent,<br /> (void**)&pObj);<br /> DeactivateActCtx(0, lpCookie);<br /> }<br /> ReleaseActCtx(pActCtx);<br />}<br /></code></pre></div>
You can’t perform that action at this time.