From: Damien Daspit Date: Thu, 17 Nov 2016 03:47:47 +0000 (+0700) Subject: [runtime] Fix bug when marshaling COM interfaces in arrays X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=dc0400056ce43c5cc0f69853acab03a821c3f339;p=mono.git [runtime] Fix bug when marshaling COM interfaces in arrays * use the correct COM interface when creating native array * do not free CCWs when freeing the native array This fixes Xamarin-47560. --- diff --git a/mono/metadata/cominterop.c b/mono/metadata/cominterop.c index d522657b62f..d57cb52796b 100644 --- a/mono/metadata/cominterop.c +++ b/mono/metadata/cominterop.c @@ -3664,3 +3664,52 @@ ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (gpointer ptr) { mono_free_bstr (ptr); } + +void* +mono_cominterop_get_com_interface (MonoObject *object, MonoClass *ic, MonoError *error) +{ + error_init (error); + +#ifndef DISABLE_COM + if (!object) + return NULL; + + if (cominterop_object_is_rcw (object)) { + MonoClass *klass = NULL; + MonoRealProxy* real_proxy = NULL; + if (!object) + return NULL; + klass = mono_object_class (object); + if (!mono_class_is_transparent_proxy (klass)) { + mono_error_set_invalid_operation (error, "Class is not transparent"); + return NULL; + } + + real_proxy = ((MonoTransparentProxy*)object)->rp; + if (!real_proxy) { + mono_error_set_invalid_operation (error, "RealProxy is null"); + return NULL; + } + + klass = mono_object_class (real_proxy); + if (klass != mono_class_get_interop_proxy_class ()) { + mono_error_set_invalid_operation (error, "Object is not a proxy"); + return NULL; + } + + if (!((MonoComInteropProxy*)real_proxy)->com_object) { + mono_error_set_invalid_operation (error, "Proxy points to null COM object"); + return NULL; + } + + void* com_itf = cominterop_get_interface_checked (((MonoComInteropProxy*)real_proxy)->com_object, ic, error); + return com_itf; + } + else { + void* ccw_entry = cominterop_get_ccw_checked (object, ic, error); + return ccw_entry; + } +#else + g_assert_not_reached (); +#endif +} diff --git a/mono/metadata/cominterop.h b/mono/metadata/cominterop.h index fc0e0029770..04abc6e5fab 100644 --- a/mono/metadata/cominterop.h +++ b/mono/metadata/cominterop.h @@ -64,4 +64,7 @@ mono_free_bstr (gpointer bstr); MonoClass* mono_class_try_get_com_object_class (void); +void* +mono_cominterop_get_com_interface (MonoObject* object, MonoClass* ic, MonoError *error); + #endif /* __MONO_COMINTEROP_H__ */ diff --git a/mono/metadata/marshal.c b/mono/metadata/marshal.c index 1cca5a3c743..5eb477a9096 100644 --- a/mono/metadata/marshal.c +++ b/mono/metadata/marshal.c @@ -799,12 +799,13 @@ mono_array_to_lparray (MonoArray *array) int i = 0; MonoClass *klass; + MonoError error; #endif if (!array) return NULL; #ifndef DISABLE_COM - + error_init (&error); klass = array->obj.vtable->klass; switch (klass->element_class->byval_arg.type) { @@ -814,8 +815,11 @@ mono_array_to_lparray (MonoArray *array) case MONO_TYPE_CLASS: nativeArraySize = array->max_length; nativeArray = (void **)malloc(sizeof(gpointer) * nativeArraySize); - for(i = 0; i < nativeArraySize; ++i) - nativeArray[i] = ves_icall_System_Runtime_InteropServices_Marshal_GetIUnknownForObjectInternal(((MonoObject **)array->vector)[i]); + for(i = 0; i < nativeArraySize; ++i) { + nativeArray[i] = mono_cominterop_get_com_interface (((MonoObject **)array->vector)[i], klass->element_class, &error); + if (mono_error_set_pending_exception (&error)) + break; + } return nativeArray; case MONO_TYPE_U1: case MONO_TYPE_BOOLEAN: @@ -853,7 +857,6 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray) { #ifndef DISABLE_COM MonoClass *klass; - int i = 0; if (!array) return; @@ -862,11 +865,8 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray) return; klass = array->obj.vtable->klass; - if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS) { - for(i = 0; i < array->max_length; ++i) - mono_marshal_free_ccw (mono_array_get (array, MonoObject*, i)); + if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS) g_free (nativeArray); - } #endif }