This commit is contained in:
110
PROMS/EPocalipse.IFilter/ComHelper.cs
Normal file
110
PROMS/EPocalipse.IFilter/ComHelper.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace EPocalipse.IFilter
|
||||
{
|
||||
[ComVisible(false)]
|
||||
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000001-0000-0000-C000-000000000046")]
|
||||
internal interface IClassFactory
|
||||
{
|
||||
void CreateInstance([MarshalAs(UnmanagedType.Interface)] object pUnkOuter, ref Guid refiid, [MarshalAs(UnmanagedType.Interface)] out object ppunk);
|
||||
void LockServer(bool fLock);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Utility class to get a Class Factory for a certain Class ID
|
||||
/// by loading the dll that implements that class
|
||||
/// </summary>
|
||||
internal static class ComHelper
|
||||
{
|
||||
//DllGetClassObject fuction pointer signature
|
||||
private delegate int DllGetClassObject(ref Guid ClassId, ref Guid InterfaceId, [Out, MarshalAs(UnmanagedType.Interface)] out object ppunk);
|
||||
|
||||
//Some win32 methods to load\unload dlls and get a function pointer
|
||||
private class Win32NativeMethods
|
||||
{
|
||||
[DllImport("kernel32.dll", CharSet=CharSet.Ansi)]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool FreeLibrary(IntPtr hModule);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern IntPtr LoadLibrary(string lpFileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Holds a list of dll handles and unloads the dlls
|
||||
/// in the destructor
|
||||
/// </summary>
|
||||
private class DllList
|
||||
{
|
||||
private List<IntPtr> _dllList=new List<IntPtr>();
|
||||
public void AddDllHandle(IntPtr dllHandle)
|
||||
{
|
||||
lock (_dllList)
|
||||
{
|
||||
_dllList.Add(dllHandle);
|
||||
}
|
||||
}
|
||||
|
||||
~DllList()
|
||||
{
|
||||
foreach (IntPtr dllHandle in _dllList)
|
||||
{
|
||||
try
|
||||
{
|
||||
Win32NativeMethods.FreeLibrary(dllHandle);
|
||||
}
|
||||
catch { };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DllList _dllList=new DllList();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a class factory for a specific COM Class ID.
|
||||
/// </summary>
|
||||
/// <param name="dllName">The dll where the COM class is implemented</param>
|
||||
/// <param name="filterPersistClass">The requested Class ID</param>
|
||||
/// <returns>IClassFactory instance used to create instances of that class</returns>
|
||||
internal static IClassFactory GetClassFactory(string dllName, string filterPersistClass)
|
||||
{
|
||||
//Load the class factory from the dll
|
||||
IClassFactory classFactory=GetClassFactoryFromDll(dllName, filterPersistClass);
|
||||
return classFactory;
|
||||
}
|
||||
|
||||
private static IClassFactory GetClassFactoryFromDll(string dllName, string filterPersistClass)
|
||||
{
|
||||
//Load the dll
|
||||
IntPtr dllHandle=Win32NativeMethods.LoadLibrary(dllName);
|
||||
if (dllHandle==IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
//Keep a reference to the dll until the process\AppDomain dies
|
||||
_dllList.AddDllHandle(dllHandle);
|
||||
|
||||
//Get a pointer to the DllGetClassObject function
|
||||
IntPtr dllGetClassObjectPtr=Win32NativeMethods.GetProcAddress(dllHandle, "DllGetClassObject");
|
||||
if (dllGetClassObjectPtr==IntPtr.Zero)
|
||||
return null;
|
||||
|
||||
//Convert the function pointer to a .net delegate
|
||||
DllGetClassObject dllGetClassObject=(DllGetClassObject)Marshal.GetDelegateForFunctionPointer(dllGetClassObjectPtr, typeof(DllGetClassObject));
|
||||
|
||||
//Call the DllGetClassObject to retreive a class factory for out Filter class
|
||||
Guid filterPersistGUID=new Guid(filterPersistClass);
|
||||
Guid IClassFactoryGUID=new Guid("00000001-0000-0000-C000-000000000046"); //IClassFactory class id
|
||||
Object unk;
|
||||
if (dllGetClassObject(ref filterPersistGUID, ref IClassFactoryGUID, out unk)!=0)
|
||||
return null;
|
||||
|
||||
//Yippie! cast the returned object to IClassFactory
|
||||
return (unk as IClassFactory);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user