171 lines
6.2 KiB
C#
171 lines
6.2 KiB
C#
|
//-----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//-----------------------------------------------------------------------------
|
||
|
namespace System.ServiceModel.ComIntegration
|
||
|
{
|
||
|
using System;
|
||
|
using System.Runtime;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.ServiceModel.Channels;
|
||
|
using System.Threading;
|
||
|
using System.Runtime.Versioning;
|
||
|
|
||
|
class ProxySupportWrapper
|
||
|
{
|
||
|
internal delegate int DelegateDllGetClassObject([In, MarshalAs(UnmanagedType.LPStruct)] Guid clsid, [In, MarshalAs(UnmanagedType.LPStruct)] Guid iid, ref IClassFactory ppv);
|
||
|
|
||
|
const string fileName = @"ServiceMonikerSupport.dll";
|
||
|
const string functionName = @"DllGetClassObject";
|
||
|
|
||
|
static readonly Guid ClsidProxyInstanceProvider = new Guid("(BF0514FB-6912-4659-AD69-B727E5B7ADD4)");
|
||
|
|
||
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
||
|
volatile SafeLibraryHandle monikerSupportLibrary;
|
||
|
|
||
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
||
|
volatile DelegateDllGetClassObject getCODelegate;
|
||
|
|
||
|
internal ProxySupportWrapper()
|
||
|
{
|
||
|
monikerSupportLibrary = null;
|
||
|
getCODelegate = null;
|
||
|
}
|
||
|
|
||
|
~ProxySupportWrapper()
|
||
|
{
|
||
|
if (null != monikerSupportLibrary)
|
||
|
{
|
||
|
monikerSupportLibrary.Close();
|
||
|
monikerSupportLibrary = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[ResourceConsumption(ResourceScope.Process)]
|
||
|
internal IProxyProvider GetProxyProvider()
|
||
|
{
|
||
|
if (null == monikerSupportLibrary)
|
||
|
{
|
||
|
lock (this)
|
||
|
{
|
||
|
if (null == monikerSupportLibrary)
|
||
|
{
|
||
|
getCODelegate = null;
|
||
|
using (RegistryHandle regKey = RegistryHandle.GetCorrectBitnessHKLMSubkey((IntPtr.Size == 8), ServiceModelInstallStrings.WinFXRegistryKey))
|
||
|
{
|
||
|
string file = regKey.GetStringValue(ServiceModelInstallStrings.RuntimeInstallPathName).TrimEnd('\0') + "\\" + fileName;
|
||
|
SafeLibraryHandle tempLibrary = UnsafeNativeMethods.LoadLibrary(file);
|
||
|
tempLibrary.DoNotFreeLibraryOnRelease();
|
||
|
|
||
|
monikerSupportLibrary = tempLibrary;
|
||
|
if (monikerSupportLibrary.IsInvalid)
|
||
|
{
|
||
|
monikerSupportLibrary.SetHandleAsInvalid();
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.ServiceMonikerSupportLoadFailed(file));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (null == getCODelegate)
|
||
|
{
|
||
|
lock (this)
|
||
|
{
|
||
|
if (null == getCODelegate)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
IntPtr procaddr = UnsafeNativeMethods.GetProcAddress(monikerSupportLibrary, functionName);
|
||
|
getCODelegate = (DelegateDllGetClassObject)Marshal.GetDelegateForFunctionPointer(procaddr, typeof(DelegateDllGetClassObject));
|
||
|
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
if (Fx.IsFatal(e))
|
||
|
throw;
|
||
|
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ComPlusProxyProviderException(SR.GetString(SR.FailedProxyProviderCreation), e));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
IClassFactory cf = null;
|
||
|
IProxyProvider proxyProvider = null;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
getCODelegate(ClsidProxyInstanceProvider, typeof(IClassFactory).GUID, ref cf);
|
||
|
|
||
|
proxyProvider = cf.CreateInstance(null, typeof(IProxyProvider).GUID) as IProxyProvider;
|
||
|
Thread.MemoryBarrier();
|
||
|
}
|
||
|
catch (Exception e)
|
||
|
{
|
||
|
if (Fx.IsFatal(e))
|
||
|
throw;
|
||
|
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ComPlusProxyProviderException(SR.GetString(SR.FailedProxyProviderCreation), e));
|
||
|
}
|
||
|
finally
|
||
|
{
|
||
|
if (null != cf)
|
||
|
{
|
||
|
Marshal.ReleaseComObject(cf);
|
||
|
cf = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return proxyProvider;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
internal static class OuterProxyWrapper
|
||
|
{
|
||
|
static ProxySupportWrapper proxySupport = new ProxySupportWrapper();
|
||
|
|
||
|
public static IntPtr CreateOuterProxyInstance(IProxyManager proxyManager, ref Guid riid)
|
||
|
{
|
||
|
IntPtr pOuter = IntPtr.Zero;
|
||
|
IProxyProvider proxyProvider = proxySupport.GetProxyProvider();
|
||
|
|
||
|
if (proxyProvider == null)
|
||
|
{
|
||
|
throw Fx.AssertAndThrowFatal("Proxy Provider cannot be NULL");
|
||
|
}
|
||
|
Guid riid2 = riid;
|
||
|
int hr = proxyProvider.CreateOuterProxyInstance(proxyManager, ref riid2, out pOuter);
|
||
|
|
||
|
Marshal.ReleaseComObject(proxyProvider);
|
||
|
|
||
|
if (hr != HR.S_OK)
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(SR.GetString(SR.FailedProxyProviderCreation), hr));
|
||
|
|
||
|
return pOuter;
|
||
|
|
||
|
}
|
||
|
|
||
|
public static IntPtr CreateDispatchProxy(IntPtr pOuter, IPseudoDispatch proxy)
|
||
|
{
|
||
|
IntPtr pInner = IntPtr.Zero;
|
||
|
IProxyProvider proxyProvider = proxySupport.GetProxyProvider();
|
||
|
|
||
|
if (proxyProvider == null)
|
||
|
{
|
||
|
throw Fx.AssertAndThrowFatal("Proxy Provider cannot be NULL");
|
||
|
}
|
||
|
int hr = proxyProvider.CreateDispatchProxyInstance(pOuter, proxy, out pInner);
|
||
|
|
||
|
Marshal.ReleaseComObject(proxyProvider);
|
||
|
|
||
|
if (hr != HR.S_OK)
|
||
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new COMException(SR.GetString(SR.FailedProxyProviderCreation), hr));
|
||
|
|
||
|
return pInner;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|