MegaBites-AI/Windows-powershell
0372
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.Text;8 9using Dbg = System.Management.Automation;10 11namespace System.Management.Automation12{13 /// <summary>14 /// Implements the interfaces used by navigation commands to work with15 /// the virtual drive system.16 /// </summary>17 internal sealed class LocationGlobber18 {19 #region Trace object20 21 /// <summary>22 /// An instance of the PSTraceSource class used for trace output23 /// using "LocationGlobber" as the category.24 /// </summary>25 [Dbg.TraceSource(26 "LocationGlobber",27 "The location globber converts PowerShell paths with glob characters to zero or more paths.")]28 private static readonly Dbg.PSTraceSource s_tracer =29 Dbg.PSTraceSource.GetTracer("LocationGlobber",30 "The location globber converts PowerShell paths with glob characters to zero or more paths.");31 32 /// <summary>33 /// User level tracing for path resolution.34 /// </summary>35 [Dbg.TraceSource(36 "PathResolution",37 "Traces the path resolution algorithm.")]38 private static readonly Dbg.PSTraceSource s_pathResolutionTracer =39 Dbg.PSTraceSource.GetTracer(40 "PathResolution",41 "Traces the path resolution algorithm.",42 false);43 44 #endregion Trace object45 46 #region Constructor47 48 /// <summary>49 /// Constructs an instance of the LocationGlobber from the current SessionState.50 /// </summary>51 /// <param name="sessionState">52 /// The instance of session state on which this location globber acts.53 /// </param>54 /// <exception cref="ArgumentNullException">55 /// If <paramref name="sessionState"/> is null.56 /// </exception>57 internal LocationGlobber(SessionState sessionState)58 {59 if (sessionState == null)60 {61 throw PSTraceSource.NewArgumentNullException(nameof(sessionState));62 }63 64 _sessionState = sessionState;65 }66 67 #endregion Constructor68 69 #region Public methods70 71 #region PowerShell paths from PowerShell path globbing72 /// <summary>73 /// Converts a PowerShell path containing glob characters to PowerShell paths that match74 /// the glob string.75 /// </summary>76 /// <param name="path">77 /// A PowerShell path containing glob characters.78 /// </param>79 /// <param name="allowNonexistingPaths">80 /// If true, a ItemNotFoundException will not be thrown for non-existing81 /// paths. Instead an appropriate path will be returned as if it did exist.82 /// </param>83 /// <param name="providerInstance">84 /// The provider instance used to resolve the path.85 /// </param>86 /// <returns>87 /// The PowerShell paths that match the glob string.88 /// </returns>89 /// <exception cref="ArgumentNullException">90 /// If <paramref name="path"/> is null.91 /// </exception>92 /// <exception cref="ProviderNotFoundException">93 /// If <paramref name="path"/> is a provider-qualified path94 /// and the specified provider does not exist.95 /// </exception>96 /// <exception cref="ProviderInvocationException">97 /// If the provider throws an exception when its MakePath gets98 /// called.99 /// </exception>100 /// <exception cref="NotSupportedException">101 /// If the provider does not support multiple items.102 /// </exception>103 /// <exception cref="InvalidOperationException">104 /// If the home location for the provider is not set and105 /// <paramref name="path"/> starts with a "~".106 /// </exception>107 /// <exception cref="ItemNotFoundException">108 /// If <paramref name="path"/> does not contain glob characters and109 /// could not be found.110 /// </exception>111 internal Collection<PathInfo> GetGlobbedMonadPathsFromMonadPath(112 string path,113 bool allowNonexistingPaths,114 out CmdletProvider providerInstance)115 {116 CmdletProviderContext context =117 new CmdletProviderContext(_sessionState.Internal.ExecutionContext);118 119 return GetGlobbedMonadPathsFromMonadPath(path, allowNonexistingPaths, context, out providerInstance);120 }121 122 /// <summary>123 /// Converts a PowerShell path containing glob characters to PowerShell paths that match124 /// the glob string.125 /// </summary>126 /// <param name="path">127 /// A PowerShell path containing glob characters.128 /// </param>129 /// <param name="allowNonexistingPaths">130 /// If true, a ItemNotFoundException will not be thrown for non-existing131 /// paths. Instead an appropriate path will be returned as if it did exist.132 /// </param>133 /// <param name="context">134 /// The context under which the command is running.135 /// </param>136 /// <param name="providerInstance">137 /// The instance of the provider used to resolve the path.138 /// </param>139 /// <returns>140 /// The PowerShell paths that match the glob string.141 /// </returns>142 /// <exception cref="ArgumentNullException">143 /// If <paramref name="path"/> or <paramref name="context"/> is null.144 /// </exception>145 /// <exception cref="ProviderNotFoundException">146 /// If <paramref name="path"/> is a provider-qualified path147 /// and the specified provider does not exist.148 /// </exception>149 /// <exception cref="ProviderInvocationException">150 /// If the provider throws an exception when its MakePath gets151 /// called.152 /// </exception>153 /// <exception cref="NotSupportedException">154 /// If the provider does not support multiple items.155 /// </exception>156 /// <exception cref="InvalidOperationException">157 /// If the home location for the provider is not set and158 /// <paramref name="path"/> starts with a "~".159 /// </exception>160 /// <exception cref="ItemNotFoundException">161 /// If <paramref name="path"/> does not contain glob characters and162 /// could not be found.163 /// </exception>164 /// <exception cref="PipelineStoppedException">165 /// If <paramref name="context"/> has been signaled for166 /// StopProcessing.167 /// </exception>168 internal Collection<PathInfo> GetGlobbedMonadPathsFromMonadPath(169 string path,170 bool allowNonexistingPaths,171 CmdletProviderContext context,172 out CmdletProvider providerInstance)173 {174 providerInstance = null;175 if (path == null)176 {177 throw PSTraceSource.NewArgumentNullException(nameof(path));178 }179 180 if (context == null)181 {182 throw PSTraceSource.NewArgumentNullException(nameof(context));183 }184 185 Collection<PathInfo> result;186 187 using (s_pathResolutionTracer.TraceScope("Resolving MSH path \"{0}\" to MSH path", path))188 {189 TraceFilters(context);190 191 // First check to see if the path starts with a ~ (home)192 193 if (IsHomePath(path))194 {195 using (s_pathResolutionTracer.TraceScope("Resolving HOME relative path."))196 {197 path = GetHomeRelativePath(path);198 }199 }200 201 // Now determine how to parse the path202 203 bool isProviderDirectPath = IsProviderDirectPath(path);204 bool isProviderQualifiedPath = IsProviderQualifiedPath(path);205 if (isProviderDirectPath || isProviderQualifiedPath)206 {207 result =208 ResolvePSPathFromProviderPath(209 path,210 context,211 allowNonexistingPaths,212 isProviderDirectPath,213 isProviderQualifiedPath,214 out providerInstance);215 }216 else217 {218 result =219 ResolveDriveQualifiedPath(220 path,221 context,222 allowNonexistingPaths,223 out providerInstance);224 }225 226 if (!allowNonexistingPaths &&227 result.Count < 1 &&228 (!WildcardPattern.ContainsWildcardCharacters(path) || context.SuppressWildcardExpansion) &&229 (context.Include == null || context.Include.Count == 0) &&230 (context.Exclude == null || context.Exclude.Count == 0))231 {232 // Since we are not globbing, throw an exception since233 // the path doesn't exist234 235 ItemNotFoundException pathNotFound =236 new ItemNotFoundException(237 path,238 "PathNotFound",239 SessionStateStrings.PathNotFound);240 241 s_pathResolutionTracer.TraceError("Item does not exist: {0}", path);242 243 throw pathNotFound;244 }245 }246 247 return result;248 }249 250 private Collection<string> ResolveProviderPathFromProviderPath(251 string providerPath,252 string providerId,253 bool allowNonexistingPaths,254 CmdletProviderContext context,255 out CmdletProvider providerInstance256 )257 {258 // Check the provider capabilities before globbing259 providerInstance = _sessionState.Internal.GetProviderInstance(providerId);260 ContainerCmdletProvider containerCmdletProvider = providerInstance as ContainerCmdletProvider;261 ItemCmdletProvider itemProvider = providerInstance as ItemCmdletProvider;262 263 Collection<string> stringResult = new Collection<string>();264 265 if (!context.SuppressWildcardExpansion)266 {267 // See if the provider will expand the wildcard268 if (CmdletProviderManagementIntrinsics.CheckProviderCapabilities(269 ProviderCapabilities.ExpandWildcards,270 providerInstance.ProviderInfo))271 {272 s_pathResolutionTracer.WriteLine("Wildcard matching is being performed by the provider.");273 274 // Only do the expansion if the path actually contains wildcard275 // characters.276 if ((itemProvider != null) &&277 (WildcardPattern.ContainsWildcardCharacters(providerPath)))278 {279 stringResult = new Collection<string>(itemProvider.ExpandPath(providerPath, context));280 }281 else282 {283 stringResult.Add(providerPath);284 }285 }286 else287 {288 s_pathResolutionTracer.WriteLine("Wildcard matching is being performed by the engine.");289 290 if (containerCmdletProvider != null)291 {292 // Since it is really a provider-internal path, use provider-to-provider globbing293 // and then add back on the provider ID.294 295 stringResult =296 GetGlobbedProviderPathsFromProviderPath(297 providerPath,298 allowNonexistingPaths,299 containerCmdletProvider,300 context);301 }302 else303 {304 // For simple CmdletProvider instances, we can't resolve the paths any305 // further, so just return the providerPath306 stringResult.Add(providerPath);307 }308 }309 }310 // They are suppressing wildcard expansion311 else312 {313 if (itemProvider != null)314 {315 if (allowNonexistingPaths || itemProvider.ItemExists(providerPath, context))316 {317 stringResult.Add(providerPath);318 }319 }320 else321 {322 stringResult.Add(providerPath);323 }324 }325 326 // Make sure this resolved to something327 if ((!allowNonexistingPaths) &&328 stringResult.Count < 1 &&329 !WildcardPattern.ContainsWildcardCharacters(providerPath) &&330 (context.Include == null || context.Include.Count == 0) &&331 (context.Exclude == null || context.Exclude.Count == 0))332 {333 ItemNotFoundException pathNotFound =334 new ItemNotFoundException(335 providerPath,336 "PathNotFound",337 SessionStateStrings.PathNotFound);338 339 s_pathResolutionTracer.TraceError("Item does not exist: {0}", providerPath);340 throw pathNotFound;341 }342 343 return stringResult;344 }345 346 private Collection<PathInfo> ResolvePSPathFromProviderPath(347 string path,348 CmdletProviderContext context,349 bool allowNonexistingPaths,350 bool isProviderDirectPath,351 bool isProviderQualifiedPath,352 out CmdletProvider providerInstance)353 {354 Collection<PathInfo> result = new Collection<PathInfo>();355 356 providerInstance = null;357 string providerId = null;358 PSDriveInfo drive = null;359 360 // The path is a provide direct path so use the current361 // provider and don't modify the path.362 363 string providerPath = null;364 365 if (isProviderDirectPath)366 {367 s_pathResolutionTracer.WriteLine("Path is PROVIDER-DIRECT");368 providerPath = path;369 providerId = _sessionState.Path.CurrentLocation.Provider.Name;370 }371 else if (isProviderQualifiedPath)372 {373 s_pathResolutionTracer.WriteLine("Path is PROVIDER-QUALIFIED");374 providerPath = ParseProviderPath(path, out providerId);375 }376 377 s_pathResolutionTracer.WriteLine("PROVIDER-INTERNAL path: {0}", providerPath);378 s_pathResolutionTracer.WriteLine("Provider: {0}", providerId);379 380 Collection<string> stringResult = ResolveProviderPathFromProviderPath(381 providerPath,382 providerId,383 allowNonexistingPaths,384 context,385 out providerInstance386 );387 388 // Get the hidden drive for the provider389 drive = providerInstance.ProviderInfo.HiddenDrive;390 391 // Now fix the paths392 foreach (string globbedPath in stringResult)393 {394 string escapedPath = globbedPath;395 396 // Making sure to obey the StopProcessing.397 if (context.Stopping)398 {399 throw new PipelineStoppedException();400 }401 402 string constructedProviderPath = null;403 404 if (IsProviderDirectPath(escapedPath))405 {406 constructedProviderPath = escapedPath;407 }408 else409 {410 constructedProviderPath =411 string.Format(412 System.Globalization.CultureInfo.InvariantCulture,413 "{0}::{1}",414 providerId,415 escapedPath);416 }417 418 result.Add(new PathInfo(drive, providerInstance.ProviderInfo, constructedProviderPath, _sessionState));419 s_pathResolutionTracer.WriteLine("RESOLVED PATH: {0}", constructedProviderPath);420 }421 422 return result;423 }424 425 private Collection<PathInfo> ResolveDriveQualifiedPath(426 string path,427 CmdletProviderContext context,428 bool allowNonexistingPaths,429 out CmdletProvider providerInstance)430 {431 providerInstance = null;432 PSDriveInfo drive = null;433 434 Collection<PathInfo> result = new Collection<PathInfo>();435 436 s_pathResolutionTracer.WriteLine("Path is DRIVE-QUALIFIED");437 438 string relativePath =439 GetDriveRootRelativePathFromPSPath(440 path,441 context,442 !context.SuppressWildcardExpansion,443 out drive,444 out providerInstance);445 446 Dbg.Diagnostics.Assert(447 drive != null,448 "GetDriveRootRelativePathFromPSPath should always return a valid drive");449 450 Dbg.Diagnostics.Assert(451 relativePath != null,452 "There should always be a way to generate a provider path for a " +453 "given path");454 455 s_pathResolutionTracer.WriteLine("DRIVE-RELATIVE path: {0}", relativePath);456 s_pathResolutionTracer.WriteLine("Drive: {0}", drive.Name);457 s_pathResolutionTracer.WriteLine("Provider: {0}", drive.Provider);458 459 // Associate the drive with the context460 461 context.Drive = drive;462 providerInstance = _sessionState.Internal.GetContainerProviderInstance(drive.Provider);463 ContainerCmdletProvider containerCmdletProvider = providerInstance as ContainerCmdletProvider;464 ItemCmdletProvider itemProvider = providerInstance as ItemCmdletProvider;465 466 ProviderInfo provider = providerInstance.ProviderInfo;467 468 string userPath = null;469 string itemPath = null;470 471 if (drive.Hidden)472 {473 userPath = GetProviderQualifiedPath(relativePath, provider);474 itemPath = relativePath;475 }476 else477 {478 userPath = GetDriveQualifiedPath(relativePath, drive);479 itemPath = GetProviderPath(path, context);480 }481 482 s_pathResolutionTracer.WriteLine("PROVIDER path: {0}", itemPath);483 484 Collection<string> stringResult = new Collection<string>();485 486 if (!context.SuppressWildcardExpansion)487 {488 // See if the provider will expand the wildcard489 if (CmdletProviderManagementIntrinsics.CheckProviderCapabilities(490 ProviderCapabilities.ExpandWildcards,491 provider))492 {493 s_pathResolutionTracer.WriteLine("Wildcard matching is being performed by the provider.");494 495 // Only do the expansion if the path actually contains wildcard496 // characters.497 if ((itemProvider != null) &&498 (WildcardPattern.ContainsWildcardCharacters(relativePath)))499 {500 foreach (string pathResult in itemProvider.ExpandPath(itemPath, context))501 {502 stringResult.Add(503 GetDriveRootRelativePathFromProviderPath(pathResult, drive, context));504 }505 }506 else507 {508 stringResult.Add(GetDriveRootRelativePathFromProviderPath(itemPath, drive, context));509 }510 }511 else512 {513 s_pathResolutionTracer.WriteLine("Wildcard matching is being performed by the engine.");514 515 // Now perform the globbing516 stringResult =517 ExpandMshGlobPath(518 relativePath,519 allowNonexistingPaths,520 drive,521 containerCmdletProvider,522 context);523 }524 }525 // They are suppressing wildcard expansion526 else527 {528 if (itemProvider != null)529 {530 if (allowNonexistingPaths || itemProvider.ItemExists(itemPath, context))531 {532 stringResult.Add(userPath);533 }534 }535 else536 {537 stringResult.Add(userPath);538 }539 }540 541 // Make sure this resolved to something542 if ((!allowNonexistingPaths) &&543 stringResult.Count < 1 &&544 !WildcardPattern.ContainsWildcardCharacters(path) &&545 (context.Include == null || context.Include.Count == 0) &&546 (context.Exclude == null || context.Exclude.Count == 0))547 {548 ItemNotFoundException pathNotFound =549 new ItemNotFoundException(550 path,551 "PathNotFound",552 SessionStateStrings.PathNotFound);553 554 s_pathResolutionTracer.TraceError("Item does not exist: {0}", path);555 throw pathNotFound;556 }557 558 // Now fix the paths559 foreach (string expandedPath in stringResult)560 {561 // Make sure to obey StopProcessing562 if (context.Stopping)563 {564 throw new PipelineStoppedException();565 }566 567 // Add the drive back into the path568 userPath = null;569 570 if (drive.Hidden)571 {572 if (IsProviderDirectPath(expandedPath))573 {574 userPath = expandedPath;575 }576 else577 {578 userPath =579 LocationGlobber.GetProviderQualifiedPath(580 expandedPath,581 provider);582 }583 }584 else585 {586 userPath =587 LocationGlobber.GetDriveQualifiedPath(588 expandedPath,589 drive);590 }591 592 result.Add(new PathInfo(drive, provider, userPath, _sessionState));593 s_pathResolutionTracer.WriteLine("RESOLVED PATH: {0}", userPath);594 }595 596 return result;597 }598 599 #endregion PowerShell paths from PowerShell path globbing600 601 #region Provider paths from PowerShell path globbing602 603 /// <summary>604 /// Converts a PowerShell path containing glob characters to the provider605 /// specific paths matching the glob strings.606 /// </summary>607 /// <param name="path">608 /// A PowerShell path containing glob characters.609 /// </param>610 /// <param name="allowNonexistingPaths">611 /// If true, a ItemNotFoundException will not be thrown for non-existing612 /// paths. Instead an appropriate path will be returned as if it did exist.613 /// </param>614 /// <param name="provider">615 /// Returns the information of the provider that was used to do the globbing.616 /// </param>617 /// <param name="providerInstance">618 /// The instance of the provider used to resolve the path.619 /// </param>620 /// <returns>621 /// An array of provider specific paths that matched the PowerShell glob path.622 /// </returns>623 /// <exception cref="ArgumentNullException">624 /// If <paramref name="path"/> is null.625 /// </exception>626 /// <exception cref="ProviderNotFoundException">627 /// If the path is a provider-qualified path for a provider that is628 /// not loaded into the system.629 /// </exception>630 /// <exception cref="DriveNotFoundException">631 /// If the <paramref name="path"/> refers to a drive that could not be found.632 /// </exception>633 /// <exception cref="ProviderInvocationException">634 /// If the provider used to build the path threw an exception.635 /// </exception>636 /// <exception cref="NotSupportedException">637 /// If the provider that the <paramref name="path"/> represents is not a NavigationCmdletProvider638 /// or ContainerCmdletProvider.639 /// </exception>640 /// <exception cref="InvalidOperationException">641 /// If the <paramref name="path"/> starts with "~" and the home location is not set for642 /// the provider.643 /// </exception>644 /// <exception cref="ProviderInvocationException">645 /// If the provider associated with the <paramref name="path"/> threw an646 /// exception when its GetParentPath or MakePath was called while647 /// processing the <paramref name="path"/>.648 /// </exception>649 /// <exception cref="ItemNotFoundException">650 /// If <paramref name="path"/> does not contain glob characters and651 /// could not be found.652 /// </exception>653 /// <exception>654 /// Any exception can be thrown by the provider that is called to build655 /// the provider path.656 /// </exception>657 internal Collection<string> GetGlobbedProviderPathsFromMonadPath(658 string path,659 bool allowNonexistingPaths,660 out ProviderInfo provider,661 out CmdletProvider providerInstance)662 {663 providerInstance = null;664 if (path == null)665 {666 throw PSTraceSource.NewArgumentNullException(nameof(path));667 }668 669 CmdletProviderContext context =670 new CmdletProviderContext(_sessionState.Internal.ExecutionContext);671 672 return GetGlobbedProviderPathsFromMonadPath(path, allowNonexistingPaths, context, out provider, out providerInstance);673 }674 675 /// <summary>676 /// Converts a PowerShell path containing glob characters to the provider677 /// specific paths matching the glob strings.678 /// </summary>679 /// <param name="path">680 /// A PowerShell path containing glob characters.681 /// </param>682 /// <param name="allowNonexistingPaths">683 /// If true, a ItemNotFoundException will not be thrown for non-existing684 /// paths. Instead an appropriate path will be returned as if it did exist.685 /// </param>686 /// <param name="context">687 /// The context under which the command is running.688 /// </param>689 /// <param name="provider">690 /// Returns the information of the provider that was used to do the globbing.691 /// </param>692 /// <param name="providerInstance">693 /// The instance of the provider used to resolve the path.694 /// </param>695 /// <returns>696 /// An array of provider specific paths that matched the PowerShell glob path.697 /// </returns>698 /// <exception cref="ArgumentNullException">699 /// If <paramref name="path"/> or <paramref name="context"/> is null.700 /// </exception>701 /// <exception cref="ProviderNotFoundException">702 /// If the path is a provider-qualified path for a provider that is703 /// not loaded into the system.704 /// </exception>705 /// <exception cref="DriveNotFoundException">706 /// If the <paramref name="path"/> refers to a drive that could not be found.707 /// </exception>708 /// <exception cref="ProviderInvocationException">709 /// If the provider used to build the path threw an exception.710 /// </exception>711 /// <exception cref="NotSupportedException">712 /// If the provider that the <paramref name="path"/> represents is not a NavigationCmdletProvider713 /// or ContainerCmdletProvider.714 /// </exception>715 /// <exception cref="InvalidOperationException">716 /// If the <paramref name="path"/> starts with "~" and the home location is not set for717 /// the provider.718 /// </exception>719 /// <exception cref="ProviderInvocationException">720 /// If the provider associated with the <paramref name="path"/> threw an721 /// exception when its GetParentPath or MakePath was called while722 /// processing the <paramref name="path"/>.723 /// </exception>724 /// <exception cref="ItemNotFoundException">725 /// If <paramref name="path"/> does not contain glob characters and726 /// could not be found.727 /// </exception>728 /// <exception>729 /// Any exception can be thrown by the provider that is called to build730 /// the provider path.731 /// </exception>732 internal Collection<string> GetGlobbedProviderPathsFromMonadPath(733 string path,734 bool allowNonexistingPaths,735 CmdletProviderContext context,736 out ProviderInfo provider,737 out CmdletProvider providerInstance)738 {739 if (path == null)740 {741 throw PSTraceSource.NewArgumentNullException(nameof(path));742 }743 744 if (context == null)745 {746 throw PSTraceSource.NewArgumentNullException(nameof(context));747 }748 749 using (s_pathResolutionTracer.TraceScope("Resolving MSH path \"{0}\" to PROVIDER-INTERNAL path", path))750 {751 TraceFilters(context);752 753 // Remove the drive from the context if this path is not associated with a drive754 if (IsProviderQualifiedPath(path))755 {756 context.Drive = null;757 }758 759 PSDriveInfo drive = null;760 string providerPath = GetProviderPath(path, context, out provider, out drive);761 762 if (providerPath == null)763 {764 providerInstance = null;765 s_tracer.WriteLine("provider returned a null path so return an empty array");766 767 s_pathResolutionTracer.WriteLine("Provider '{0}' returned null", provider);768 return new Collection<string>();769 }770 771 if (drive != null)772 {773 context.Drive = drive;774 }775 776 Collection<string> paths = new Collection<string>();777 778 foreach (PathInfo currentPath in779 GetGlobbedMonadPathsFromMonadPath(780 path,781 allowNonexistingPaths,782 context,783 out providerInstance))784 {785 paths.Add(currentPath.ProviderPath);786 }787 788 return paths;789 }790 }791 792 #endregion Provider paths from Monad path globbing793 794 #region Provider paths from provider path globbing795 796 /// <summary>797 /// Given a provider specific path that contains glob characters, this method798 /// will perform the globbing using the specified provider and return the799 /// matching provider specific paths.800 /// </summary>801 /// <param name="path">802 /// The path containing the glob characters to resolve.803 /// </param>804 /// <param name="allowNonexistingPaths">805 /// If true, a ItemNotFoundException will not be thrown for non-existing806 /// paths. Instead an appropriate path will be returned as if it did exist.807 /// </param>808 /// <param name="providerId">809 /// The ID of the provider to use to do the resolution.810 /// </param>811 /// <param name="providerInstance">812 /// The instance of the provider that was used to resolve the path.813 /// </param>814 /// <returns>815 /// An array of provider specific paths that match the glob path.816 /// </returns>817 /// <exception cref="ArgumentNullException">818 /// If <paramref name="path"/> is null.819 /// </exception>820 /// <exception cref="ProviderNotFoundException">821 /// If <paramref name="providerId"/> references a provider that does not exist.822 /// </exception>823 /// <exception cref="NotSupportedException">824 /// If the <paramref name="providerId"/> references a provider that is not825 /// a ContainerCmdletProvider.826 /// </exception>827 /// <exception cref="ProviderInvocationException">828 /// If the provider used to build the path threw an exception.829 /// </exception>830 /// <exception cref="InvalidOperationException">831 /// If the <paramref name="path"/> starts with "~" and the home location is not set for832 /// the provider.833 /// </exception>834 /// <exception cref="ItemNotFoundException">835 /// If <paramref name="path"/> does not contain glob characters and836 /// could not be found.837 /// </exception>838 /// <exception>839 /// Any exception can be thrown by the provider that is called to build840 /// the provider path.841 /// </exception>842 internal Collection<string> GetGlobbedProviderPathsFromProviderPath(843 string path,844 bool allowNonexistingPaths,845 string providerId,846 out CmdletProvider providerInstance)847 {848 providerInstance = null;849 850 if (path == null)851 {852 throw PSTraceSource.NewArgumentNullException(nameof(path));853 }854 855 CmdletProviderContext context =856 new CmdletProviderContext(_sessionState.Internal.ExecutionContext);857 858 Collection<string> results =859 GetGlobbedProviderPathsFromProviderPath(860 path,861 allowNonexistingPaths,862 providerId,863 context,864 out providerInstance);865 866 if (context.HasErrors())867 {868 // Throw the first error869 ErrorRecord errorRecord = context.GetAccumulatedErrorObjects()[0];870 871 if (errorRecord != null)872 {873 throw errorRecord.Exception;874 }875 }876 877 return results;878 }879 880 /// <summary>881 /// Given a provider specific path that contains glob characters, this method882 /// will perform the globbing using the specified provider and return the883 /// matching provider specific paths.884 /// </summary>885 /// <param name="path">886 /// The path containing the glob characters to resolve. The path must be in the887 /// form providerId::providerPath.888 /// </param>889 /// <param name="allowNonexistingPaths">890 /// If true, a ItemNotFoundException will not be thrown for non-existing891 /// paths. Instead an appropriate path will be returned as if it did exist.892 /// </param>893 /// <param name="providerId">894 /// The provider identifier for the provider to use to do the globbing.895 /// </param>896 /// <param name="context">897 /// The context under which the command is occurring.898 /// </param>899 /// <param name="providerInstance">900 /// An instance of the provider that was used to perform the globbing.901 /// </param>902 /// <returns>903 /// An array of provider specific paths that match the glob path.904 /// </returns>905 /// <exception cref="ArgumentNullException">906 /// If <paramref name="path"/>, <paramref name="providerId"/>, or907 /// <paramref name="context"/> is null.908 /// </exception>909 /// <exception cref="ProviderNotFoundException">910 /// If <paramref name="providerId"/> references a provider that does not exist.911 /// </exception>912 /// <exception cref="NotSupportedException">913 /// If the <paramref name="providerId"/> references a provider that is not914 /// a ContainerCmdletProvider.915 /// </exception>916 /// <exception cref="ProviderInvocationException">917 /// If the provider used to build the path threw an exception.918 /// </exception>919 /// <exception cref="InvalidOperationException">920 /// If the <paramref name="path"/> starts with "~" and the home location is not set for921 /// the provider.922 /// </exception>923 /// <exception>924 /// Any exception can be thrown by the provider that is called to build925 /// the provider path.926 /// </exception>927 internal Collection<string> GetGlobbedProviderPathsFromProviderPath(928 string path,929 bool allowNonexistingPaths,930 string providerId,931 CmdletProviderContext context,932 out CmdletProvider providerInstance)933 {934 providerInstance = null;935 936 if (path == null)937 {938 throw PSTraceSource.NewArgumentNullException(nameof(path));939 }940 941 if (providerId == null)942 {943 throw PSTraceSource.NewArgumentNullException(nameof(providerId));944 }945 946 if (context == null)947 {948 throw PSTraceSource.NewArgumentNullException(nameof(context));949 }950 951 using (s_pathResolutionTracer.TraceScope("Resolving PROVIDER-INTERNAL path \"{0}\" to PROVIDER-INTERNAL path", path))952 {953 TraceFilters(context);954 955 return ResolveProviderPathFromProviderPath(956 path,957 providerId,958 allowNonexistingPaths,959 context,960 out providerInstance);961 }962 }963 964 #endregion Provider path to provider paths globbing965 966 #region Path manipulation967 968 /// <summary>969 /// Gets a provider specific path when given an Msh path without resolving the970 /// glob characters.971 /// </summary>972 /// <param name="path">973 /// An Msh path.974 /// </param>975 /// <returns>976 /// A provider specific path that the Msh path represents.977 /// </returns>978 /// <exception cref="ArgumentNullException">979 /// If <paramref name="path"/> is null.980 /// </exception>981 /// <exception cref="ProviderNotFoundException">982 /// If the path is a provider-qualified path for a provider that is983 /// not loaded into the system.984 /// </exception>985 /// <exception cref="DriveNotFoundException">986 /// If the <paramref name="path"/> refers to a drive that could not be found.987 /// </exception>988 /// <exception cref="ProviderInvocationException">989 /// If the provider used to build the path threw an exception.990 /// </exception>991 /// <exception cref="NotSupportedException">992 /// If the provider that the <paramref name="path"/> represents is not a NavigationCmdletProvider993 /// or ContainerCmdletProvider.994 /// </exception>995 /// <exception cref="InvalidOperationException">996 /// If the <paramref name="path"/> starts with "~" and the home location is not set for997 /// the provider.998 /// </exception>999 /// <exception cref="ProviderInvocationException">1000 /// If the provider specified by <paramref name="path"/> threw an1001 /// exception.1002 /// </exception>1003 /// <exception>1004 /// Any exception can be thrown by the provider that is called to build1005 /// the provider path.1006 /// </exception>1007 internal string GetProviderPath(string path)1008 {1009 ProviderInfo provider = null;1010 return GetProviderPath(path, out provider);1011 }1012 1013 /// <summary>1014 /// Gets a provider specific path when given an Msh path without resolving the1015 /// glob characters.1016 /// </summary>1017 /// <param name="path">1018 /// An Msh path.1019 /// </param>1020 /// <param name="provider">1021 /// The information of the provider that was used to resolve the path.1022 /// </param>1023 /// <returns>1024 /// A provider specific path that the Msh path represents.1025 /// </returns>1026 /// <exception cref="ArgumentNullException">1027 /// If <paramref name="path"/> is null.1028 /// </exception>1029 /// <exception cref="ProviderNotFoundException">1030 /// If the path is a provider-qualified path for a provider that is1031 /// not loaded into the system.1032 /// </exception>1033 /// <exception cref="DriveNotFoundException">1034 /// If the <paramref name="path"/> refers to a drive that could not be found.1035 /// </exception>1036 /// <exception cref="ProviderInvocationException">1037 /// If the provider used to build the path threw an exception.1038 /// </exception>1039 /// <exception cref="NotSupportedException">1040 /// If the provider that the <paramref name="path"/> represents is not a NavigationCmdletProvider1041 /// or ContainerCmdletProvider.1042 /// </exception>1043 /// <exception cref="InvalidOperationException">1044 /// If the <paramref name="path"/> starts with "~" and the home location is not set for1045 /// the provider.1046 /// </exception>1047 /// <exception cref="ProviderInvocationException">1048 /// If the provider specified by <paramref name="provider"/> threw an1049 /// exception when its GetParentPath or MakePath was called while1050 /// processing the <paramref name="path"/>.1051 /// </exception>1052 /// <exception>1053 /// Any exception can be thrown by the provider that is called to build1054 /// the provider path.1055 /// </exception>1056 internal string GetProviderPath(string path, out ProviderInfo provider)1057 {1058 if (path == null)1059 {1060 throw PSTraceSource.NewArgumentNullException(nameof(path));1061 }1062 1063 CmdletProviderContext context =1064 new CmdletProviderContext(_sessionState.Internal.ExecutionContext);1065 1066 PSDriveInfo drive = null;1067 provider = null;1068 1069 string result = GetProviderPath(path, context, out provider, out drive);1070 1071 if (context.HasErrors())1072 {1073 Collection<ErrorRecord> errors = context.GetAccumulatedErrorObjects();1074 1075 if (errors != null &&1076 errors.Count > 0)1077 {1078 throw errors[0].Exception;1079 }1080 }1081 1082 return result;1083 }1084 1085 /// <summary>1086 /// Gets a provider specific path when given an Msh path without resolving the1087 /// glob characters.1088 /// </summary>1089 /// <param name="path">1090 /// An Msh path.1091 /// </param>1092 /// <param name="context">1093 /// The context of the command.1094 /// </param>1095 /// <returns>1096 /// A provider specific path that the Msh path represents.1097 /// </returns>1098 /// <exception cref="ArgumentNullException">1099 /// If <paramref name="path"/> is null.1100 /// </exception>1101 /// <exception cref="ProviderNotFoundException">1102 /// If the path is a provider-qualified path for a provider that is1103 /// not loaded into the system.1104 /// </exception>1105 /// <exception cref="DriveNotFoundException">1106 /// If the <paramref name="path"/> refers to a drive that could not be found.1107 /// </exception>1108 /// <exception cref="ProviderInvocationException">1109 /// If the provider used to build the path threw an exception.1110 /// </exception>1111 /// <exception cref="NotSupportedException">1112 /// If the provider that the <paramref name="path"/> represents is not a NavigationCmdletProvider1113 /// or ContainerCmdletProvider.1114 /// </exception>1115 /// <exception cref="InvalidOperationException">1116 /// If the <paramref name="path"/> starts with "~" and the home location is not set for1117 /// the provider.1118 /// </exception>1119 /// <exception cref="ProviderInvocationException">1120 /// If the provider specified by <paramref name="provider"/> threw an1121 /// exception when its GetParentPath or MakePath was called while1122 /// processing the <paramref name="path"/>.1123 /// </exception>1124 /// <exception>1125 /// Any exception can be thrown by the provider that is called to build1126 /// the provider path.1127 /// </exception>1128 internal string GetProviderPath(string path, CmdletProviderContext context)1129 {1130 if (path == null)1131 {1132 throw PSTraceSource.NewArgumentNullException(nameof(path));1133 }1134 1135 PSDriveInfo drive = null;1136 ProviderInfo provider = null;1137 1138 string result = GetProviderPath(path, context, out provider, out drive);1139 1140 return result;1141 }1142 1143 /// <summary>1144 /// Returns a provider specific path for given PowerShell path.1145 /// </summary>1146 /// <param name="path">1147 /// Either a PowerShell path or a provider path in the form providerId::providerPath1148 /// </param>1149 /// <param name="context">1150 /// The command context under which this operation is occurring.1151 /// </param>1152 /// <param name="provider">1153 /// This parameter is filled with the provider information for the given path.1154 /// </param>1155 /// <param name="drive">1156 /// This parameter is filled with the PowerShell drive that represents the given path. If a1157 /// provider path is given drive will be null.1158 /// </param>1159 /// <returns>1160 /// The provider specific path generated from the given path.1161 /// </returns>1162 /// <exception cref="ArgumentNullException">1163 /// If <paramref name="path"/> or <paramref name="context"/> is null.1164 /// </exception>1165 /// <exception cref="ProviderNotFoundException">1166 /// If the path is a provider-qualified path for a provider that is1167 /// not loaded into the system.1168 /// </exception>1169 /// <exception cref="DriveNotFoundException">1170 /// If the <paramref name="path"/> refers to a drive that could not be found.1171 /// </exception>1172 /// <exception cref="ProviderInvocationException">1173 /// If the provider used to build the path threw an exception.1174 /// </exception>1175 /// <exception cref="NotSupportedException">1176 /// If the provider that the <paramref name="path"/> represents is not a NavigationCmdletProvider1177 /// or ContainerCmdletProvider.1178 /// </exception>1179 /// <exception cref="InvalidOperationException">1180 /// If the <paramref name="path"/> starts with "~" and the home location is not set for1181 /// the provider.1182 /// </exception>1183 /// <exception cref="ProviderInvocationException">1184 /// If the provider specified by <paramref name="provider"/> threw an1185 /// exception when its GetParentPath or MakePath was called while1186 /// processing the <paramref name="path"/>.1187 /// </exception>1188 internal string GetProviderPath(1189 string path,1190 CmdletProviderContext context,1191 out ProviderInfo provider,1192 out PSDriveInfo drive)1193 {1194 return GetProviderPath(1195 path,1196 context,1197 false,1198 out provider,1199 out drive);1200 }