MegaBites-AI/Windows-powershell
0308
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Collections.ObjectModel;6using System.Management.Automation.Provider;7using System.Management.Automation.Runspaces;8using System.Text;9 10using Dbg = System.Management.Automation;11 12#pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings13#pragma warning disable 5650014 15namespace System.Management.Automation16{17 /// <summary>18 /// Holds the state of a PowerShell session.19 /// </summary>20 internal sealed partial class SessionStateInternal21 {22 /// <summary>23 /// A collection of the providers. Any provider in this collection can24 /// have drives in any scope in session state.25 /// </summary>26 internal Dictionary<string, List<ProviderInfo>> Providers27 {28 get29 {30 if (this == ExecutionContext.TopLevelSessionState)31 return _providers;32 return ExecutionContext.TopLevelSessionState.Providers;33 }34 }35 36 private Dictionary<string, List<ProviderInfo>> _providers =37 new Dictionary<string, List<ProviderInfo>>(38 SessionStateConstants.DefaultDictionaryCapacity, StringComparer.OrdinalIgnoreCase);39 40 /// <summary>41 /// Stores the current working drive for each provider. This42 /// allows for retrieving the current working directory for each43 /// individual provider.44 /// </summary>45 internal Dictionary<ProviderInfo, PSDriveInfo> ProvidersCurrentWorkingDrive46 {47 get48 {49 if (this == ExecutionContext.TopLevelSessionState)50 return _providersCurrentWorkingDrive;51 return ExecutionContext.TopLevelSessionState.ProvidersCurrentWorkingDrive;52 }53 }54 55 private readonly Dictionary<ProviderInfo, PSDriveInfo> _providersCurrentWorkingDrive = new Dictionary<ProviderInfo, PSDriveInfo>();56 57 /// <summary>58 /// Entrypoint used by to add a provider to the current session state59 /// based on a SessionStateProviderEntry.60 /// </summary>61 /// <param name="providerEntry"></param>62 internal void AddSessionStateEntry(SessionStateProviderEntry providerEntry)63 {64 AddProvider(providerEntry.ImplementingType,65 providerEntry.Name,66 providerEntry.HelpFileName,67 providerEntry.PSSnapIn,68 providerEntry.Module);69 }70 71 private ProviderInfo AddProvider(Type implementingType, string name, string helpFileName, PSSnapInInfo psSnapIn, PSModuleInfo module)72 {73 ProviderInfo provider = null;74 75 try76 {77 provider =78 new ProviderInfo(79 new SessionState(this),80 implementingType,81 name,82 helpFileName,83 psSnapIn);84 provider.SetModule(module);85 86 NewProvider(provider);87 88 // Log the provider start event89 90 MshLog.LogProviderLifecycleEvent(91 this.ExecutionContext,92 provider.Name,93 ProviderState.Started);94 }95 catch (LoopFlowException)96 {97 throw;98 }99 catch (PipelineStoppedException)100 {101 throw;102 }103 catch (ActionPreferenceStopException)104 {105 throw;106 }107 catch (SessionStateException sessionStateException)108 {109 if (sessionStateException.GetType() == typeof(SessionStateException))110 {111 throw;112 }113 else114 {115 // NTRAID#Windows OS Bugs-1009281-2004/02/11-JeffJon116 this.ExecutionContext.ReportEngineStartupError(sessionStateException);117 }118 }119 catch (Exception e) // Catch-all OK, 3rd party callout120 {121 // NTRAID#Windows OS Bugs-1009281-2004/02/11-JeffJon122 this.ExecutionContext.ReportEngineStartupError(e);123 }124 125 return provider;126 }127 128 /// <summary>129 /// Determines the appropriate provider for the drive and then calls the NewDrive130 /// method of that provider.131 /// </summary>132 /// <param name="drive">133 /// The drive to have the provider verify.134 /// </param>135 /// <param name="context">136 /// The command context under which the drive is being added.137 /// </param>138 /// <param name="resolvePathIfPossible">139 /// If true, the drive root will be resolved as an MSH path before verifying with140 /// the provider. If false, the path is assumed to be a provider-internal path.141 /// </param>142 /// <returns>143 /// The instance of the drive to be added as approved by the provider.144 /// </returns>145 /// <exception cref="NotSupportedException">146 /// If the provider is not a DriveCmdletProvider.147 /// </exception>148 /// <exception cref="ProviderNotFoundException">149 /// The provider for the <paramref name="drive"/> could not be found.150 /// </exception>151 /// <exception cref="ProviderInvocationException">152 /// If the provider throws an exception while validating the drive.153 /// </exception>154 private PSDriveInfo ValidateDriveWithProvider(PSDriveInfo drive, CmdletProviderContext context, bool resolvePathIfPossible)155 {156 Dbg.Diagnostics.Assert(157 drive != null,158 "drive should have been validated by the caller");159 160 DriveCmdletProvider namespaceProvider =161 GetDriveProviderInstance(drive.Provider);162 163 return ValidateDriveWithProvider(namespaceProvider, drive, context, resolvePathIfPossible);164 }165 166 private PSDriveInfo ValidateDriveWithProvider(167 DriveCmdletProvider driveProvider,168 PSDriveInfo drive,169 CmdletProviderContext context,170 bool resolvePathIfPossible)171 {172 Dbg.Diagnostics.Assert(173 drive != null,174 "drive should have been validated by the caller");175 176 Dbg.Diagnostics.Assert(177 driveProvider != null,178 "driveProvider should have been validated by the caller");179 180 // Mark the drive as being created so that the provider can modify the181 // root if necessary182 183 drive.DriveBeingCreated = true;184 185 // Only try to resolve the root as an MSH path if there is a current drive.186 187 if (CurrentDrive != null && resolvePathIfPossible)188 {189 string newRoot = GetProviderRootFromSpecifiedRoot(drive.Root, drive.Provider);190 191 if (newRoot != null)192 {193 drive.SetRoot(newRoot);194 }195 }196 197 PSDriveInfo result = null;198 199 try200 {201 result = driveProvider.NewDrive(drive, context);202 }203 catch (LoopFlowException)204 {205 throw;206 }207 catch (PipelineStoppedException)208 {209 throw;210 }211 catch (ActionPreferenceStopException)212 {213 throw;214 }215 catch (Exception e) // Catch-all OK, 3rd party callout216 {217 ProviderInvocationException pie =218 NewProviderInvocationException(219 "NewDriveProviderException",220 SessionStateStrings.NewDriveProviderException,221 driveProvider.ProviderInfo,222 drive.Root,223 e);224 context.WriteError(225 new ErrorRecord(226 pie.ErrorRecord,227 pie));228 }229 finally230 {231 drive.DriveBeingCreated = false;232 }233 234 return result;235 }236 237 /// <summary>238 /// Gets an instance of a provider given the provider ID.239 /// </summary>240 /// <param name="providerId">241 /// The identifier for the provider to return an instance of.242 /// </param>243 /// <returns>244 /// An instance of the specified provider.245 /// </returns>246 /// <exception cref="ArgumentNullException">247 /// If <paramref name="providerId"/> is null.248 /// </exception>249 /// <exception cref="ProviderNotFoundException">250 /// If the <paramref name="providerId"/> refers to a provider that doesn't exist or251 /// the name passed matched multiple providers.252 /// </exception>253 internal Provider.CmdletProvider GetProviderInstance(string providerId)254 {255 if (providerId == null)256 {257 throw PSTraceSource.NewArgumentNullException(nameof(providerId));258 }259 260 ProviderInfo provider = GetSingleProvider(providerId);261 262 return GetProviderInstance(provider);263 }264 265 /// <summary>266 /// Gets an instance of a provider given the provider information.267 /// </summary>268 /// <param name="provider">269 /// The provider to return an instance of.270 /// </param>271 /// <returns>272 /// An instance of the specified provider.273 /// </returns>274 /// <exception cref="ArgumentNullException">275 /// If <paramref name="provider"/> is null.276 /// </exception>277 internal Provider.CmdletProvider GetProviderInstance(ProviderInfo provider)278 {279 if (provider == null)280 {281 throw PSTraceSource.NewArgumentNullException(nameof(provider));282 }283 284 return provider.CreateInstance();285 }286 287 /// <summary>288 /// Creates an exception for the case where the provider name matched multiple providers.289 /// </summary>290 /// <param name="name">291 /// The name of the provider.292 /// </param>293 /// <param name="matchingProviders">294 /// The ProviderInfo of the possible matches.295 /// </param>296 /// <returns>297 /// An exception representing the error with a message stating which providers are possible matches.298 /// </returns>299 internal static ProviderNameAmbiguousException NewAmbiguousProviderName(string name, Collection<ProviderInfo> matchingProviders)300 {301 string possibleMatches = GetPossibleMatches(matchingProviders);302 303 ProviderNameAmbiguousException e =304 new ProviderNameAmbiguousException(305 name,306 "ProviderNameAmbiguous",307 SessionStateStrings.ProviderNameAmbiguous,308 matchingProviders,309 possibleMatches);310 311 return e;312 }313 314 private static string GetPossibleMatches(Collection<ProviderInfo> matchingProviders)315 {316 StringBuilder possibleMatches = new StringBuilder();317 318 foreach (ProviderInfo matchingProvider in matchingProviders)319 {320 possibleMatches.Append(' ');321 possibleMatches.Append(matchingProvider.FullName);322 }323 324 return possibleMatches.ToString();325 }326 327 /// <summary>328 /// Gets an instance of an DriveCmdletProvider given the provider ID.329 /// </summary>330 /// <param name="providerId">331 /// The provider ID of the provider to get an instance of.332 /// </param>333 /// <returns>334 /// An instance of a DriveCmdletProvider for the specified provider ID.335 /// </returns>336 /// <exception cref="ArgumentNullException">337 /// if <paramref name="providerId"/> is null.338 /// </exception>339 /// <exception cref="NotSupportedException">340 /// if the <paramref name="providerId"/> is not for a provider341 /// that is derived from NavigationCmdletProvider.342 /// </exception>343 /// <exception cref="ProviderNotFoundException">344 /// If the <paramref name="providerId"/> refers to a provider that doesn't exist.345 /// </exception>346 internal DriveCmdletProvider GetDriveProviderInstance(string providerId)347 {348 if (providerId == null)349 {350 throw PSTraceSource.NewArgumentNullException(nameof(providerId));351 }352 353 if (GetProviderInstance(providerId) is not DriveCmdletProvider driveCmdletProvider)354 {355 throw356 PSTraceSource.NewNotSupportedException(SessionStateStrings.DriveCmdletProvider_NotSupported);357 }358 359 return driveCmdletProvider;360 }361 362 /// <summary>363 /// Gets an instance of an DriveCmdletProvider given the provider information.364 /// </summary>365 /// <param name="provider">366 /// The provider to get an instance of.367 /// </param>368 /// <returns>369 /// An instance of a DriveCmdletProvider for the specified provider.370 /// </returns>371 /// <exception cref="ArgumentNullException">372 /// if <paramref name="provider"/> is null.373 /// </exception>374 /// <exception cref="NotSupportedException">375 /// if the <paramref name="provider"/> is not for a provider376 /// that is derived from NavigationCmdletProvider.377 /// </exception>378 internal DriveCmdletProvider GetDriveProviderInstance(ProviderInfo provider)379 {380 if (provider == null)381 {382 throw PSTraceSource.NewArgumentNullException(nameof(provider));383 }384 385 if (GetProviderInstance(provider) is not DriveCmdletProvider driveCmdletProvider)386 {387 throw388 PSTraceSource.NewNotSupportedException(SessionStateStrings.DriveCmdletProvider_NotSupported);389 }390 391 return driveCmdletProvider;392 }393 394 /// <summary>395 /// Gets an instance of an DriveCmdletProvider given the provider ID.396 /// </summary>397 /// <param name="providerInstance">398 /// The instance of the provider to use.399 /// </param>400 /// <returns>401 /// An instance of a DriveCmdletProvider for the specified provider ID.402 /// </returns>403 /// <exception cref="ArgumentNullException">404 /// if <paramref name="providerInstance"/> is null.405 /// </exception>406 /// <exception cref="NotSupportedException">407 /// if the <paramref name="providerInstance"/> is not for a provider408 /// that is derived from DriveCmdletProvider.409 /// </exception>410 private static DriveCmdletProvider GetDriveProviderInstance(CmdletProvider providerInstance)411 {412 if (providerInstance == null)413 {414 throw PSTraceSource.NewArgumentNullException(nameof(providerInstance));415 }416 417 if (providerInstance is not DriveCmdletProvider driveCmdletProvider)418 {419 throw420 PSTraceSource.NewNotSupportedException(SessionStateStrings.DriveCmdletProvider_NotSupported);421 }422 423 return driveCmdletProvider;424 }425 426 /// <summary>427 /// Gets an instance of an ItemCmdletProvider given the provider ID.428 /// </summary>429 /// <param name="providerId">430 /// The provider ID of the provider to get an instance of.431 /// </param>432 /// <returns>433 /// An instance of a ItemCmdletProvider for the specified provider ID.434 /// </returns>435 /// <exception cref="ArgumentNullException">436 /// if <paramref name="providerId"/> is null.437 /// </exception>438 /// <exception cref="NotSupportedException">439 /// if the <paramref name="providerId"/> is not for a provider440 /// that is derived from NavigationCmdletProvider.441 /// </exception>442 /// <exception cref="ProviderNotFoundException">443 /// If the <paramref name="providerId"/> refers to a provider that doesn't exist.444 /// </exception>445 internal ItemCmdletProvider GetItemProviderInstance(string providerId)446 {447 if (providerId == null)448 {449 throw PSTraceSource.NewArgumentNullException(nameof(providerId));450 }451 452 if (GetProviderInstance(providerId) is not ItemCmdletProvider itemCmdletProvider)453 {454 throw455 PSTraceSource.NewNotSupportedException(SessionStateStrings.ItemCmdletProvider_NotSupported);456 }457 458 return itemCmdletProvider;459 }460 461 /// <summary>462 /// Gets an instance of an ItemCmdletProvider given the provider.463 /// </summary>464 /// <param name="provider">465 /// The provider to get an instance of.466 /// </param>467 /// <returns>468 /// An instance of a ItemCmdletProvider for the specified provider.469 /// </returns>470 /// <exception cref="ArgumentNullException">471 /// if <paramref name="provider"/> is null.472 /// </exception>473 /// <exception cref="NotSupportedException">474 /// if the <paramref name="provider"/> is not for a provider475 /// that is derived from NavigationCmdletProvider.476 /// </exception>477 internal ItemCmdletProvider GetItemProviderInstance(ProviderInfo provider)478 {479 if (provider == null)480 {481 throw PSTraceSource.NewArgumentNullException(nameof(provider));482 }483 484 if (GetProviderInstance(provider) is not ItemCmdletProvider itemCmdletProvider)485 {486 throw487 PSTraceSource.NewNotSupportedException(SessionStateStrings.ItemCmdletProvider_NotSupported);488 }489 490 return itemCmdletProvider;491 }492 493 /// <summary>494 /// Gets an instance of an ItemCmdletProvider given the provider ID.495 /// </summary>496 /// <param name="providerInstance">497 /// The instance of the provider to use.498 /// </param>499 /// <returns>500 /// An instance of a ItemCmdletProvider for the specified provider ID.501 /// </returns>502 /// <exception cref="ArgumentNullException">503 /// if <paramref name="providerInstance"/> is null.504 /// </exception>505 /// <exception cref="NotSupportedException">506 /// if the <paramref name="providerInstance"/> is not for a provider507 /// that is derived from ItemCmdletProvider.508 /// </exception>509 private static ItemCmdletProvider GetItemProviderInstance(CmdletProvider providerInstance)510 {511 if (providerInstance == null)512 {513 throw PSTraceSource.NewArgumentNullException(nameof(providerInstance));514 }515 516 if (providerInstance is not ItemCmdletProvider itemCmdletProvider)517 {518 throw519 PSTraceSource.NewNotSupportedException(SessionStateStrings.ItemCmdletProvider_NotSupported);520 }521 522 return itemCmdletProvider;523 }524 525 /// <summary>526 /// Gets an instance of an ContainerCmdletProvider given the provider ID.527 /// </summary>528 /// <param name="providerId">529 /// The provider ID of the provider to get an instance of.530 /// </param>531 /// <returns>532 /// An instance of a ContainerCmdletProvider for the specified provider ID.533 /// </returns>534 /// <exception cref="ArgumentNullException">535 /// if <paramref name="providerId"/> is null.536 /// </exception>537 /// <exception cref="NotSupportedException">538 /// if the <paramref name="providerId"/> is not for a provider539 /// that is derived from NavigationCmdletProvider.540 /// </exception>541 /// <exception cref="ProviderNotFoundException">542 /// If the <paramref name="providerId"/> refers to a provider that doesn't exist.543 /// </exception>544 internal ContainerCmdletProvider GetContainerProviderInstance(string providerId)545 {546 if (providerId == null)547 {548 throw PSTraceSource.NewArgumentNullException(nameof(providerId));549 }550 551 if (GetProviderInstance(providerId) is not ContainerCmdletProvider containerCmdletProvider)552 {553 throw554 PSTraceSource.NewNotSupportedException(SessionStateStrings.ContainerCmdletProvider_NotSupported);555 }556 557 return containerCmdletProvider;558 }559 560 /// <summary>561 /// Gets an instance of an ContainerCmdletProvider given the provider.562 /// </summary>563 /// <param name="provider">564 /// The provider to get an instance of.565 /// </param>566 /// <returns>567 /// An instance of a ContainerCmdletProvider for the specified provider.568 /// </returns>569 /// <exception cref="ArgumentNullException">570 /// if <paramref name="provider"/> is null.571 /// </exception>572 /// <exception cref="NotSupportedException">573 /// if the <paramref name="provider"/> is not for a provider574 /// that is derived from NavigationCmdletProvider.575 /// </exception>576 internal ContainerCmdletProvider GetContainerProviderInstance(ProviderInfo provider)577 {578 if (provider == null)579 {580 throw PSTraceSource.NewArgumentNullException(nameof(provider));581 }582 583 if (GetProviderInstance(provider) is not ContainerCmdletProvider containerCmdletProvider)584 {585 throw586 PSTraceSource.NewNotSupportedException(SessionStateStrings.ContainerCmdletProvider_NotSupported);587 }588 589 return containerCmdletProvider;590 }591 592 /// <summary>593 /// Gets an instance of an ContainerCmdletProvider given the provider ID.594 /// </summary>595 /// <param name="providerInstance">596 /// The instance of the provider to use.597 /// </param>598 /// <returns>599 /// An instance of a ContainerCmdletProvider for the specified provider ID.600 /// </returns>601 /// <exception cref="ArgumentNullException">602 /// if <paramref name="providerInstance"/> is null.603 /// </exception>604 /// <exception cref="NotSupportedException">605 /// if the <paramref name="providerInstance"/> is not for a provider606 /// that is derived from ContainerCmdletProvider.607 /// </exception>608 private static ContainerCmdletProvider GetContainerProviderInstance(CmdletProvider providerInstance)609 {610 if (providerInstance == null)611 {612 throw PSTraceSource.NewArgumentNullException(nameof(providerInstance));613 }614 615 if (providerInstance is not ContainerCmdletProvider containerCmdletProvider)616 {617 throw618 PSTraceSource.NewNotSupportedException(SessionStateStrings.ContainerCmdletProvider_NotSupported);619 }620 621 return containerCmdletProvider;622 }623 624 /// <summary>625 /// Gets an instance of an NavigationCmdletProvider given the provider.626 /// </summary>627 /// <param name="provider">628 /// The provider to get an instance of.629 /// </param>630 /// <returns>631 /// An instance of a NavigationCmdletProvider for the specified provider ID.632 /// </returns>633 /// <exception cref="ArgumentNullException">634 /// if <paramref name="provider"/> is null.635 /// </exception>636 /// <exception cref="NotSupportedException">637 /// if the <paramref name="provider"/> is not for a provider638 /// that is derived from NavigationCmdletProvider.639 /// </exception>640 internal NavigationCmdletProvider GetNavigationProviderInstance(ProviderInfo provider)641 {642 if (provider == null)643 {644 throw PSTraceSource.NewArgumentNullException(nameof(provider));645 }646 647 if (GetProviderInstance(provider) is not NavigationCmdletProvider navigationCmdletProvider)648 {649 throw650 PSTraceSource.NewNotSupportedException(SessionStateStrings.NavigationCmdletProvider_NotSupported);651 }652 653 return navigationCmdletProvider;654 }655 656 /// <summary>657 /// Gets an instance of an NavigationCmdletProvider given the provider ID.658 /// </summary>659 /// <param name="providerInstance">660 /// The instance of the provider to use.661 /// </param>662 /// <param name="acceptNonContainerProviders">663 /// Specify True if the method should just return the Path if the664 /// provider doesn't support container overloads.665 /// </param>666 /// <returns>667 /// An instance of a NavigationCmdletProvider for the specified provider ID.668 /// </returns>669 /// <exception cref="ArgumentNullException">670 /// if <paramref name="providerInstance"/> is null.671 /// </exception>672 /// <exception cref="NotSupportedException">673 /// if the <paramref name="providerInstance"/> is not for a provider674 /// that is derived from NavigationCmdletProvider.675 /// </exception>676 private static NavigationCmdletProvider GetNavigationProviderInstance(CmdletProvider providerInstance, bool acceptNonContainerProviders)677 {678 if (providerInstance == null)679 {680 throw PSTraceSource.NewArgumentNullException(nameof(providerInstance));681 }682 683 NavigationCmdletProvider navigationCmdletProvider =684 providerInstance as NavigationCmdletProvider;685 686 if ((navigationCmdletProvider == null) && (!acceptNonContainerProviders))687 {688 throw689 PSTraceSource.NewNotSupportedException(SessionStateStrings.NavigationCmdletProvider_NotSupported);690 }691 692 return navigationCmdletProvider;693 }694 695 #region GetProvider696 697 /// <summary>698 /// Determines if the specified CmdletProvider is loaded.699 /// </summary>700 /// <param name="name">701 /// The name of the CmdletProvider.702 /// </param>703 /// <returns>704 /// true if the CmdletProvider is loaded, or false otherwise.705 /// </returns>706 /// <exception cref="ArgumentException">707 /// If <paramref name="name"/> is null or empty.708 /// </exception>709 internal bool IsProviderLoaded(string name)710 {711 bool result = false;712 713 if (string.IsNullOrEmpty(name))714 {715 throw PSTraceSource.NewArgumentException(nameof(name));716 }717 718 // Get the provider from the providers container719 720 try721 {722 ProviderInfo providerInfo = GetSingleProvider(name);723 724 result = providerInfo != null;725 }726 catch (ProviderNotFoundException)727 {728 }729 730 return result;731 }732 733 /// <summary>734 /// Gets the provider of the specified name.735 /// </summary>736 /// <param name="name">737 /// The name of the provider to retrieve738 /// </param>739 /// <returns>740 /// The provider of the given name741 /// </returns>742 /// <exception cref="ArgumentException">743 /// If <paramref name="name"/> is null or empty.744 /// </exception>745 /// <exception cref="ProviderNotFoundException">746 /// The provider with the specified <paramref name="name"/>747 /// could not be found.748 /// </exception>749 internal Collection<ProviderInfo> GetProvider(string name)750 {751 if (string.IsNullOrEmpty(name))752 {753 throw PSTraceSource.NewArgumentException(nameof(name));754 }755 756 PSSnapinQualifiedName providerName = PSSnapinQualifiedName.GetInstance(name);757 758 if (providerName == null)759 {760 ProviderNotFoundException e =761 new ProviderNotFoundException(762 name,763 SessionStateCategory.CmdletProvider,764 "ProviderNotFoundBadFormat",765 SessionStateStrings.ProviderNotFoundBadFormat);766 767 throw e;768 }769 770 return GetProvider(providerName);771 }772 773 /// <summary>774 /// Gets the provider of the specified name.775 /// </summary>776 /// <param name="name">777 /// The name of the provider to retrieve778 /// </param>779 /// <returns>780 /// The provider of the given name781 /// </returns>782 /// <exception cref="ArgumentException">783 /// If <paramref name="name"/> is null or empty.784 /// </exception>785 /// <exception cref="ProviderNotFoundException">786 /// The provider with the specified <paramref name="name"/>787 /// could not be found or the name was ambiguous.788 /// If the name is ambiguous then the PSSnapin qualified name must789 /// be specified.790 /// </exception>791 internal ProviderInfo GetSingleProvider(string name)792 {793 Collection<ProviderInfo> matchingProviders = GetProvider(name);794 795 if (matchingProviders.Count != 1)796 {797 if (matchingProviders.Count == 0)798 {799 ProviderNotFoundException e =800 new ProviderNotFoundException(801 name,802 SessionStateCategory.CmdletProvider,803 "ProviderNotFound",804 SessionStateStrings.ProviderNotFound);805 806 throw e;807 }808 else809 {810 throw NewAmbiguousProviderName(name, matchingProviders);811 }812 }813 814 return matchingProviders[0];815 }816 817 internal Collection<ProviderInfo> GetProvider(PSSnapinQualifiedName providerName)818 {819 Collection<ProviderInfo> result = new Collection<ProviderInfo>();820 821 if (providerName == null)822 {823 ProviderNotFoundException e =824 new ProviderNotFoundException(825 "null",826 SessionStateCategory.CmdletProvider,827 "ProviderNotFound",828 SessionStateStrings.ProviderNotFound);829 830 throw e;831 }832 833 // Get the provider from the providers container834 835 List<ProviderInfo> matchingProviders = null;836 837 if (!Providers.TryGetValue(providerName.ShortName, out matchingProviders))838 {839 // If the provider was not found, we may need to auto-mount it.840 SessionStateInternal.MountDefaultDrive(providerName.ShortName, ExecutionContext);841 842 if (!Providers.TryGetValue(providerName.ShortName, out matchingProviders))843 {844 ProviderNotFoundException e =845 new ProviderNotFoundException(846 providerName.ToString(),847 SessionStateCategory.CmdletProvider,848 "ProviderNotFound",849 SessionStateStrings.ProviderNotFound);850 851 throw e;852 }853 }854 855 if (!string.IsNullOrEmpty(providerName.PSSnapInName))856 {857 // Be sure the PSSnapin/Module name matches858 859 foreach (ProviderInfo provider in matchingProviders)860 {861 if (string.Equals(862 provider.PSSnapInName,863 providerName.PSSnapInName,864 StringComparison.OrdinalIgnoreCase) ||865 string.Equals(866 provider.ModuleName,867 providerName.PSSnapInName,868 StringComparison.OrdinalIgnoreCase))869 {870 result.Add(provider);871 }872 }873 }874 else875 {876 foreach (ProviderInfo provider in matchingProviders)877 {878 result.Add(provider);879 }880 }881 882 return result;883 }884 885 /// <summary>886 /// Gets all the CoreCommandProviders.887 /// </summary>888 internal IEnumerable<ProviderInfo> ProviderList889 {890 get891 {892 Collection<ProviderInfo> result = new Collection<ProviderInfo>();893 894 foreach (List<ProviderInfo> providerValues in Providers.Values)895 {896 foreach (ProviderInfo provider in providerValues)897 {898 result.Add(provider);899 }900 }901 902 return result;903 }904 }905 906 /// <summary>907 /// Copy the Providers from another session state instance...908 /// </summary>909 /// <param name="ss">The session state instance to copy from...</param>910 internal void CopyProviders(SessionStateInternal ss)911 {912 if (ss == null || ss.Providers == null)913 return;914 915 // private Dictionary<string, List<ProviderInfo>> providers;916 _providers = new Dictionary<string, List<ProviderInfo>>();917 918 foreach (KeyValuePair<string, List<ProviderInfo>> e in ss._providers)919 {920 _providers.Add(e.Key, e.Value);921 }922 }923 924 #endregion GetProvider925 926 #region NewProvider927 928 /// <summary>929 /// Initializes a provider by loading the assembly, creating an instance of the930 /// provider, calling its start method followed by the InitializeDefaultDrives method. The931 /// Drives that are returned from the InitializeDefaultDrives method are then mounted.932 /// </summary>933 /// <param name="providerInstance">934 /// An instance of the provider to use for the initialization.935 /// </param>936 /// <param name="provider">937 /// The provider to be initialized.938 /// </param>939 /// <param name="context">940 /// The context under which the initialization is occurring. If this parameter is not941 /// null, errors will be written to the WriteError method of the context.942 /// </param>943 /// <exception cref="ArgumentNullException">944 /// If <paramref name="provider"/> or <paramref name="context"/> is null.945 /// </exception>946 /// <exception cref="NotSupportedException">947 /// If the provider is not a DriveCmdletProvider.948 /// </exception>949 /// <exception cref="SessionStateException">950 /// If a drive already exists for the name of one of the drives the951 /// provider tries to add.952 /// </exception>953 internal void InitializeProvider(954 Provider.CmdletProvider providerInstance,955 ProviderInfo provider,956 CmdletProviderContext context)957 {958 if (provider == null)959 {960 throw PSTraceSource.NewArgumentNullException(nameof(provider));961 }962 963 context ??= new CmdletProviderContext(this.ExecutionContext);964 965 // Initialize the provider so that it can add any drives966 // that it needs.967 968 List<PSDriveInfo> newDrives = new List<PSDriveInfo>();969 DriveCmdletProvider driveProvider =970 GetDriveProviderInstance(providerInstance);971 972 if (driveProvider != null)973 {974 try975 {976 Collection<PSDriveInfo> drives = driveProvider.InitializeDefaultDrives(context);977 if (drives != null && drives.Count > 0)978 {979 newDrives.AddRange(drives);980 ProvidersCurrentWorkingDrive[provider] = drives[0];981 }982 }983 catch (LoopFlowException)984 {985 throw;986 }987 catch (PipelineStoppedException)988 {989 throw;990 }991 catch (ActionPreferenceStopException)992 {993 throw;994 }995 catch (Exception e) // Catch-all OK, 3rd party callout996 {997 ProviderInvocationException providerException =998 NewProviderInvocationException(999 "InitializeDefaultDrivesException",1000 SessionStateStrings.InitializeDefaultDrivesException,1001 provider,1002 string.Empty,1003 e);1004 1005 context.WriteError(1006 new ErrorRecord(1007 providerException,1008 "InitializeDefaultDrivesException",1009 ErrorCategory.InvalidOperation,1010 provider));1011 }1012 }1013 1014 if (newDrives != null && newDrives.Count > 0)1015 {1016 // Add the drives.1017 1018 foreach (PSDriveInfo newDrive in newDrives)1019 {1020 if (newDrive == null)1021 {1022 continue;1023 }1024 1025 // Only mount drives for the current provider1026 1027 if (!provider.NameEquals(newDrive.Provider.FullName))1028 {1029 continue;1030 }1031 1032 try1033 {1034 PSDriveInfo validatedNewDrive = ValidateDriveWithProvider(driveProvider, newDrive, context, false);1035 1036 if (validatedNewDrive != null)1037 {1038 // Since providers are global then the drives created1039 // through InitializeDefaultDrives should also be global.1040 1041 GlobalScope.NewDrive(validatedNewDrive);1042 }1043 }1044 catch (SessionStateException exception)1045 {1046 context.WriteError(exception.ErrorRecord);1047 }1048 }1049 }1050 }1051 1052 /// <summary>1053 /// Creates and adds a provider to the provider container.1054 /// </summary>1055 /// <param name="provider">1056 /// The provider to add.1057 /// </param>1058 /// <returns>1059 /// The provider that was added or null if the provider failed to be added.1060 /// </returns>1061 /// <exception cref="ArgumentNullException">1062 /// If <paramref name="provider"/> is null.1063 /// </exception>1064 /// <exception cref="SessionStateException">1065 /// If the provider already exists.1066 /// </exception>1067 /// <exception cref="ProviderInvocationException">1068 /// If there was a failure to load the provider or the provider1069 /// threw an exception.1070 /// </exception>1071 internal ProviderInfo NewProvider(ProviderInfo provider)1072 {1073 if (provider == null)1074 {1075 throw PSTraceSource.NewArgumentNullException(nameof(provider));1076 }1077 1078 // Check to see if the provider already exists.1079 // We do the check instead of allowing the hashtable to1080 // throw the exception so that we give a better error1081 // message.1082 ProviderInfo existingProvider = ProviderExists(provider);1083 if (existingProvider != null)1084 {1085 // If it's an already loaded provider, don't return an error...1086 if (existingProvider.ImplementingType == provider.ImplementingType)1087 return existingProvider;1088 1089 SessionStateException sessionStateException =1090 new SessionStateException(1091 provider.Name,1092 SessionStateCategory.CmdletProvider,1093 "CmdletProviderAlreadyExists",1094 SessionStateStrings.CmdletProviderAlreadyExists,1095 ErrorCategory.ResourceExists);1096 1097 throw sessionStateException;1098 }1099 1100 // Make sure we are able to create an instance of the provider.1101 // Note, this will also set the friendly name if the user didn't1102 // specify one.1103 1104 Provider.CmdletProvider providerInstance = provider.CreateInstance();1105 1106 // Now call start to let the provider initialize itself1107 CmdletProviderContext context = new CmdletProviderContext(this.ExecutionContext);1108 ProviderInfo newProviderInfo = null;1109 1110 try1111 {1112 newProviderInfo = providerInstance.Start(provider, context);1113 1114 // Set the new provider info in the instance in case the provider1115 // derived a new one1116 1117 providerInstance.SetProviderInformation(newProviderInfo);1118 }1119 catch (LoopFlowException)1120 {1121 throw;1122 }1123 catch (PipelineStoppedException)1124 {1125 throw;1126 }1127 catch (ActionPreferenceStopException)1128 {1129 throw;1130 }1131 catch (InvalidOperationException)1132 {1133 throw;1134 }1135 catch (Exception e) // Catch-call OK, 3rd party callout1136 {1137 throw1138 NewProviderInvocationException(1139 "ProviderStartException",1140 SessionStateStrings.ProviderStartException,1141 provider,1142 null,1143 e);1144 }1145 1146 context.ThrowFirstErrorOrDoNothing(true);1147 1148 if (newProviderInfo == null)1149 {1150 throw1151 PSTraceSource.NewInvalidOperationException(1152 SessionStateStrings.InvalidProviderInfoNull);1153 }1154 1155 if (newProviderInfo != provider)1156 {1157 // Since the references are not the same, ensure that the provider1158 // name is the same.1159 1160 if (!string.Equals(newProviderInfo.Name, provider.Name, StringComparison.OrdinalIgnoreCase))1161 {1162 throw1163 PSTraceSource.NewInvalidOperationException(1164 SessionStateStrings.InvalidProviderInfo);1165 }1166 1167 // Use the new provider info instead1168 provider = newProviderInfo;1169 }1170 1171 // Add the newly create provider to the providers container1172 1173 try1174 {1175 NewProviderEntry(provider);1176 }1177 catch (ArgumentException)1178 {1179 SessionStateException sessionStateException =1180 new SessionStateException(1181 provider.Name,1182 SessionStateCategory.CmdletProvider,1183 "CmdletProviderAlreadyExists",1184 SessionStateStrings.CmdletProviderAlreadyExists,1185 ErrorCategory.ResourceExists);1186 1187 throw sessionStateException;1188 }1189 1190 // Add the provider to the provider current working1191 // drive hashtable so that we can associate a current working1192 // drive with it.1193 1194 ProvidersCurrentWorkingDrive.Add(provider, null);1195 1196 bool initializeProviderError = false;1197 try1198 {1199 // Initialize the provider and give it a chance to1200 // mount some drives.