Initial commit
[mono.git] / mcs / class / referencesource / mscorlib / system / runtime / interopservices / registrationservices.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*=============================================================================
7 **
8 ** Class: RegistrationServices
9 **
10 **
11 ** Purpose: This class provides services for registering and unregistering
12 **          a managed server for use by COM.
13 **
14 **
15 **
16 **
17 ** Change the way how to register and unregister a managed server
18 **
19 =============================================================================*/
20 namespace System.Runtime.InteropServices {
21     
22     using System;
23     using System.Collections;
24     using System.IO;
25     using System.Reflection;
26     using System.Security;
27     using System.Security.Permissions;
28     using System.Text;
29     using System.Threading;
30     using Microsoft.Win32;
31     using System.Runtime.CompilerServices;
32     using System.Globalization;
33     using System.Runtime.Versioning;
34     using System.Diagnostics.Contracts;
35
36     [Flags]
37     public enum RegistrationClassContext
38     {
39     
40  
41         InProcessServer                 = 0x1, 
42         InProcessHandler                = 0x2, 
43         LocalServer                     = 0x4, 
44         InProcessServer16               = 0x8,
45         RemoteServer                    = 0x10,
46         InProcessHandler16              = 0x20,
47         Reserved1                       = 0x40,
48         Reserved2                       = 0x80,
49         Reserved3                       = 0x100,
50         Reserved4                       = 0x200,
51         NoCodeDownload                  = 0x400,
52         Reserved5                       = 0x800,
53         NoCustomMarshal                 = 0x1000,
54         EnableCodeDownload              = 0x2000,
55         NoFailureLog                    = 0x4000,
56         DisableActivateAsActivator      = 0x8000,
57         EnableActivateAsActivator       = 0x10000,
58         FromDefaultContext              = 0x20000
59     }
60
61
62     [Flags]
63     public enum RegistrationConnectionType
64     {
65         SingleUse                = 0, 
66         MultipleUse              = 1, 
67         MultiSeparate            = 2, 
68         Suspended                = 4, 
69         Surrogate                = 8, 
70     }
71
72     [Guid("475E398F-8AFA-43a7-A3BE-F4EF8D6787C9")]
73     [ClassInterface(ClassInterfaceType.None)]
74 [System.Runtime.InteropServices.ComVisible(true)]
75     public class RegistrationServices : IRegistrationServices
76     {
77         #region Constants
78
79         private const String strManagedCategoryGuid = "{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}";
80         private const String strDocStringPrefix = "";
81         private const String strManagedTypeThreadingModel = "Both";
82         private const String strComponentCategorySubKey = "Component Categories";
83         private const String strManagedCategoryDescription = ".NET Category";
84         private const String strImplementedCategoriesSubKey = "Implemented Categories";       
85         private const String strMsCorEEFileName = "mscoree.dll";
86         private const String strRecordRootName = "Record";      
87         private const String strClsIdRootName = "CLSID";  
88         private const String strTlbRootName = "TypeLib";
89         private static Guid s_ManagedCategoryGuid = new Guid(strManagedCategoryGuid);
90
91         #endregion
92
93         
94         #region IRegistrationServices
95
96         [System.Security.SecurityCritical]  // auto-generated_required
97         [ResourceExposure(ResourceScope.None)]
98         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
99         public virtual bool RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags)
100         {
101             // Validate the arguments.
102             if (assembly == null)
103                 throw new ArgumentNullException("assembly");
104
105             if (assembly.ReflectionOnly)
106                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly"));
107             Contract.EndContractBlock();
108
109             RuntimeAssembly rtAssembly = assembly as RuntimeAssembly;
110             if (rtAssembly == null)
111                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"));
112
113             // Retrieve the assembly names.
114             String strAsmName = assembly.FullName;
115             if (strAsmName == null)
116                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoAsmName"));
117
118             // Retrieve the assembly codebase.
119             String strAsmCodeBase = null;
120             if ((flags & AssemblyRegistrationFlags.SetCodeBase) != 0)
121             {
122                 strAsmCodeBase = rtAssembly.GetCodeBase(false);
123                 if (strAsmCodeBase == null)
124                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoAsmCodeBase"));
125             }
126
127             // Go through all the registerable types in the assembly and register them.
128             Type[] aTypes = GetRegistrableTypesInAssembly(assembly);
129             int NumTypes = aTypes.Length;
130
131             String strAsmVersion = rtAssembly.GetVersion().ToString();
132             
133             // Retrieve the runtime version used to build the assembly.
134             String strRuntimeVersion = assembly.ImageRuntimeVersion;
135
136             for (int cTypes = 0; cTypes < NumTypes; cTypes++)
137             {
138                 if (IsRegisteredAsValueType(aTypes[cTypes]))
139                     RegisterValueType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion);
140                 else if (TypeRepresentsComType(aTypes[cTypes]))
141                     RegisterComImportedType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion);
142                 else
143                     RegisterManagedType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion);
144
145                 CallUserDefinedRegistrationMethod(aTypes[cTypes], true);
146             }
147
148             // If this assembly has the PIA attribute, then register it as a PIA.
149             Object[] aPIAAttrs = assembly.GetCustomAttributes(typeof(PrimaryInteropAssemblyAttribute), false);
150             int NumPIAAttrs = aPIAAttrs.Length;
151             for (int cPIAAttrs = 0; cPIAAttrs < NumPIAAttrs; cPIAAttrs++)
152                 RegisterPrimaryInteropAssembly(rtAssembly, strAsmCodeBase, (PrimaryInteropAssemblyAttribute)aPIAAttrs[cPIAAttrs]);
153
154             // Return value indicating if we actually registered any types.
155             if (aTypes.Length > 0 || NumPIAAttrs > 0)
156                 return true;
157             else 
158                 return false;
159         }
160
161         [System.Security.SecurityCritical]  // auto-generated_required
162         public virtual bool UnregisterAssembly(Assembly assembly)
163         {
164             // Validate the arguments.
165             if (assembly == null)
166                 throw new ArgumentNullException("assembly");
167
168             if (assembly.ReflectionOnly)
169                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly"));
170             Contract.EndContractBlock();
171
172             RuntimeAssembly rtAssembly = assembly as RuntimeAssembly;
173             if (rtAssembly == null)
174                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"));
175
176             bool bAllVersionsGone = true;
177
178             // Go through all the registrable types in the assembly and register them.
179             Type[] aTypes = GetRegistrableTypesInAssembly(assembly);
180             int NumTypes = aTypes.Length;
181
182             // Retrieve the assembly version
183             String strAsmVersion = rtAssembly.GetVersion().ToString();
184             for (int cTypes = 0;cTypes < NumTypes;cTypes++)
185             {
186                 CallUserDefinedRegistrationMethod(aTypes[cTypes], false);
187
188                 if (IsRegisteredAsValueType(aTypes[cTypes]))
189                 {
190                     if (!UnregisterValueType(aTypes[cTypes], strAsmVersion))
191                         bAllVersionsGone = false;
192                 }
193                 else if (TypeRepresentsComType(aTypes[cTypes]))
194                 {
195                     if (!UnregisterComImportedType(aTypes[cTypes], strAsmVersion))
196                         bAllVersionsGone = false;
197                 }
198                 else
199                 {
200                     if (!UnregisterManagedType(aTypes[cTypes], strAsmVersion))
201                         bAllVersionsGone = false;
202                 }
203             }
204
205             // If this assembly has the PIA attribute, then unregister it as a PIA.
206             Object[] aPIAAttrs = assembly.GetCustomAttributes(typeof(PrimaryInteropAssemblyAttribute),false);
207             int NumPIAAttrs = aPIAAttrs.Length;
208             if (bAllVersionsGone)
209             {
210                 for (int cPIAAttrs = 0;cPIAAttrs < NumPIAAttrs;cPIAAttrs++)
211                     UnregisterPrimaryInteropAssembly(assembly, (PrimaryInteropAssemblyAttribute)aPIAAttrs[cPIAAttrs]);
212             }
213
214             // Return value indicating if we actually un-registered any types.
215             if (aTypes.Length > 0 || NumPIAAttrs > 0)
216                 return true;
217             else 
218                 return false;
219         }
220
221         [System.Security.SecurityCritical]  // auto-generated_required
222         public virtual Type[] GetRegistrableTypesInAssembly(Assembly assembly)
223         {
224             // Validate the arguments.
225             if (assembly == null)
226                 throw new ArgumentNullException("assembly");
227             Contract.EndContractBlock();
228
229             if (!(assembly is RuntimeAssembly))
230                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "assembly");
231
232             // Retrieve the list of types in the assembly.
233             Type[] aTypes = assembly.GetExportedTypes();
234             int NumTypes = aTypes.Length;
235
236             // Create an array list that will be filled in.
237             ArrayList TypeList = new ArrayList();
238
239             // Register all the types that require registration.
240             for (int cTypes = 0; cTypes < NumTypes; cTypes++)
241             {
242                 Type CurrentType = aTypes[cTypes];
243                 if (TypeRequiresRegistration(CurrentType))
244                     TypeList.Add(CurrentType);
245             }
246
247             // Copy the array list to an array and return it.
248             Type[] RetArray = new Type[TypeList.Count];
249             TypeList.CopyTo(RetArray);
250             return RetArray;
251         }
252
253         [System.Security.SecurityCritical]  // auto-generated_required
254         public virtual String GetProgIdForType(Type type)
255         {
256             return Marshal.GenerateProgIdForType(type);
257         }
258
259         [System.Security.SecurityCritical]  // auto-generated_required
260         public virtual void RegisterTypeForComClients(Type type, ref Guid g)
261         {
262 #if FEATURE_COMINTEROP_MANAGED_ACTIVATION
263             if(type == null)
264                 throw new ArgumentNullException("type");
265             Contract.EndContractBlock();
266             if((type as RuntimeType) == null)
267                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type");
268             if(!TypeRequiresRegistration(type))
269                 throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"type");
270             
271             // Call the native method to do CoRegisterClassObject
272             RegisterTypeForComClientsNative(type, ref g);
273 #else // FEATURE_COMINTEROP_MANAGED_ACTIVATION
274             throw new NotImplementedException("CoreCLR_REMOVED -- managed activation removed"); // @
275 #endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION
276         }
277
278         public virtual Guid GetManagedCategoryGuid()
279         {
280             return s_ManagedCategoryGuid;
281         }
282
283         [System.Security.SecurityCritical]  // auto-generated_required
284         public virtual bool TypeRequiresRegistration(Type type)
285         {
286             return TypeRequiresRegistrationHelper(type);
287         }
288
289         [System.Security.SecuritySafeCritical]  // auto-generated
290         public virtual bool TypeRepresentsComType(Type type)
291         {
292             // If the type is not a COM import, then it does not represent a COM type.
293             if (!type.IsCOMObject)
294                 return false;
295
296             // If it is marked as tdImport, then it represents a COM type directly.
297             if (type.IsImport)
298                 return true;
299
300             // If the type is derived from a tdImport class and has the same GUID as the
301             // imported class, then it represents a COM type.
302             Type baseComImportType = GetBaseComImportType(type);
303             Contract.Assert(baseComImportType != null, "baseComImportType != null");
304             if (Marshal.GenerateGuidForType(type) == Marshal.GenerateGuidForType(baseComImportType))
305                 return true;
306
307             return false;
308         }
309
310         #endregion
311
312         
313         #region Public methods not on IRegistrationServices
314         [System.Security.SecurityCritical]  // auto-generated_required
315         [ComVisible(false)]
316         public virtual int RegisterTypeForComClients(Type type, RegistrationClassContext classContext, RegistrationConnectionType flags)
317         {
318 #if FEATURE_COMINTEROP_MANAGED_ACTIVATION
319             if (type == null)
320                 throw new ArgumentNullException("type");
321             Contract.EndContractBlock();
322             if ((type as RuntimeType) == null)
323                 throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type");
324             if (!TypeRequiresRegistration(type))
325                 throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"type");
326             
327             // Call the native method to do CoRegisterClassObject
328             return RegisterTypeForComClientsExNative(type, classContext, flags);
329 #else // FEATURE_COMINTEROP_MANAGED_ACTIVATION
330             throw new NotImplementedException("CoreCLR_REMOVED -- managed activation removed"); // @
331 #endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION
332         }
333
334         [System.Security.SecurityCritical]  // auto-generated_required
335         [ComVisible(false)]
336         public virtual void UnregisterTypeForComClients(int cookie)
337         {
338             // Call the native method to do CoRevokeClassObject.
339             CoRevokeClassObject(cookie);
340         }
341
342         #endregion
343
344
345         #region Internal helpers
346
347         [System.Security.SecurityCritical]  // auto-generated_required
348         internal static bool TypeRequiresRegistrationHelper(Type type)
349         {
350             // If the type is not a class or a value class, then it does not get registered.
351             if (!type.IsClass && !type.IsValueType)
352                 return false;
353
354             // If the type is abstract then it does not get registered.
355             if (type.IsAbstract)
356                 return false;
357
358             // If the does not have a public default constructor then is not creatable from COM so 
359             // it does not require registration unless it is a value class.
360             if (!type.IsValueType && type.GetConstructor(BindingFlags.Instance | BindingFlags.Public,null,new Type[0],null) == null)
361                 return false;
362
363             // All other conditions are met so check to see if the type is visible from COM.
364             return Marshal.IsTypeVisibleFromCom(type);
365         }
366
367         #endregion
368
369
370         #region Private helpers
371
372         [System.Security.SecurityCritical]  // auto-generated
373         [ResourceExposure(ResourceScope.Machine)]
374         [ResourceConsumption(ResourceScope.Machine)]
375         private void RegisterValueType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion)
376         {
377             // Retrieve some information that will be used during the registration process.
378             String strRecordId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";           
379
380             // Create the HKEY_CLASS_ROOT\Record key.
381             using (RegistryKey RecordRootKey = Registry.ClassesRoot.CreateSubKey(strRecordRootName))
382             {
383                 // Create the HKEY_CLASS_ROOT\Record\<RecordID> key.
384                 using (RegistryKey RecordKey = RecordRootKey.CreateSubKey(strRecordId))
385                 {
386                     // Create the HKEY_CLASS_ROOT\Record\<RecordId>\<version> key.
387                     using (RegistryKey RecordVersionKey = RecordKey.CreateSubKey(strAsmVersion))
388                     {                   
389                         // Set the class value.
390                         RecordVersionKey.SetValue("Class", type.FullName);
391
392                         // Set the assembly value.
393                         RecordVersionKey.SetValue("Assembly", strAsmName);
394
395                         // Set the runtime version value.
396                         RecordVersionKey.SetValue("RuntimeVersion", strRuntimeVersion);
397
398                         // Set the assembly code base value if a code base was specified.
399                         if (strAsmCodeBase != null)
400                             RecordVersionKey.SetValue("CodeBase", strAsmCodeBase);
401                     }
402                 }
403             }
404         }
405
406         [System.Security.SecurityCritical]  // auto-generated
407         [ResourceExposure(ResourceScope.Machine)]
408         [ResourceConsumption(ResourceScope.Machine)]
409         private void RegisterManagedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion)
410         {
411             //
412             // Retrieve some information that will be used during the registration process.
413             //
414
415             String strDocString = strDocStringPrefix + type.FullName;
416             String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
417             String strProgId = GetProgIdForType(type);
418
419
420             //
421             // Write the actual type information in the registry.
422             //
423
424             if (strProgId != String.Empty)
425             {
426                 // Create the HKEY_CLASS_ROOT\<wzProgId> key.
427                 using (RegistryKey TypeNameKey = Registry.ClassesRoot.CreateSubKey(strProgId))
428                 {
429                     TypeNameKey.SetValue("", strDocString);
430
431                     // Create the HKEY_CLASS_ROOT\<wzProgId>\CLSID key.
432                     using (RegistryKey ProgIdClsIdKey = TypeNameKey.CreateSubKey("CLSID"))
433                     {
434                         ProgIdClsIdKey.SetValue("", strClsId);
435                     }
436                 }
437             }
438
439             // Create the HKEY_CLASS_ROOT\CLSID key.
440             using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.CreateSubKey(strClsIdRootName))
441             {           
442                 // Create the HKEY_CLASS_ROOT\CLSID\<CLSID> key.
443                 using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId))
444                 {
445                     ClsIdKey.SetValue("", strDocString);
446
447                     // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32 key.
448                     using (RegistryKey InProcServerKey = ClsIdKey.CreateSubKey("InprocServer32"))
449                     {
450                         InProcServerKey.SetValue("", strMsCorEEFileName);
451                         InProcServerKey.SetValue("ThreadingModel", strManagedTypeThreadingModel);
452                         InProcServerKey.SetValue("Class", type.FullName);
453                         InProcServerKey.SetValue("Assembly", strAsmName);
454                         InProcServerKey.SetValue("RuntimeVersion", strRuntimeVersion);
455                         if (strAsmCodeBase != null)
456                             InProcServerKey.SetValue("CodeBase", strAsmCodeBase);
457
458                         // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32\<Version> subkey
459                         using (RegistryKey VersionSubKey = InProcServerKey.CreateSubKey(strAsmVersion))
460                         {
461                             VersionSubKey.SetValue("Class", type.FullName);
462                             VersionSubKey.SetValue("Assembly", strAsmName);
463                             VersionSubKey.SetValue("RuntimeVersion", strRuntimeVersion);
464                             if (strAsmCodeBase != null)
465                                 VersionSubKey.SetValue("CodeBase", strAsmCodeBase);
466                         }
467
468                         if (strProgId != String.Empty)
469                         {
470                             // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\ProdId key.
471                             using (RegistryKey ProgIdKey = ClsIdKey.CreateSubKey("ProgId"))
472                             {
473                                 ProgIdKey.SetValue("", strProgId);
474                             }
475                         }
476                     }
477
478                     // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\Implemented Categories\<Managed Category Guid> key.
479                     using (RegistryKey CategoryKey = ClsIdKey.CreateSubKey(strImplementedCategoriesSubKey))
480                     {
481                         using (RegistryKey ManagedCategoryKey = CategoryKey.CreateSubKey(strManagedCategoryGuid)) {}
482                     }
483                 }
484             }
485
486
487             //
488             // Ensure that the managed category exists.
489             //
490
491             EnsureManagedCategoryExists();
492         } 
493         
494         [System.Security.SecurityCritical]  // auto-generated
495         [ResourceExposure(ResourceScope.Machine)]
496         [ResourceConsumption(ResourceScope.Machine)]
497         private void RegisterComImportedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion)
498         {
499             // Retrieve some information that will be used during the registration process.
500             String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
501
502             // Create the HKEY_CLASS_ROOT\CLSID key.
503             using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.CreateSubKey(strClsIdRootName))
504             {
505                 // Create the HKEY_CLASS_ROOT\CLSID\<CLSID> key.
506                 using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId))
507                 {
508                     // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InProcServer32 key.
509                     using (RegistryKey InProcServerKey = ClsIdKey.CreateSubKey("InprocServer32"))
510                     {              
511                         // Set the class value.
512                         InProcServerKey.SetValue("Class", type.FullName);
513
514                         // Set the assembly value.
515                         InProcServerKey.SetValue("Assembly", strAsmName);
516
517                         // Set the runtime version value.
518                         InProcServerKey.SetValue("RuntimeVersion", strRuntimeVersion);
519
520                         // Set the assembly code base value if a code base was specified.
521                         if (strAsmCodeBase != null)
522                             InProcServerKey.SetValue("CodeBase", strAsmCodeBase);
523
524                         // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32\<Version> subkey
525                         using (RegistryKey VersionSubKey = InProcServerKey.CreateSubKey(strAsmVersion))
526                         {
527                             VersionSubKey.SetValue("Class", type.FullName);
528                             VersionSubKey.SetValue("Assembly", strAsmName);
529                             VersionSubKey.SetValue("RuntimeVersion", strRuntimeVersion);
530                             if (strAsmCodeBase != null)
531                                 VersionSubKey.SetValue("CodeBase", strAsmCodeBase);
532                         }
533                     }
534                 }
535             }
536         }
537
538         [System.Security.SecurityCritical]  // auto-generated
539         [ResourceExposure(ResourceScope.None)]
540         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
541         private bool UnregisterValueType(Type type, String strAsmVersion)
542         {
543             bool bAllVersionsGone = true;
544
545             // Try to open the HKEY_CLASS_ROOT\Record key.
546             String strRecordId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
547             
548             using (RegistryKey RecordRootKey = Registry.ClassesRoot.OpenSubKey(strRecordRootName, true))
549             {
550                 if (RecordRootKey != null)
551                 {
552                     // Open the HKEY_CLASS_ROOT\Record\{RecordId} key.
553                     using (RegistryKey RecordKey = RecordRootKey.OpenSubKey(strRecordId,true))
554                     {
555                         if (RecordKey != null)
556                         {
557                             using (RegistryKey VersionSubKey = RecordKey.OpenSubKey(strAsmVersion,true))
558                             {
559                                 if (VersionSubKey != null)
560                                 {
561                                     // Delete the values we created.
562                                     VersionSubKey.DeleteValue("Assembly",false);
563                                     VersionSubKey.DeleteValue("Class",false);
564                                     VersionSubKey.DeleteValue("CodeBase",false);
565                                     VersionSubKey.DeleteValue("RuntimeVersion",false);
566
567                                     // delete the version sub key if no value or subkeys under it
568                                     if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0))
569                                         RecordKey.DeleteSubKey(strAsmVersion);
570                                 }
571                             }
572
573                             // If there are sub keys left then there are versions left.
574                             if (RecordKey.SubKeyCount != 0)
575                                 bAllVersionsGone = false;
576
577                             // If there are no other values or subkeys then we can delete the HKEY_CLASS_ROOT\Record\{RecordId}.
578                             if ((RecordKey.SubKeyCount == 0) && (RecordKey.ValueCount == 0))
579                                 RecordRootKey.DeleteSubKey(strRecordId);
580                         }
581                     }
582
583                     // If there are no other values or subkeys then we can delete the HKEY_CLASS_ROOT\Record.
584                     if ((RecordRootKey.SubKeyCount == 0) && (RecordRootKey.ValueCount == 0))
585                         Registry.ClassesRoot.DeleteSubKey(strRecordRootName);
586                 }
587             }
588
589             return bAllVersionsGone;
590         }
591
592         // UnregisterManagedType
593         //
594         // Return :
595         //      true:   All versions are gone.
596         //      false:  Some versions are still left in registry
597         [System.Security.SecurityCritical]  // auto-generated
598         [ResourceExposure(ResourceScope.None)]
599         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
600         private bool UnregisterManagedType(Type type,String strAsmVersion)
601         {
602             bool bAllVersionsGone = true;
603             
604             //
605             // Create the CLSID string.
606             //
607
608             String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
609             String strProgId = GetProgIdForType(type);
610
611
612             //
613             // Remove the entries under HKEY_CLASS_ROOT\CLSID key.
614             //
615
616             using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.OpenSubKey(strClsIdRootName, true))
617             {
618                 if (ClsIdRootKey != null)
619                 {
620                     //
621                     // Remove the entries under HKEY_CLASS_ROOT\CLSID\<CLSID> key.
622                     //
623
624                     using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true))
625                     {
626                         if (ClsIdKey != null)
627                         {
628                             //
629                             // Remove the entries in the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32 key.
630                             //
631
632                             using (RegistryKey InProcServerKey = ClsIdKey.OpenSubKey("InprocServer32", true))
633                             {
634                                 if (InProcServerKey != null)
635                                 {
636                                     //
637                                     // Remove the entries in HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32\<Version>
638                                     //
639
640                                     using (RegistryKey VersionSubKey = InProcServerKey.OpenSubKey(strAsmVersion, true))
641                                     {
642                                         if (VersionSubKey != null)
643                                         {
644                                             // Delete the values we created
645                                             VersionSubKey.DeleteValue("Assembly",false);
646                                             VersionSubKey.DeleteValue("Class",false);
647                                             VersionSubKey.DeleteValue("RuntimeVersion",false);
648                                             VersionSubKey.DeleteValue("CodeBase",false);
649
650                                             // If there are no other values or subkeys then we can delete the VersionSubKey.
651                                             if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0))
652                                                 InProcServerKey.DeleteSubKey(strAsmVersion);
653                                         }
654                                     }
655
656                                     // If there are sub keys left then there are versions left.
657                                     if (InProcServerKey.SubKeyCount != 0)
658                                         bAllVersionsGone = false;
659
660                                     // If there are no versions left, then delete the threading model and default value.
661                                     if (bAllVersionsGone)
662                                     {
663                                         InProcServerKey.DeleteValue("",false);
664                                         InProcServerKey.DeleteValue("ThreadingModel",false);
665                                     }
666
667                                     InProcServerKey.DeleteValue("Assembly",false);
668                                     InProcServerKey.DeleteValue("Class",false);
669                                     InProcServerKey.DeleteValue("RuntimeVersion",false);
670                                     InProcServerKey.DeleteValue("CodeBase",false);
671
672                                     // If there are no other values or subkeys then we can delete the InProcServerKey.
673                                     if ((InProcServerKey.SubKeyCount == 0) && (InProcServerKey.ValueCount == 0))
674                                         ClsIdKey.DeleteSubKey("InprocServer32");
675                                 }
676                             }
677
678                             // remove HKEY_CLASS_ROOT\CLSID\<CLSID>\ProgId
679                             // and HKEY_CLASS_ROOT\CLSID\<CLSID>\Implemented Category
680                             // only when all versions are removed
681                             if (bAllVersionsGone)
682                             {
683                                 // Delete the value we created.
684                                 ClsIdKey.DeleteValue("",false);
685
686                                 if (strProgId != String.Empty)
687                                 {
688                                     //
689                                     // Remove the entries in the HKEY_CLASS_ROOT\CLSID\<CLSID>\ProgId key.
690                                     //
691
692                                     using (RegistryKey ProgIdKey = ClsIdKey.OpenSubKey("ProgId", true))
693                                     {
694                                         if (ProgIdKey != null)
695                                         {
696                                             // Delete the value we created.
697                                             ProgIdKey.DeleteValue("",false);
698
699                                             // If there are no other values or subkeys then we can delete the ProgIdSubKey.
700                                             if ((ProgIdKey.SubKeyCount == 0) && (ProgIdKey.ValueCount == 0))
701                                                 ClsIdKey.DeleteSubKey("ProgId");
702                                         }
703                                     }
704                                 }
705                 
706             
707                                 //
708                                 // Remove entries in the  HKEY_CLASS_ROOT\CLSID\<CLSID>\Implemented Categories\<Managed Category Guid> key.
709                                 //
710         
711                                 using (RegistryKey CategoryKey = ClsIdKey.OpenSubKey(strImplementedCategoriesSubKey, true))
712                                 {
713                                     if (CategoryKey != null)
714                                     {
715                                         using (RegistryKey ManagedCategoryKey = CategoryKey.OpenSubKey(strManagedCategoryGuid, true))
716                                         {
717                                             if (ManagedCategoryKey != null)
718                                             {
719                                                 // If there are no other values or subkeys then we can delete the ManagedCategoryKey.
720                                                 if ((ManagedCategoryKey.SubKeyCount == 0) && (ManagedCategoryKey.ValueCount == 0))
721                                                     CategoryKey.DeleteSubKey(strManagedCategoryGuid);
722                                             }
723                                         }
724
725                                         // If there are no other values or subkeys then we can delete the CategoryKey.
726                                         if ((CategoryKey.SubKeyCount == 0) && (CategoryKey.ValueCount == 0))
727                                             ClsIdKey.DeleteSubKey(strImplementedCategoriesSubKey);
728                                     }
729                                 }
730                             }
731
732                             // If there are no other values or subkeys then we can delete the ClsIdKey.
733                             if ((ClsIdKey.SubKeyCount == 0) && (ClsIdKey.ValueCount == 0))
734                                 ClsIdRootKey.DeleteSubKey(strClsId);
735                         }
736                     }
737
738                     // If there are no other values or subkeys then we can delete the CLSID key.
739                     if ((ClsIdRootKey.SubKeyCount == 0) && (ClsIdRootKey.ValueCount == 0))
740                         Registry.ClassesRoot.DeleteSubKey(strClsIdRootName);
741                 }
742             
743
744                 //
745                 // Remove the entries under HKEY_CLASS_ROOT\<wzProgId> key.
746                 //
747
748                 if (bAllVersionsGone)
749                 {
750                     if (strProgId != String.Empty)
751                     {
752                         using (RegistryKey TypeNameKey = Registry.ClassesRoot.OpenSubKey(strProgId, true))
753                         {                            
754                             if (TypeNameKey != null)
755                             {
756                                 // Delete the values we created.
757                                 TypeNameKey.DeleteValue("",false);
758
759
760                                 //
761                                 // Remove the entries in the HKEY_CLASS_ROOT\<wzProgId>\CLSID key.
762                                 //
763
764                                 using (RegistryKey ProgIdClsIdKey = TypeNameKey.OpenSubKey("CLSID", true))
765                                 {
766                                     if (ProgIdClsIdKey != null)
767                                     {
768                                         // Delete the values we created.
769                                         ProgIdClsIdKey.DeleteValue("",false);
770
771                                         // If there are no other values or subkeys then we can delete the ProgIdClsIdKey.
772                                         if ((ProgIdClsIdKey.SubKeyCount == 0) && (ProgIdClsIdKey.ValueCount == 0))
773                                             TypeNameKey.DeleteSubKey("CLSID");
774                                     }
775                                 }
776
777                                 // If there are no other values or subkeys then we can delete the TypeNameKey.
778                                 if ((TypeNameKey.SubKeyCount == 0) && (TypeNameKey.ValueCount == 0))
779                                     Registry.ClassesRoot.DeleteSubKey(strProgId);
780                             }
781                         }
782                     }
783                 }
784             }
785
786             return bAllVersionsGone;
787         }
788
789         // UnregisterComImportedType
790         // Return:
791         //      true:      All version information are gone.
792         //      false:     There are still some version left in registry
793         [System.Security.SecurityCritical]  // auto-generated
794         [ResourceExposure(ResourceScope.None)]
795         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
796         private bool UnregisterComImportedType(Type type, String strAsmVersion)
797         {
798             bool bAllVersionsGone = true;
799             
800             String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
801         
802             // Try to open the HKEY_CLASS_ROOT\CLSID key.
803             using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.OpenSubKey(strClsIdRootName, true))
804             {
805                 if (ClsIdRootKey != null)
806                 {
807                     // Try to open the HKEY_CLASS_ROOT\CLSID\<CLSID> key.
808                     using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true))
809                     {
810                         if (ClsIdKey != null)
811                         {
812                             // Try to open the HKEY_CLASS_ROOT\CLSID\<CLSID>\InProcServer32 key.
813                             using (RegistryKey InProcServerKey = ClsIdKey.OpenSubKey("InprocServer32", true))
814                             {
815                                 if (InProcServerKey != null)
816                                 {
817                                     // Delete the values we created.
818                                     InProcServerKey.DeleteValue("Assembly",false);
819                                     InProcServerKey.DeleteValue("Class",false);
820                                     InProcServerKey.DeleteValue("RuntimeVersion",false);
821                                     InProcServerKey.DeleteValue("CodeBase",false);
822                                 
823                                     // Try to open the entries in HKEY_CLASS_ROOT\CLSID\<CLSID>\InProcServer32\<Version>
824                                     using (RegistryKey VersionSubKey = InProcServerKey.OpenSubKey(strAsmVersion,true))
825                                     {
826                                         if (VersionSubKey != null)
827                                         {
828                                             // Delete the value we created
829                                             VersionSubKey.DeleteValue("Assembly",false);
830                                             VersionSubKey.DeleteValue("Class",false);
831                                             VersionSubKey.DeleteValue("RuntimeVersion",false);
832                                             VersionSubKey.DeleteValue("CodeBase",false);
833
834                                             // If there are no other values or subkeys then we can delete the VersionSubKey
835                                             if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0))
836                                                 InProcServerKey.DeleteSubKey(strAsmVersion);
837                                         }
838                                     }
839
840                                     // If there are sub keys left then there are versions left.
841                                     if (InProcServerKey.SubKeyCount != 0)
842                                         bAllVersionsGone = false;
843
844                                     // If there are no other values or subkeys then we can delete the InProcServerKey.
845                                     if ((InProcServerKey.SubKeyCount == 0) && (InProcServerKey.ValueCount == 0))
846                                         ClsIdKey.DeleteSubKey("InprocServer32");
847                                 }
848                             }
849
850                             // If there are no other values or subkeys then we can delete the ClsIdKey.
851                             if ((ClsIdKey.SubKeyCount == 0) && (ClsIdKey.ValueCount == 0))
852                                 ClsIdRootKey.DeleteSubKey(strClsId);                            
853                         }                       
854                     }
855
856                     // If there are no other values or subkeys then we can delete the CLSID key.
857                     if ((ClsIdRootKey.SubKeyCount == 0) && (ClsIdRootKey.ValueCount == 0))
858                         Registry.ClassesRoot.DeleteSubKey(strClsIdRootName);                    
859                 }
860             }
861
862             return bAllVersionsGone;
863         }
864
865         [System.Security.SecurityCritical]  // auto-generated
866         [ResourceExposure(ResourceScope.Machine)]
867         [ResourceConsumption(ResourceScope.Machine)]
868         private void RegisterPrimaryInteropAssembly(RuntimeAssembly assembly, String strAsmCodeBase, PrimaryInteropAssemblyAttribute attr)
869         {
870             // Validate that the PIA has a strong name.
871             if (assembly.GetPublicKey().Length == 0)
872                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_PIAMustBeStrongNamed"));
873
874             String strTlbId = "{" + Marshal.GetTypeLibGuidForAssembly(assembly).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
875             String strVersion = attr.MajorVersion.ToString("x", CultureInfo.InvariantCulture) + "." + attr.MinorVersion.ToString("x", CultureInfo.InvariantCulture);
876
877             // Create the HKEY_CLASS_ROOT\TypeLib key.
878             using (RegistryKey TypeLibRootKey = Registry.ClassesRoot.CreateSubKey(strTlbRootName))
879             {
880                 // Create the HKEY_CLASS_ROOT\TypeLib\<TLBID> key.
881                 using (RegistryKey TypeLibKey = TypeLibRootKey.CreateSubKey(strTlbId))
882                 {
883                     // Create the HKEY_CLASS_ROOT\TypeLib\<TLBID>\<Major.Minor> key.
884                     using (RegistryKey VersionSubKey = TypeLibKey.CreateSubKey(strVersion))
885                     {
886                         // Create the HKEY_CLASS_ROOT\TypeLib\<TLBID>\PrimaryInteropAssembly key.
887                         VersionSubKey.SetValue("PrimaryInteropAssemblyName", assembly.FullName);
888                         if (strAsmCodeBase != null)
889                             VersionSubKey.SetValue("PrimaryInteropAssemblyCodeBase", strAsmCodeBase);
890                     }
891                 }
892             }
893         }
894
895         [System.Security.SecurityCritical]  // auto-generated
896         [ResourceExposure(ResourceScope.None)]
897         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
898         private void UnregisterPrimaryInteropAssembly(Assembly assembly, PrimaryInteropAssemblyAttribute attr)
899         {
900             String strTlbId = "{" + Marshal.GetTypeLibGuidForAssembly(assembly).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
901             String strVersion = attr.MajorVersion.ToString("x", CultureInfo.InvariantCulture) + "." + attr.MinorVersion.ToString("x", CultureInfo.InvariantCulture);
902
903             // Try to open the HKEY_CLASS_ROOT\TypeLib key.
904             using (RegistryKey TypeLibRootKey = Registry.ClassesRoot.OpenSubKey(strTlbRootName, true))
905             {
906                 if (TypeLibRootKey != null)
907                 {
908                     // Try to open the HKEY_CLASS_ROOT\TypeLib\<TLBID> key.
909                     using (RegistryKey TypeLibKey = TypeLibRootKey.OpenSubKey(strTlbId, true))
910                     {
911                         if (TypeLibKey != null)
912                         {
913                             // Try to open the HKEY_CLASS_ROOT\TypeLib<TLBID>\<Major.Minor> key.
914                             using (RegistryKey VersionSubKey = TypeLibKey.OpenSubKey(strVersion, true))
915                             {
916                                 if (VersionSubKey != null)
917                                 {
918                                     // Delete the values we created.
919                                     VersionSubKey.DeleteValue("PrimaryInteropAssemblyName",false);
920                                     VersionSubKey.DeleteValue("PrimaryInteropAssemblyCodeBase",false);
921
922                                     // If there are no other values or subkeys then we can delete the VersionKey.
923                                     if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0))
924                                         TypeLibKey.DeleteSubKey(strVersion);
925                                 }
926                             }
927
928                             // If there are no other values or subkeys then we can delete the TypeLibKey.
929                             if ((TypeLibKey.SubKeyCount == 0) && (TypeLibKey.ValueCount == 0))
930                                 TypeLibRootKey.DeleteSubKey(strTlbId);                            
931                         }
932                     }
933
934                     // If there are no other values or subkeys then we can delete the TypeLib key.
935                     if ((TypeLibRootKey.SubKeyCount == 0) && (TypeLibRootKey.ValueCount == 0))
936                         Registry.ClassesRoot.DeleteSubKey(strTlbRootName);                    
937                 }
938             }
939         }
940
941         [ResourceExposure(ResourceScope.None)]
942         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
943         private void EnsureManagedCategoryExists()
944         {
945             if (!ManagedCategoryExists())
946             {
947                 // Create the HKEY_CLASS_ROOT\Component Category key.
948                 using (RegistryKey ComponentCategoryKey = Registry.ClassesRoot.CreateSubKey(strComponentCategorySubKey))
949                 {
950                     // Create the HKEY_CLASS_ROOT\Component Category\<Managed Category Guid> key.
951                     using (RegistryKey ManagedCategoryKey = ComponentCategoryKey.CreateSubKey(strManagedCategoryGuid))
952                     {
953                         ManagedCategoryKey.SetValue("0", strManagedCategoryDescription);
954                     }
955                 }
956             }
957         }
958
959         [ResourceExposure(ResourceScope.None)]
960         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
961         private static bool ManagedCategoryExists()
962         {
963             using (RegistryKey componentCategoryKey = Registry.ClassesRoot.OpenSubKey(strComponentCategorySubKey, 
964 #if FEATURE_MACL
965                                                                                       RegistryKeyPermissionCheck.ReadSubTree))
966 #else
967                                                                                       false))
968 #endif
969             {
970                 if (componentCategoryKey == null)
971                     return false;
972                 using (RegistryKey managedCategoryKey = componentCategoryKey.OpenSubKey(strManagedCategoryGuid,
973 #if FEATURE_MACL
974                                                                                         RegistryKeyPermissionCheck.ReadSubTree))
975 #else
976                                                                                         false))
977 #endif
978                 {
979                     if (managedCategoryKey == null)
980                         return false;
981                     object value = managedCategoryKey.GetValue("0");
982                     if (value == null || value.GetType() != typeof(string))
983                         return false;
984                     string stringValue = (string)value;
985                     if (stringValue != strManagedCategoryDescription)
986                         return false;
987                 }
988             }
989             
990             return true;
991         }
992         
993         [System.Security.SecurityCritical]  // auto-generated
994         private void CallUserDefinedRegistrationMethod(Type type, bool bRegister)
995         {
996             bool bFunctionCalled = false;
997
998             // Retrieve the attribute type to use to determine if a function is the requested user defined
999             // registration function.
1000             Type RegFuncAttrType = null;
1001             if(bRegister)
1002                 RegFuncAttrType = typeof(ComRegisterFunctionAttribute);
1003             else 
1004                 RegFuncAttrType = typeof(ComUnregisterFunctionAttribute);
1005
1006             for(Type currType = type; !bFunctionCalled && currType != null; currType = currType.BaseType)
1007             {
1008                 // Retrieve all the methods.
1009                 MethodInfo[] aMethods = currType.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static);
1010                 int NumMethods = aMethods.Length;
1011
1012                 // Go through all the methods and check for the ComRegisterMethod custom attribute.
1013                 for(int cMethods = 0;cMethods < NumMethods;cMethods++)
1014                 {
1015                     MethodInfo CurrentMethod = aMethods[cMethods];
1016
1017                     // Check to see if the method has the custom attribute.
1018                     if(CurrentMethod.GetCustomAttributes(RegFuncAttrType, true).Length != 0)
1019                     {
1020                         // Check to see if the method is static before we call it.
1021                         if(!CurrentMethod.IsStatic)
1022                         {
1023                             if(bRegister)
1024                                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NonStaticComRegFunction",CurrentMethod.Name,currType.Name));
1025                             else
1026                                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NonStaticComUnRegFunction",CurrentMethod.Name,currType.Name));
1027                         }
1028
1029                         // Finally check that the signature is string ret void.
1030                         ParameterInfo[] aParams = CurrentMethod.GetParameters();
1031                         if (CurrentMethod.ReturnType != typeof(void) || 
1032                             aParams == null ||
1033                             aParams.Length != 1 || 
1034                             (aParams[0].ParameterType != typeof(String) && aParams[0].ParameterType != typeof(Type)))
1035                         {
1036                             if(bRegister)
1037                                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_InvalidComRegFunctionSig",CurrentMethod.Name,currType.Name));
1038                             else
1039                                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_InvalidComUnRegFunctionSig",CurrentMethod.Name,currType.Name));
1040                         }
1041
1042                         // There can only be one register and one unregister function per type.
1043                         if(bFunctionCalled)
1044                         {
1045                             if(bRegister)
1046                                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MultipleComRegFunctions",currType.Name));
1047                             else
1048                                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MultipleComUnRegFunctions",currType.Name));
1049                         }
1050
1051                         // The function is valid so set up the arguments to call it.
1052                         Object[] objs = new Object[1];
1053                         if(aParams[0].ParameterType == typeof(String))
1054                         {
1055                             // We are dealing with the string overload of the function.
1056                             objs[0] = "HKEY_CLASSES_ROOT\\CLSID\\{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
1057                         }
1058                         else
1059                         {
1060                             // We are dealing with the type overload of the function.
1061                             objs[0] = type;
1062                         }
1063
1064                         // Invoke the COM register function.
1065                         CurrentMethod.Invoke(null, objs);
1066
1067                         // Mark the function as having been called.
1068                         bFunctionCalled = true;
1069                     }
1070                 }
1071             }
1072         }
1073
1074         private Type GetBaseComImportType(Type type)
1075         {
1076             for (; type != null && !type.IsImport; type = type.BaseType);
1077             return type;
1078         }
1079
1080         private bool IsRegisteredAsValueType(Type type)
1081         {
1082             if (!type.IsValueType)
1083                 return false;
1084
1085             return true;
1086         }
1087
1088         #endregion
1089
1090     
1091         #region FCalls and DllImports
1092
1093 #if FEATURE_COMINTEROP_MANAGED_ACTIVATION
1094         // GUID versioning can be controlled by using the GuidAttribute or 
1095         // letting the runtime generate it based on type and assembly strong name.
1096         [System.Security.SecurityCritical]  // auto-generated
1097         [ResourceExposure(ResourceScope.None)]
1098         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1099         private static extern void RegisterTypeForComClientsNative(Type type,ref Guid g);
1100         
1101         // GUID versioning can be controlled by using the GuidAttribute or 
1102         // letting the runtime generate it based on type and assembly strong name.
1103         [System.Security.SecurityCritical]  // auto-generated
1104         [ResourceExposure(ResourceScope.None)]
1105         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1106         private static extern int RegisterTypeForComClientsExNative(Type t, RegistrationClassContext clsContext, RegistrationConnectionType flags);
1107 #endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION
1108
1109         [DllImport(Win32Native.OLE32,CharSet=CharSet.Auto,PreserveSig=false)]
1110         [ResourceExposure(ResourceScope.None)]
1111         private static extern void CoRevokeClassObject(int cookie);
1112         #endregion
1113     }
1114 }