TypeCacheManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / ComIntegration / TypeCacheManager.cs / 2 / TypeCacheManager.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.ServiceModel.ComIntegration
{ 
    using System;
    using System.Globalization; 
    using System.Runtime.InteropServices; 
    using System.Runtime.InteropServices.ComTypes;
    using Microsoft.Win32; 
    using System.Reflection;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Threading; 
    using System.Diagnostics;
 
    using System.ServiceModel.Diagnostics; 

 
    internal class TypeCacheManager : ITypeCacheManager
    {
        private enum RegKind
        { 
             Default = 0,
             Register = 1, 
             None = 2 
        }
 

        // TypeCacheManager.Provider will give access to the static instance of the TypeCache
        private static Guid clrAssemblyCustomID = new Guid("90883F05-3D28-11D2-8F17-00A0C9A6186D");
        private static  object instanceLock = new object(); 

 
        static public ITypeCacheManager Provider 
        {
            get 
            {
                  lock (instanceLock)
                  {
                      if (instance == null) 
                      {
                          ITypeCacheManager localInstance = new TypeCacheManager (); 
                          Thread.MemoryBarrier (); 
                          instance = localInstance;
                      } 
                  }

                  return instance;
             } 
        }
        static internal ITypeCacheManager instance; 
 

        // Convert to typeLibrary ID (GUID) 
        private Dictionary  assemblyTable ;
        private Dictionary  typeTable;
        private object typeTableLock;
        private object assemblyTableLock; 

          internal TypeCacheManager () 
          { 
               assemblyTable = new  Dictionary  ();
               typeTable = new Dictionary  (); 
               typeTableLock = new object ();
               assemblyTableLock = new object ();
          }
          private Guid GettypeLibraryIDFromIID (Guid iid, bool isServer, out String version) 
          {
               // In server we need to open the the User hive for the Process User. 
               RegistryKey interfaceKey = null; 
               try
               { 
                    string keyName = null;
                    if (isServer)
                    {
                        keyName = String.Concat("software\\classes\\interface\\{", iid.ToString(), "}\\typelib"); 
                        interfaceKey = Registry.LocalMachine.OpenSubKey(keyName, false);
                    } 
                    else 
                    {
                        keyName = String.Concat("interface\\{", iid.ToString(), "}\\typelib"); 
                        interfaceKey = Registry.ClassesRoot.OpenSubKey(keyName, false);
                    }
                    if (interfaceKey == null)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError (new InvalidOperationException (SR.GetString (SR.InterfaceNotRegistered))); 
                    string typeLibID = interfaceKey.GetValue ("").ToString ();
                    if (string.IsNullOrEmpty(typeLibID)) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError (new InvalidOperationException (SR.GetString (SR.NoTypeLibraryFoundForInterface))); 
                    version = interfaceKey.GetValue ("Version").ToString ();
                    if (string.IsNullOrEmpty(version)) 
                        version = "1.0";

                    Guid typeLibraryID ;
                    if ( !DiagnosticUtility.Utility.TryCreateGuid(typeLibID, out typeLibraryID)) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError (new InvalidOperationException (SR.GetString (SR.BadInterfaceRegistration))); 
                    } 
                    return typeLibraryID;
 
               }
               finally
               {
                    if (interfaceKey != null) 
                         interfaceKey.Close ();
               } 
 
          }
          private void ParseVersion (string version, out ushort major, out ushort minor) 
          {
               major = 0;
               minor = 0;
               if (String.IsNullOrEmpty(version)) 
                    return;
               int indexOfDot = version.IndexOf (".", StringComparison.Ordinal); 
               try 
               {
 
                    if (indexOfDot == -1)
                    {
                         major = Convert.ToUInt16 (version, NumberFormatInfo.InvariantInfo);
                         minor = 0; 
                    }
                    else 
                    { 
                         major = Convert.ToUInt16 (version.Substring (0, indexOfDot ), NumberFormatInfo.InvariantInfo);
                         string minorVersion = version.Substring (indexOfDot + 1); 
                         int indexOfDot2 = version.IndexOf (".", StringComparison.Ordinal);

                         if (indexOfDot2 != -1) // Ignore anything beyond the first minor version.
                            minorVersion = minorVersion.Substring (0, indexOfDot2); 

                         minor = Convert.ToUInt16 (minorVersion, NumberFormatInfo.InvariantInfo); 
                    } 
               }
               catch (FormatException) 
               {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError (new InvalidOperationException (SR.GetString (SR.BadInterfaceVersion)));
               }
               catch (OverflowException ) 
               {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError (new InvalidOperationException (SR.GetString (SR.BadInterfaceVersion))); 
               } 

          } 
          private ITypeLib2 GettypeLibrary (Guid typeLibraryID, string version)
          {
              ushort major = 0;
              ushort minor = 0; 
              const int lcidLocalIndependent = 0;
              ParseVersion (version, out major, out minor); 
              object otlb; 
              int hr = SafeNativeMethods.LoadRegTypeLib (ref typeLibraryID, major, minor, lcidLocalIndependent, out otlb);
              if (hr != 0 || null == otlb) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError (new COMException (SR.GetString (SR.FailedToLoadTypeLibrary), hr));
              return otlb as ITypeLib2;

 
          }
 
 
            private Assembly ResolveAssemblyFromIID (Guid iid, bool noAssemblyGeneration, bool isServer)
            { 

                String version;
                Guid typeLibraryID = GettypeLibraryIDFromIID (iid, isServer, out version);
 
                return ResolveAssemblyFromTypeLibID(iid, typeLibraryID, version, noAssemblyGeneration);
 
            } 

            private Assembly ResolveAssemblyFromTypeLibID(Guid iid, Guid typeLibraryID, string version, bool noAssemblyGeneration) 
            {
                 ComPlusTLBImportTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTLBImportStarting,
                                                SR.TraceCodeComIntegrationTLBImportStarting, iid, typeLibraryID);
                 Assembly asm; 

                 bool generateNativeAssembly = false; 
                 ITypeLib2 typeLibrary = null; 

                 try 
                 {
                     lock (assemblyTableLock)
                     {
                         assemblyTable.TryGetValue(typeLibraryID, out asm); 
                         if (asm == null)
                         { 
                             typeLibrary = GettypeLibrary(typeLibraryID, version); 
                             object opaqueData = null;
                             typeLibrary.GetCustData(ref clrAssemblyCustomID, out opaqueData); 
                             if (opaqueData == null)
                                 generateNativeAssembly = true;      // No custom data for this IID this is not a CLR typeLibrary
                             String assembly = opaqueData as String;
                             if (String.IsNullOrEmpty(assembly)) 
                                 generateNativeAssembly = true;      // No custom data for this IID this is not a CLR typeLibrary
                             if (noAssemblyGeneration && generateNativeAssembly) 
                                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.NativeTypeLibraryNotAllowed, typeLibraryID))); 
                             else if (!generateNativeAssembly)
                             { 
                                 ComPlusTLBImportTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTLBImportFromAssembly,
                                               SR.TraceCodeComIntegrationTLBImportFromAssembly, iid, typeLibraryID, assembly);
                                 asm = Assembly.Load(assembly);            // Assembly.Load will get a full assembly name
                             } 
                             else
                             { 
                                 ComPlusTLBImportTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTLBImportFromTypelib, 
                                                    SR.TraceCodeComIntegrationTLBImportFromTypelib, iid, typeLibraryID);
                                 asm = TypeLibraryHelper.GenerateAssemblyFromNativeTypeLibrary(iid, typeLibraryID, typeLibrary as ITypeLib); 
                             }

                             assemblyTable[typeLibraryID] = asm;
                         } 
                     }
                 } 
                 catch (Exception e) 
                 {
                     DiagnosticUtility.EventLog.LogEvent(TraceEventType.Error, 
                         EventLogCategory.ComPlus,
                         EventLogEventId.ComPlusTLBImportError,
                         iid.ToString(),
                         typeLibraryID.ToString(), 
                         e.ToString());
                     throw; 
                 } 
                 finally
                 { 

                     // Add Try Finally to cleanup typeLibrary
                     if (typeLibrary != null)
                         Marshal.ReleaseComObject((object)typeLibrary); 
                 }
 
                 if (null == asm) 
                 {
                     DiagnosticUtility.DebugAssert("Assembly should not be null"); 

                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(true);
                 }
                 ComPlusTLBImportTrace.Trace(TraceEventType.Verbose, TraceCode.ComIntegrationTLBImportFinished, 
                                    SR.TraceCodeComIntegrationTLBImportFinished, iid, typeLibraryID);
                 return asm; 
          } 
          private bool NoCoClassAttributeOnType (ICustomAttributeProvider attrProvider)
          { 
                object[] attrs = System.ServiceModel.Description.ServiceReflector.GetCustomAttributes(attrProvider, typeof(CoClassAttribute), false);
                if (attrs.Length == 0)
                    return true;
                else 
                    return false;
          } 
 
        Assembly ITypeCacheManager.ResolveAssembly(Guid assembly)
        { 
            Assembly ret = null;

            lock (assemblyTableLock)
            { 
                this.assemblyTable.TryGetValue(assembly, out ret);
            } 
 
            return ret;
        } 

         void ITypeCacheManager.FindOrCreateType(Guid typeLibId, string typeLibVersion, Guid typeDefId, out Type userDefinedType, bool noAssemblyGeneration)
         {
             lock (typeTableLock) 
             {
                 typeTable.TryGetValue(typeDefId, out userDefinedType); 
                 if (userDefinedType == null) 
                 {
                     Assembly asm = ResolveAssemblyFromTypeLibID(Guid.Empty, typeLibId, typeLibVersion, noAssemblyGeneration); 
                     foreach (Type t in asm.GetTypes())
                     {
                         if (t.GUID == typeDefId)
                         { 
                             if (t.IsValueType)
                             { 
                                 userDefinedType = t; 
                                 break;
                             } 
                         }
                     }
                     if (userDefinedType == null)
                         throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.UdtNotFoundInAssembly, typeDefId))); 

                     typeTable[typeDefId] = userDefinedType; 
 
                 }
             } 
         }


          public void FindOrCreateType (Guid iid, out Type interfaceType, bool noAssemblyGeneration, bool isServer) 
          {
              lock(typeTableLock) 
              { 
                   typeTable.TryGetValue (iid, out interfaceType);
                   if (interfaceType == null) 
                   {
                         Type coClassInterface = null;
                         Assembly asm = ResolveAssemblyFromIID (iid, noAssemblyGeneration, isServer);
                         foreach (Type t in asm.GetTypes ()) 
                         {
                              if (t.GUID == iid) 
                              { 
                                  if (t.IsInterface && NoCoClassAttributeOnType (t) )
                                  { 
                                      interfaceType = t;
                                      break;

                                  } 
                                  else if (t.IsInterface && !NoCoClassAttributeOnType (t))
                                  { 
                                      coClassInterface = t; 
                                  }
                              } 

                         }
                         if ((interfaceType == null) && (coClassInterface != null))
                              interfaceType = coClassInterface; 
                         else if (interfaceType == null)
                              throw DiagnosticUtility.ExceptionUtility.ThrowHelperError (new InvalidOperationException (SR.GetString(SR.InterfaceNotFoundInAssembly))); 
 
                         typeTable[iid] = interfaceType;
                   } 
               }
          }
          void ITypeCacheManager.FindOrCreateType (Type serverType, Guid iid, out Type interfaceType, bool noAssemblyGeneration, bool isServer)
          { 
              interfaceType = null;
              if (serverType == null) 
                 FindOrCreateType (iid, out interfaceType, noAssemblyGeneration, isServer); 
              else
              { 
                  if (!serverType.IsClass)
                  {
                      DiagnosticUtility.DebugAssert("This should be a class");
 
                      throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(false);
                  } 
                  foreach (Type interfaceInType in serverType.GetInterfaces ()) 
                  {
                        if (interfaceInType.GUID == iid) 
                        {
                           interfaceType = interfaceInType;
                           break;
                        } 
                  }
                  if (interfaceType == null) 
                     throw DiagnosticUtility.ExceptionUtility.ThrowHelperError (new InvalidOperationException (SR.GetString(SR.InterfaceNotFoundInAssembly))); 
              }
 
          }

          public static Type ResolveClsidToType (Guid clsid)
          { 
               string keyName = String.Concat("software\\classes\\clsid\\{", clsid.ToString(), "}\\InprocServer32");
               using (RegistryKey clsidKey = Registry.LocalMachine.OpenSubKey(keyName, false)) 
               { 
                   if (clsidKey != null)
                   { 
                        using (RegistryKey assemblyKey = clsidKey.OpenSubKey (typeof (TypeCacheManager).Assembly.ImageRuntimeVersion))
                        {
                            string assemblyName = null;
                            if (assemblyKey == null) 
                            {
                                keyName = null; 
                                foreach(string subKeyName in clsidKey.GetSubKeyNames()) 
                                {
                                    keyName = subKeyName; 
                                    if (String.IsNullOrEmpty (keyName))
                                        continue;
                                    using (RegistryKey assemblyKeyAny = clsidKey.OpenSubKey (keyName))
                                    { 
                                        assemblyName = (string) assemblyKeyAny.GetValue ("Assembly");
                                        if (String.IsNullOrEmpty (assemblyName)) 
                                            continue; 
                                        else
                                            break; 
                                    }
                                }
                            }
                            else 
                            {
                                assemblyName = (string) assemblyKey.GetValue ("Assembly"); 
                            } 
                            if (String.IsNullOrEmpty (assemblyName))
                                    return null; 
                            Assembly asm = Assembly.Load (assemblyName);
                            foreach (Type type in asm.GetTypes ())
                            {
                                if (type.IsClass && (type.GUID == clsid)) 
                                    return type;
                            } 
                            return null; 
                        }
                   } 

               }
               // We failed to get the hive information from a native process hive lets go for the alternative bitness
 
               using (RegistryHandle hkcr = RegistryHandle.GetBitnessHKCR (IntPtr.Size == 8 ? false : true))
               { 
                   if (hkcr != null) 
                   {
                        using (RegistryHandle clsidKey = hkcr.OpenSubKey (String.Concat ("CLSID\\{" , clsid.ToString () , "}\\InprocServer32"))) 
                        {
                            using (RegistryHandle assemblyKey = clsidKey.OpenSubKey (typeof (TypeCacheManager).Assembly.ImageRuntimeVersion))
                            {
                                string assemblyName = null; 
                                if (assemblyKey == null)
                                { 
                                    keyName = null; 
                                    foreach(string subKeyName in clsidKey.GetSubKeyNames())
                                    { 
                                        keyName = subKeyName;
                                        if (String.IsNullOrEmpty (keyName))
                                            continue;
                                        using (RegistryHandle assemblyKeyAny = clsidKey.OpenSubKey (keyName)) 
                                        {
                                            assemblyName = (string) assemblyKeyAny.GetStringValue ("Assembly"); 
                                            if (String.IsNullOrEmpty (assemblyName)) 
                                                continue;
                                            else 
                                                break;
                                        }
                                    }
                                } 
                                else
                                { 
                                    assemblyName =  assemblyKey.GetStringValue ("Assembly"); 
                                }
                                if (String.IsNullOrEmpty (assemblyName)) 
                                    return null;
                                Assembly asm = Assembly.Load (assemblyName);
                                foreach (Type type in asm.GetTypes ())
                                { 
                                    if (type.IsClass && (type.GUID == clsid))
                                        return type; 
                                } 
                                return null;
                            } 
                       }
                   }

               } 
               return null;
          } 
 
          internal Type VerifyType (Guid iid )
          { 

                Type interfaceType = null;
                ((ITypeCacheManager)(this)).FindOrCreateType (iid, out interfaceType, false, true);
                return interfaceType; 

          } 
     } 

} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK