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.