Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes308downloads
DataStoreAdapterProvider.cs689 linesDownload Raw Back to engine
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Collections.ObjectModel;6using System.Linq;7using System.Management.Automation.Provider;8using System.Reflection;9using System.Threading;10 11using Dbg = System.Management.Automation;12 13namespace System.Management.Automation14{15    /// <summary>16    /// Information about a loaded Cmdlet Provider.17    /// </summary>18    /// <remarks>19    /// A cmdlet provider may want to derive from this class to provide their20    /// own public members to expose to the user or to cache information related to the provider.21    /// </remarks>22    public class ProviderInfo23    {24        /// <summary>25        /// Gets the System.Type of the class that implements the provider.26        /// </summary>27        public Type ImplementingType { get; }28 29        /// <summary>30        /// Gets the help file path for the provider.31        /// </summary>32        public string HelpFile { get; } = string.Empty;33 34        /// <summary>35        /// The instance of session state the provider belongs to.36        /// </summary>37        private readonly SessionState _sessionState;38 39        private string _fullName;40        private string _cachedModuleName;41 42        /// <summary>43        /// Gets the name of the provider.44        /// </summary>45        public string Name { get; }46 47        /// <summary>48        /// Gets the full name of the provider including the module name if available.49        /// </summary>50        internal string FullName51        {52            get53            {54                static string GetFullName(string name, string psSnapInName, string moduleName)55                {56                    string result = name;57                    if (!string.IsNullOrEmpty(psSnapInName))58                    {59                        result =60                            string.Format(61                                System.Globalization.CultureInfo.InvariantCulture,62                                "{0}\\{1}",63                                psSnapInName,64                                name);65                    }66 67                    // After converting core snapins to load as modules, the providers will have Module property populated68                    else if (!string.IsNullOrEmpty(moduleName))69                    {70                        result =71                            string.Format(72                                System.Globalization.CultureInfo.InvariantCulture,73                                "{0}\\{1}",74                                moduleName,75                                name);76                    }77 78                    return result;79                }80 81                if (_fullName != null && ModuleName.Equals(_cachedModuleName, StringComparison.Ordinal))82                {83                    return _fullName;84                }85 86                _cachedModuleName = ModuleName;87                return _fullName = GetFullName(Name, PSSnapInName, ModuleName);88            }89        }90 91        /// <summary>92        /// Gets the Snap-in in which the provider is implemented.93        /// </summary>94        public PSSnapInInfo PSSnapIn { get; }95 96        /// <summary>97        /// Gets the pssnapin name that the provider is implemented in.98        /// </summary>99        internal string PSSnapInName100        {101            get102            {103                string result = null;104                if (PSSnapIn != null)105                {106                    result = PSSnapIn.Name;107                }108 109                return result;110            }111        }112 113        internal string ApplicationBase114        {115            get116            {117                string psHome = null;118                try119                {120                    psHome = Utils.DefaultPowerShellAppBase;121                }122                catch (System.Security.SecurityException)123                {124                    psHome = null;125                }126 127                return psHome;128            }129        }130 131        /// <summary>132        /// Get the name of the module exporting this provider.133        /// </summary>134        public string ModuleName135        {136            get137            {138                if (PSSnapIn != null)139                    return PSSnapIn.Name;140                if (Module != null)141                    return Module.Name;142                return string.Empty;143            }144        }145 146        /// <summary>147        /// Gets the module the defined this provider.148        /// </summary>149        public PSModuleInfo Module { get; private set; }150 151        internal void SetModule(PSModuleInfo module)152        {153            Module = module;154            _fullName = null;155        }156 157        /// <summary>158        /// Gets or sets the description for the provider.159        /// </summary>160        public string Description { get; set; }161 162        /// <summary>163        /// Gets the capabilities that are implemented by the provider.164        /// </summary>165        public Provider.ProviderCapabilities Capabilities166        {167            get168            {169                if (!_capabilitiesRead)170                {171                    try172                    {173                        // Get the CmdletProvider declaration attribute174 175                        Type providerType = this.ImplementingType;176 177                        var attrs = providerType.GetCustomAttributes<CmdletProviderAttribute>(false);178                        var cmdletProviderAttributes = attrs as CmdletProviderAttribute[] ?? attrs.ToArray();179 180                        if (cmdletProviderAttributes.Length == 1)181                        {182                            _capabilities = cmdletProviderAttributes[0].ProviderCapabilities;183                            _capabilitiesRead = true;184                        }185                    }186                    catch (Exception) // Catch-all OK, 3rd party callout187                    {188                        // Assume no capabilities for now189                    }190                }191 192                return _capabilities;193            }194        }195 196        private ProviderCapabilities _capabilities = ProviderCapabilities.None;197        private bool _capabilitiesRead;198 199        /// <summary>200        /// Gets or sets the home for the provider.201        /// </summary>202        /// <remarks>203        /// The location can be either a fully qualified provider path204        /// or a PowerShell path. This is the location that is substituted for the ~.205        /// </remarks>206        public string Home { get; set; }207 208        /// <summary>209        /// Gets an enumeration of drives that are available for210        /// this provider.211        /// </summary>212        public Collection<PSDriveInfo> Drives213        {214            get215            {216                return _sessionState.Drive.GetAllForProvider(FullName);217            }218        }219 220        /// <summary>221        /// A hidden drive for the provider that is used for setting222        /// the location to a provider-qualified path.223        /// </summary>224        private readonly PSDriveInfo _hiddenDrive;225 226        /// <summary>227        /// Gets the hidden drive for the provider that is used228        /// for setting a location to a provider-qualified path.229        /// </summary>230        internal PSDriveInfo HiddenDrive231        {232            get233            {234                return _hiddenDrive;235            }236        }237 238        /// <summary>239        /// Gets the string representation of the instance which is the name of the provider.240        /// </summary>241        /// <returns>242        /// The name of the provider. If single-shell, the name is pssnapin-qualified. If custom-shell,243        /// the name is just the provider name.244        /// </returns>245        public override string ToString()246        {247            return FullName;248        }249 250#if USE_TLS251        /// <summary>252        /// Allocates some thread local storage to an instance of the253        /// provider. We don't want to cache a single instance of the254        /// provider because that could lead to problems in a multi-threaded255        /// environment.256        /// </summary>257        private LocalDataStoreSlot instance =258            Thread.AllocateDataSlot();259#endif260 261        /// <summary>262        /// Gets or sets if the drive-root relative paths on drives of this provider263        ///  are separated by a colon or not.264        ///265        /// This is true for all PSDrives on all platforms, except for filesystems on266        /// non-windows platforms.267        /// </summary>268        public bool VolumeSeparatedByColon { get; internal set; } = true;269 270        /// <summary>271        /// Gets the default item separator character for this provider.272        /// </summary>273        public char ItemSeparator { get; private set; }274 275        /// <summary>276        /// Gets the alternate item separator character for this provider.277        /// </summary>278        public char AltItemSeparator { get; private set; }279 280        /// <summary>281        /// Constructs an instance of the class using an existing reference282        /// as a template.283        /// </summary>284        /// <param name="providerInfo">285        /// The provider information to copy to this instance.286        /// </param>287        /// <remarks>288        /// This constructor should be used by derived types to easily copying289        /// the base class members from an existing ProviderInfo.290        /// This is designed for use by a <see cref="System.Management.Automation.Provider.CmdletProvider"/>291        /// during calls to their <see cref="System.Management.Automation.Provider.CmdletProvider.Start(ProviderInfo)"/> method.292        /// </remarks>293        /// <exception cref="ArgumentNullException">294        /// If <paramref name="providerInfo"/> is null.295        /// </exception>296        protected ProviderInfo(ProviderInfo providerInfo)297        {298            if (providerInfo == null)299            {300                throw PSTraceSource.NewArgumentNullException(nameof(providerInfo));301            }302 303            Name = providerInfo.Name;304            ImplementingType = providerInfo.ImplementingType;305            _capabilities = providerInfo._capabilities;306            Description = providerInfo.Description;307            _hiddenDrive = providerInfo._hiddenDrive;308            Home = providerInfo.Home;309            HelpFile = providerInfo.HelpFile;310            PSSnapIn = providerInfo.PSSnapIn;311            _sessionState = providerInfo._sessionState;312            VolumeSeparatedByColon = providerInfo.VolumeSeparatedByColon;313            ItemSeparator = providerInfo.ItemSeparator;314            AltItemSeparator = providerInfo.AltItemSeparator;315        }316 317        /// <summary>318        /// Constructor for the ProviderInfo class.319        /// </summary>320        /// <param name="sessionState">321        /// The instance of session state that the provider is being added to.322        /// </param>323        /// <param name="implementingType">324        /// The type that implements the provider325        /// </param>326        /// <param name="name">327        /// The name of the provider.328        /// </param>329        /// <param name="helpFile">330        /// The help file for the provider.331        /// </param>332        /// <param name="psSnapIn">333        /// The Snap-In name for the provider.334        /// </param>335        /// <exception cref="ArgumentException">336        /// If <paramref name="name"/> is null or empty.337        /// </exception>338        /// <exception cref="ArgumentNullException">339        /// If <paramref name="sessionState"/> is null.340        /// </exception>341        /// <exception cref="ArgumentNullException">342        /// If <paramref name="implementingType"/> is null.343        /// </exception>344        internal ProviderInfo(345            SessionState sessionState,346            Type implementingType,347            string name,348            string helpFile,349            PSSnapInInfo psSnapIn)350            : this(sessionState, implementingType, name, string.Empty, string.Empty, helpFile, psSnapIn)351        {352        }353 354        /// <summary>355        /// Constructor for the ProviderInfo class.356        /// </summary>357        /// <param name="sessionState">358        /// The instance of session state that the provider is being added to.359        /// </param>360        /// <param name="implementingType">361        /// The type that implements the provider362        /// </param>363        /// <param name="name">364        /// The alternate name to use for the provider instead of the one specified365        /// in the .cmdletprovider file.366        /// </param>367        /// <param name="description">368        /// The description of the provider.369        /// </param>370        /// <param name="home">371        /// The home path for the provider. This must be a PowerShell path.372        /// </param>373        /// <param name="helpFile">374        /// The help file for the provider.375        /// </param>376        /// <param name="psSnapIn">377        /// The Snap-In for the provider.378        /// </param>379        /// <exception cref="ArgumentNullException">380        /// If <paramref name="implementingType"/> or <paramref name="sessionState"/> is null.381        /// </exception>382        /// <exception cref="ArgumentException">383        /// If <paramref name="name"/> is null or empty.384        /// </exception>385        internal ProviderInfo(386            SessionState sessionState,387            Type implementingType,388            string name,389            string description,390            string home,391            string helpFile,392            PSSnapInInfo psSnapIn)393        {394            // Verify parameters395            if (sessionState == null)396            {397                throw PSTraceSource.NewArgumentNullException(nameof(sessionState));398            }399 400            if (implementingType == null)401            {402                throw PSTraceSource.NewArgumentNullException(nameof(implementingType));403            }404 405            if (string.IsNullOrEmpty(name))406            {407                throw PSTraceSource.NewArgumentException(nameof(name));408            }409 410            _sessionState = sessionState;411 412            Name = name;413            Description = description;414            Home = home;415            ImplementingType = implementingType;416            HelpFile = helpFile;417            PSSnapIn = psSnapIn;418 419            // Create the hidden drive. The name doesn't really420            // matter since we are not adding this drive to a scope.421 422            _hiddenDrive =423                new PSDriveInfo(424                    this.FullName,425                    this,426                    string.Empty,427                    string.Empty,428                    null);429 430            _hiddenDrive.Hidden = true;431 432            // TODO:PSL433            // this is probably not right here434            if (implementingType == typeof(Microsoft.PowerShell.Commands.FileSystemProvider) && !Platform.IsWindows)435            {436                VolumeSeparatedByColon = false;437            }438        }439 440        /// <summary>441        /// Determines if the passed in name is either the fully-qualified pssnapin name or442        /// short name of the provider.443        /// </summary>444        /// <param name="providerName">445        /// The name to compare with the provider name.446        /// </param>447        /// <returns>448        /// True if the name is the fully-qualified pssnapin name or the short name of the provider.449        /// </returns>450        internal bool NameEquals(string providerName)451        {452            PSSnapinQualifiedName qualifiedProviderName = PSSnapinQualifiedName.GetInstance(providerName);453 454            bool result = false;455            if (qualifiedProviderName != null)456            {457                // If the pssnapin name and provider name are specified, then both must match458                do // false loop459                {460                    if (!string.IsNullOrEmpty(qualifiedProviderName.PSSnapInName))461                    {462                        // After converting core snapins to load as modules, the providers will have Module property populated463                        if (!string.Equals(qualifiedProviderName.PSSnapInName, this.PSSnapInName, StringComparison.OrdinalIgnoreCase) &&464                            !string.Equals(qualifiedProviderName.PSSnapInName, this.ModuleName, StringComparison.OrdinalIgnoreCase))465                        {466                            break;467                        }468                    }469 470                    result = string.Equals(qualifiedProviderName.ShortName, this.Name, StringComparison.OrdinalIgnoreCase);471                } while (false);472            }473            else474            {475                // If only the provider name is specified, then only the name must match476                result = string.Equals(providerName, Name, StringComparison.OrdinalIgnoreCase);477            }478 479            return result;480        }481 482        internal bool IsMatch(string providerName)483        {484            PSSnapinQualifiedName psSnapinQualifiedName = PSSnapinQualifiedName.GetInstance(providerName);485 486            WildcardPattern namePattern = null;487 488            if (psSnapinQualifiedName != null && WildcardPattern.ContainsWildcardCharacters(psSnapinQualifiedName.ShortName))489            {490                namePattern = WildcardPattern.Get(psSnapinQualifiedName.ShortName, WildcardOptions.IgnoreCase);491            }492 493            return IsMatch(namePattern, psSnapinQualifiedName);494        }495 496        internal bool IsMatch(WildcardPattern namePattern, PSSnapinQualifiedName psSnapinQualifiedName)497        {498            bool result = false;499 500            if (psSnapinQualifiedName == null)501            {502                result = true;503            }504            else505            {506                if (namePattern == null)507                {508                    if (string.Equals(Name, psSnapinQualifiedName.ShortName, StringComparison.OrdinalIgnoreCase) &&509                        IsPSSnapinNameMatch(psSnapinQualifiedName))510                    {511                        result = true;512                    }513                }514                else if (namePattern.IsMatch(Name) && IsPSSnapinNameMatch(psSnapinQualifiedName))515                {516                    result = true;517                }518            }519 520            return result;521        }522 523        private bool IsPSSnapinNameMatch(PSSnapinQualifiedName psSnapinQualifiedName)524        {525            bool result = false;526 527            if (string.IsNullOrEmpty(psSnapinQualifiedName.PSSnapInName) ||528                string.Equals(psSnapinQualifiedName.PSSnapInName, PSSnapInName, StringComparison.OrdinalIgnoreCase))529            {530                result = true;531            }532 533            return result;534        }535 536        /// <summary>537        /// Creates an instance of the provider.538        /// </summary>539        /// <returns>540        /// An instance of the provider or null if one could not be created.541        /// </returns>542        /// <exception cref="ProviderNotFoundException">543        /// If an instance of the provider could not be created because the544        /// type could not be found in the assembly.545        /// </exception>546        internal Provider.CmdletProvider CreateInstance()547        {548            // It doesn't really seem that using thread local storage to store an549            // instance of the provider is really much of a performance gain and it550            // still causes problems with the CmdletProviderContext when piping two551            // commands together that use the same provider.552            // get-child -filter a*.txt | get-content553            // This pipeline causes problems when using a cached provider instance because554            // the CmdletProviderContext gets changed when get-content gets called.555            // When get-content finishes writing content from the first output of get-child556            // get-child gets control back and writes out a FileInfo but the WriteObject557            // from get-content gets used because the CmdletProviderContext is still from558            // that cmdlet.559            // Possible solutions are to not cache the provider instance, or to maintain560            // a CmdletProviderContext stack in ProviderBase.  Each method invocation pushes561            // the current context and the last action of the method pops back to the562            // previous context.563#if USE_TLS564            // Next see if we already have an instance in thread local storage565 566            object providerInstance = Thread.GetData(instance);567 568            if (providerInstance == null)569            {570#else571            object providerInstance = null;572#endif573            // Finally create an instance of the class574            Exception invocationException = null;575 576            try577            {578                providerInstance =579                    Activator.CreateInstance(this.ImplementingType);580            }581            catch (TargetInvocationException targetException)582            {583                invocationException = targetException.InnerException;584            }585            catch (MissingMethodException)586            {587            }588            catch (MemberAccessException)589            {590            }591            catch (ArgumentException)592            {593            }594#if USE_TLS595                // cache the instance in thread local storage596 597                Thread.SetData(instance, providerInstance);598            }599#endif600 601            if (providerInstance == null)602            {603                ProviderNotFoundException e = null;604 605                if (invocationException != null)606                {607                    e =608                        new ProviderNotFoundException(609                            this.Name,610                            SessionStateCategory.CmdletProvider,611                            "ProviderCtorException",612                            SessionStateStrings.ProviderCtorException,613                            invocationException.Message);614                }615                else616                {617                    e =618                        new ProviderNotFoundException(619                            this.Name,620                            SessionStateCategory.CmdletProvider,621                            "ProviderNotFoundInAssembly",622                            SessionStateStrings.ProviderNotFoundInAssembly);623                }624 625                throw e;626            }627 628            Provider.CmdletProvider result = providerInstance as Provider.CmdletProvider;629            ItemSeparator = result.ItemSeparator;630            AltItemSeparator = result.AltItemSeparator;631 632            Dbg.Diagnostics.Assert(633                result != null,634                "DiscoverProvider should verify that the class is derived from CmdletProvider so this is just validation of that");635 636            result.SetProviderInformation(this);637            return result;638        }639 640        /// <summary>641        /// Get the output types specified on this provider for the cmdlet requested.642        /// </summary>643        internal void GetOutputTypes(string cmdletname, List<PSTypeName> listToAppend)644        {645            if (_providerOutputType == null)646            {647                _providerOutputType = new Dictionary<string, List<PSTypeName>>();648                foreach (OutputTypeAttribute outputType in ImplementingType.GetCustomAttributes<OutputTypeAttribute>(false))649                {650                    if (string.IsNullOrEmpty(outputType.ProviderCmdlet))651                    {652                        continue;653                    }654 655                    List<PSTypeName> l;656                    if (!_providerOutputType.TryGetValue(outputType.ProviderCmdlet, out l))657                    {658                        l = new List<PSTypeName>();659                        _providerOutputType[outputType.ProviderCmdlet] = l;660                    }661 662                    l.AddRange(outputType.Type);663                }664            }665 666            List<PSTypeName> cmdletOutputType = null;667            if (_providerOutputType.TryGetValue(cmdletname, out cmdletOutputType))668            {669                listToAppend.AddRange(cmdletOutputType);670            }671        }672 673        private Dictionary<string, List<PSTypeName>> _providerOutputType;674 675        private PSNoteProperty _noteProperty;676 677        internal PSNoteProperty GetNotePropertyForProviderCmdlets(string name)678        {679            if (_noteProperty == null)680            {681                Interlocked.CompareExchange(ref _noteProperty,682                                            new PSNoteProperty(name, this), null);683            }684 685            return _noteProperty;686        }687    }688}689