Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
VariantBuilder.cs176 linesDownload Raw Back to ComInterop
1// Licensed to the .NET Foundation under one or more agreements.2// The .NET Foundation licenses this file to you under the MIT license.3 4using System.Diagnostics;5using System.Linq.Expressions;6using System.Management.Automation.InteropServices;7using System.Runtime.InteropServices;8 9namespace System.Management.Automation.ComInterop10{11    /// <summary>12    /// VariantBuilder handles packaging of arguments into a Variant for a call to IDispatch.Invoke.13    /// </summary>14    internal class VariantBuilder15    {16        private MemberExpression _variant;17        private readonly ArgBuilder _argBuilder;18        private readonly VarEnum _targetComType;19 20        internal ParameterExpression TempVariable { get; private set; }21 22        internal VariantBuilder(VarEnum targetComType, ArgBuilder builder)23        {24            _targetComType = targetComType;25            _argBuilder = builder;26        }27 28        internal bool IsByRef29        {30            get { return (_targetComType & VarEnum.VT_BYREF) != 0; }31        }32 33        internal Expression InitializeArgumentVariant(MemberExpression variant, Expression parameter)34        {35            //NOTE: we must remember our variant36            //the reason is that argument order does not map exactly to the order of variants for invoke37            //and when we are doing clean-up we must be sure we are cleaning the variant we have initialized.38 39            _variant = variant;40 41            if (IsByRef)42            {43                // temp = argument44                // paramVariants._elementN.SetAsByrefT(ref temp)45                Debug.Assert(TempVariable == null);46                Expression argExpr = _argBuilder.MarshalToRef(parameter);47 48                TempVariable = Expression.Variable(argExpr.Type, null);49                return Expression.Block(50                    Expression.Assign(TempVariable, argExpr),51                    Expression.Call(52                        variant,53                        Variant.GetByrefSetter(_targetComType & ~VarEnum.VT_BYREF),54                        TempVariable55                    )56                );57            }58 59            Expression argument = _argBuilder.Marshal(parameter);60 61            // we are forced to special case ConvertibleArgBuilder since it does not have62            // a corresponding _targetComType.63            if (_argBuilder is ConvertibleArgBuilder)64            {65                return Expression.Call(66                    variant,67                    typeof(Variant).GetMethod(nameof(Variant.SetAsIConvertible)),68                    argument69                );70            }71 72            if (Variant.IsPrimitiveType(_targetComType) ||73               (_targetComType == VarEnum.VT_DISPATCH) ||74               (_targetComType == VarEnum.VT_UNKNOWN) ||75               (_targetComType == VarEnum.VT_VARIANT) ||76               (_targetComType == VarEnum.VT_RECORD) ||77               (_targetComType == VarEnum.VT_ARRAY))78            {79                // paramVariants._elementN.AsT = (cast)argN80                return Expression.Assign(81                    Expression.Property(82                        variant,83                        Variant.GetAccessor(_targetComType)84                    ),85                    argument86                );87            }88 89            switch (_targetComType)90            {91                case VarEnum.VT_EMPTY:92                    return null;93 94                case VarEnum.VT_NULL:95                    // paramVariants._elementN.SetAsNull();96                    return Expression.Call(variant, typeof(Variant).GetMethod(nameof(Variant.SetAsNULL)));97 98                default:99                    Debug.Assert(false, "Unexpected VarEnum");100                    return null;101            }102        }103 104        private static Expression Release(Expression pUnk)105        {106            return Expression.Call(typeof(UnsafeMethods).GetMethod(nameof(UnsafeMethods.IUnknownReleaseNotZero)), pUnk);107        }108 109        internal Expression Clear()110        {111            if (IsByRef)112            {113                if (_argBuilder is StringArgBuilder)114                {115                    Debug.Assert(TempVariable != null);116                    return Expression.Call(typeof(Marshal).GetMethod(nameof(Marshal.FreeBSTR)), TempVariable);117                }118 119                if (_argBuilder is DispatchArgBuilder)120                {121                    Debug.Assert(TempVariable != null);122                    return Release(TempVariable);123                }124 125                if (_argBuilder is UnknownArgBuilder)126                {127                    Debug.Assert(TempVariable != null);128                    return Release(TempVariable);129                }130 131                if (_argBuilder is VariantArgBuilder)132                {133                    Debug.Assert(TempVariable != null);134                    return Expression.Call(TempVariable, typeof(Variant).GetMethod(nameof(Variant.Clear)));135                }136                return null;137            }138 139            switch (_targetComType)140            {141                case VarEnum.VT_EMPTY:142                case VarEnum.VT_NULL:143                    return null;144 145                case VarEnum.VT_BSTR:146                case VarEnum.VT_UNKNOWN:147                case VarEnum.VT_DISPATCH:148                case VarEnum.VT_ARRAY:149                case VarEnum.VT_RECORD:150                case VarEnum.VT_VARIANT:151                    // paramVariants._elementN.Clear()152                    return Expression.Call(_variant, typeof(Variant).GetMethod(nameof(Variant.Clear)));153 154                default:155                    Debug.Assert(Variant.IsPrimitiveType(_targetComType), "Unexpected VarEnum");156                    return null;157            }158        }159 160        internal Expression UpdateFromReturn(Expression parameter)161        {162            if (TempVariable == null)163            {164                return null;165            }166            return Expression.Assign(167                parameter,168                Helpers.Convert(169                    _argBuilder.UnmarshalFromRef(TempVariable),170                    parameter.Type171                )172            );173        }174    }175}176