From 4ef63ba6eb807ab5eec80d9127a510af6756cb36 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Mon, 6 Nov 2023 11:44:38 +0300 Subject: [PATCH] =?UTF-8?q?fixes=20#1376=20=D0=92=D1=8B=D0=B7=D0=BE=D0=B2?= =?UTF-8?q?=20=D0=BA=D0=BE=D0=BC-=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=B1=D0=B5=D0=B7=20=D0=BF=D0=B0=D1=80=D0=B0=D0=BC?= =?UTF-8?q?=D0=B5=D1=82=D1=80=D0=BE=D0=B2=20=D0=B2=D1=8B=D0=B7=D1=8B=D0=B2?= =?UTF-8?q?=D0=B0=D0=B5=D1=82=20NRE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Machine/Contexts/COMWrapperContext.cs | 666 +++++++++--------- 1 file changed, 335 insertions(+), 331 deletions(-) diff --git a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs index 97b93ee57..6737a8a72 100644 --- a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs +++ b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs @@ -1,331 +1,335 @@ -/*---------------------------------------------------------- -This Source Code Form is subject to the terms of the -Mozilla Public License, v.2.0. If a copy of the MPL -was not distributed with this file, You can obtain one -at http://mozilla.org/MPL/2.0/. -----------------------------------------------------------*/ -//#if !__MonoCS__ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; - -namespace ScriptEngine.Machine.Contexts -{ - [ContextClass("COMОбъект", "COMObject")] - public abstract class COMWrapperContext : PropertyNameIndexAccessor, ICollectionContext, IDisposable, IObjectWrapper, IEnumerable - { - protected static readonly DateTime MIN_OLE_DATE = new DateTime(100,1,1); - - protected object Instance; - - protected COMWrapperContext(object instance) - : base(TypeManager.GetTypeByFrameworkType(typeof(COMWrapperContext))) - { - Instance = instance; - } - - private static Type FindTypeByName(string typeName) - { - foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Reverse()) - { - var tt = assembly.GetType(typeName, throwOnError:false, ignoreCase:true); - if (tt != null) - { - return tt; - } - } - return Type.GetType(typeName, throwOnError:false, ignoreCase:true); - } - - public static COMWrapperContext Create(string progId, IValue[] arguments) - { - Type type = null; - if (Type.GetType("Mono.Runtime") == null) - { - type = Type.GetTypeFromProgID(progId, throwOnError: false); - } - if (type == null) - { - type = FindTypeByName(progId); - } - - if (type == null) - { - throw new TypeLoadException(String.Format("Тип {0} не найден!", progId)); - } - - if (type.IsGenericType) - { - // В первом приближении мы заполняем параметры шаблона классом Object - // TODO: Продумать параметры шаблонного класса - var genericTypes = new List(); - foreach (var ga in type.GetGenericArguments()) - { - genericTypes.Add(typeof(object)); - } - type = type.MakeGenericType(genericTypes.ToArray()); - } - - object instance = Activator.CreateInstance(type, MarshalArguments(arguments).values); - - return InitByInstance(type, instance); - } - - public static COMWrapperContext Create(object instance) - { - return InitByInstance(instance.GetType(), instance); - } - - private static COMWrapperContext InitByInstance(Type type, object instance) - { - if (TypeIsRuntimeCallableWrapper(type)) - { - return new UnmanagedCOMWrapperContext(instance); - } - else if (IsObjectType(type) || IsAStruct(type)) - { - return new ManagedCOMWrapperContext(instance); - } - else - throw new ArgumentException(String.Format("Can't create COM wrapper for type {0}", type.ToString())); - } - - private static bool IsObjectType(Type type) - { - return !type.IsPrimitive && !type.IsValueType; - } - - private static bool IsAStruct(Type type) - { - return !type.IsPrimitive && type.IsValueType; - } - - private static bool TypeIsRuntimeCallableWrapper(Type type) - { - return type.FullName == "System.__ComObject" || type.BaseType.FullName == "System.__ComObject"; // string, cause it's hidden type - } - - protected static (object[] values, ParameterModifier[] flags) MarshalArguments(IValue[] arguments) - { - var values = new object[arguments.Length]; - ParameterModifier[] flagsArray = null; - if (arguments.Length > 0) - { - var flags = new ParameterModifier(arguments.Length); - for (int i = 0; i < arguments.Length; i++) - { - values[i] = MarshalIValue(arguments[i]); - flags[i] = arguments[i] is IVariable; - } - - flagsArray = new[] { flags }; - } - - return (values, flagsArray); - } - - public static object MarshalIValue(IValue val) - { - object retValue; - if (val != null && val.DataType == Machine.DataType.Date) - { - var date = val.AsDate(); - if (date <= MIN_OLE_DATE) - { - retValue = MIN_OLE_DATE; - } - else - { - retValue = date; - } - } - else - { - retValue = ContextValuesMarshaller.ConvertToCLRObject(val); - } - - return retValue; - } - - protected static object[] MarshalArgumentsStrict(IValue[] arguments, Type[] argumentsTypes) - { - if (argumentsTypes.Length < arguments.Length) - throw RuntimeException.TooManyArgumentsPassed(); - - object[] marshalledArgs = new object[arguments.Length]; - for (int i = 0; i < arguments.Length; i++) - { - marshalledArgs[i] = ContextValuesMarshaller.ConvertParam(arguments[i], argumentsTypes[i]); - } - - return marshalledArgs; - } - - public static object[] MarshalArgumentsStrict(System.Reflection.MethodInfo method, IValue[] arguments) - { - var parameters = method.GetParameters(); - - object[] marshalledArgs = new object[parameters.Length]; - for (int i = 0; i < parameters.Length; i++) - { - if(i < arguments.Length) - { - if (IsMissedArg(arguments[i]) && parameters[i].IsOptional) - marshalledArgs[i] = Type.Missing; - else - marshalledArgs[i] = ContextValuesMarshaller.ConvertParam(arguments[i], parameters[i].ParameterType); - } - else - { - marshalledArgs[i] = Type.Missing; - } - } - - return marshalledArgs; - } - - private static bool IsMissedArg(IValue arg) - { - return arg == null || arg.DataType == DataType.NotAValidValue; - } - - public static IValue CreateIValue(object objParam) - { - if (objParam == null) - return ValueFactory.Create(); - - var type = objParam.GetType(); - if (typeof(IValue).IsAssignableFrom(type)) - { - return (IValue)objParam; - } - else if (type == typeof(string)) - { - return ValueFactory.Create((string)objParam); - } - else if (type == typeof(int) || type == typeof(uint) || type == typeof(byte) || type == typeof(sbyte) || type == typeof(short) || type == typeof(ushort)) - { - return ValueFactory.Create(System.Convert.ToInt32(objParam)); - } - else if(type == typeof(long) || type == typeof(ulong)) - { - return ValueFactory.Create(System.Convert.ToInt64(objParam)); - } - else if (type == typeof(double)) - { - return ValueFactory.Create((decimal)(double)objParam); - } - else if (type == typeof(Single)) - { - return ValueFactory.Create((decimal)System.Convert.ToDouble(objParam)); - } - else if (type == typeof(decimal)) - { - return ValueFactory.Create((decimal)objParam); - } - else if (type == typeof(DateTime)) - { - var unboxed = (DateTime)objParam; - if (unboxed == MIN_OLE_DATE) - unboxed = DateTime.MinValue; - - return ValueFactory.Create(unboxed); - } - else if (type == typeof(bool)) - { - return ValueFactory.Create((bool)objParam); - } - else if (type.IsArray) - { - return new SafeArrayWrapper(objParam); - } - else if (IsObjectType(type) || IsAStruct(type)) - { - COMWrapperContext ctx; - try - { - ctx = COMWrapperContext.Create(objParam); - } - catch (ArgumentException e) - { - throw new RuntimeException("Тип " + type + " невозможно преобразовать в один из поддерживаемых типов", e); - } - return ValueFactory.Create(ctx); - } - - else - { - throw new RuntimeException("Тип " + type + " невозможно преобразовать в один из поддерживаемых типов"); - } - } - - #region ICollectionContext Members - - public virtual int Count() => 0; - - public virtual void Clear() - { - throw new NotImplementedException(); - } - - public CollectionEnumerator GetManagedIterator() - { - return new CollectionEnumerator(GetEnumerator()); - } - - public abstract IEnumerator GetEnumerator(); - - public object UnderlyingObject => Instance; - - #region IEnumerable Members - - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - throw new NotImplementedException(); - } - - #endregion - - #endregion - - #region IDisposable Members - - protected virtual void Dispose(bool manualDispose) - { - if (manualDispose) - { - GC.SuppressFinalize(this); - } - - } - - public void Dispose() - { - Dispose(true); - } - - ~COMWrapperContext() - { - Dispose(false); - } - - #endregion - - public override bool DynamicMethodSignatures - { - get - { - return true; - } - } - - [ScriptConstructor] - public static COMWrapperContext Constructor(IValue[] args) - { - return COMWrapperContext.Create(args[0].AsString(), args.Skip(1).ToArray()); - } - - } -} -//#endif +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +//#if !__MonoCS__ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace ScriptEngine.Machine.Contexts +{ + [ContextClass("COMОбъект", "COMObject")] + public abstract class COMWrapperContext : PropertyNameIndexAccessor, ICollectionContext, IDisposable, IObjectWrapper, IEnumerable + { + protected static readonly DateTime MIN_OLE_DATE = new DateTime(100,1,1); + + protected object Instance; + + protected COMWrapperContext(object instance) + : base(TypeManager.GetTypeByFrameworkType(typeof(COMWrapperContext))) + { + Instance = instance; + } + + private static Type FindTypeByName(string typeName) + { + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies().Reverse()) + { + var tt = assembly.GetType(typeName, throwOnError:false, ignoreCase:true); + if (tt != null) + { + return tt; + } + } + return Type.GetType(typeName, throwOnError:false, ignoreCase:true); + } + + public static COMWrapperContext Create(string progId, IValue[] arguments) + { + Type type = null; + if (Type.GetType("Mono.Runtime") == null) + { + type = Type.GetTypeFromProgID(progId, throwOnError: false); + } + if (type == null) + { + type = FindTypeByName(progId); + } + + if (type == null) + { + throw new TypeLoadException(String.Format("Тип {0} не найден!", progId)); + } + + if (type.IsGenericType) + { + // В первом приближении мы заполняем параметры шаблона классом Object + // TODO: Продумать параметры шаблонного класса + var genericTypes = new List(); + foreach (var ga in type.GetGenericArguments()) + { + genericTypes.Add(typeof(object)); + } + type = type.MakeGenericType(genericTypes.ToArray()); + } + + object instance = Activator.CreateInstance(type, MarshalArguments(arguments).values); + + return InitByInstance(type, instance); + } + + public static COMWrapperContext Create(object instance) + { + return InitByInstance(instance.GetType(), instance); + } + + private static COMWrapperContext InitByInstance(Type type, object instance) + { + if (TypeIsRuntimeCallableWrapper(type)) + { + return new UnmanagedCOMWrapperContext(instance); + } + else if (IsObjectType(type) || IsAStruct(type)) + { + return new ManagedCOMWrapperContext(instance); + } + else + throw new ArgumentException(String.Format("Can't create COM wrapper for type {0}", type.ToString())); + } + + private static bool IsObjectType(Type type) + { + return !type.IsPrimitive && !type.IsValueType; + } + + private static bool IsAStruct(Type type) + { + return !type.IsPrimitive && type.IsValueType; + } + + private static bool TypeIsRuntimeCallableWrapper(Type type) + { + return type.FullName == "System.__ComObject" || type.BaseType.FullName == "System.__ComObject"; // string, cause it's hidden type + } + + protected static (object[] values, ParameterModifier[] flags) MarshalArguments(IValue[] arguments) + { + var values = new object[arguments.Length]; + ParameterModifier[] flagsArray = new ParameterModifier[1]; + if (arguments.Length > 0) + { + var flags = new ParameterModifier(arguments.Length); + for (int i = 0; i < arguments.Length; i++) + { + values[i] = MarshalIValue(arguments[i]); + flags[i] = arguments[i] is IVariable; + } + + flagsArray[0] = flags; + } + else + { + flagsArray[0] = new ParameterModifier(); + } + + return (values, flagsArray); + } + + public static object MarshalIValue(IValue val) + { + object retValue; + if (val != null && val.DataType == Machine.DataType.Date) + { + var date = val.AsDate(); + if (date <= MIN_OLE_DATE) + { + retValue = MIN_OLE_DATE; + } + else + { + retValue = date; + } + } + else + { + retValue = ContextValuesMarshaller.ConvertToCLRObject(val); + } + + return retValue; + } + + protected static object[] MarshalArgumentsStrict(IValue[] arguments, Type[] argumentsTypes) + { + if (argumentsTypes.Length < arguments.Length) + throw RuntimeException.TooManyArgumentsPassed(); + + object[] marshalledArgs = new object[arguments.Length]; + for (int i = 0; i < arguments.Length; i++) + { + marshalledArgs[i] = ContextValuesMarshaller.ConvertParam(arguments[i], argumentsTypes[i]); + } + + return marshalledArgs; + } + + public static object[] MarshalArgumentsStrict(System.Reflection.MethodInfo method, IValue[] arguments) + { + var parameters = method.GetParameters(); + + object[] marshalledArgs = new object[parameters.Length]; + for (int i = 0; i < parameters.Length; i++) + { + if(i < arguments.Length) + { + if (IsMissedArg(arguments[i]) && parameters[i].IsOptional) + marshalledArgs[i] = Type.Missing; + else + marshalledArgs[i] = ContextValuesMarshaller.ConvertParam(arguments[i], parameters[i].ParameterType); + } + else + { + marshalledArgs[i] = Type.Missing; + } + } + + return marshalledArgs; + } + + private static bool IsMissedArg(IValue arg) + { + return arg == null || arg.DataType == DataType.NotAValidValue; + } + + public static IValue CreateIValue(object objParam) + { + if (objParam == null) + return ValueFactory.Create(); + + var type = objParam.GetType(); + if (typeof(IValue).IsAssignableFrom(type)) + { + return (IValue)objParam; + } + else if (type == typeof(string)) + { + return ValueFactory.Create((string)objParam); + } + else if (type == typeof(int) || type == typeof(uint) || type == typeof(byte) || type == typeof(sbyte) || type == typeof(short) || type == typeof(ushort)) + { + return ValueFactory.Create(System.Convert.ToInt32(objParam)); + } + else if(type == typeof(long) || type == typeof(ulong)) + { + return ValueFactory.Create(System.Convert.ToInt64(objParam)); + } + else if (type == typeof(double)) + { + return ValueFactory.Create((decimal)(double)objParam); + } + else if (type == typeof(Single)) + { + return ValueFactory.Create((decimal)System.Convert.ToDouble(objParam)); + } + else if (type == typeof(decimal)) + { + return ValueFactory.Create((decimal)objParam); + } + else if (type == typeof(DateTime)) + { + var unboxed = (DateTime)objParam; + if (unboxed == MIN_OLE_DATE) + unboxed = DateTime.MinValue; + + return ValueFactory.Create(unboxed); + } + else if (type == typeof(bool)) + { + return ValueFactory.Create((bool)objParam); + } + else if (type.IsArray) + { + return new SafeArrayWrapper(objParam); + } + else if (IsObjectType(type) || IsAStruct(type)) + { + COMWrapperContext ctx; + try + { + ctx = COMWrapperContext.Create(objParam); + } + catch (ArgumentException e) + { + throw new RuntimeException("Тип " + type + " невозможно преобразовать в один из поддерживаемых типов", e); + } + return ValueFactory.Create(ctx); + } + + else + { + throw new RuntimeException("Тип " + type + " невозможно преобразовать в один из поддерживаемых типов"); + } + } + + #region ICollectionContext Members + + public virtual int Count() => 0; + + public virtual void Clear() + { + throw new NotImplementedException(); + } + + public CollectionEnumerator GetManagedIterator() + { + return new CollectionEnumerator(GetEnumerator()); + } + + public abstract IEnumerator GetEnumerator(); + + public object UnderlyingObject => Instance; + + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + + #endregion + + #endregion + + #region IDisposable Members + + protected virtual void Dispose(bool manualDispose) + { + if (manualDispose) + { + GC.SuppressFinalize(this); + } + + } + + public void Dispose() + { + Dispose(true); + } + + ~COMWrapperContext() + { + Dispose(false); + } + + #endregion + + public override bool DynamicMethodSignatures + { + get + { + return true; + } + } + + [ScriptConstructor] + public static COMWrapperContext Constructor(IValue[] args) + { + return COMWrapperContext.Create(args[0].AsString(), args.Skip(1).ToArray()); + } + + } +} +//#endif