private static unsafe void GetFullPathName(string path, ref StringBuffer fullPath) { // If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as // it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here. Debug.Assert(PathInternal.IsPartiallyQualified(path) || !PathInternal.IsExtended(path)); // Historically we would skip leading spaces *only* if the path started with a drive " C:" or a UNC " \\" int startIndex = PathInternal.PathStartSkip(path); fixed(char *pathStart = path) { uint result = 0; while ((result = Interop.Kernel32.GetFullPathNameW(pathStart + startIndex, (uint)fullPath.Capacity, fullPath.UnderlyingArray, IntPtr.Zero)) > fullPath.Capacity) { // Reported size is greater than the buffer size. Increase the capacity. fullPath.EnsureCapacity(checked ((int)result)); } if (result == 0) { // Failure, get the error and throw int errorCode = Marshal.GetLastWin32Error(); if (errorCode == 0) { errorCode = Interop.Errors.ERROR_BAD_PATHNAME; } throw Win32Marshal.GetExceptionForWin32Error(errorCode, path); } fullPath.Length = checked ((int)result); } }
unsafe private static void GetFullPathName(string path, StringBuffer fullPath) { // If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as // it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here. Contract.Assert(PathInternal.IsPartiallyQualified(path) || !PathInternal.IsExtended(path)); // Historically we would skip leading spaces *only* if the path started with a drive " C:" or a UNC " \\" int startIndex = PathInternal.PathStartSkip(path); fixed(char *pathStart = path) { uint result = 0; while ((result = Win32Native.GetFullPathNameW(pathStart + startIndex, fullPath.CharCapacity, fullPath.GetHandle(), IntPtr.Zero)) > fullPath.CharCapacity) { // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity. fullPath.EnsureCharCapacity(result); } if (result == 0) { // Failure, get the error and throw int errorCode = Marshal.GetLastWin32Error(); if (errorCode == 0) { errorCode = Win32Native.ERROR_BAD_PATHNAME; } __Error.WinIOError(errorCode, path); } fullPath.Length = result; } }
private unsafe static void GetFullPathName(string path, StringBuffer fullPath) { int num = PathInternal.PathStartSkip(path); fixed(string text = path) { char *ptr = text; if (ptr != null) { ptr += RuntimeHelpers.OffsetToStringData / 2; } uint fullPathNameW; while ((fullPathNameW = Win32Native.GetFullPathNameW(ptr + num, fullPath.CharCapacity, fullPath.GetHandle(), IntPtr.Zero)) > fullPath.CharCapacity) { fullPath.EnsureCharCapacity(fullPathNameW); } if (fullPathNameW == 0U) { int num2 = Marshal.GetLastWin32Error(); if (num2 == 0) { num2 = 161; } __Error.WinIOError(num2, path); } fullPath.Length = fullPathNameW; } }
// Token: 0x0600195D RID: 6493 RVA: 0x000546C8 File Offset: 0x000528C8 internal static string NormalizeDirectorySeparators(string path) { if (string.IsNullOrEmpty(path)) { return(path); } int num = PathInternal.PathStartSkip(path); if (num == 0) { bool flag = true; for (int i = 0; i < path.Length; i++) { char c = path[i]; if (PathInternal.IsDirectorySeparator(c) && (c != Path.DirectorySeparatorChar || (i > 0 && i + 1 < path.Length && PathInternal.IsDirectorySeparator(path[i + 1])))) { flag = false; break; } } if (flag) { return(path); } } StringBuilder stringBuilder = StringBuilderCache.Acquire(path.Length); if (PathInternal.IsDirectorySeparator(path[num])) { num++; stringBuilder.Append(Path.DirectorySeparatorChar); } int j = num; while (j < path.Length) { char c = path[j]; if (!PathInternal.IsDirectorySeparator(c)) { goto IL_D2; } if (j + 1 >= path.Length || !PathInternal.IsDirectorySeparator(path[j + 1])) { c = Path.DirectorySeparatorChar; goto IL_D2; } IL_DA: j++; continue; IL_D2: stringBuilder.Append(c); goto IL_DA; } return(StringBuilderCache.GetStringAndRelease(stringBuilder)); }
private static string NormalizePath(string path, bool fullCheck = true, bool expandShortPaths = true) { Debug.Assert(path != null, "path can't be null"); bool isExtended = PathInternal.IsExtended(path); if (fullCheck) { // Embedded null characters are the only invalid character case we want to check up front. // This is because the nulls will signal the end of the string to Win32 and therefore have // unpredictable results. Other invalid characters we give a chance to be normalized out. if (path.IndexOf('\0') != -1) { throw new ArgumentException(SR.Argument_InvalidPathChars, "path"); } // Toss out paths with colons that aren't a valid drive specifier. // Cannot start with a colon and can only be of the form "C:" or "\\?\C:". // (Note that we used to explicitly check "http:" and "file:"- these are caught by this check now.) int startIndex = PathInternal.PathStartSkip(path) + 2; if (isExtended) { startIndex += PathInternal.ExtendedPathPrefix.Length; } if ((path.Length > 0 && path[0] == VolumeSeparatorChar) || (path.Length >= startIndex && path[startIndex - 1] == VolumeSeparatorChar && !PathInternal.IsValidDriveChar(path[startIndex - 2])) || (path.Length > startIndex && path.IndexOf(VolumeSeparatorChar, startIndex) != -1)) { throw new NotSupportedException(SR.Argument_PathFormatNotSupported); } } if (isExtended) { return(NormalizeExtendedPath(path, fullCheck)); } else { // Technically this doesn't matter but we used to throw for this case if (String.IsNullOrWhiteSpace(path)) { throw new ArgumentException(SR.Arg_PathIllegal); } return(PathHelper.Normalize(path, fullCheck, expandShortPaths)); } }
private StringBuilder GetFullPathName(string path) { // Historically we would skip leading spaces *only* if the path started with a drive " C:" or a UNC " \\" int startIndex = PathInternal.PathStartSkip(path); int capacity = path.Length; if (PathInternal.IsRelative(path)) { // If the initial path is relative the final path will likely be no more than the current directory length (which can only // be MaxPath) so we'll pick that as a reasonable start. capacity += PathInternal.MaxShortPath; } else { // If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as // it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here. Debug.Assert(!PathInternal.IsExtended(path)); } StringBuilder outputBuffer = this.GetOutputBuffer(capacity); fixed(char *pathStart = path) { int result = 0; while ((result = Interop.mincore.GetFullPathNameW(pathStart + startIndex, outputBuffer.Capacity + 1, outputBuffer, IntPtr.Zero)) > outputBuffer.Capacity) { // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity. outputBuffer.Capacity = result; } if (result == 0) { // Failure, get the error and throw int errorCode = Marshal.GetLastWin32Error(); if (errorCode == 0) { errorCode = Interop.mincore.Errors.ERROR_BAD_PATHNAME; } throw Win32Marshal.GetExceptionForWin32Error(errorCode, path); } } return(outputBuffer); }
// Expands the given path to a fully qualified path. public static string GetFullPath(string path) { if (path == null) { throw new ArgumentNullException(nameof(path)); } // Embedded null characters are the only invalid character case we want to check up front. // This is because the nulls will signal the end of the string to Win32 and therefore have // unpredictable results. Other invalid characters we give a chance to be normalized out. if (path.IndexOf('\0') != -1) { throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path)); } if (PathInternal.IsExtended(path)) { // We can't really know what is valid for all cases of extended paths. // // - object names can include other characters as well (':', '/', etc.) // - even file objects have different rules (pipe names can contain most characters) // // As such we will do no further analysis of extended paths to avoid blocking known and unknown // scenarios as well as minimizing compat breaks should we block now and need to unblock later. return(path); } bool isDevice = PathInternal.IsDevice(path); if (!isDevice) { // Toss out paths with colons that aren't a valid drive specifier. // Cannot start with a colon and can only be of the form "C:". // (Note that we used to explicitly check "http:" and "file:"- these are caught by this check now.) int startIndex = PathInternal.PathStartSkip(path); // Move past the colon startIndex += 2; if ((path.Length > 0 && path[0] == PathInternal.VolumeSeparatorChar) || (path.Length >= startIndex && path[startIndex - 1] == PathInternal.VolumeSeparatorChar && !PathInternal.IsValidDriveChar(path[startIndex - 2])) || (path.Length > startIndex && path.IndexOf(PathInternal.VolumeSeparatorChar, startIndex) != -1)) { throw new NotSupportedException(SR.Format(SR.Argument_PathFormatNotSupported_Path, path)); } } // Technically this doesn't matter but we used to throw for this case if (PathInternal.IsEffectivelyEmpty(path)) { throw new ArgumentException(SR.Arg_PathEmpty, nameof(path)); } // We don't want to check invalid characters for device format- see comments for extended above string fullPath = PathHelper.Normalize(path, checkInvalidCharacters: !isDevice, expandShortPaths: true); if (!isDevice) { // Emulate FileIOPermissions checks, retained for compatibility (normal invalid characters have already been checked) if (PathInternal.HasWildCardCharacters(fullPath)) { throw new ArgumentException(SR.Argument_InvalidPathChars, nameof(path)); } } return(fullPath); }
// Token: 0x06001941 RID: 6465 RVA: 0x00053E6C File Offset: 0x0005206C internal static bool HasInvalidVolumeSeparator(string path) { int num = (!AppContextSwitches.UseLegacyPathHandling && PathInternal.IsExtended(path)) ? "\\\\?\\".Length : PathInternal.PathStartSkip(path); return((path.Length > num && path[num] == Path.VolumeSeparatorChar) || (path.Length >= num + 2 && path[num + 1] == Path.VolumeSeparatorChar && !PathInternal.IsValidDriveChar(path[num])) || (path.Length > num + 2 && path.IndexOf(Path.VolumeSeparatorChar, num + 2) != -1)); }
/// <summary> /// Normalize the path and check for bad characters or other invalid syntax. /// </summary> /// <remarks> /// The legacy NormalizePath /// </remarks> private static string NormalizeAndValidatePath(string path) { Debug.Assert(path != null, "path can't be null"); // Embedded null characters are the only invalid character case we want to check up front. // This is because the nulls will signal the end of the string to Win32 and therefore have // unpredictable results. Other invalid characters we give a chance to be normalized out. if (path.IndexOf('\0') != -1) { throw new ArgumentException(SR.Argument_InvalidPathChars, "path"); } // Toss out paths with colons that aren't a valid drive specifier. // Cannot start with a colon and can only be of the form "C:" or "\\?\C:". // (Note that we used to explicitly check "http:" and "file:"- these are caught by this check now.) int startIndex = PathInternal.PathStartSkip(path); bool isExtended = path.Length >= PathInternal.ExtendedPathPrefix.Length + startIndex && path.IndexOf(PathInternal.ExtendedPathPrefix, startIndex, PathInternal.ExtendedPathPrefix.Length, StringComparison.Ordinal) >= 0; if (isExtended) { startIndex += PathInternal.ExtendedPathPrefix.Length; } // Move past the colon startIndex += 2; if ((path.Length > 0 && path[0] == VolumeSeparatorChar) || (path.Length >= startIndex && path[startIndex - 1] == VolumeSeparatorChar && !PathInternal.IsValidDriveChar(path[startIndex - 2])) || (path.Length > startIndex && path.IndexOf(VolumeSeparatorChar, startIndex) != -1)) { throw new NotSupportedException(SR.Argument_PathFormatNotSupported); } if (isExtended) { // If the path is in extended syntax, we don't need to normalize, but we still do some basic validity checks if (!ValidateExtendedPath(path)) { throw new ArgumentException(SR.Arg_PathIllegal); } // \\?\GLOBALROOT gives access to devices out of the scope of the current user, we // don't want to allow this for security reasons. // https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#nt_namespaces if (path.StartsWith(@"\\?\globalroot", StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException(SR.Arg_PathGlobalRoot); } // Look for illegal path characters. PathInternal.CheckInvalidPathChars(path); return(path); } else { // Technically this doesn't matter but we used to throw for this case if (String.IsNullOrWhiteSpace(path)) { throw new ArgumentException(SR.Arg_PathIllegal); } return(PathHelper.Normalize(path, checkInvalidCharacters: true, expandShortPaths: true)); } }