API DLL or COM object? Creating a COM object without registration

creating a COM object w/o registrationOne of the major questions that an architector might face creating a multi-component project is how the components will interact. The mechanism of interaction could consist of COM interfaces usage and traditional import / export of functions and classes if we are talking about components that export a set of functions (in fact libraries).

The way of nteraction using functions import / export from libraries is often chosen because its implementation is simple and due to problems with necessary components registration in case of COM usage, whilst one might have no rights for it.

What if you do not have to register a COM component?

Yes, this is possible. For instance, Microsoft is using one of the methods to create a DirectDraw object. This is in fact a combination of two approaches. That is a call of an exported function is used at the stage of creating the object, and then the work continues with object’s COM interfaces.

HRESULT WINAPI DirectDrawCreate(GUID         FAR* lpGUID, 
                                LPDIRECTDRAW FAR* lplpDD, 
                                IUnknown     FAR* pUnkOuter); 

The second method seems to be more attractive in my opinion: you can use the DllGetClassObject function, which has to be exported by every COM object. It is this function that COM Windows Subsystem calls for registered components when some program is trying to create their copy by calling CoCreateInstance.

HRESULT CoCreateInstance(REFCLSID   rclsid,
                         LPUNKNOWN  pUnkOuter,
                         DWORD      dwClsContext,
                         REFIID     riid,
                         LPVOID *   ppv);

CoCreateInstance -> 
  search registration data of the object ->
    read the file location path from registration data ->
      call DllGetClassObject component to create a copy of the requested object

Thus, a copy of the object can be created by loading a module and calling its DllGetClassObject, if the file location is known:

        HINSTANCE hModule = CoLoadLibrary(pszModulePathName);
        if (hModule)
        {
            LPFNGETCLASSOBJECT pfnGetClassObject = 
                (LPFNGETCLASSOBJECT)GetProcAddress(hModule, "DllGetClassObject");

            if (pfnGetClassObject)
            {
                hr = pfnGetClassObject(rclsid, riid, ppv);
                ...

Parameters of a pfnGetClassObject call are the same as in case of CoCreateInstance, considering that pUnkOuter equals zero (do not use aggregation) and dwClsContext equals CLSCTX_INPROC_SERVER constant.

Conclusion

Well, here’s the whole method. It’s simple and effective. I think it is also worth mentioning that if the COM component is a part of your software package, it can be physically located in your application’s resources and copied to disk (and maybe decompressed / decrypted as well) right before its first use. This approach to COM component usage is implemented in the example that you can download via the link at the bottom of this page.

libcom.zip

Leave a Reply