7
7
using System . Diagnostics . CodeAnalysis ;
8
8
using System . IO ;
9
9
using System . Reflection ;
10
+ using System . Runtime . CompilerServices ;
10
11
using System . Runtime . InteropServices ;
11
12
using System . Runtime . Loader ;
12
13
using System . Runtime . Versioning ;
@@ -616,7 +617,6 @@ public void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock)
616
617
[ RequiresUnreferencedCode ( "Built-in COM support is not trim compatible" , Url = "https://aka.ms/dotnet-illink/com" ) ]
617
618
private sealed class LicenseClassFactory : IClassFactory2
618
619
{
619
- private readonly LicenseInteropProxy _licenseProxy = new LicenseInteropProxy ( ) ;
620
620
private readonly Guid _classId ;
621
621
622
622
[ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . Interfaces | DynamicallyAccessedMemberTypes . PublicConstructors ) ]
@@ -643,7 +643,7 @@ public void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock)
643
643
644
644
public void GetLicInfo ( ref LICINFO licInfo )
645
645
{
646
- _licenseProxy . GetLicInfo ( _classType , out bool runtimeKeyAvail , out bool licVerified ) ;
646
+ LicenseInteropProxy . GetLicInfo ( _classType , out bool runtimeKeyAvail , out bool licVerified ) ;
647
647
648
648
// The LICINFO is a struct with a DWORD size field and two BOOL fields. Each BOOL
649
649
// is typedef'd from a DWORD, therefore the size is manually computed as below.
@@ -654,7 +654,7 @@ public void GetLicInfo(ref LICINFO licInfo)
654
654
655
655
public void RequestLicKey ( int dwReserved , [ MarshalAs ( UnmanagedType . BStr ) ] out string pBstrKey )
656
656
{
657
- pBstrKey = _licenseProxy . RequestLicKey ( _classType ) ;
657
+ pBstrKey = LicenseInteropProxy . RequestLicKey ( _classType ) ;
658
658
}
659
659
660
660
public void CreateInstanceLic (
@@ -677,7 +677,7 @@ private void CreateInstanceInner(
677
677
{
678
678
var interfaceType = BasicClassFactory . CreateValidatedInterfaceType ( _classType , ref riid , pUnkOuter ) ;
679
679
680
- object obj = _licenseProxy . AllocateAndValidateLicense ( _classType , key , isDesignTime ) ;
680
+ object obj = LicenseInteropProxy . AllocateAndValidateLicense ( _classType , key , isDesignTime ) ;
681
681
if ( pUnkOuter != null )
682
682
{
683
683
obj = BasicClassFactory . CreateAggregatedObject ( pUnkOuter , obj ) ;
@@ -699,51 +699,68 @@ internal sealed class LicenseInteropProxy
699
699
private static readonly Type ? s_licenseAttrType = Type . GetType ( "System.ComponentModel.LicenseProviderAttribute, System.ComponentModel.TypeConverter" , throwOnError : false ) ;
700
700
private static readonly Type ? s_licenseExceptionType = Type . GetType ( "System.ComponentModel.LicenseException, System.ComponentModel.TypeConverter" , throwOnError : false ) ;
701
701
702
- // LicenseManager
703
- private readonly MethodInfo _createWithContext ;
704
-
705
- // LicenseInteropHelper
706
- private readonly MethodInfo _validateTypeAndReturnDetails ;
707
- private readonly MethodInfo _getCurrentContextInfo ;
708
-
709
- // CLRLicenseContext
710
- private readonly MethodInfo _createDesignContext ;
711
- private readonly MethodInfo _createRuntimeContext ;
712
-
713
- // LicenseContext
714
- private readonly MethodInfo _setSavedLicenseKey ;
715
-
716
- [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicMethods | DynamicallyAccessedMemberTypes . PublicParameterlessConstructor ) ]
717
- private readonly Type _licInfoHelper ;
718
-
719
- private readonly MethodInfo _licInfoHelperContains ;
702
+ private const string LicenseManagerTypeName = "System.ComponentModel.LicenseManager, System.ComponentModel.TypeConverter" ;
703
+ private const string LicenseContextTypeName = "System.ComponentModel.LicenseContext, System.ComponentModel.TypeConverter" ;
704
+ private const string LicenseInteropHelperTypeName = "System.ComponentModel.LicenseManager+LicenseInteropHelper, System.ComponentModel.TypeConverter" ;
705
+ private const string CLRLicenseContextTypeName = "System.ComponentModel.LicenseManager+CLRLicenseContext, System.ComponentModel.TypeConverter" ;
706
+ private const string LicenseRefTypeName = "System.ComponentModel.License&, System.ComponentModel.TypeConverter" ;
707
+ private const string LicInfoHelperLicenseContextTypeName = "System.ComponentModel.LicenseManager+LicInfoHelperLicenseContext, System.ComponentModel.TypeConverter" ;
720
708
721
709
// RCW Activation
722
710
private object ? _licContext ;
723
711
private Type ? _targetRcwType ;
724
712
725
- [ UnconditionalSuppressMessage ( "ReflectionAnalysis" , "IL2111:ReflectionToDynamicallyAccessedMembers" ,
726
- Justification = "The type parameter to LicenseManager.CreateWithContext method has PublicConstructors annotation. We only invoke this method" +
727
- "from AllocateAndValidateLicense which annotates the value passed in with the same annotation." ) ]
728
- public LicenseInteropProxy ( )
729
- {
730
- Type licManager = Type . GetType ( "System.ComponentModel.LicenseManager, System.ComponentModel.TypeConverter" , throwOnError : true ) ! ;
731
-
732
- Type licContext = Type . GetType ( "System.ComponentModel.LicenseContext, System.ComponentModel.TypeConverter" , throwOnError : true ) ! ;
733
- _setSavedLicenseKey = licContext . GetMethod ( "SetSavedLicenseKey" , BindingFlags . Instance | BindingFlags . Public ) ! ;
734
- _createWithContext = licManager . GetMethod ( "CreateWithContext" , [ typeof ( Type ) , licContext ] ) ! ;
735
-
736
- Type interopHelper = licManager . GetNestedType ( "LicenseInteropHelper" , BindingFlags . NonPublic ) ! ;
737
- _validateTypeAndReturnDetails = interopHelper . GetMethod ( "ValidateAndRetrieveLicenseDetails" , BindingFlags . Static | BindingFlags . Public ) ! ;
738
- _getCurrentContextInfo = interopHelper . GetMethod ( "GetCurrentContextInfo" , BindingFlags . Static | BindingFlags . Public ) ! ;
739
-
740
- Type clrLicContext = licManager . GetNestedType ( "CLRLicenseContext" , BindingFlags . NonPublic ) ! ;
741
- _createDesignContext = clrLicContext . GetMethod ( "CreateDesignContext" , BindingFlags . Static | BindingFlags . Public ) ! ;
742
- _createRuntimeContext = clrLicContext . GetMethod ( "CreateRuntimeContext" , BindingFlags . Static | BindingFlags . Public ) ! ;
743
-
744
- _licInfoHelper = licManager . GetNestedType ( "LicInfoHelperLicenseContext" , BindingFlags . NonPublic ) ! ;
745
- _licInfoHelperContains = _licInfoHelper . GetMethod ( "Contains" , BindingFlags . Instance | BindingFlags . Public ) ! ;
746
- }
713
+ [ UnsafeAccessor ( UnsafeAccessorKind . Method ) ]
714
+ private static extern void SetSavedLicenseKey (
715
+ [ UnsafeAccessorType ( LicenseContextTypeName ) ] object licContext ,
716
+ Type type ,
717
+ string key ) ;
718
+
719
+ [ UnconditionalSuppressMessage ( "Trimming" , "IL2111" , Justification = "Manually validated that the annotations are kept in sync." ) ]
720
+ [ UnsafeAccessor ( UnsafeAccessorKind . StaticMethod ) ]
721
+ private static extern object ? CreateWithContext (
722
+ [ UnsafeAccessorType ( LicenseManagerTypeName ) ] object ? licManager ,
723
+ [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ] Type type ,
724
+ [ UnsafeAccessorType ( LicenseContextTypeName ) ] object licContext
725
+ ) ;
726
+
727
+ [ UnsafeAccessor ( UnsafeAccessorKind . StaticMethod ) ]
728
+ private static extern bool ValidateAndRetrieveLicenseDetails (
729
+ [ UnsafeAccessorType ( LicenseInteropHelperTypeName ) ] object ? licInteropHelper ,
730
+ [ UnsafeAccessorType ( LicenseContextTypeName ) ] object ? licContext ,
731
+ Type type ,
732
+ [ UnsafeAccessorType ( LicenseRefTypeName ) ] out object ? license ,
733
+ out string ? licenseKey ) ;
734
+
735
+ [ UnsafeAccessor ( UnsafeAccessorKind . StaticMethod ) ]
736
+ [ return : UnsafeAccessorType ( LicenseContextTypeName ) ]
737
+ private static extern object ? GetCurrentContextInfo (
738
+ [ UnsafeAccessorType ( LicenseInteropHelperTypeName ) ] object ? licInteropHelper ,
739
+ Type type ,
740
+ out bool isDesignTime ,
741
+ out string ? key ) ;
742
+
743
+ [ UnsafeAccessor ( UnsafeAccessorKind . StaticMethod ) ]
744
+ [ return : UnsafeAccessorType ( CLRLicenseContextTypeName ) ]
745
+ private static extern object CreateDesignContext (
746
+ [ UnsafeAccessorType ( CLRLicenseContextTypeName ) ] object ? context ,
747
+ Type type ) ;
748
+
749
+ [ UnsafeAccessor ( UnsafeAccessorKind . StaticMethod ) ]
750
+ [ return : UnsafeAccessorType ( CLRLicenseContextTypeName ) ]
751
+ private static extern object CreateRuntimeContext (
752
+ [ UnsafeAccessorType ( CLRLicenseContextTypeName ) ] object ? context ,
753
+ Type type ,
754
+ string ? key ) ;
755
+
756
+ [ UnsafeAccessor ( UnsafeAccessorKind . Constructor ) ]
757
+ [ return : UnsafeAccessorType ( LicInfoHelperLicenseContextTypeName ) ]
758
+ private static extern object CreateLicInfoHelperLicenseContext ( ) ;
759
+
760
+ [ UnsafeAccessor ( UnsafeAccessorKind . Method ) ]
761
+ private static extern bool Contains (
762
+ [ UnsafeAccessorType ( LicInfoHelperLicenseContextTypeName ) ] object ? licInfoHelperContext ,
763
+ string assemblyName ) ;
747
764
748
765
// Helper function to create an object from the native side
749
766
public static object Create ( )
@@ -769,35 +786,35 @@ public static bool HasLicense(Type type)
769
786
//
770
787
// COM normally doesn't expect this function to fail so this method
771
788
// should only throw in the case of a catastrophic error (stack, memory, etc.)
772
- public void GetLicInfo ( Type type , out bool runtimeKeyAvail , out bool licVerified )
789
+ public static void GetLicInfo ( Type type , out bool runtimeKeyAvail , out bool licVerified )
773
790
{
774
791
runtimeKeyAvail = false ;
775
792
licVerified = false ;
776
793
777
- // Types are as follows:
778
- // LicenseContext, Type, out License, out string
779
- object licContext = Activator . CreateInstance ( _licInfoHelper ) ! ;
780
- var parameters = new object ? [ ] { licContext , type , /* out */ null , /* out */ null } ;
781
- bool isValid = ( bool ) _validateTypeAndReturnDetails . Invoke ( null , BindingFlags . DoNotWrapExceptions , binder : null , parameters : parameters , culture : null ) ! ;
794
+ object licContext = CreateLicInfoHelperLicenseContext ( ) ;
795
+ bool isValid = ValidateAndRetrieveLicenseDetails ( null , licContext , type , out object ? license , out _ ) ;
782
796
if ( ! isValid )
783
797
{
784
798
return ;
785
799
}
786
800
787
- var license = ( IDisposable ? ) parameters [ 2 ] ;
788
- if ( license != null )
801
+ if ( license is IDisposable disp )
789
802
{
790
- license . Dispose ( ) ;
803
+ // Dispose of the license if it implements IDisposable
804
+ // and we are not in design mode. This is a bit of a hack
805
+ // but we need to do this to avoid leaking the license.
806
+ // The license will be disposed of when the context is
807
+ // disposed of.
808
+ disp . Dispose ( ) ;
791
809
licVerified = true ;
792
810
}
793
811
794
- parameters = [ type. AssemblyQualifiedName ] ;
795
- runtimeKeyAvail = ( bool ) _licInfoHelperContains . Invoke ( licContext , BindingFlags . DoNotWrapExceptions , binder : null , parameters : parameters , culture : null ) ! ;
812
+ runtimeKeyAvail = Contains ( licContext , type . AssemblyQualifiedName ! ) ;
796
813
}
797
814
798
815
// The CLR invokes this whenever a COM client invokes
799
816
// IClassFactory2::RequestLicKey on a managed class.
800
- public string RequestLicKey ( Type type )
817
+ public static string RequestLicKey ( Type type )
801
818
{
802
819
// License will be null, since we passed no instance,
803
820
// however we can still retrieve the "first" license
@@ -806,20 +823,14 @@ public string RequestLicKey(Type type)
806
823
// like LicFileLicenseProvider that don't require the
807
824
// instance to grant a key.
808
825
809
- // Types are as follows:
810
- // LicenseContext, Type, out License, out string
811
- var parameters = new object ? [ ] { /* use global LicenseContext */ null , type , /* out */ null , /* out */ null } ;
812
- bool isValid = ( bool ) _validateTypeAndReturnDetails . Invoke ( null , BindingFlags . DoNotWrapExceptions , binder : null , parameters : parameters , culture : null ) ! ;
813
- if ( ! isValid )
826
+ if ( ! ValidateAndRetrieveLicenseDetails ( null , null , type , out object ? license , out string ? licenseKey ) )
814
827
{
815
828
throw new COMException ( ) ; // E_FAIL
816
829
}
817
830
818
- ( ( IDisposable ? ) parameters [ 2 ] ) ? . Dispose ( ) ;
819
-
820
- var licenseKey = ( string ? ) parameters [ 3 ] ?? throw new COMException ( ) ; // E_FAIL
831
+ ( ( IDisposable ? ) license ) ? . Dispose ( ) ;
821
832
822
- return licenseKey ;
833
+ return licenseKey ?? throw new COMException ( ) ; // E_FAIL
823
834
}
824
835
825
836
// The CLR invokes this whenever a COM client invokes
@@ -832,25 +843,21 @@ public string RequestLicKey(Type type)
832
843
// If we are being entered because of a call to ICF::CreateInstanceLic(),
833
844
// "isDesignTime" will be "false" and "key" will point to a non-null
834
845
// license key.
835
- public object AllocateAndValidateLicense ( [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ] Type type , string ? key , bool isDesignTime )
846
+ public static object AllocateAndValidateLicense ( [ DynamicallyAccessedMembers ( DynamicallyAccessedMemberTypes . PublicConstructors ) ] Type type , string ? key , bool isDesignTime )
836
847
{
837
- object ? [ ] parameters ;
838
- object ? licContext ;
848
+ object licContext ;
839
849
if ( isDesignTime )
840
850
{
841
- parameters = [ type] ;
842
- licContext = _createDesignContext . Invoke ( null , BindingFlags . DoNotWrapExceptions , binder : null , parameters : parameters , culture : null ) ;
851
+ licContext = CreateDesignContext ( null , type ) ;
843
852
}
844
853
else
845
854
{
846
- parameters = [ type, key ] ;
847
- licContext = _createRuntimeContext . Invoke ( null , BindingFlags . DoNotWrapExceptions , binder : null , parameters : parameters , culture : null ) ;
855
+ licContext = CreateRuntimeContext ( null , type , key ) ;
848
856
}
849
857
850
858
try
851
859
{
852
- parameters = [ type, licContext ] ;
853
- return _createWithContext . Invoke ( null , BindingFlags . DoNotWrapExceptions , binder : null , parameters : parameters , culture : null ) ! ;
860
+ return CreateWithContext ( null , type , licContext ) ! ;
854
861
}
855
862
catch ( Exception exception ) when ( exception . GetType ( ) == s_licenseExceptionType )
856
863
{
@@ -864,14 +871,10 @@ public void GetCurrentContextInfo(RuntimeTypeHandle rth, out bool isDesignTime,
864
871
{
865
872
Type targetRcwTypeMaybe = Type . GetTypeFromHandle ( rth ) ! ;
866
873
867
- // Types are as follows:
868
- // Type, out bool, out string -> LicenseContext
869
- var parameters = new object ? [ ] { targetRcwTypeMaybe , /* out */ null , /* out */ null } ;
870
- _licContext = _getCurrentContextInfo . Invoke ( null , BindingFlags . DoNotWrapExceptions , binder : null , parameters : parameters , culture : null ) ;
874
+ _licContext = GetCurrentContextInfo ( null , targetRcwTypeMaybe , out isDesignTime , out string ? key ) ;
871
875
872
876
_targetRcwType = targetRcwTypeMaybe ;
873
- isDesignTime = ( bool ) parameters [ 1 ] ! ;
874
- bstrKey = Marshal . StringToBSTR ( ( string ) parameters [ 2 ] ! ) ;
877
+ bstrKey = Marshal . StringToBSTR ( ( string ) key ! ) ;
875
878
}
876
879
877
880
// The CLR invokes this when instantiating a licensed COM
@@ -886,8 +889,8 @@ public void SaveKeyInCurrentContext(IntPtr bstrKey)
886
889
}
887
890
888
891
string key = Marshal . PtrToStringBSTR ( bstrKey ) ;
889
- var parameters = new object ? [ ] { _targetRcwType , key } ;
890
- _setSavedLicenseKey . Invoke ( _licContext , BindingFlags . DoNotWrapExceptions , binder : null , parameters : parameters , culture : null ) ;
892
+
893
+ SetSavedLicenseKey ( _licContext ! , _targetRcwType ! , key ) ;
891
894
}
892
895
}
893
896
}
0 commit comments