MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Concurrent;6using System.Collections.Generic;7using System.Collections.Specialized;8#if !UNIX9using System.DirectoryServices;10#endif11using System.Globalization;12using System.Linq;13using System.Management.Automation.Language;14using System.Management.Automation.Runspaces;15using System.Net;16using System.Net.Mail;17using System.Net.NetworkInformation;18using System.Numerics;19using System.Reflection;20using System.Security;21using System.Security.AccessControl;22using System.Security.Cryptography.X509Certificates;23using System.Text.RegularExpressions;24using System.Xml;25 26using Microsoft.Management.Infrastructure;27using Microsoft.PowerShell.Commands;28 29namespace System.Management.Automation.Language30{31 internal static class TypeResolver32 {33 // our interface34 // internal static Type ConvertTypeNameToType(TypeName typeName, out Exception exception)35 // Used by TypeName.GetReflectionType and in TypeResolver36 // internal static bool TryResolveType(string typeName, out Type type)37 // Used in a bunch of places38 // internal static Type ConvertStringToType(string typeName, out Exception exception)39 // Used primarily in LanguagePrimitives.ConvertTo40 41 private static Type LookForTypeInSingleAssembly(Assembly assembly, string typename)42 {43 Type targetType = assembly.GetType(typename, false, true);44 if (targetType != null && IsPublic(targetType))45 {46 return targetType;47 }48 49 return null;50 }51 52 /// <summary>53 /// Inherited from InvalidCastException, because it happens in [string] -> [Type] conversion.54 /// </summary>55 internal class AmbiguousTypeException : InvalidCastException56 {57 public string[] Candidates { get; }58 59 public TypeName TypeName { get; }60 61 public AmbiguousTypeException(TypeName typeName, IEnumerable<string> candidates)62 {63 Candidates = candidates.ToArray();64 TypeName = typeName;65 Diagnostics.Assert(Candidates.Length > 1, "AmbiguousTypeException can be created only when there are more then 1 candidate.");66 }67 }68 69 private static Type LookForTypeInAssemblies(TypeName typeName,70 IEnumerable<Assembly> assemblies,71 HashSet<Assembly> searchedAssemblies,72 TypeResolutionState typeResolutionState,73 bool reportAmbiguousException,74 out Exception exception)75 {76 exception = null;77 string alternateNameToFind = typeResolutionState.GetAlternateTypeName(typeName.Name);78 Type foundType = null;79 Type foundType2 = null;80 foreach (Assembly assembly in assemblies)81 {82 // Skip the assemblies that we already searched and found no matching type.83 if (searchedAssemblies.Contains(assembly))84 {85 continue;86 }87 88 try89 {90 Type targetType = LookForTypeInSingleAssembly(assembly, typeName.Name);91 if (targetType == null && alternateNameToFind != null)92 {93 targetType = LookForTypeInSingleAssembly(assembly, alternateNameToFind);94 }95 96 if (targetType != null)97 {98 if (!reportAmbiguousException)99 {100 // accelerator for the common case, when we are not interested in ambiguity exception.101 return targetType;102 }103 104 // .NET has forward notation for types, when they declared in one assembly and implemented in another one.105 // We want to support both scenarios:106 // 1) When we pass assembly with declared forwarded type (CoreCLR)107 // 2) When we pass assembly with declared forwarded type and assembly with implemented forwarded type (FullCLR)108 // In the case (2) we should not report duplicate, hence this check109 if (foundType != targetType)110 {111 if (foundType != null)112 {113 foundType2 = targetType;114 break;115 }116 else117 {118 foundType = targetType;119 }120 }121 }122 else123 {124 // We didn't find a match from the current assembly, so update the searchedAssemblies set.125 searchedAssemblies.Add(assembly);126 }127 }128 catch (Exception) // Assembly.GetType might throw unadvertised exceptions129 {130 }131 }132 133 if (foundType2 != null)134 {135 exception = new AmbiguousTypeException(typeName, new string[] { foundType.AssemblyQualifiedName, foundType2.AssemblyQualifiedName });136 return null;137 }138 139 return foundType;140 }141 142 /// <summary>143 /// A type IsPublic if IsPublic or (IsNestedPublic and is nested in public type(s))144 /// </summary>145 internal static bool IsPublic(Type type)146 {147 if (type.IsPublic)148 {149 return true;150 }151 152 if (!type.IsNestedPublic)153 {154 return false;155 }156 157 while ((type = type.DeclaringType) != null)158 {159 if (!(type.IsPublic || type.IsNestedPublic))160 {161 return false;162 }163 }164 165 return true;166 }167 168 private static Type ResolveTypeNameWorker(TypeName typeName,169 SessionStateScope currentScope,170 IEnumerable<Assembly> loadedAssemblies,171 HashSet<Assembly> searchedAssemblies,172 TypeResolutionState typeResolutionState,173 bool onlySearchInGivenAssemblies,174 bool reportAmbiguousException,175 out Exception exception)176 {177 Type result;178 exception = null;179 180 if (!onlySearchInGivenAssemblies)181 {182 while (currentScope != null)183 {184 result = currentScope.LookupType(typeName.Name);185 if (result != null)186 {187 return result;188 }189 190 currentScope = currentScope.Parent;191 }192 193 if (TypeAccelerators.builtinTypeAccelerators.TryGetValue(typeName.Name, out result))194 {195 return result;196 }197 }198 199 result = LookForTypeInAssemblies(typeName, loadedAssemblies, searchedAssemblies, typeResolutionState, reportAmbiguousException, out exception);200 if (exception != null)201 {202 // skip the rest of lookups, if exception reported.203 return result;204 }205 206 if (!onlySearchInGivenAssemblies && result == null)207 {208 lock (TypeAccelerators.userTypeAccelerators)209 {210 TypeAccelerators.userTypeAccelerators.TryGetValue(typeName.Name, out result);211 }212 }213 214 return result;215 }216 217 /// <summary>218 /// A set of assemblies that we have searched from but found no matching type. By checking this set, we can219 /// avoid searching from some assemblies multiple times.220 /// This set is made thread static, so that type resolution happens on the same thread can reuse the HashSet221 /// without having to create a new HashSet instance every time. This will reduce GC given that type resolution222 /// is a frequent operation in powershell script.223 /// </summary>224 /// <remarks>225 /// This set should be used directly only in the method CallResolveTypeNameWorkerHelper.226 /// </remarks>227 [ThreadStatic]228 private static HashSet<Assembly> t_searchedAssemblies = null;229 230 /// <summary>231 /// A helper method to call ResolveTypeNameWorker in steps.232 /// </summary>233 private static Type CallResolveTypeNameWorkerHelper(TypeName typeName,234 ExecutionContext context,235 IEnumerable<Assembly> assemblies,236 bool isAssembliesExplicitlyPassedIn,237 TypeResolutionState typeResolutionState,238 out Exception exception)239 {240 if (t_searchedAssemblies == null)241 {242 t_searchedAssemblies = new HashSet<Assembly>();243 }244 else245 {246 // Clear the set before starting a full search to make sure we have a clean start.247 t_searchedAssemblies.Clear();248 }249 250 try251 {252 exception = null;253 var currentScope = context?.EngineSessionState.CurrentScope;254 Type result = ResolveTypeNameWorker(typeName, currentScope, typeResolutionState.assemblies, t_searchedAssemblies, typeResolutionState,255 /*onlySearchInGivenAssemblies*/ false, /* reportAmbiguousException */ true, out exception);256 if (exception == null && result == null)257 {258 if (context != null && !isAssembliesExplicitlyPassedIn)259 {260 // If the assemblies to search from is not specified by the caller of 'ResolveTypeNameWithContext',261 // then we search our assembly cache first, so as to give preference to resolving the type against262 // assemblies explicitly loaded by powershell, for example, via importing module/snapin.263 result = ResolveTypeNameWorker(typeName, currentScope, context.AssemblyCache.Values, t_searchedAssemblies, typeResolutionState,264 /*onlySearchInGivenAssemblies*/ true, /* reportAmbiguousException */ false, out exception);265 }266 267 if (result == null)268 {269 // Search from the assembly list passed in.270 result = ResolveTypeNameWorker(typeName, currentScope, assemblies, t_searchedAssemblies, typeResolutionState,271 /*onlySearchInGivenAssemblies*/ true, /* reportAmbiguousException */ false, out exception);272 }273 }274 275 return result;276 }277 finally278 {279 // Clear the set after a full search, so dynamic assemblies can get reclaimed as needed.280 t_searchedAssemblies.Clear();281 }282 }283 284 internal static Type ResolveAssemblyQualifiedTypeName(TypeName typeName, out Exception exception)285 {286 // If an assembly name was specified, we let Type.GetType deal with loading the assembly287 // and resolving the type.288 exception = null;289 try290 {291 // We shouldn't really bother looking for the type in System namespace, but292 // we've always done that. We explicitly are not supporting arbitrary293 // 'using namespace' here because there is little value, if you need the assembly294 // qualifier, it's best to just fully specify the type.295 var result = Type.GetType(typeName.FullName, false, true) ??296 Type.GetType("System." + typeName.FullName, false, true);297 298 if (result != null && IsPublic(result))299 {300 return result;301 }302 }303 catch (Exception e)304 {305 exception = e;306 }307 308 return null;309 }310 311 internal static Type ResolveTypeNameWithContext(TypeName typeName, out Exception exception, Assembly[] assemblies, TypeResolutionState typeResolutionState)312 {313 ExecutionContext context = null;314 exception = null;315 316 if (typeResolutionState == null)317 {318 // Usings from script scope (and if no script scope, fall back to default 'using namespace system')319 context = LocalPipeline.GetExecutionContextFromTLS();320 typeResolutionState = TypeResolutionState.GetDefaultUsingState(context);321 }322 323 // We can do the cache lookup only if we don't define type in the current scope (cache would be invalid in this case).324 var result = typeResolutionState.ContainsTypeDefined(typeName.Name)325 ? null326 : TypeCache.Lookup(typeName, typeResolutionState);327 if (result != null)328 {329 return result;330 }331 332 if (typeName.AssemblyName != null)333 {334 result = ResolveAssemblyQualifiedTypeName(typeName, out exception);335 TypeCache.Add(typeName, typeResolutionState, result);336 return result;337 }338 339 // Simple typename (no generics, no arrays, no assembly name)340 // We use the following search order, using the specified name (assumed to be fully namespace qualified):341 //342 // * Search scope table (includes 'using type x = ...' aliases)343 // * Built in type accelerators (implicit 'using type x = ...' aliases that are effectively in global scope344 // * typeResolutionState.assemblies, which contains:345 // - Assemblies with PS types, added by 'using module'346 // - Assemblies added by 'using assembly'.347 // For this case, we REPORT ambiguity, since user explicitly specifies the set of assemblies.348 // * All other loaded assemblies (excluding dynamic assemblies created for PS defined types).349 // IGNORE ambiguity. It mimics PS v4. There are two reasons:350 // 1) If we report ambiguity, we need to fix our caching logic accordingly.351 // Consider this code352 // Add-Type 'public class Q {}' # ok353 // Add-Type 'public class Q { }' # get error about the same name354 // [Q] # we would get error about ambiguous type, because we added assembly with duplicated type355 // # before we can report TYPE_ALREADY_EXISTS error.356 //357 // Add-Type 'public class Q2 {}' # ok358 // [Q2] # caching Q2 type359 // Add-Type 'public class Q2 { }' # get error about the same name360 // [Q2] # we don't get an error about ambiguous type, because it's cached already361 // 2) NuGet (VS Package Management console) uses MEF extensibility model.362 // Different assemblies includes same interface (i.e. NuGet.VisualStudio.IVsPackageInstallerServices),363 // where they include only methods that they are interested in the interface declaration (result interfaces are different!).364 // Then, at runtime VS provides an instance. Everything work as far as instance has compatible API.365 // So [NuGet.VisualStudio.IVsPackageInstallerServices] can be resolved to several different assemblies and it's ok.366 // * User defined type accelerators (rare - interface was never public)367 //368 // If nothing is found, we search again, this time applying any 'using namespace ...' declarations including the implicit 'using namespace System'.369 // We must search all using aliases and REPORT an error if there is an ambiguity.370 371 // If this is TypeDefinition we should not cache anything in TypeCache.372 if (typeName._typeDefinitionAst != null)373 {374 return typeName._typeDefinitionAst.Type;375 }376 377 context ??= LocalPipeline.GetExecutionContextFromTLS();378 379 // Use the explicitly passed-in assembly list when it's specified by the caller.380 // Otherwise, retrieve all currently loaded assemblies.381 var assemList = assemblies ?? ClrFacade.GetAssemblies(typeResolutionState, typeName);382 var isAssembliesExplicitlyPassedIn = assemblies != null;383 384 result = CallResolveTypeNameWorkerHelper(typeName, context, assemList, isAssembliesExplicitlyPassedIn, typeResolutionState, out exception);385 386 if (result != null)387 {388 TypeCache.Add(typeName, typeResolutionState, result);389 return result;390 }391 392 if (exception == null)393 {394 foreach (var ns in typeResolutionState.namespaces)395 {396 var newTypeNameToSearch = ns + "." + typeName.Name;397 newTypeNameToSearch = typeResolutionState.GetAlternateTypeName(newTypeNameToSearch) ??398 newTypeNameToSearch;399 var newTypeName = new TypeName(typeName.Extent, newTypeNameToSearch);400#if CORECLR401 if (!isAssembliesExplicitlyPassedIn)402 {403 // We called 'ClrFacade.GetAssemblies' to get assemblies. That means the assemblies to search from404 // are not pre-defined, and thus we have to refetch assembly again based on the new type name.405 assemList = ClrFacade.GetAssemblies(typeResolutionState, newTypeName);406 }407#endif408 var newResult = CallResolveTypeNameWorkerHelper(newTypeName, context, assemList, isAssembliesExplicitlyPassedIn, typeResolutionState, out exception);409 410 if (exception != null)411 {412 break;413 }414 415 if (newResult != null)416 {417 if (result == null)418 {419 result = newResult;420 }421 else422 {423 exception = new AmbiguousTypeException(typeName, new string[] { result.FullName, newResult.FullName });424 result = null;425 break;426 }427 }428 }429 }430 431 if (exception != null)432 {433 // AmbiguousTypeException is for internal representation only.434 var ambiguousException = exception as AmbiguousTypeException;435 if (ambiguousException != null)436 {437 exception = new PSInvalidCastException("AmbiguousTypeReference", exception,438 ParserStrings.AmbiguousTypeReference, ambiguousException.TypeName.Name,439 ambiguousException.Candidates[0], ambiguousException.Candidates[1]);440 }441 }442 443 if (result != null)444 {445 TypeCache.Add(typeName, typeResolutionState, result);446 }447 448 return result;449 }450 451 internal static Type ResolveTypeName(TypeName typeName, out Exception exception)452 {453 return ResolveTypeNameWithContext(typeName, out exception, null, null);454 }455 456 internal static bool TryResolveType(string typeName, out Type type)457 {458 Exception exception;459 type = ResolveType(typeName, out exception);460 return (type != null);461 }462 463 internal static Type ResolveITypeName(ITypeName iTypeName, out Exception exception)464 {465 exception = null;466 var typeName = iTypeName as TypeName;467 if (typeName == null)468 {469 // The type is something more complicated - generic or array.470 try471 {472 return iTypeName.GetReflectionType();473 }474 catch (Exception e)475 {476 exception = e;477 return null;478 }479 }480 481 return ResolveTypeName(typeName, out exception);482 }483 484 /// <summary>485 /// This routine converts a string into a Type object using the msh rules.486 /// </summary>487 /// <param name="strTypeName">A string representing the name of the type to convert.</param>488 /// <param name="exception">The exception, if one happened, trying to find the type.</param>489 /// <returns>A type if the conversion was successful, null otherwise.</returns>490 internal static Type ResolveType(string strTypeName, out Exception exception)491 {492 exception = null;493 if (string.IsNullOrWhiteSpace(strTypeName))494 {495 return null;496 }497 498 var iTypeName = Parser.ScanType(strTypeName, ignoreErrors: false);499 if (iTypeName == null)500 {501 return null;502 }503 504 return ResolveITypeName(iTypeName, out exception);505 }506 }507 508 /// <summary>509 /// The idea behind this class is: I should be able to re-use expensive510 /// type resolution operation result in the same context.511 /// Hence, this class is a key for TypeCache dictionary.512 ///513 /// Every SessionStateScope has TypeResolutionState.514 /// typesDefined contains PowerShell types names defined in the current scope and all scopes above.515 /// Same for namespaces.516 ///517 /// If TypeResolutionState doesn't add anything new compare to it's parent, we represent it as null.518 /// So, when we do lookup, we need to find first non-null TypeResolutionState.519 /// </summary>520 internal class TypeResolutionState521 {522 internal static readonly string[] systemNamespace = { "System" };523 internal static readonly Assembly[] emptyAssemblies = Array.Empty<Assembly>();524 internal static readonly TypeResolutionState UsingSystem = new TypeResolutionState();525 526 internal readonly string[] namespaces;527 internal readonly Assembly[] assemblies;528 private readonly HashSet<string> _typesDefined;529 internal readonly int genericArgumentCount;530 internal readonly bool attribute;531 532 private TypeResolutionState()533 : this(systemNamespace, emptyAssemblies)534 {535 }536 537 /// <summary>538 /// TypeResolutionState can be shared and that's why it should be represented as an immutable object.539 /// So, we use this API to alternate TypeResolutionState, but instead of mutating existing one, we clone it.540 /// </summary>541 /// <param name="types"></param>542 /// <returns></returns>543 internal TypeResolutionState CloneWithAddTypesDefined(IEnumerable<string> types)544 {545 var newTypesDefined = new HashSet<string>(_typesDefined, StringComparer.OrdinalIgnoreCase);546 foreach (var type in types)547 {548 newTypesDefined.Add(type);549 }550 551 return new TypeResolutionState(this, newTypesDefined);552 }553 554 internal bool ContainsTypeDefined(string type)555 {556 return _typesDefined.Contains(type);557 }558 559 internal TypeResolutionState(string[] namespaces, Assembly[] assemblies)560 {561 this.namespaces = namespaces ?? systemNamespace;562 this.assemblies = assemblies ?? emptyAssemblies;563 _typesDefined = new HashSet<string>(StringComparer.OrdinalIgnoreCase);564 }565 566 internal TypeResolutionState(TypeResolutionState other, int genericArgumentCount, bool attribute)567 {568 this.namespaces = other.namespaces;569 this.assemblies = other.assemblies;570 _typesDefined = other._typesDefined;571 this.genericArgumentCount = genericArgumentCount;572 this.attribute = attribute;573 }574 575 private TypeResolutionState(TypeResolutionState other, HashSet<string> typesDefined)576 {577 this.namespaces = other.namespaces;578 this.assemblies = other.assemblies;579 _typesDefined = typesDefined;580 this.genericArgumentCount = other.genericArgumentCount;581 this.attribute = other.attribute;582 }583 584 internal static TypeResolutionState GetDefaultUsingState(ExecutionContext context)585 {586 context ??= LocalPipeline.GetExecutionContextFromTLS();587 588 if (context != null)589 {590 return context.EngineSessionState.CurrentScope.TypeResolutionState;591 }592 593 return TypeResolutionState.UsingSystem;594 }595 596 internal string GetAlternateTypeName(string typeName)597 {598 string alternateName = null;599 if (genericArgumentCount > 0 && typeName.IndexOf('`') < 0)600 {601 alternateName = typeName + "`" + genericArgumentCount;602 }603 else if (attribute && !typeName.EndsWith("Attribute", StringComparison.OrdinalIgnoreCase))604 {605 alternateName = typeName + "Attribute";606 }607 608 return alternateName;609 }610 611 public override bool Equals(object obj)612 {613 if (object.ReferenceEquals(this, obj))614 return true;615 616 if (!(obj is TypeResolutionState other))617 return false;618 619 if (this.attribute != other.attribute)620 return false;621 622 if (this.genericArgumentCount != other.genericArgumentCount)623 return false;624 625 if (this.namespaces.Length != other.namespaces.Length)626 return false;627 628 if (this.assemblies.Length != other.assemblies.Length)629 return false;630 631 for (int i = 0; i < namespaces.Length; i++)632 {633 if (!this.namespaces[i].Equals(other.namespaces[i], StringComparison.OrdinalIgnoreCase))634 return false;635 }636 637 for (int i = 0; i < assemblies.Length; i++)638 {639 if (!this.assemblies[i].Equals(other.assemblies[i]))640 return false;641 }642 643 if (_typesDefined.Count != other._typesDefined.Count)644 return false;645 646 return _typesDefined.SetEquals(other._typesDefined);647 }648 649 public override int GetHashCode()650 {651 var stringComparer = StringComparer.OrdinalIgnoreCase;652 int result = Utils.CombineHashCodes(genericArgumentCount.GetHashCode(), attribute.GetHashCode());653 for (int i = 0; i < namespaces.Length; i++)654 {655 result = Utils.CombineHashCodes(result, stringComparer.GetHashCode(namespaces[i]));656 }657 658 for (int i = 0; i < assemblies.Length; i++)659 {660 result = Utils.CombineHashCodes(result, this.assemblies[i].GetHashCode());661 }662 663 foreach (var t in _typesDefined)664 {665 result = Utils.CombineHashCodes(result, t.GetHashCode());666 }667 668 return result;669 }670 }671 672 internal static class TypeCache673 {674 private sealed class KeyComparer : IEqualityComparer<Tuple<ITypeName, TypeResolutionState>>675 {676 public bool Equals(Tuple<ITypeName, TypeResolutionState> x,677 Tuple<ITypeName, TypeResolutionState> y)678 {679 return x.Item1.Equals(y.Item1) && x.Item2.Equals(y.Item2);680 }681 682 public int GetHashCode(Tuple<ITypeName, TypeResolutionState> obj)683 {684 return obj.GetHashCode();685 }686 }687 688 private static readonly ConcurrentDictionary<Tuple<ITypeName, TypeResolutionState>, Type> s_cache = new ConcurrentDictionary<Tuple<ITypeName, TypeResolutionState>, Type>(new KeyComparer());689 690 internal static Type Lookup(ITypeName typeName, TypeResolutionState typeResolutionState)691 {692 Type result;693 s_cache.TryGetValue(Tuple.Create(typeName, typeResolutionState), out result);694 return result;695 }696 697 internal static void Add(ITypeName typeName, TypeResolutionState typeResolutionState, Type type)698 {699 s_cache.GetOrAdd(Tuple.Create(typeName, typeResolutionState), type);700 }701 }702}703 704namespace System.Management.Automation705{706 /// <summary>707 /// A class to the core types in PowerShell.708 /// </summary>709 internal static class CoreTypes710 {711 // A list of the core PowerShell types, and their accelerator.712 //713 // These types are frequently used in scripting, and for parameter validation in scripts.714 //715 // When in ConstrainedLanguage mode, all operations on these types are fully supported unlike all other716 // types that are assumed to have dangerous constructors or methods.717 //718 // Do not add types to this pool unless they can be safely exposed to an attacker and will not719 // expose the ability to corrupt or escape PowerShell's environment. The following operations must720 // be safe: type conversion, all constructors, all methods (instance and static), and721 // and properties (instance and static).722 internal static readonly Lazy<Dictionary<Type, string[]>> Items = new Lazy<Dictionary<Type, string[]>>(723 () =>724 new Dictionary<Type, string[]>725 {726 { typeof(AliasAttribute), new[] { "Alias" } },727 { typeof(AllowEmptyCollectionAttribute), new[] { "AllowEmptyCollection" } },728 { typeof(AllowEmptyStringAttribute), new[] { "AllowEmptyString" } },729 { typeof(AllowNullAttribute), new[] { "AllowNull" } },730 { typeof(ArgumentCompleterAttribute), new[] { "ArgumentCompleter" } },731 { typeof(ArgumentCompletionsAttribute), new[] { "ArgumentCompletions" } },732 { typeof(Array), new[] { "array" } },733 { typeof(bool), new[] { "bool" } },734 { typeof(byte), new[] { "byte" } },735 { typeof(char), new[] { "char" } },736 { typeof(CmdletBindingAttribute), new[] { "CmdletBinding" } },737 { typeof(DateTime), new[] { "datetime" } },738 { typeof(decimal), new[] { "decimal" } },739 { typeof(double), new[] { "double" } },740 { typeof(DscResourceAttribute), new[] { "DscResource" } },741 { typeof(ExperimentAction), new[] { "ExperimentAction" } },742 { typeof(ExperimentalAttribute), new[] { "Experimental" } },743 { typeof(ExperimentalFeature), new[] { "ExperimentalFeature" } },744 { typeof(float), new[] { "float", "single" } },745 { typeof(Guid), new[] { "guid" } },746 { typeof(Hashtable), new[] { "hashtable" } },747 { typeof(int), new[] { "int", "int32" } },748 { typeof(Int16), new[] { "short", "int16" } },749 { typeof(long), new[] { "long", "int64" } },750 { typeof(CimInstance), new[] { "ciminstance" } },751 { typeof(CimClass), new[] { "cimclass" } },752 { typeof(Microsoft.Management.Infrastructure.CimType), new[] { "cimtype" } },753 { typeof(CimConverter), new[] { "cimconverter" } },754 { typeof(ModuleSpecification), null },755 { typeof(IPEndPoint), new[] { "IPEndpoint" } },756 { typeof(NoRunspaceAffinityAttribute), new[] { "NoRunspaceAffinity" } },757 { typeof(NullString), new[] { "NullString" } },758 { typeof(OutputTypeAttribute), new[] { "OutputType" } },759 { typeof(object[]), null },760 { typeof(ObjectSecurity), new[] { "ObjectSecurity" } },761 { typeof(OrderedDictionary), new[] { "ordered" } },762 { typeof(ParameterAttribute), new[] { "Parameter" } },763 { typeof(PhysicalAddress), new[] { "PhysicalAddress" } },764 { typeof(PSCredential), new[] { "pscredential" } },765 { typeof(PSDefaultValueAttribute), new[] { "PSDefaultValue" } },766 { typeof(PSListModifier), new[] { "pslistmodifier" } },767 { typeof(PSObject), new[] { "psobject", "pscustomobject" } },768 { typeof(PSPrimitiveDictionary), new[] { "psprimitivedictionary" } },769 { typeof(PSReference), new[] { "ref" } },770 { typeof(PSTypeNameAttribute), new[] { "PSTypeNameAttribute" } },771 { typeof(Regex), new[] { "regex" } },772 { typeof(DscPropertyAttribute), new[] { "DscProperty" } },773 { typeof(sbyte), new[] { "sbyte" } },774 { typeof(string), new[] { "string" } },775 { typeof(SupportsWildcardsAttribute), new[] { "SupportsWildcards" } },776 { typeof(SwitchParameter), new[] { "switch" } },777 { typeof(CultureInfo), new[] { "cultureinfo" } },778 { typeof(BigInteger), new[] { "bigint" } },779 { typeof(SecureString), new[] { "securestring" } },780 { typeof(TimeSpan), new[] { "timespan" } },781 { typeof(UInt16), new[] { "ushort", "uint16" } },782 { typeof(UInt32), new[] { "uint", "uint32" } },783 { typeof(UInt64), new[] { "ulong", "uint64" } },784 { typeof(Uri), new[] { "uri" } },785 { typeof(ValidateCountAttribute), new[] { "ValidateCount" } },786 { typeof(ValidateDriveAttribute), new[] { "ValidateDrive" } },787 { typeof(ValidateLengthAttribute), new[] { "ValidateLength" } },788 { typeof(ValidateNotNullAttribute), new[] { "ValidateNotNull" } },789 { typeof(ValidateNotNullOrEmptyAttribute), new[] { "ValidateNotNullOrEmpty" } },790 { typeof(ValidateNotNullOrWhiteSpaceAttribute), new[] { "ValidateNotNullOrWhiteSpace" } },791 { typeof(ValidatePatternAttribute), new[] { "ValidatePattern" } },792 { typeof(ValidateRangeAttribute), new[] { "ValidateRange" } },793 { typeof(ValidateScriptAttribute), new[] { "ValidateScript" } },794 { typeof(ValidateSetAttribute), new[] { "ValidateSet" } },795 { typeof(ValidateTrustedDataAttribute), new[] { "ValidateTrustedData" } },796 { typeof(ValidateUserDriveAttribute), new[] { "ValidateUserDrive"} },797 { typeof(Version), new[] { "version" } },798 { typeof(void), new[] { "void" } },799 { typeof(IPAddress), new[] { "ipaddress" } },800 { typeof(DscLocalConfigurationManagerAttribute), new[] {"DscLocalConfigurationManager"}},801 { typeof(WildcardPattern), new[] { "WildcardPattern" } },802 { typeof(X509Certificate), new[] { "X509Certificate" } },803 { typeof(X500DistinguishedName), new[] { "X500DistinguishedName" } },804 { typeof(XmlDocument), new[] { "xml" } },805 { typeof(CimSession), new[] { "CimSession" } },806 { typeof(MailAddress), new[] { "mailaddress" } },807 { typeof(SemanticVersion), new[] { "semver" } },808#if !UNIX809 { typeof(DirectoryEntry), new[] { "adsi" } },810 { typeof(DirectorySearcher), new[] { "adsisearcher" } },811 { typeof(ManagementClass), new[] { "wmiclass" } },812 { typeof(ManagementObject), new[] { "wmi" } },813 { typeof(ManagementObjectSearcher), new[] { "wmisearcher" } }814#endif815 }816 );817 818 internal static bool Contains(Type inputType)819 {820 if (Items.Value.ContainsKey(inputType))821 {822 return true;823 }824 825 if (inputType.IsEnum)826 {827 return true;828 }829 830 if (inputType.IsGenericType)831 {832 var genericTypeDefinition = inputType.GetGenericTypeDefinition();833 return genericTypeDefinition == typeof(Nullable<>) || genericTypeDefinition == typeof(FlagsExpression<>);834 }835 836 return (inputType.IsArray && Contains(inputType.GetElementType()));837 }838 }839 840 /// <summary>841 /// A class to view and modify the type accelerators used by the PowerShell engine. Builtin842 /// type accelerators are read only, but user defined type accelerators may be added.843 /// </summary>844 internal static class TypeAccelerators845 {846 // builtins are not exposed publicly in a direct manner so they can't be changed at all847 internal static readonly Dictionary<string, Type> builtinTypeAccelerators = new Dictionary<string, Type>(64, StringComparer.OrdinalIgnoreCase);848 849 // users can add to user added accelerators (but not currently remove any.) Keeping a separate850 // list allows us to add removing in the future w/o worrying about breaking the builtins.851 internal static readonly Dictionary<string, Type> userTypeAccelerators = new Dictionary<string, Type>(64, StringComparer.OrdinalIgnoreCase);852 853 // We expose this one publicly for programmatic access to our type accelerator table, but it is854 // otherwise unused (so changes to this dictionary don't affect internals.)855 private static Dictionary<string, Type> s_allTypeAccelerators;856 857 static TypeAccelerators()858 {859 // Add all the core types860 foreach (KeyValuePair<Type, string[]> coreType in CoreTypes.Items.Value)861 {862 if (coreType.Value != null)863 {864 foreach (string accelerator in coreType.Value)865 {866 builtinTypeAccelerators.Add(accelerator, coreType.Key);867 }868 }869 }870 871 // Add additional utility types that are useful as type accelerators, but aren't872 // fundamentally "core language", or may be unsafe to expose to untrusted input.873 builtinTypeAccelerators.Add("scriptblock", typeof(ScriptBlock));874 builtinTypeAccelerators.Add("pspropertyexpression", typeof(PSPropertyExpression));875 builtinTypeAccelerators.Add("psvariable", typeof(PSVariable));876 builtinTypeAccelerators.Add("type", typeof(Type));877 builtinTypeAccelerators.Add("psmoduleinfo", typeof(PSModuleInfo));878 builtinTypeAccelerators.Add("powershell", typeof(PowerShell));879 builtinTypeAccelerators.Add("runspacefactory", typeof(RunspaceFactory));880 builtinTypeAccelerators.Add("runspace", typeof(Runspace));881 builtinTypeAccelerators.Add("initialsessionstate", typeof(InitialSessionState));882 builtinTypeAccelerators.Add("psscriptmethod", typeof(PSScriptMethod));883 builtinTypeAccelerators.Add("psscriptproperty", typeof(PSScriptProperty));884 builtinTypeAccelerators.Add("psnoteproperty", typeof(PSNoteProperty));885 builtinTypeAccelerators.Add("psaliasproperty", typeof(PSAliasProperty));886 builtinTypeAccelerators.Add("psvariableproperty", typeof(PSVariableProperty));887 }888 889 internal static string FindBuiltinAccelerator(Type type, string expectedKey = null)890 {891 // Taking attributes as special case. In this case, we only want to return the892 // accelerator.893 if (expectedKey == null || typeof(Attribute).IsAssignableFrom(type))894 {895 foreach (KeyValuePair<string, Type> entry in builtinTypeAccelerators)896 {897 if (entry.Value == type)898 {899 return entry.Key;900 }901 }902 }903 else904 {905 Type resultType = null;906 builtinTypeAccelerators.TryGetValue(expectedKey, out resultType);907 if (resultType != null && resultType == type)908 {909 return expectedKey;910 }911 }912 913 return null;914 }915 /// <summary>916 /// Add a type accelerator.917 /// </summary>918 /// <param name="typeName">The type accelerator name.</param>919 /// <param name="type">The type of the type accelerator.</param>920 public static void Add(string typeName, Type type)921 {922 userTypeAccelerators[typeName] = type;923 if (s_allTypeAccelerators != null)924 {925 s_allTypeAccelerators[typeName] = type;926 }927 }928 929 /// <summary>930 /// Remove a type accelerator.931 /// </summary>932 /// <returns>True if the accelerator was removed, false otherwise.</returns>933 /// <param name="typeName">The accelerator to remove.</param>934 public static bool Remove(string typeName)935 {936 userTypeAccelerators.Remove(typeName);937 s_allTypeAccelerators?.Remove(typeName);938 939 return true;940 }941 942 /// <summary>943 /// This property is useful to tools that need to know what944 /// type accelerators are available (e.g. to allow for autocompletion.)945 /// </summary>946 /// <remarks>947 /// The returned dictionary should be treated as read only. Changes made948 /// to the dictionary will not affect PowerShell scripts in any way. Use949 /// <see cref="TypeAccelerators.Add"/> and950 /// <see cref="TypeAccelerators.Remove"/> to951 /// affect the type resolution in PowerShell scripts.952 /// </remarks>953 public static Dictionary<string, Type> Get954 {955 get956 {957 if (s_allTypeAccelerators == null)958 {959 s_allTypeAccelerators = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);960 FillCache(s_allTypeAccelerators);961 }962 963 return s_allTypeAccelerators;964 }965 }966 967 internal static void FillCache(Dictionary<string, Type> cache)968 {969 foreach (KeyValuePair<string, Type> val in builtinTypeAccelerators)970 {971 cache.Add(val.Key, val.Value);972 }973 974 foreach (KeyValuePair<string, Type> val in userTypeAccelerators)975 {976 cache.Add(val.Key, val.Value);977 }978 }979 }980}981 