private object GetClassInstance(Guid classguid, Guid interfguid, Guid classfactoryguid, Guid classfactory2guid) { object classinstance = null; // create instance via raw dll functions // ensures we get the real vtable try { if (classinstance == null) { // Single do..while loop - to support "break;" do { Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey("CLSID\\{" + classguid.ToString() + "}\\InprocServer32"); if (rk == null) { break; } string classdllname = rk.GetValue(null).ToString(); IntPtr libH = KERNEL32.LoadLibrary(classdllname); if (libH == IntPtr.Zero) { break; } IntPtr factoryFunc = KERNEL32.GetProcAddress(libH, "DllGetClassObject"); if (factoryFunc == IntPtr.Zero) { break; } DllGetClassObjectDelegate factoryDel = (DllGetClassObjectDelegate)Marshal.GetDelegateForFunctionPointer(factoryFunc, typeof(DllGetClassObjectDelegate)); object classfactoryO; // Try with IClassFactory first factoryDel(ref classguid, ref classfactoryguid, out classfactoryO); if (classfactoryO != null) { IClassFactory classfactory = (IClassFactory)classfactoryO; classfactory.CreateInstance(null, ref interfguid, out classinstance); Marshal.FinalReleaseComObject(classfactory); } else { // Now try with IClassFactory2 factoryDel(ref classguid, ref classfactory2guid, out classfactoryO); if (classfactoryO == null) { break; } IClassFactory2 classfactory = (IClassFactory2)classfactoryO; classinstance = classfactory.CreateInstance(null, interfguid); Marshal.FinalReleaseComObject(classfactory); } } while (false); } } catch { } return(classinstance); }
public static extern HRESULT CoGetClassObject( ref Guid rclsid, CLSCTX dwContext, IntPtr pvReserved, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IClassFactory2 ppv);
public static unsafe void Query(ComClassInfo cci) { Guid classguid = cci.ClassType.GUID; Guid interfguid = cci.InterfaceType.GUID; Guid classfactoryguid = typeof(IClassFactory).GUID; Guid classfactory2guid = typeof(IClassFactory2).GUID; object classinstance = null; #if false // create an instance via .NET built-in functionality // vtable might be hijacked by rpcrt4.dll classinstance = cci.ClassType.InvokeMember("", BindingFlags.CreateInstance, null, null, null); #endif #if false // create via ole-convenience-function // vtable might be hijacked by rpcrt4.dll OLE32.CoCreateInstance(ref classguid, null, 1 + 4, ref interfguid, out classinstance); #endif #if false // create via ole-functions // vtable might be hijacked by rpcrt4.dll try { if (classinstance == null) { object classfactoryO; OLE32.CoGetClassObject(ref classguid, 1 + 4, 0, ref classfactoryguid, out classfactoryO); IClassFactory classfactory = (IClassFactory)classfactoryO; classfactory.CreateInstance(null, ref interfguid, out classinstance); Marshal.FinalReleaseComObject(classfactory); } } catch { } try { if (classinstance == null) { object classfactoryO; OLE32.CoGetClassObject(ref classguid, 1 + 4, 0, ref classfactoryguid, out classfactoryO); IClassFactory2 classfactory = (IClassFactory2)classfactoryO; classinstance = classfactory.CreateInstance(null, interfguid); Marshal.FinalReleaseComObject(classfactory); } } catch { } if (classinstance == null) { // Error... } #endif #if true // create via raw dll functions // no chance for other people to hijack the vtable try { do { RegistryKey rk = Registry.ClassesRoot.OpenSubKey("CLSID\\{" + classguid + "}\\InprocServer32"); if (rk == null) { break; } string classdllname = rk.GetValue(null).ToString(); IntPtr libH = KERNEL32.LoadLibrary(classdllname); if (libH == IntPtr.Zero) { break; } IntPtr factoryFunc = KERNEL32.GetProcAddress(libH, "DllGetClassObject"); if (factoryFunc == IntPtr.Zero) { break; } var factoryDel = (DllGetClassObjectDelegate) Marshal.GetDelegateForFunctionPointer(factoryFunc, typeof(DllGetClassObjectDelegate)); object classfactoryO; factoryDel(ref classguid, ref classfactoryguid, out classfactoryO); if (classfactoryO == null) { break; } var classfactory = (IClassFactory)classfactoryO; classfactory.CreateInstance(null, ref interfguid, out classinstance); Marshal.FinalReleaseComObject(classfactory); } while (false); } catch { } try { if (classinstance == null) { do { RegistryKey rk = Registry.ClassesRoot.OpenSubKey("CLSID\\{" + classguid + "}\\InprocServer32"); if (rk == null) { break; } string classdllname = rk.GetValue(null).ToString(); IntPtr libH = KERNEL32.LoadLibrary(classdllname); if (libH == IntPtr.Zero) { break; } IntPtr factoryFunc = KERNEL32.GetProcAddress(libH, "DllGetClassObject"); if (factoryFunc == IntPtr.Zero) { break; } var factoryDel = (DllGetClassObjectDelegate) Marshal.GetDelegateForFunctionPointer(factoryFunc, typeof(DllGetClassObjectDelegate)); object classfactoryO; factoryDel(ref classguid, ref classfactory2guid, out classfactoryO); if (classfactoryO == null) { break; } var classfactory = (IClassFactory2)classfactoryO; classinstance = classfactory.CreateInstance(null, interfguid); Marshal.FinalReleaseComObject(classfactory); } while (false); } } catch { } if (classinstance == null) { // Error... } #endif IntPtr interfaceIntPtr = Marshal.GetComInterfaceForObject(classinstance, cci.InterfaceType); var interfaceRawPtr = (int ***)interfaceIntPtr.ToPointer(); // get vtable int **vTable = *interfaceRawPtr; // get com-slot-number (vtable-index) of function X // get function-address from vtable int mi_vto = Marshal.GetComSlotForMethodInfo(cci.Method); int *faddr = vTable[mi_vto]; cci.MFunctionPointer = new IntPtr(faddr); // release intptr Marshal.Release(interfaceIntPtr); Marshal.FinalReleaseComObject(classinstance); }
/// <summary> /// Creates an instance of a COM server using the specified license key. /// </summary> public static object CreateInstanceWithLicenseKey(Guid clsid, string hostName, NetworkCredential credential, string licenseKey) { var serverInfo = new ServerInfo(); COSERVERINFO coserverInfo = serverInfo.Allocate(hostName, credential); object instance = null; IClassFactory2 factory = null; try { // Check whether connecting locally or remotely. uint clsctx = ComConstants.CLSCTX_INPROC_SERVER | ComConstants.CLSCTX_LOCAL_SERVER; if (!string.IsNullOrEmpty(hostName)) { clsctx = ComConstants.CLSCTX_LOCAL_SERVER | ComConstants.CLSCTX_REMOTE_SERVER; } // Get the class factory. object unknown = null; CoGetClassObject( clsid, clsctx, ref coserverInfo, typeof(IClassFactory2).GUID, out unknown); factory = (IClassFactory2)unknown; // Set the proper connect authentication level var security = (IClientSecurity)factory; uint pAuthnSvc = 0; uint pAuthzSvc = 0; var pServerPrincName = ""; uint pAuthnLevel = 0; uint pImpLevel = 0; IntPtr pAuthInfo = IntPtr.Zero; uint pCapabilities = 0; // Get existing security settings. security.QueryBlanket( factory, ref pAuthnSvc, ref pAuthzSvc, ref pServerPrincName, ref pAuthnLevel, ref pImpLevel, ref pAuthInfo, ref pCapabilities); pAuthnSvc = ComConstants.RPC_C_AUTHN_DEFAULT; pAuthnLevel = ComConstants.RPC_C_AUTHN_LEVEL_CONNECT; // Update security settings. security.SetBlanket( factory, pAuthnSvc, pAuthzSvc, pServerPrincName, pAuthnLevel, pImpLevel, pAuthInfo, pCapabilities); // Create instance. factory.CreateInstanceLic( null, null, IUnknownIID, licenseKey, out instance); } catch (Exception ex) { throw ex; } finally { serverInfo.Deallocate(); } return(instance); }