Skip to content

Instantly share code, notes, and snippets.

@ogxd
Created January 25, 2023 08:50
Show Gist options
  • Save ogxd/69431ea17643687e9a36d30b0193c16a to your computer and use it in GitHub Desktop.
Save ogxd/69431ea17643687e9a36d30b0193c16a to your computer and use it in GitHub Desktop.
Manual COM Loading
public static class ComUtils
{
private delegate int DllGetClassObject(ref Guid clsid, ref Guid iid, out nint classFactoryPtr);
private delegate void CreateInstance(nint self, nint pUnkOuter, ref Guid riid, out nint ppvObjectPtr);
public static nint Load(string library)
{
Guid exceptionProfilerGuid = new Guid("805A308B-061C-47F3-9B30-F785C3186E82");
Guid iclassFactoryGuid = new Guid("00000001-0000-0000-c000-000000000046");
Guid iCorProfilerCallback8Guid = new Guid("5BED9B15-C079-4D47-BFE2-215A140C07E0");
// Load profilers library (dlopen on linux)
NativeLibrary.TryLoad(library, typeof(Segfault).Assembly, DllImportSearchPath.AssemblyDirectory, out nint handle);
Debug.Assert(nint.Zero != handle);
// Get pointer to method DllGetClassObject (dlsym on linux)
nint methodHandle = NativeLibrary.GetExport(handle, "DllGetClassObject");
Debug.Assert(nint.Zero != methodHandle);
// Cast pointer to DllGetClassObject delegate
DllGetClassObject dllGetClassObject = Marshal.GetDelegateForFunctionPointer<DllGetClassObject>(methodHandle);
Debug.Assert(dllGetClassObject != null);
// Call DllGetClassObject to query the IClassFactory interface that can create instances of Exception Profiler
dllGetClassObject(ref exceptionProfilerGuid, ref iclassFactoryGuid, out nint classFactoryPtr);
Debug.Assert(nint.Zero != classFactoryPtr);
// Since we can't use COM marshalling on Linux, we need to manually get the CreateInstance method pointer from the virtual table
nint vtablePtr = Marshal.ReadIntPtr(classFactoryPtr);
nint createInstancePtr = vtablePtr + nint.Size * 3;
CreateInstance createInstance = Marshal.GetDelegateForFunctionPointer<CreateInstance>(Marshal.ReadIntPtr(createInstancePtr));
Debug.Assert(createInstance != null);
// Create instance of profiler, which implements ICoreProfilerCallback8 interface
createInstance(nint.Zero, ref iCorProfilerCallback8Guid, out nint ppvObjectPtr);
Debug.Assert(nint.Zero != ppvObjectPtr);
return ppvObjectPtr;
// Free library
// NativeLibrary.Free(handle);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment