internal static IEnumerable <string> GetVolumePathNamesForVolumeName(string volumeName)
            {
                return(StringBufferCache.CachedBufferInvoke((buffer) =>
                {
                    uint returnLength = 0;

                    // GetLogicalDriveStringsPrivate takes the buffer count in TCHARs, which is 2 bytes for Unicode (WCHAR)
                    while (!Private.GetVolumePathNamesForVolumeNameW(volumeName, buffer, (uint)buffer.CharCapacity, ref returnLength))
                    {
                        int lastError = Marshal.GetLastWin32Error();
                        switch (lastError)
                        {
                        case WinError.ERROR_MORE_DATA:
                            buffer.EnsureCharCapacity(returnLength);
                            break;

                        default:
                            throw GetIoExceptionForError(lastError, volumeName);
                        }
                    }

                    buffer.Length = returnLength;
                    return buffer.Split('\0');
                }));
            }
Ejemplo n.º 2
0
        internal static string BufferInvoke(Func <StringBuffer, uint> invoker, string value = null, Func <int, bool> shouldThrow = null)
        {
            return(StringBufferCache.CachedBufferInvoke(Paths.MaxPath, (buffer) =>
            {
                uint returnValue = 0;

                while ((returnValue = invoker(buffer)) > (uint)buffer.CharCapacity)
                {
                    // Need more room for the output string
                    buffer.EnsureCharCapacity(returnValue);
                }

                if (returnValue == 0)
                {
                    // Failed
                    int error = Marshal.GetLastWin32Error();

                    if (shouldThrow != null && !shouldThrow(error))
                    {
                        return null;
                    }
                    throw GetIoExceptionForError(error, value);
                }

                buffer.Length = returnValue;
                return buffer.ToString();
            }));
        }
            internal static string GetVolumeNameForVolumeMountPoint(string volumeMountPoint)
            {
                volumeMountPoint = Paths.AddTrailingSeparator(volumeMountPoint);

                // MSDN claims 50 is "reasonable", let's go double.
                return(StringBufferCache.CachedBufferInvoke(100, (volumeName) =>
                {
                    if (!Private.GetVolumeNameForVolumeMountPointW(volumeMountPoint, volumeName, (uint)volumeName.CharCapacity))
                    {
                        int lastError = Marshal.GetLastWin32Error();
                        throw GetIoExceptionForError(lastError, volumeMountPoint);
                    }

                    volumeName.SetLengthToFirstNull();
                    return volumeName.ToString();
                }));
            }
            internal static IEnumerable <string> GetLogicalDriveStrings()
            {
                return(StringBufferCache.CachedBufferInvoke((buffer) =>
                {
                    uint result = 0;

                    // GetLogicalDriveStringsPrivate takes the buffer count in TCHARs, which is 2 bytes for Unicode (WCHAR)
                    while ((result = Private.GetLogicalDriveStringsW((uint)buffer.CharCapacity, buffer)) > (uint)buffer.CharCapacity)
                    {
                        buffer.EnsureCharCapacity(result);
                    }

                    if (result == 0)
                    {
                        int lastError = Marshal.GetLastWin32Error();
                        throw GetIoExceptionForError(lastError);
                    }

                    buffer.Length = result;
                    return buffer.Split('\0');
                }));
            }
            internal static string GetVolumePathName(string path)
            {
                // Most paths are mounted at the root, 50 should handle the canonical (guid) root
                return(StringBufferCache.CachedBufferInvoke(50, (volumePathName) =>
                {
                    while (!Private.GetVolumePathNameW(path, volumePathName, (uint)volumePathName.CharCapacity))
                    {
                        int lastError = Marshal.GetLastWin32Error();
                        switch (lastError)
                        {
                        case WinError.ERROR_FILENAME_EXCED_RANGE:
                            volumePathName.EnsureCharCapacity(volumePathName.CharCapacity * 2);
                            break;

                        default:
                            throw GetIoExceptionForError(lastError, path);
                        }
                    }

                    volumePathName.SetLengthToFirstNull();
                    return volumePathName.ToString();
                }));
            }
Ejemplo n.º 6
0
        internal static string BufferPathInvoke(string path, Func <string, StringBuffer, uint> invoker, bool utilizeExtendedSyntax = true)
        {
            if (path == null)
            {
                return(null);
            }
            string originalPath = path;

            bool hadExtendedPrefix   = Paths.IsExtended(path);
            bool addedExtendedPrefix = false;

            if (utilizeExtendedSyntax && !hadExtendedPrefix && (path.Length > Paths.MaxPath))
            {
                path = Paths.AddExtendedPrefix(path);
                addedExtendedPrefix = true;
            }

            return(StringBufferCache.CachedBufferInvoke(Paths.MaxPath, (buffer) =>
            {
                uint returnValue = 0;

                while ((returnValue = invoker(path, buffer)) > (uint)buffer.CharCapacity)
                {
                    // Need more room for the output string
                    buffer.EnsureCharCapacity(returnValue);
                }

                if (returnValue == 0)
                {
                    // Failed
                    int error = Marshal.GetLastWin32Error();
                    throw GetIoExceptionForError(error, originalPath);
                }

                buffer.Length = returnValue;

                uint startIndex = 0;
                if (addedExtendedPrefix && buffer.StartsWithOrdinal(Paths.ExtendedPathPrefix))
                {
                    // Remove the prefix
                    if (buffer.StartsWithOrdinal(Paths.ExtendedUncPrefix))
                    {
                        // UNC, need to convert from \\?\UNC\ to \\.
                        startIndex = (uint)Paths.ExtendedUncPrefix.Length - 2;
                        buffer[startIndex] = Paths.DirectorySeparator;
                    }
                    else
                    {
                        startIndex = (uint)Paths.ExtendedPathPrefix.Length;
                    }
                }

                // If the string did not change, return the original (to cut back on identical string pressure)
                if (buffer.SubStringEquals(originalPath, startIndex: startIndex))
                {
                    return originalPath;
                }
                else
                {
                    return buffer.SubString(startIndex: startIndex);
                }
            }));
        }