Fix WinRT marshalling for NotifyPropertyChangedEventArgs and NotifyCollectionChangedE...
authorJeremy Koritzinsky <jkoritzinsky@gmail.com>
Sat, 23 Mar 2019 00:09:21 +0000 (17:09 -0700)
committerGitHub <noreply@github.com>
Sat, 23 Mar 2019 00:09:21 +0000 (17:09 -0700)
* Enable marshalling IntPtr and UIntPtr in WinRT scenarios to support our marshalling infrastructure.

* Enable getting an RCW for a native COM object while ignoring WinRT projections.

* Rename to Marshal.GetUniqueObjectForIUnknownWithoutUnboxing

* Clean up contract.

* Move GetUniqueObjectForIUnknownWithoutUnboxing to WindowsRuntimeMarshal.

* Move WinRT-specific FCalls to WindowsRuntimeMarshal.

src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs
src/System.Private.CoreLib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs
src/vm/dllimport.cpp
src/vm/ecalllist.h
src/vm/marshalnative.cpp
src/vm/marshalnative.h
src/vm/mlinfo.cpp
src/vm/mscorlib.h

index 4cdf838..e399ad6 100644 (file)
@@ -309,15 +309,6 @@ namespace System.Runtime.InteropServices
         public static extern int GetHRForException(Exception e);
 
         /// <summary>
-        /// Converts the CLR exception to an HRESULT. This function also sets
-        /// up an IErrorInfo for the exception.
-        /// This function is only used in WinRT and converts ObjectDisposedException
-        /// to RO_E_CLOSED
-        /// </summary>
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        internal static extern int GetHRForException_WinRT(Exception e);
-
-        /// <summary>
         /// Given a managed object that wraps an ITypeInfo, return its name.
         /// </summary>
         public static string GetTypeInfoName(ITypeInfo typeInfo)
@@ -743,21 +734,6 @@ namespace System.Runtime.InteropServices
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         public static extern void ChangeWrapperHandleStrength(object otp, bool fIsWeak);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        internal static extern void InitializeWrapperForWinRT(object o, ref IntPtr pUnk);
-
-#if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        internal static extern void InitializeManagedWinRTFactoryObject(object o, RuntimeType runtimeClassType);
-#endif
-
-        /// <summary>
-        /// Create activation factory and wraps it with a unique RCW.
-        /// </summary>
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        internal static extern object GetNativeActivationFactory(Type type);
-
 #endif // FEATURE_COMINTEROP
 
         [MethodImpl(MethodImplOptions.InternalCall)]
index 3199d2e..5a151e7 100644 (file)
@@ -1155,7 +1155,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
                         Marshal.QueryInterface(exceptionIUnknown, ref s_iidIErrorInfo, out exceptionIErrorInfo);
                         if (exceptionIErrorInfo != IntPtr.Zero)
                         {
-                            if (RoOriginateLanguageException(Marshal.GetHRForException_WinRT(e), e.Message, exceptionIErrorInfo))
+                            if (RoOriginateLanguageException(Marshal.GetHRForException(e), e.Message, exceptionIErrorInfo))
                             {
                                 IRestrictedErrorInfo restrictedError = UnsafeNativeMethods.GetRestrictedErrorInfo();
                                 if (restrictedError != null)
@@ -1199,7 +1199,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
 
             // If the type has any associated factory interfaces (i.e. supports non-default activation
             // or has statics), the CCW for this instance of ManagedActivationFactory must support them.
-            Marshal.InitializeManagedWinRTFactoryObject(activationFactory, (RuntimeType)type);
+            InitializeManagedWinRTFactoryObject(activationFactory, (RuntimeType)type);
             return activationFactory;
         }
 
@@ -1223,7 +1223,7 @@ namespace System.Runtime.InteropServices.WindowsRuntime
 
             if (type.IsWindowsRuntimeObject && type.IsImport)
             {
-                return (IActivationFactory)Marshal.GetNativeActivationFactory(type);
+                return (IActivationFactory)GetNativeActivationFactory(type);
             }
             else
             {
@@ -1276,6 +1276,33 @@ namespace System.Runtime.InteropServices.WindowsRuntime
             }
         }
 
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        public static extern object GetUniqueObjectForIUnknownWithoutUnboxing(IntPtr unknown);
+        
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void InitializeWrapper(object o, ref IntPtr pUnk);
+        
+        /// <summary>
+        /// Converts the CLR exception to an HRESULT. This function also sets
+        /// up an IErrorInfo for the exception.
+        /// This function is only used in WinRT and converts ObjectDisposedException
+        /// to RO_E_CLOSED
+        /// </summary>
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern int GetHRForException(Exception e);
+
+        
+#if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern void InitializeManagedWinRTFactoryObject(object o, RuntimeType runtimeClassType);
+#endif
+
+        /// <summary>
+        /// Create activation factory and wraps it with a unique RCW.
+        /// </summary>
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        internal static extern object GetNativeActivationFactory(Type type);
+
         [Conditional("_LOGGING")]
         private static void Log(string s)
         {
index f4c2838..b200a1b 100644 (file)
@@ -401,7 +401,7 @@ public:
             pcsUnmarshal->EmitLDLOCA(dwFactoryRetValLocalNum);
         }
 
-        pcsUnmarshal->EmitCALL(METHOD__MARSHAL__INITIALIZE_WRAPPER_FOR_WINRT, 2, 0);
+        pcsUnmarshal->EmitCALL(METHOD__WINDOWSRUNTIMEMARSHAL__INITIALIZE_WRAPPER, 2, 0);
 
         /*
         *   CLEANUP 
@@ -650,7 +650,7 @@ public:
         BinderMethodID getHRForException;
         if (SF_IsWinRTStub(m_dwStubFlags))
         {
-            getHRForException = METHOD__MARSHAL__GET_HR_FOR_EXCEPTION_WINRT;
+            getHRForException = METHOD__WINDOWSRUNTIMEMARSHAL__GET_HR_FOR_EXCEPTION;
         }
         else
         {
index c184633..ae98cff 100644 (file)
@@ -818,7 +818,6 @@ FCFuncStart(gInteropMarshalFuncs)
 
 #ifdef FEATURE_COMINTEROP
     FCFuncElement("GetHRForException", MarshalNative::GetHRForException)
-    FCFuncElement("GetHRForException_WinRT", MarshalNative::GetHRForException_WinRT)
     FCFuncElement("GetRawIUnknownForComObjectNoAddRef", MarshalNative::GetRawIUnknownForComObjectNoAddRef)
     FCFuncElement("IsComObject", MarshalNative::IsComObject)
     FCFuncElement("GetObjectForIUnknown", MarshalNative::GetObjectForIUnknown)
@@ -835,21 +834,26 @@ FCFuncStart(gInteropMarshalFuncs)
     FCFuncElement("GetObjectsForNativeVariants", MarshalNative::GetObjectsForNativeVariants)
     FCFuncElement("GetStartComSlot", MarshalNative::GetStartComSlot)
     FCFuncElement("GetEndComSlot", MarshalNative::GetEndComSlot)
-
-    FCFuncElement("InitializeManagedWinRTFactoryObject", MarshalNative::InitializeManagedWinRTFactoryObject)
-
-    FCFuncElement("GetNativeActivationFactory", MarshalNative::GetNativeActivationFactory)
     FCFuncElement("GetIUnknownForObjectNative", MarshalNative::GetIUnknownForObjectNative)
     FCFuncElement("GetComInterfaceForObjectNative", MarshalNative::GetComInterfaceForObjectNative)
     FCFuncElement("InternalReleaseComObject", MarshalNative::ReleaseComObject)
     FCFuncElement("Release", MarshalNative::Release)
-    FCFuncElement("InitializeWrapperForWinRT", MarshalNative::InitializeWrapperForWinRT)
     FCFuncElement("GetTypedObjectForIUnknown", MarshalNative::GetTypedObjectForIUnknown)
     FCFuncElement("ChangeWrapperHandleStrength", MarshalNative::ChangeWrapperHandleStrength)
     FCFuncElement("CleanupUnusedObjectsInCurrentContext", MarshalNative::CleanupUnusedObjectsInCurrentContext)
 #endif // FEATURE_COMINTEROP
 FCFuncEnd()
 
+#ifdef FEATURE_COMINTEROP
+FCFuncStart(gWindowsRuntimeMarshalFuncs)
+    FCFuncElement("GetNativeActivationFactory", MarshalNative::GetNativeActivationFactory)
+    FCFuncElement("GetHRForException", MarshalNative::GetHRForException_WinRT)
+    FCFuncElement("GetUniqueObjectForIUnknownWithoutUnboxing", MarshalNative::GetUniqueObjectForIUnknownWithoutUnboxing)
+    FCFuncElement("InitializeManagedWinRTFactoryObject", MarshalNative::InitializeManagedWinRTFactoryObject)
+    FCFuncElement("InitializeWrapper", MarshalNative::InitializeWrapperForWinRT)
+FCFuncEnd()
+#endif
+
 FCFuncStart(gInteropNativeLibraryFuncs)
     QCFuncElement("LoadFromPath", NativeLibraryNative::LoadFromPath)
     QCFuncElement("LoadByName", NativeLibraryNative::LoadByName)
@@ -1300,6 +1304,7 @@ FCClassElement("WeakReference`1", "System", gWeakReferenceOfTFuncs)
 
 #ifdef FEATURE_COMINTEROP
 FCClassElement("WinRTTypeNameConverter", "System.StubHelpers", gWinRTTypeNameConverterFuncs)
+FCClassElement("WindowsRuntimeMarshal", "System.Runtime.InteropServices.WindowsRuntime", gWindowsRuntimeMarshalFuncs)
 #endif // FEATURE_COMINTEROP
 
 
index 23df97d..bd4ad09 100644 (file)
@@ -1024,6 +1024,28 @@ FCIMPL1(Object*, MarshalNative::GetUniqueObjectForIUnknown, IUnknown* pUnk)
 }
 FCIMPLEND
 
+FCIMPL1(Object*, MarshalNative::GetUniqueObjectForIUnknownWithoutUnboxing, IUnknown* pUnk)
+{
+    FCALL_CONTRACT;
+
+    OBJECTREF oref = NULL;
+    HELPER_METHOD_FRAME_BEGIN_RET_1(oref);
+
+    HRESULT hr = S_OK;
+
+    if(!pUnk)
+        COMPlusThrowArgumentNull(W("pUnk"));
+
+    // Ensure COM is started up.
+    EnsureComStarted();
+
+    GetObjectRefFromComIP(&oref, pUnk, NULL, NULL, ObjFromComIP::UNIQUE_OBJECT | ObjFromComIP::IGNORE_WINRT_AND_SKIP_UNBOXING);
+
+    HELPER_METHOD_FRAME_END();
+    return OBJECTREFToObject(oref);    
+}
+FCIMPLEND
+
 //====================================================================
 // return an Object for IUnknown, using the Type T, 
 //  NOTE: 
index eaadfac..bac0c24 100644 (file)
@@ -122,6 +122,11 @@ public:
     static FCDECL1(Object*, GetUniqueObjectForIUnknown, IUnknown* pUnk);
 
     //====================================================================
+    // return a unique cacheless Object for IUnknown
+    //====================================================================
+    static FCDECL1(Object*, GetUniqueObjectForIUnknownWithoutUnboxing, IUnknown* pUnk);
+
+    //====================================================================
     // return an Object for IUnknown, using the Type T, 
     // NOTE: 
     // Type T should be either a COM imported Type or a sub-type of COM imported Type
index edbf759..f861c43 100644 (file)
@@ -1875,13 +1875,9 @@ MarshalInfo::MarshalInfo(Module* pModule,
             break;
 
         case ELEMENT_TYPE_I:
-#ifdef FEATURE_COMINTEROP
-            if (IsWinRTScenario())
-            {
-                m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
-                IfFailGoto(E_FAIL, lFail);
-            }
-#endif // FEATURE_COMINTEROP
+            // Technically the "native int" and "native uint" types aren't supported in the WinRT scenario,
+            // but we need to not block ourselves from using them to enable accurate managed->native marshalling of
+            // projected types such as NotifyCollectionChangedEventArgs and NotifyPropertyChangedEventArgs.
 
             if (!(nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_DEFAULT))
             {
@@ -1892,13 +1888,6 @@ MarshalInfo::MarshalInfo(Module* pModule,
             break;
 
         case ELEMENT_TYPE_U:
-#ifdef FEATURE_COMINTEROP
-            if (IsWinRTScenario())
-            {
-                m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
-                IfFailGoto(E_FAIL, lFail);
-            }
-#endif // FEATURE_COMINTEROP
 
             if (!(nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_DEFAULT))
             {
index 7cb76d3..d2a0ad6 100644 (file)
@@ -492,9 +492,7 @@ DEFINE_CLASS(LCID_CONVERSION_TYPE,  Interop,                LCIDConversionAttrib
 
 DEFINE_CLASS(MARSHAL,               Interop,                Marshal)
 #ifdef FEATURE_COMINTEROP
-DEFINE_METHOD(MARSHAL,              INITIALIZE_WRAPPER_FOR_WINRT, InitializeWrapperForWinRT, SM_Obj_RefIntPtr_RetVoid)
 DEFINE_METHOD(MARSHAL,              GET_HR_FOR_EXCEPTION,              GetHRForException,             SM_Exception_RetInt)
-DEFINE_METHOD(MARSHAL,              GET_HR_FOR_EXCEPTION_WINRT,        GetHRForException_WinRT,       SM_Exception_RetInt)
 #endif // FEATURE_COMINTEROP
 DEFINE_METHOD(MARSHAL,              GET_FUNCTION_POINTER_FOR_DELEGATE, GetFunctionPointerForDelegate, SM_Delegate_RetIntPtr)
 DEFINE_METHOD(MARSHAL,              GET_DELEGATE_FOR_FUNCTION_POINTER, GetDelegateForFunctionPointer, SM_IntPtr_Type_RetDelegate)
@@ -936,6 +934,8 @@ DEFINE_METHOD(BUFFER,               MEMCPY,                 Memcpy,
 
 #ifdef FEATURE_COMINTEROP
 DEFINE_CLASS(WINDOWSRUNTIMEMARSHAL, WinRT,  WindowsRuntimeMarshal)
+DEFINE_METHOD(WINDOWSRUNTIMEMARSHAL, GET_HR_FOR_EXCEPTION, GetHRForException, SM_Exception_RetInt)
+DEFINE_METHOD(WINDOWSRUNTIMEMARSHAL, INITIALIZE_WRAPPER, InitializeWrapper, SM_Obj_RefIntPtr_RetVoid)
 #ifdef FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
 DEFINE_METHOD(WINDOWSRUNTIMEMARSHAL, GET_ACTIVATION_FACTORY_FOR_TYPE, GetActivationFactoryForType, SM_Type_RetIntPtr)
 #endif // FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION