MegaBites-AI/Windows-powershell
0308
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Globalization;6using System.Linq;7using System.Reflection;8 9using Dbg = System.Management.Automation.Diagnostics;10 11namespace System.Management.Automation12{13 /// <summary>14 /// This is used for automatic conversions to be performed in shell variables.15 /// </summary>16 internal sealed class ArgumentTypeConverterAttribute : ArgumentTransformationAttribute17 {18 /// <summary>19 /// This ctor form is used to initialize shell variables20 /// whose type is not permitted to change.21 /// </summary>22 /// <param name="types"></param>23 internal ArgumentTypeConverterAttribute(params Type[] types)24 {25 _convertTypes = types;26 }27 28 private readonly Type[] _convertTypes;29 30 internal Type TargetType31 {32 get33 {34 return _convertTypes?.LastOrDefault();35 }36 }37 38 public override object Transform(EngineIntrinsics engineIntrinsics, object inputData)39 {40 return Transform(engineIntrinsics, inputData, false, false);41 }42 43 internal object Transform(EngineIntrinsics engineIntrinsics, object inputData, bool bindingParameters, bool bindingScriptCmdlet)44 {45 if (_convertTypes == null)46 return inputData;47 48 object result = inputData;49 50 try51 {52 for (int i = 0; i < _convertTypes.Length; i++)53 {54 if (bindingParameters)55 {56 // We should not be doing a conversion here if [ref] is the last type.57 // When [ref] appears in an argument list, it is used for checking only.58 // No Conversion should be done.59 if (_convertTypes[i].Equals(typeof(System.Management.Automation.PSReference)))60 {61 object temp;62 PSObject mshObject = result as PSObject;63 if (mshObject != null)64 temp = mshObject.BaseObject;65 else66 temp = result;67 68 if (temp is not PSReference reference)69 {70 throw new PSInvalidCastException("InvalidCastExceptionReferenceTypeExpected", null,71 ExtendedTypeSystem.ReferenceTypeExpected);72 }73 }74 else75 {76 object temp;77 PSObject mshObject = result as PSObject;78 if (mshObject != null)79 temp = mshObject.BaseObject;80 else81 temp = result;82 83 // If a non-ref type is expected but currently passed in is a ref, do an implicit dereference.84 PSReference reference = temp as PSReference;85 86 if (reference != null)87 {88 result = reference.Value;89 }90 91 if (bindingScriptCmdlet && _convertTypes[i] == typeof(string))92 {93 // Don't allow conversion from array to string in script w/ cmdlet binding. Allow94 // the conversion for ordinary script parameter binding for V1 compatibility.95 temp = PSObject.Base(result);96 if (temp != null && temp.GetType().IsArray)97 {98 throw new PSInvalidCastException("InvalidCastFromAnyTypeToString", null,99 ExtendedTypeSystem.InvalidCastCannotRetrieveString);100 }101 }102 }103 }104 105 // BUGBUG106 // NTRAID#Windows Out of Band Releases - 930116 - 03/14/06107 // handling special case for boolean, switchparameter and Nullable<bool>108 // These parameter types will not be converted if the incoming value types are not109 // one of the accepted categories - $true/$false or numbers (0 or otherwise)110 if (LanguagePrimitives.IsBoolOrSwitchParameterType(_convertTypes[i]))111 {112 CheckBoolValue(result, _convertTypes[i]);113 }114 115 if (bindingScriptCmdlet)116 {117 // Check for conversion to something like bool[] or ICollection<bool>, but only for cmdlet binding118 // to stay compatible with V1.119 ParameterCollectionTypeInformation collectionTypeInfo = new ParameterCollectionTypeInformation(_convertTypes[i]);120 if (collectionTypeInfo.ParameterCollectionType != ParameterCollectionType.NotCollection121 && LanguagePrimitives.IsBoolOrSwitchParameterType(collectionTypeInfo.ElementType))122 {123 IList currentValueAsIList = ParameterBinderBase.GetIList(result);124 if (currentValueAsIList != null)125 {126 foreach (object val in currentValueAsIList)127 {128 CheckBoolValue(val, collectionTypeInfo.ElementType);129 }130 }131 else132 {133 CheckBoolValue(result, collectionTypeInfo.ElementType);134 }135 }136 }137 138 result = LanguagePrimitives.ConvertTo(result, _convertTypes[i], CultureInfo.InvariantCulture);139 140 // Do validation of invalid direct variable assignments which are allowed to141 // be used for parameters.142 //143 // Note - this is duplicated in ExecutionContext.cs as parameter binding for script cmdlets can avoid this code path.144 if ((!bindingScriptCmdlet) && (!bindingParameters))145 {146 // ActionPreference.Suspend is reserved for future use and is not supported as a preference variable.147 if (_convertTypes[i] == typeof(ActionPreference))148 {149 ActionPreference resultPreference = (ActionPreference)result;150 151 if (resultPreference == ActionPreference.Suspend)152 {153 throw new PSInvalidCastException("InvalidActionPreference", null, ErrorPackage.ActionPreferenceReservedForFutureUseError, resultPreference);154 }155 }156 }157 }158 }159 catch (PSInvalidCastException e)160 {161 throw new ArgumentTransformationMetadataException(e.Message, e);162 }163 164 // Track the flow of untrusted object during the conversion when it's called directly from ParameterBinderBase.165 // When it's called from the override Transform method, the tracking is taken care of in the base type.166 if (bindingParameters || bindingScriptCmdlet)167 {168 ExecutionContext.PropagateInputSource(inputData, result, engineIntrinsics.SessionState.Internal.LanguageMode);169 }170 171 return result;172 }173 174 private static void CheckBoolValue(object value, Type boolType)175 {176 if (value != null)177 {178 Type resultType = value.GetType();179 180 if (resultType == typeof(PSObject))181 resultType = ((PSObject)value).BaseObject.GetType();182 183 if (!(LanguagePrimitives.IsNumeric(resultType.GetTypeCode()) ||184 LanguagePrimitives.IsBoolOrSwitchParameterType(resultType)))185 {186 ThrowPSInvalidBooleanArgumentCastException(resultType, boolType);187 }188 }189 else190 {191 bool isNullable = boolType.IsGenericType &&192 boolType.GetGenericTypeDefinition() == typeof(Nullable<>);193 194 if (!isNullable && LanguagePrimitives.IsBooleanType(boolType))195 {196 ThrowPSInvalidBooleanArgumentCastException(null, boolType);197 }198 }199 }200 201 internal static void ThrowPSInvalidBooleanArgumentCastException(Type resultType, Type convertType)202 {203 throw new PSInvalidCastException("InvalidCastExceptionUnsupportedParameterType", null,204 ExtendedTypeSystem.InvalidCastExceptionForBooleanArgumentValue,205 resultType, convertType);206 }207 }208}209 