MegaBites-AI/Windows-powershell
0372
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 