Unlike standard ccall
for C interfaces in Julia, COM or the Component Object Model, mirrors classes in C++ more than straight dll calls.
In C++ or VB there are tons of examples out there. Code Project has several nice examples. Consider looking at the implementation of comtypes.py for complete scripting API info. https://github.com/enthought/comtypes/blob/master/comtypes/__init__.py
Another great intro to COM is found on Code Project:
https://www.codeproject.com/Articles/633/Introduction-to-COM-What-It-Is-and-How-to-Use-It
To handle this idea of using COM, their are multiple steps to interact with a COM class, interface and eventually its function call.
Below are the layers for the simplest call to a COM Interface. Most of these calls interact with "Ole32.dll".
- Get GUIDs for Class and Interface
- CoInitializeEx
- CoCreateInstance
- interface->Method
- Release(interface)
- CoUninitialize
Oh, and CoCreateInstance
doesn't work unless you are in the context of a registered dll. (See regsvr32
).
This project showed a bunch of examples for Win32 ccalls
: https://github.com/ihnorton/Win32GUIDemo.jl
So to hack around the need to be registered as a COM enabled server, there are multiple good examples of this on Code Project:
https://www.codeproject.com/Articles/18433/Emulating-CoCreateInstance
https://www.codeproject.com/Tips/1037909/Using-COM-Without-Registration
The underlying code for both of these show drilling into DllGetClassObject
and pulling out an instance of the IClassFactory
and calling CreateInstance
on the instance of the Class Factory interface. Easy right?
I've used techique in the example code.
Now instead of using C++ calling conventions in Julia, ccalls are used. To drill into an interface and to pass in the right REFIID takes some doing but its not too bad.
https://gist.github.com/peteristhegreat/924832e88806b05dafd434fb1e71252c
The best listing of HRESULT errors are here: https://github.com/SecureAuthCorp/impacket/blob/master/impacket/hresult_errors.py
A short list is found here: https://docs.microsoft.com/en-us/windows/win32/seccrypto/common-hresult-values
Make a small file in Visual Studio C++ that looks like this:
#include <windows.h>
#include <winnt.h>
#include <stdio.h>
#include <Wincrypt.h>
#include <objbase.h>
#include <combaseapi.h>
#include <wtypesbase.h>
#include "windows.h"
#include "winnls.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "certadm.h"
#include "shlguid.h"
#pragma comment(lib, "crypt32.lib")
#pragma comment(lib, "Ole32.lib")
#pragma comment(lib, "Certidl.lib")
#include <atlbase.h>
#include <iostream>
#include <Certcli.h>
#include <Certsrv.h>
#include <Unknwn.h>
REFIID r = IID_ICertAdmin2;
REFIID r = IID_IClassFactory;
REFIID r = IID_ICertAdmin;
REFIID r = CLSID_CCertAdmin;
And right click on one of the IID_XXXXX
variables and select Go to definition
to find the GUIDs associated with it. Googling works to some extent, but MSDN doesn't publish all the GUIDs nicely.