File: System\ServiceModel\ComIntegration\OuterProxyWrapper.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//-----------------------------------------------------------------------------
// 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;
 
        }
    }
}