I am quite inexperienced with COM objects, following is what I did:
Now comes the difficult part:
How to make windows to link/use the DLL:
How to register and how to check if registered a COM dll?
Is there compilation restrictions like compiler/architecture?
EDITED Simplified:
It seem that I had a very incomplete vision of COM implementation, and in order to register the COM object, 2 directions are possible:
To simplify the problem, I removed everything else up to having only those 2 functions:
STDAPI DllRegisterServer(void)
{
return NOERROR;
}
STDAPI DllUnregisterServer(void)
{
return NOERROR;
}
Unfortunately, this is not exported to the DLL, (as no __declspec(dllexport) is specified). As soon as I try to add this declaration, the compiler complain and no DLL is generated.
SOLUTION STEP 1:
Olectl.h is very very bad and avoid DllRegisterServer to be exported.
In order to create a COM
object manually (without wizard), following steps are required:
DllGetClassObject
& DllCanUnloadNow
IClassFactory
IUknown
COM
in the registryDllRegisterServe
r & DllUnregisterServer
to make registry easier.Implements DllGetClassObject & DllCanUnloadNow
Those are the only exported to the DLL functions:
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID * ppObject)
STDAPI DllCanUnloadNow(void)
DllGetClassObject, if the provided rclsid
is the TargetClassCLSID
and riid
is the `FactoryCLSID, it creates and return a Factory object.
DllCanUnloadNow return if the DLL is in use (S_OK
) or not, in which case the user/client may unload the DLL (S_FALSE
).
The problem is, the definition do not allows to add __declspec(dllexport)
due probably to some Microsoft monopol directive to make VS "mandatory".
To export them, just add before
#pragma comment( linker, "/export:DllGetClassObject,PRIVATE" )
#pragma comment( linker, "/export:DllCanUnloadNow,PRIVATE" )
//TODO: make this cross-compiler compatible?
Implementing the Factory
Implements AddRef
and Release
: they maintain how many client/users are currently using this Factory object. AddRef increment it by 1, Release decrements it by 1. As soon as the number is 0, Release
may auto delete itself.
Implements QueryInterface
which return if riid
is the FactoryCLSID.
Implements CreateInstance
, which return an instance of the TargetObject if riid match TargetClassCLSID
Implementing the Target Class
Again, we have to implements AddRef, Release and QueryInterface, but for the final class this time.
In my case, this Target class extends IShellIconOverlayIdentifier.
Register the COM object into the OS registry
After generating the dll, several registry need to be set. Some of them are linked together, so adding one may automatically add another.
HKEY_CLASS_ROOT::CLSID::<Add Here>
HKEY_CLASS_ROOT::Wow6432Node::CLSID::<Add Here>
HKEY_LOCAL_MACHINE::SOFTWARE::Classes::CLSID::<Add Here>
HKEY_LOCAL_MACHINE::SOFTWARE::Classes::Wow6432Node::CLSID::<Add Here>
HKEY_LOCAL_MACHINE::SOFTWARE::Wow6432Node::Classes::CLSID::<Add Here>
Content to add is:
{TargetClassCLSID}
, value=<Any app name>
InProcServer32
, value=<link to your dll>
ThreadingModel
, value=Apartment
//TODO: probably there are other alternatives, to better understand what that mean.
In my case, I had to register some more registers for the IconHandler:
HKEY_LOCAL_MACHINE::SOFTWARE::Microsoft::Windows::CurrentVersion::Explorer::ShellIconOverlayIdentifier::<Overlay here>
HKEY_LOCAL_MACHINE::SOFTWARE::Microsoft::Windows::CurrentVersion::ShellExtensions::Aproved::<new entry here>
Where the overlay entry is a key: name=<Any app name>
, value=<TargetClassCLSID>
The new entry is a string value which name=<TargetClassCLSID>
and value=Any app name
Those values need also to be in:
HKEY_LOCAL_MACHINE::SOFTWARE::Wow6432Node::Microsoft::Windows....