}
}
}
+ }
- // This is a helper class that supports the CLR's IClassFactory2 marshaling
- // support.
- //
- // When a managed object is exposed to COM, the CLR invokes
- // AllocateAndValidateLicense() to set up the appropriate
- // license context and instantiate the object.
- private class LicenseInteropProxy
+ // This is a helper class that supports the CLR's IClassFactory2 marshaling
+ // support.
+ //
+ // When a managed object is exposed to COM, the CLR invokes
+ // AllocateAndValidateLicense() to set up the appropriate
+ // license context and instantiate the object.
+ internal sealed class LicenseInteropProxy
+ {
+ private static readonly Type s_licenseAttrType;
+ private static readonly Type s_licenseExceptionType;
+
+ // LicenseManager
+ private MethodInfo _createWithContext;
+
+ // LicenseInteropHelper
+ private MethodInfo _validateTypeAndReturnDetails;
+ private MethodInfo _getCurrentContextInfo;
+
+ // CLRLicenseContext
+ private MethodInfo _createDesignContext;
+ private MethodInfo _createRuntimeContext;
+
+ // LicenseContext
+ private MethodInfo _setSavedLicenseKey;
+
+ private Type _licInfoHelper;
+ private MethodInfo _licInfoHelperContains;
+
+ // RCW Activation
+ private object _licContext;
+ private Type _targetRcwType;
+
+ static LicenseInteropProxy()
{
- private static readonly Type s_licenseAttrType;
- private static readonly Type s_licenseExceptionType;
+ s_licenseAttrType = Type.GetType("System.ComponentModel.LicenseProviderAttribute, System.ComponentModel.TypeConverter", throwOnError: false);
+ s_licenseExceptionType = Type.GetType("System.ComponentModel.LicenseException, System.ComponentModel.TypeConverter", throwOnError: false);
+ }
- private MethodInfo _createWithContext;
- private MethodInfo _validateTypeAndReturnDetails;
- private MethodInfo _createDesignContext;
- private MethodInfo _createRuntimeContext;
+ public LicenseInteropProxy()
+ {
+ Type licManager = Type.GetType("System.ComponentModel.LicenseManager, System.ComponentModel.TypeConverter", throwOnError: true);
- private Type _licInfoHelper;
- private MethodInfo _licInfoHelperContains;
+ Type licContext = Type.GetType("System.ComponentModel.LicenseContext, System.ComponentModel.TypeConverter", throwOnError: true);
+ _setSavedLicenseKey = licContext.GetMethod("SetSavedLicenseKey", BindingFlags.Instance | BindingFlags.Public);
+ _createWithContext = licManager.GetMethod("CreateWithContext", new[] { typeof(Type), licContext });
- static LicenseInteropProxy()
- {
- s_licenseAttrType = Type.GetType("System.ComponentModel.LicenseProviderAttribute, System.ComponentModel.TypeConverter", throwOnError: false);
- s_licenseExceptionType = Type.GetType("System.ComponentModel.LicenseException, System.ComponentModel.TypeConverter", throwOnError: false);
- }
+ Type interopHelper = licManager.GetNestedType("LicenseInteropHelper", BindingFlags.NonPublic);
+ _validateTypeAndReturnDetails = interopHelper.GetMethod("ValidateAndRetrieveLicenseDetails", BindingFlags.Static | BindingFlags.Public);
+ _getCurrentContextInfo = interopHelper.GetMethod("GetCurrentContextInfo", BindingFlags.Static | BindingFlags.Public);
- public LicenseInteropProxy()
- {
- Type licManager = Type.GetType("System.ComponentModel.LicenseManager, System.ComponentModel.TypeConverter", throwOnError: true);
+ Type clrLicContext = licManager.GetNestedType("CLRLicenseContext", BindingFlags.NonPublic);
+ _createDesignContext = clrLicContext.GetMethod("CreateDesignContext", BindingFlags.Static | BindingFlags.Public);
+ _createRuntimeContext = clrLicContext.GetMethod("CreateRuntimeContext", BindingFlags.Static | BindingFlags.Public);
- Type licContext = Type.GetType("System.ComponentModel.LicenseContext, System.ComponentModel.TypeConverter", throwOnError: true);
- _createWithContext = licManager.GetMethod("CreateWithContext", new[] { typeof(Type), licContext });
+ _licInfoHelper = licManager.GetNestedType("LicInfoHelperLicenseContext", BindingFlags.NonPublic);
+ _licInfoHelperContains = _licInfoHelper.GetMethod("Contains", BindingFlags.Instance | BindingFlags.Public);
+ }
+
+ // Helper function to create an object from the native side
+ public static object Create()
+ {
+ return new LicenseInteropProxy();
+ }
- Type interopHelper = licManager.GetNestedType("LicenseInteropHelper", BindingFlags.NonPublic);
- _validateTypeAndReturnDetails = interopHelper.GetMethod("ValidateAndRetrieveLicenseDetails", BindingFlags.Static | BindingFlags.Public);
+ // Determine if the type supports licensing
+ public static bool HasLicense(Type type)
+ {
+ // If the attribute type can't be found, then the type
+ // definitely doesn't support licensing.
+ if (s_licenseAttrType == null)
+ {
+ return false;
+ }
- Type clrLicContext = licManager.GetNestedType("CLRLicenseContext", BindingFlags.NonPublic);
- _createDesignContext = clrLicContext.GetMethod("CreateDesignContext", BindingFlags.Static | BindingFlags.Public);
- _createRuntimeContext = clrLicContext.GetMethod("CreateRuntimeContext", BindingFlags.Static | BindingFlags.Public);
+ return type.IsDefined(s_licenseAttrType, inherit: true);
+ }
- _licInfoHelper = licManager.GetNestedType("LicInfoHelperLicenseContext", BindingFlags.NonPublic);
- _licInfoHelperContains = _licInfoHelper.GetMethod("Contains", BindingFlags.Instance | BindingFlags.Public);
+ // The CLR invokes this whenever a COM client invokes
+ // IClassFactory2::GetLicInfo on a managed class.
+ //
+ // COM normally doesn't expect this function to fail so this method
+ // should only throw in the case of a catastrophic error (stack, memory, etc.)
+ public void GetLicInfo(Type type, out bool runtimeKeyAvail, out bool licVerified)
+ {
+ runtimeKeyAvail = false;
+ licVerified = false;
+
+ // Types are as follows:
+ // LicenseContext, Type, out License, out string
+ object licContext = Activator.CreateInstance(_licInfoHelper);
+ var parameters = new object[] { licContext, type, /* out */ null, /* out */ null };
+ bool isValid = (bool)_validateTypeAndReturnDetails.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
+ if (!isValid)
+ {
+ return;
}
- // Determine if the type supports licensing
- public static bool HasLicense(Type type)
+ var license = (IDisposable)parameters[2];
+ if (license != null)
{
- // If the attribute type can't be found, then the type
- // definitely doesn't support licensing.
- if (s_licenseAttrType == null)
- {
- return false;
- }
+ license.Dispose();
+ licVerified = true;
+ }
- return type.IsDefined(s_licenseAttrType, inherit: true);
+ parameters = new object[] { type.AssemblyQualifiedName };
+ runtimeKeyAvail = (bool)_licInfoHelperContains.Invoke(licContext, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
+ }
+
+ // The CLR invokes this whenever a COM client invokes
+ // IClassFactory2::RequestLicKey on a managed class.
+ public string RequestLicKey(Type type)
+ {
+ // License will be null, since we passed no instance,
+ // however we can still retrieve the "first" license
+ // key from the file. This really will only
+ // work for simple COM-compatible license providers
+ // like LicFileLicenseProvider that don't require the
+ // instance to grant a key.
+
+ // Types are as follows:
+ // LicenseContext, Type, out License, out string
+ var parameters = new object[] { /* use global LicenseContext */ null, type, /* out */ null, /* out */ null };
+ bool isValid = (bool)_validateTypeAndReturnDetails.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
+ if (!isValid)
+ {
+ throw new COMException(); //E_FAIL
}
- // The CLR invokes this whenever a COM client invokes
- // IClassFactory2::GetLicInfo on a managed class.
- //
- // COM normally doesn't expect this function to fail so this method
- // should only throw in the case of a catastrophic error (stack, memory, etc.)
- public void GetLicInfo(Type type, out bool runtimeKeyAvail, out bool licVerified)
+ var license = (IDisposable)parameters[2];
+ if (license != null)
{
- runtimeKeyAvail = false;
- licVerified = false;
+ license.Dispose();
+ }
- // Types are as follows:
- // LicenseContext, Type, out License, out string
- object licContext = Activator.CreateInstance(_licInfoHelper);
- var parameters = new object[] { licContext, type, /* out */ null, /* out */ null };
- bool isValid = (bool)_validateTypeAndReturnDetails.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
- if (!isValid)
- {
- return;
- }
+ string licenseKey = (string)parameters[3];
+ if (licenseKey == null)
+ {
+ throw new COMException(); //E_FAIL
+ }
- var license = (IDisposable)parameters[2];
- if (license != null)
- {
- license.Dispose();
- licVerified = true;
- }
+ return licenseKey;
+ }
- parameters = new object[] { type.AssemblyQualifiedName };
- runtimeKeyAvail = (bool)_licInfoHelperContains.Invoke(licContext, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
+ // The CLR invokes this whenever a COM client invokes
+ // IClassFactory::CreateInstance() or IClassFactory2::CreateInstanceLic()
+ // on a managed that has a LicenseProvider custom attribute.
+ //
+ // If we are being entered because of a call to ICF::CreateInstance(),
+ // "isDesignTime" will be "true".
+ //
+ // If we are being entered because of a call to ICF::CreateInstanceLic(),
+ // "isDesignTime" will be "false" and "key" will point to a non-null
+ // license key.
+ public object AllocateAndValidateLicense(Type type, string key, bool isDesignTime)
+ {
+ object[] parameters;
+ object licContext;
+ if (isDesignTime)
+ {
+ parameters = new object[] { type };
+ licContext = _createDesignContext.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
}
-
- // The CLR invokes this whenever a COM client invokes
- // IClassFactory2::RequestLicKey on a managed class.
- public string RequestLicKey(Type type)
+ else
{
- // License will be null, since we passed no instance,
- // however we can still retrieve the "first" license
- // key from the file. This really will only
- // work for simple COM-compatible license providers
- // like LicFileLicenseProvider that don't require the
- // instance to grant a key.
+ parameters = new object[] { type, key };
+ licContext = _createRuntimeContext.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
+ }
- // Types are as follows:
- // LicenseContext, Type, out License, out string
- var parameters = new object[] { /* use global LicenseContext */ null, type, /* out */ null, /* out */ null };
- bool isValid = (bool)_validateTypeAndReturnDetails.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
- if (!isValid)
- {
- throw new COMException(); //E_FAIL
- }
+ try
+ {
+ parameters = new object[] { type, licContext };
+ return _createWithContext.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
+ }
+ catch (Exception exception) when (exception.GetType() == s_licenseExceptionType)
+ {
+ const int CLASS_E_NOTLICENSED = unchecked((int)0x80040112);
+ throw new COMException(exception.Message, CLASS_E_NOTLICENSED);
+ }
+ }
- var license = (IDisposable)parameters[2];
- if (license != null)
- {
- license.Dispose();
- }
+ // See usage in native RCW code
+ public void GetCurrentContextInfo(RuntimeTypeHandle rth, out bool isDesignTime, out IntPtr bstrKey)
+ {
+ Type targetRcwTypeMaybe = Type.GetTypeFromHandle(rth);
- string licenseKey = (string)parameters[3];
- if (licenseKey == null)
- {
- throw new COMException(); //E_FAIL
- }
+ // Types are as follows:
+ // Type, out bool, out string -> LicenseContext
+ var parameters = new object[] { targetRcwTypeMaybe, /* out */ null, /* out */ null };
+ _licContext = _getCurrentContextInfo.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
- return licenseKey;
- }
+ _targetRcwType = targetRcwTypeMaybe;
+ isDesignTime = (bool)parameters[1];
+ bstrKey = Marshal.StringToBSTR((string)parameters[2]);
+ }
- // The CLR invokes this whenever a COM client invokes
- // IClassFactory::CreateInstance() or IClassFactory2::CreateInstanceLic()
- // on a managed that has a LicenseProvider custom attribute.
- //
- // If we are being entered because of a call to ICF::CreateInstance(),
- // "isDesignTime" will be "true".
- //
- // If we are being entered because of a call to ICF::CreateInstanceLic(),
- // "isDesignTime" will be "false" and "key" will point to a non-null
- // license key.
- public object AllocateAndValidateLicense(Type type, string key, bool isDesignTime)
+ // The CLR invokes this when instantiating a licensed COM
+ // object inside a designtime license context.
+ // It's purpose is to save away the license key that the CLR
+ // retrieved using RequestLicKey().
+ public void SaveKeyInCurrentContext(IntPtr bstrKey)
+ {
+ if (bstrKey == IntPtr.Zero)
{
- object[] parameters;
- object licContext;
- if (isDesignTime)
- {
- parameters = new object[] { type };
- licContext = _createDesignContext.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
- }
- else
- {
- parameters = new object[] { type, key };
- licContext = _createRuntimeContext.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
- }
-
- try
- {
- parameters = new object[] { type, licContext };
- return _createWithContext.Invoke(null, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
- }
- catch (Exception exception) when (exception.GetType() == s_licenseExceptionType)
- {
- const int CLASS_E_NOTLICENSED = unchecked((int)0x80040112);
- throw new COMException(exception.Message, CLASS_E_NOTLICENSED);
- }
+ return;
}
+
+ string key = Marshal.PtrToStringBSTR(bstrKey);
+ var parameters = new object[] { _targetRcwType, key };
+ _setSavedLicenseKey.Invoke(_licContext, BindingFlags.DoNotWrapExceptions, binder: null, parameters: parameters, culture: null);
}
}
}
}
CONTRACT_END;
- HRESULT hr = S_OK;
- SafeComHolder<IClassFactory2> pClassFact2 = NULL;
- SafeComHolder<IUnknown> pUnk = NULL;
- BSTRHolder bstrKey = NULL;
-
- Thread *pThread = GetThread();
+ HRESULT hr = S_OK;
+ SafeComHolder<IClassFactory2> pClassFact2 = NULL;
+ SafeComHolder<IUnknown> pUnk = NULL;
+ BSTRHolder bstrKey = NULL;
- // Does this support licensing?
- if (FAILED(SafeQueryInterface(pClassFact, IID_IClassFactory2, (IUnknown**)&pClassFact2)))
+ // If the class doesn't support licensing or if it is missing a managed
+ // type to use for querying a license, just use IClassFactory.
+ if (FAILED(SafeQueryInterface(pClassFact, IID_IClassFactory2, (IUnknown**)&pClassFact2))
+ || m_pClassMT == NULL)
{
- // not a licensed class - just createinstance the usual way.
- // Create an instance of the object.
FrameWithCookie<DebuggerExitFrame> __def;
{
GCX_PREEMP();
}
else
{
- if (m_pClassMT == NULL)
+ _ASSERTE(m_pClassMT != NULL);
+
+ // Get the type to query for licensing.
+ TypeHandle rth = TypeHandle(m_pClassMT);
+
+ struct
{
- // Create an instance of the object.
- FrameWithCookie<DebuggerExitFrame> __def;
+ OBJECTREF pProxy;
+ OBJECTREF pType;
+ } gc;
+ gc.pProxy = NULL; // LicenseInteropProxy
+ gc.pType = NULL;
+
+ GCPROTECT_BEGIN(gc);
+
+ // Create an instance of the object
+ MethodDescCallSite createObj(METHOD__LICENSE_INTEROP_PROXY__CREATE);
+ gc.pProxy = createObj.Call_RetOBJECTREF(NULL);
+ gc.pType = rth.GetManagedClassObject();
+
+ // Query the current licensing context
+ MethodDescCallSite getCurrentContextInfo(METHOD__LICENSE_INTEROP_PROXY__GETCURRENTCONTEXTINFO, &gc.pProxy);
+ CLR_BOOL fDesignTime = FALSE;
+ ARG_SLOT args[4];
+ args[0] = ObjToArgSlot(gc.pProxy);
+ args[1] = ObjToArgSlot(gc.pType);
+ args[2] = (ARG_SLOT)&fDesignTime;
+ args[3] = (ARG_SLOT)(BSTR*)&bstrKey;
+
+ getCurrentContextInfo.Call(args);
+
+ if (fDesignTime)
+ {
+ // If designtime, we're supposed to obtain the runtime license key
+ // from the component and save it away in the license context.
+ // (the design tool can then grab it and embedded it into the
+ // app it is creating)
+ if (bstrKey != NULL)
{
- GCX_PREEMP();
- hr = pClassFact->CreateInstance(punkOuter, IID_IUnknown, (void **)&pUnk);
- if (FAILED(hr) && punkOuter)
- {
- hr = pClassFact->CreateInstance(NULL, IID_IUnknown, (void**)&pUnk);
- if (pfDidContainment)
- *pfDidContainment = TRUE;
- }
+ // It's illegal for our helper to return a non-null bstrKey
+ // when the context is design-time. But we'll try to do the
+ // right thing anyway.
+ _ASSERTE(!"We're not supposed to get here, but we'll try to cope anyway.");
+ SysFreeString(bstrKey);
+ bstrKey = NULL;
}
- __def.Pop();
- }
- else
- {
- MethodTable *pHelperMT = pThread->GetDomain()->GetLicenseInteropHelperMethodTable();
- MethodDesc *pMD = MemberLoader::FindMethod(pHelperMT, "GetCurrentContextInfo", &gsig_IM_LicenseInteropHelper_GetCurrentContextInfo);
- MethodDescCallSite getCurrentContextInfo(pMD);
-
- TypeHandle rth = TypeHandle(m_pClassMT);
-
- struct _gc {
- OBJECTREF pHelper;
- OBJECTREF pType;
- } gc;
- gc.pHelper = NULL; // LicenseInteropHelper
- gc.pType = NULL;
-
- GCPROTECT_BEGIN(gc);
-
- gc.pHelper = pHelperMT->Allocate();
- gc.pType = rth.GetManagedClassObject();
- // First, crack open the current licensing context.
- INT32 fDesignTime = 0;
- ARG_SLOT args[4];
- args[0] = ObjToArgSlot(gc.pHelper);
- args[1] = (ARG_SLOT)&fDesignTime;
- args[2] = (ARG_SLOT)(BSTR*)&bstrKey;
- args[3] = ObjToArgSlot(gc.pType);
-
- getCurrentContextInfo.Call(args);
-
- if (fDesignTime)
{
- // If designtime, we're supposed to obtain the runtime license key
- // from the component and save it away in the license context
- // (the design tool can then grab it and embedded it into the
- // app it's creating.)
-
- if (bstrKey != NULL)
- {
- // It's illegal for our helper to return a non-null bstrKey
- // when the context is design-time. But we'll try to do the
- // right thing anyway.
- _ASSERTE(!"We're not supposed to get here, but we'll try to cope anyway.");
- SysFreeString(bstrKey);
- bstrKey = NULL;
- }
+ GCX_PREEMP();
+ hr = pClassFact2->RequestLicKey(0, &bstrKey);
+ }
- {
- GCX_PREEMP();
- hr = pClassFact2->RequestLicKey(0, &bstrKey);
- }
-
- // E_NOTIMPL is not a true failure. It simply indicates that
- // the component doesn't support a runtime license key.
- if (hr == E_NOTIMPL)
- hr = S_OK;
+ // E_NOTIMPL is not a true failure. It simply indicates that
+ // the component doesn't support a runtime license key.
+ if (hr == E_NOTIMPL)
+ hr = S_OK;
- if (SUCCEEDED(hr))
- {
- MethodDesc *pMDSaveKey = MemberLoader::FindMethod(pHelperMT, "SaveKeyInCurrentContext", &gsig_IM_LicenseInteropHelper_SaveKeyInCurrentContext);
- MethodDescCallSite saveKeyInCurrentContext(pMDSaveKey);
+ // Store the requested license key
+ if (SUCCEEDED(hr))
+ {
+ MethodDescCallSite saveKeyInCurrentContext(METHOD__LICENSE_INTEROP_PROXY__SAVEKEYINCURRENTCONTEXT, &gc.pProxy);
- args[0] = ObjToArgSlot(gc.pHelper);
- args[1] = (ARG_SLOT)(BSTR)bstrKey;
- saveKeyInCurrentContext.Call(args);
- }
+ args[0] = ObjToArgSlot(gc.pProxy);
+ args[1] = (ARG_SLOT)(BSTR)bstrKey;
+ saveKeyInCurrentContext.Call(args);
}
-
- if (SUCCEEDED(hr))
+ }
+
+ // Create the instance
+ if (SUCCEEDED(hr))
+ {
+ FrameWithCookie<DebuggerExitFrame> __def;
{
- FrameWithCookie<DebuggerExitFrame> __def;
+ GCX_PREEMP();
+ if (fDesignTime || bstrKey == NULL)
{
- GCX_PREEMP();
-
- if (fDesignTime || bstrKey == NULL)
+ // Either it's design time, or the current context doesn't
+ // supply a runtime license key.
+ hr = pClassFact->CreateInstance(punkOuter, IID_IUnknown, (void **)&pUnk);
+ if (FAILED(hr) && punkOuter)
{
- // Either it's design time, or the current context doesn't
- // supply a runtime license key.
- hr = pClassFact->CreateInstance(punkOuter, IID_IUnknown, (void **)&pUnk);
- if (FAILED(hr) && punkOuter)
- {
- hr = pClassFact->CreateInstance(NULL, IID_IUnknown, (void**)&pUnk);
- if (pfDidContainment)
- *pfDidContainment = TRUE;
- }
+ hr = pClassFact->CreateInstance(NULL, IID_IUnknown, (void**)&pUnk);
+ if (pfDidContainment)
+ *pfDidContainment = TRUE;
}
- else
+ }
+ else
+ {
+ // It is runtime and we have a license key.
+ _ASSERTE(bstrKey != NULL);
+ hr = pClassFact2->CreateInstanceLic(punkOuter, NULL, IID_IUnknown, bstrKey, (void**)&pUnk);
+ if (FAILED(hr) && punkOuter)
{
- // It's runtime, and we do have a non-null license key.
- _ASSERTE(bstrKey != NULL);
- hr = pClassFact2->CreateInstanceLic(punkOuter, NULL, IID_IUnknown, bstrKey, (void**)&pUnk);
- if (FAILED(hr) && punkOuter)
- {
- hr = pClassFact2->CreateInstanceLic(NULL, NULL, IID_IUnknown, bstrKey, (void**)&pUnk);
- if (pfDidContainment)
- *pfDidContainment = TRUE;
- }
-
+ hr = pClassFact2->CreateInstanceLic(NULL, NULL, IID_IUnknown, bstrKey, (void**)&pUnk);
+ if (pfDidContainment)
+ *pfDidContainment = TRUE;
}
}
- __def.Pop();
}
-
- GCPROTECT_END();
+ __def.Pop();
}
+
+ GCPROTECT_END();
}
if (FAILED(hr))