views:

240

answers:

2

I'd like to intercept the COM CoCreateInstanceEx and/or CoGetClassObject functions to replace a class with a testing shim in a unit test. This will only be for a single CLSID; all others can go through unchanged. Is there a way to do this without horrible, evil hacks?

+1  A: 

It depends on what exactly you want.

If you want to detect who is loading that class or to find whether it is loaded at all you can use Process Monitor. A call to CoGetClassObject() (or CoCreateInstanceEx()) will lead to a HKCR\CLSID\{Class of interest id} key being read and Process Monitor will show you what process and when does this and how successful it is.

If you want to replace an existing class with yours - compile a library with your version of class with the same class id and change the path to the COM server inside HKCR\CLSID\{Class of interest id} so that your library is used to serve a class with that id. You can do that manually or with regsvr32 - first register the original library, then yours to override the class of interest registartion. COM does class id -> library mapping through that key when a consumer calls CoGetClassObject() or CoCreateInstanceEx().

sharptooth
Unfortunately, I can't be messing around with the registry for this - it'll run on an automated test suite, and the class I'm intending to override is `CLSID_KnownFolderManager`, so it's probably a bad idea to override that in a system-wide manner :) In the worst case, I could instrument the code to be tested, but if there's a clean way to replace it just for one process, that would be nice.
bdonlan
First, you can register the original library after the test suite is run and this will restore the sanity. Second, you can register your modified library for the current user only - modify HKCU\Software\Classes\CLSID. Other than that you can't do anything more or less elegant.
sharptooth
+2  A: 

There's always the CoTreatAsClass function: http://msdn.microsoft.com/en-us/library/ms693452%28VS.85%29.aspx

But, as you noted, it will be a system-wide replacement of the class, not a local change.

Alternatively, you could look into hooking CoCreateInstance as suggested in the post referenced by Shay Erlichmen's comment.

Kim Gräsman