internal string NormalizeRelativePath(string path, string basePath, CmdletProviderContext context) { string str2; if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } CmdletProviderContext context2 = new CmdletProviderContext(context); try { PSDriveInfo drive = null; ProviderInfo provider = null; string str = this.Globber.GetProviderPath(path, context2, out provider, out drive); if (context2.HasErrors()) { context2.WriteErrorsToContext(context); return null; } if ((str == null) || (provider == null)) { Exception exception = PSTraceSource.NewArgumentException("path"); context.WriteError(new ErrorRecord(exception, "NormalizePathNullResult", ErrorCategory.InvalidArgument, path)); return null; } if (drive != null) { context.Drive = drive; if (((this.GetProviderInstance(provider) is NavigationCmdletProvider) && !string.IsNullOrEmpty(drive.Root)) && path.StartsWith(drive.Root, StringComparison.OrdinalIgnoreCase)) { str = path; } } str2 = this.NormalizeRelativePath(provider, str, basePath, context); } finally { context2.RemoveStopReferral(); } return str2; }
internal string GetParentPath(string path, string root, CmdletProviderContext context, bool useDefaultProvider) { string str4; if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } CmdletProviderContext context2 = new CmdletProviderContext(context); try { PSDriveInfo drive = null; ProviderInfo provider = null; try { this.Globber.GetProviderPath(path, context2, out provider, out drive); } catch (System.Management.Automation.DriveNotFoundException) { if (!useDefaultProvider) { throw; } provider = this.PublicSessionState.Internal.GetSingleProvider("FileSystem"); } if (context2.HasErrors()) { context2.WriteErrorsToContext(context); return null; } if (drive != null) { context.Drive = drive; } bool isProviderQualified = false; bool isDriveQualified = false; string qualifier = null; string str2 = this.RemoveQualifier(path, out qualifier, out isProviderQualified, out isDriveQualified); string str3 = this.GetParentPath(provider, str2, root, context); if (!string.IsNullOrEmpty(qualifier) && !string.IsNullOrEmpty(str3)) { str3 = this.AddQualifier(str3, qualifier, isProviderQualified, isDriveQualified); } tracer.WriteLine("result = {0}", new object[] { str3 }); str4 = str3; } finally { context2.RemoveStopReferral(); } return str4; }
private void DoManualGetChildItems(CmdletProvider providerInstance, string path, bool recurse, CmdletProviderContext context, bool skipIsItemContainerCheck = false) { Collection<WildcardPattern> patterns = SessionStateUtilities.CreateWildcardsFromStrings(context.Include, WildcardOptions.IgnoreCase); Collection<WildcardPattern> collection2 = SessionStateUtilities.CreateWildcardsFromStrings(context.Exclude, WildcardOptions.IgnoreCase); if (skipIsItemContainerCheck || this.IsItemContainer(providerInstance, path, context)) { CmdletProviderContext context2 = new CmdletProviderContext(context); Collection<PSObject> accumulatedObjects = null; Dictionary<string, bool> dictionary = null; try { this.GetChildNames(providerInstance, path, recurse ? ReturnContainers.ReturnAllContainers : ReturnContainers.ReturnMatchingContainers, context2); context2.WriteErrorsToContext(context); accumulatedObjects = context2.GetAccumulatedObjects(); if (recurse && providerInstance.IsFilterSet()) { context2.RemoveStopReferral(); context2 = new CmdletProviderContext(context); Collection<PSObject> collection4 = new Collection<PSObject>(); dictionary = new Dictionary<string, bool>(); this.GetChildNames(providerInstance, path, ReturnContainers.ReturnMatchingContainers, context2); foreach (PSObject obj2 in context2.GetAccumulatedObjects()) { string baseObject = obj2.BaseObject as string; if (baseObject != null) { dictionary[baseObject] = true; } } } } finally { context2.RemoveStopReferral(); } for (int i = 0; i < accumulatedObjects.Count; i++) { if (context.Stopping) { return; } string child = accumulatedObjects[i].BaseObject as string; if (child != null) { string str3 = this.MakePath(providerInstance, path, child, context); if (str3 != null) { if (SessionStateUtilities.MatchesAnyWildcardPattern(child, patterns, true) && !SessionStateUtilities.MatchesAnyWildcardPattern(child, collection2, false)) { bool flag2 = true; if (dictionary != null) { bool flag3 = false; flag2 = dictionary.TryGetValue(child, out flag3); } if (flag2) { this.GetItemPrivate(providerInstance, str3, context); } } if (this.IsItemContainer(providerInstance, str3, context) && recurse) { if (context.Stopping) { return; } this.DoManualGetChildItems(providerInstance, str3, recurse, context, true); } } } } } else { string text = path; text = this.GetChildName(providerInstance, path, context, true); if (SessionStateUtilities.MatchesAnyWildcardPattern(text, patterns, true) && !SessionStateUtilities.MatchesAnyWildcardPattern(text, collection2, false)) { this.GetItemPrivate(providerInstance, path, context); } } }
} //NormalizeRelativePath /// <summary> /// Normalizes the path that was passed in and returns the normalized path /// as a relative path to the basePath that was passed. /// </summary> /// /// <param name="path"> /// An MSH path to an item. The item should exist /// or the provider should write out an error. /// </param> /// /// <param name="basePath"> /// The path that the return value should be relative to. /// </param> /// /// <param name="context"> /// The context under which the command is running. /// </param> /// /// <returns> /// A normalized path that is relative to the basePath that was passed. /// </returns> /// /// <exception cref="ArgumentNullException"> /// If <paramref name="path"/> is null. /// </exception> /// /// <exception cref="NotSupportedException"> /// If the <paramref name="providerInstance"/> does not support this operation. /// </exception> /// /// <exception cref="PipelineStoppedException"> /// If the pipeline is being stopped while executing the command. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider threw an exception. /// </exception> /// internal string NormalizeRelativePath( string path, string basePath, CmdletProviderContext context) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } CmdletProviderContext getProviderPathContext = new CmdletProviderContext(context); try { PSDriveInfo drive = null; ProviderInfo provider = null; string workingPath = Globber.GetProviderPath( path, getProviderPathContext, out provider, out drive); if (getProviderPathContext.HasErrors()) { getProviderPathContext.WriteErrorsToContext(context); return null; } if (workingPath == null || provider == null) { // Since the provider didn't write an error, and we didn't get any // results ourselves, we need to write out our own error. Exception e = PSTraceSource.NewArgumentException("path"); context.WriteError(new ErrorRecord(e, "NormalizePathNullResult", ErrorCategory.InvalidArgument, path)); return null; } if (basePath != null) { PSDriveInfo baseDrive = null; ProviderInfo baseProvider = null; Globber.GetProviderPath( basePath, getProviderPathContext, out baseProvider, out baseDrive); if (drive != null && baseDrive != null) { if (!drive.Name.Equals(baseDrive.Name, StringComparison.OrdinalIgnoreCase)) { // Make sure they are from physically different drives // Doing StartsWith from both directions covers the following cases // C:\ and C:\Temp // C:\Temp and C:\ if (!(drive.Root.StartsWith(baseDrive.Root, StringComparison.OrdinalIgnoreCase) || (baseDrive.Root.StartsWith(drive.Root, StringComparison.OrdinalIgnoreCase)))) { // In this case, no normalization is necessary return path; } } } } if (drive != null) { context.Drive = drive; // Detect if the original path was already a // provider path. This happens when a drive doesn't // have a rooted root -- such as HKEY_LOCAL_MACHINE instead of // \\HKEY_LOCAL_MACHINE if ( (GetProviderInstance(provider) is NavigationCmdletProvider) && (!String.IsNullOrEmpty(drive.Root)) && (path.StartsWith(drive.Root, StringComparison.OrdinalIgnoreCase))) { // // If the drive root doesn't end with a path separator then there is a chance the // path starts with the drive root name but doesn't actually refer to it. For example, // (see Win8 bug 922001) consider drive with root HKEY_LOCAL_MACHINE named // HKEY_LOCAL_MACHINE_foo. The path would start with the drive root but is not a provider // path. // // We will remediate this by only considering this a provider path if // 1. The drive root ends with a path separator. // OR // 2. The path starts with the drive root followed by a path separator // OR // 3. The path exactly matches the drive root. // // 1. Test for the drive root ending with a path separator. bool driveRootEndsWithPathSeparator = IsPathSeparator(drive.Root[drive.Root.Length - 1]); // 2. Test for the path starting with the drive root followed by a path separator int indexAfterDriveRoot = drive.Root.Length; bool pathStartsWithDriveRootAndPathSeparator = indexAfterDriveRoot < path.Length && IsPathSeparator(path[indexAfterDriveRoot]); // 3. Test for the drive root exactly matching the path. // Since we know the path starts with the drive root then they are equal if the lengths are equal. bool pathEqualsDriveRoot = drive.Root.Length == path.Length; if (driveRootEndsWithPathSeparator || pathStartsWithDriveRootAndPathSeparator || pathEqualsDriveRoot) { workingPath = path; } } } return NormalizeRelativePath(provider, workingPath, basePath, context); } finally { getProviderPathContext.RemoveStopReferral(); } } // NormalizeRelativePath
/// <summary> /// Gets the path to the parent object for the given object. /// Allow to use FileSystem as the default provider when the /// given path is drive-qualified and the drive cannot be found. /// </summary> /// /// <param name="path"> /// The path to the object to get the parent path from /// </param> /// /// <param name="root"> /// The root of the drive. Namespace providers should /// return the root if GetParentPath is called for the root. /// </param> /// /// <param name="context"> /// The context which the core command is running. /// </param> /// /// <param name="useDefaultProvider"> /// Specify whether to use default provider when needed. /// </param> /// /// <returns> /// The path to the parent object /// </returns> internal string GetParentPath( string path, string root, CmdletProviderContext context, bool useDefaultProvider) { if (path == null) { throw PSTraceSource.NewArgumentNullException("path"); } CmdletProviderContext getProviderPathContext = new CmdletProviderContext(context); try { PSDriveInfo drive = null; ProviderInfo provider = null; try { Globber.GetProviderPath( path, getProviderPathContext, out provider, out drive); } catch (DriveNotFoundException) { // the path is sure to be drive_qualified and it is absolute path, otherwise the // drive would be set to the current drive and the DriveNotFoundException will not happen if (useDefaultProvider) { // the default provider is FileSystem provider = PublicSessionState.Internal.GetSingleProvider(Microsoft.PowerShell.Commands.FileSystemProvider.ProviderName); } else { throw; } } if (getProviderPathContext.HasErrors()) { getProviderPathContext.WriteErrorsToContext(context); return null; } if (drive != null) { context.Drive = drive; } bool isProviderQualified = false; bool isDriveQualified = false; string qualifier = null; string pathNoQualifier = RemoveQualifier(path, provider, out qualifier, out isProviderQualified, out isDriveQualified); string result = GetParentPath(provider, pathNoQualifier, root, context); if (!String.IsNullOrEmpty(qualifier) && !String.IsNullOrEmpty(result)) { result = AddQualifier(result, provider, qualifier, isProviderQualified, isDriveQualified); } return result; } finally { getProviderPathContext.RemoveStopReferral(); } } // GetParentPath
} // GetChildItems /// <summary> /// Since we can't do include and exclude filtering on items we have to /// do the recursion ourselves. We get each child name and see if it matches /// the include and exclude filters. If the child is a container we recurse /// into that container. /// </summary> /// /// <param name="providerInstance"> /// The instance of the provider to use. /// </param> /// /// <param name="path"> /// The path to the item to get the children from. /// </param> /// /// <param name="recurse"> /// Recurse into sub-containers when getting children. /// </param> /// /// <param name="context"> /// The context under which the command is running. /// </param> /// /// <param name="childrenNotMatchingFilterCriteria"> /// The count of items that do not match any include/exclude criteria. /// </param> /// /// <param name="processMode">Indicates if this is a Enumerate/Remove operation</param> /// /// <param name="skipIsItemContainerCheck">a hint used to skip IsItemContainer checks</param> /// /// <exception cref="ProviderNotFoundException"> /// If the <paramref name="path"/> refers to a provider that could not be found. /// </exception> /// /// <exception cref="DriveNotFoundException"> /// If the <paramref name="path"/> refers to a drive that could not be found. /// </exception> /// /// <exception cref="NotSupportedException"> /// If the provider that the <paramref name="path"/> refers to does /// not support this operation. /// </exception> /// /// <exception cref="ProviderInvocationException"> /// If the provider threw an exception. /// </exception> /// private void ProcessPathItems( CmdletProvider providerInstance, string path, bool recurse, CmdletProviderContext context, out int childrenNotMatchingFilterCriteria, ProcessMode processMode = ProcessMode.Enumerate, bool skipIsItemContainerCheck = false) { ContainerCmdletProvider containerCmdletProvider = GetContainerProviderInstance(providerInstance); childrenNotMatchingFilterCriteria = 0; Dbg.Diagnostics.Assert( providerInstance != null, "The caller should have verified the providerInstance"); Dbg.Diagnostics.Assert( path != null, "The caller should have verified the path"); Dbg.Diagnostics.Assert( context != null, "The caller should have verified the context"); // Construct the include filter Collection<WildcardPattern> includeMatcher = SessionStateUtilities.CreateWildcardsFromStrings( context.Include, WildcardOptions.IgnoreCase); // Construct the exclude filter Collection<WildcardPattern> excludeMatcher = SessionStateUtilities.CreateWildcardsFromStrings( context.Exclude, WildcardOptions.IgnoreCase); // If the item is a container we have to filter its children // Use a hint + lazy evaluation to skip a container check if (skipIsItemContainerCheck || IsItemContainer(providerInstance, path, context)) { CmdletProviderContext newContext = new CmdletProviderContext(context); Collection<PSObject> childNameObjects = null; System.Collections.Generic.Dictionary<string, bool> filteredChildNameDictionary = null; try { // Get all the child names GetChildNames( providerInstance, path, (recurse) ? ReturnContainers.ReturnAllContainers : ReturnContainers.ReturnMatchingContainers, newContext); newContext.WriteErrorsToContext(context); childNameObjects = newContext.GetAccumulatedObjects(); // The code above initially retrieves all of the containers so that it doesn't limit the recursion, // but then emits the non-matching container further down. The public API doesn't support a way to // differentiate the two, so we need to do a diff. // So if there was a filter, do it again to get the fully filtered items. if (recurse && (providerInstance.IsFilterSet())) { newContext.RemoveStopReferral(); newContext = new CmdletProviderContext(context); filteredChildNameDictionary = new System.Collections.Generic.Dictionary<string, bool>(); GetChildNames( providerInstance, path, ReturnContainers.ReturnMatchingContainers, newContext); var filteredChildNameObjects = newContext.GetAccumulatedObjects(); foreach (PSObject filteredChildName in filteredChildNameObjects) { string filteredName = filteredChildName.BaseObject as string; if (filteredName != null) { filteredChildNameDictionary[filteredName] = true; } } } } finally { newContext.RemoveStopReferral(); } // Now loop through all the child objects matching the filters and recursing // into containers for (int index = 0; index < childNameObjects.Count; ++index) { // Making sure to obey the StopProcessing. if (context.Stopping) { return; } string childName = childNameObjects[index].BaseObject as string; if (childName == null) { continue; } // Generate the provider path for the child string qualifiedPath = MakePath(providerInstance, path, childName, context); if (qualifiedPath == null) { continue; } bool isIncludeMatch = !context.SuppressWildcardExpansion && SessionStateUtilities.MatchesAnyWildcardPattern( childName, includeMatcher, true); if (isIncludeMatch) { if (!SessionStateUtilities.MatchesAnyWildcardPattern( childName, excludeMatcher, false)) { bool emitItem = true; if (filteredChildNameDictionary != null) { bool isChildNameInDictionary = false; emitItem = filteredChildNameDictionary.TryGetValue(childName, out isChildNameInDictionary); } if (emitItem) { if (processMode == ProcessMode.Delete) { containerCmdletProvider.RemoveItem(qualifiedPath, false, context); } else if (processMode != ProcessMode.Delete) { // The object is a match so get it and write it out. GetItemPrivate(providerInstance, qualifiedPath, context); } } } else { childrenNotMatchingFilterCriteria++; } } else { childrenNotMatchingFilterCriteria++; } // Now recurse if it is a container if (recurse && IsItemContainer(providerInstance, qualifiedPath, context)) { // Making sure to obey the StopProcessing. if (context.Stopping) { return; } // The item is a container so recurse into it. ProcessPathItems(providerInstance, qualifiedPath, recurse, context, out childrenNotMatchingFilterCriteria, processMode, skipIsItemContainerCheck: true); } } // for each childName } else { // The path is not a container so write it out if its name // matches the filter string childName = path; childName = GetChildName(providerInstance, path, context, true); // Write out the object if it is a match bool isIncludeMatch = SessionStateUtilities.MatchesAnyWildcardPattern( childName, includeMatcher, true); if (isIncludeMatch) { if (!SessionStateUtilities.MatchesAnyWildcardPattern( childName, excludeMatcher, false)) { if (processMode != ProcessMode.Delete) { // The object is a match so get it and write it out. GetItemPrivate(providerInstance, path, context); } else { // The object is a match so, remove it. containerCmdletProvider.RemoveItem(path, recurse, context); } } } } } // ProcessPathItems