Example #1
0
        private static bool FirstFileExists(FastIOSearchOption searchOption, string path, params string[] searchPatterns)
        {
            path = path.TrimEnd('\\');

            if (string.IsNullOrWhiteSpace(path) || Path.GetInvalidPathChars().Any(path.Contains))
            {
                throw new ArgumentException("The path '" + path + "' is invalid in some, or other, regard.");
            }

            const int fileAttributeDirectory = 0x10;

            const int ERROR_FILE_NOT_FOUND = 0x2;

            // Other relevant errors (though we don't use them specifically at the moment)
            //const int ERROR_PATH_NOT_FOUND = 0x3;
            //const int ERROR_REM_NOT_LIST = 0x33;
            //const int ERROR_BAD_NETPATH = 0x35;

            WIN32_FIND_DATAW findData;

            // Search the base directory first, and only then search subdirectories.
            // TODO: Fix goofy duplicate code

            if (searchOption != FastIOSearchOption.AllDirectoriesSkipTop)
            {
                foreach (var p in searchPatterns)
                {
                    using var findHandle = FindFirstFileW(@"\\?\" + path.TrimEnd('\\') + '\\' + p, out findData);

                    if (findHandle.IsInvalid)
                    {
                        var err = Marshal.GetLastWin32Error();
                        if (err == ERROR_FILE_NOT_FOUND)
                        {
                            continue;
                        }

                        // Since the framework isn't here to save us, we should blanket-catch and throw on every
                        // possible error other than file-not-found (as that's an intended scenario, obviously).
                        // This isn't as nice as you'd get from a framework method call, but it gets the job done.
                        ThrowException(searchPatterns, err, path, p, 0);
                    }
                    do
                    {
                        if ((findData.dwFileAttributes & fileAttributeDirectory) != fileAttributeDirectory &&
                            findData.cFileName != "." && findData.cFileName != "..")
                        {
                            return(true);
                        }
                    } while (FindNextFileW(findHandle, out findData));

                    if (searchOption == FastIOSearchOption.TopDirectoryOnly)
                    {
                        return(false);
                    }
                }
            }

            using (var findHandle = FindFirstFileW(@"\\?\" + path.TrimEnd('\\') + @"\*", out findData))
            {
                if (findHandle.IsInvalid)
                {
                    var err = Marshal.GetLastWin32Error();
                    if (err != ERROR_FILE_NOT_FOUND)
                    {
                        ThrowException(searchPatterns, err, path, @"\* [looking for all directories]", 1);
                    }
                }
                do
                {
                    if ((findData.dwFileAttributes & fileAttributeDirectory) == fileAttributeDirectory &&
                        findData.cFileName != "." && findData.cFileName != ".." &&
                        FirstFileExists(FastIOSearchOption.AllDirectories, Path.Combine(path, findData.cFileName),
                                        searchPatterns))
                    {
                        return(true);
                    }
                } while (FindNextFileW(findHandle, out findData));

                return(false);
            }
        }
Example #2
0
        private static bool FirstFileExists(FastIOSearchOption searchOption, string path, params string[] searchPatterns)
        {
            path = NormalizeAndCheckPath(path, pathIsKnownValid: false);

            // Other relevant errors (though we don't use them specifically at the moment)
            //const int ERROR_PATH_NOT_FOUND = 0x3;
            //const int ERROR_REM_NOT_LIST = 0x33;
            //const int ERROR_BAD_NETPATH = 0x35;

            WIN32_FIND_DATAW findData;

            // Search the base directory first, and only then search subdirectories.

            string pathC = @"\\?\" + path + "\\";

            foreach (string p in searchPatterns)
            {
                using SafeSearchHandle findHandle = FindFirstFileExW(
                          pathC + p,
                          FINDEX_INFO_LEVELS.FindExInfoBasic,
                          out findData,
                          FINDEX_SEARCH_OPS.FindExSearchNameMatch,
                          IntPtr.Zero,
                          0);

                if (findHandle.IsInvalid)
                {
                    int err = Marshal.GetLastWin32Error();
                    if (err == ERROR_FILE_NOT_FOUND)
                    {
                        continue;
                    }

                    // Since the framework isn't here to save us, we should blanket-catch and throw on every
                    // possible error other than file-not-found (as that's an intended scenario, obviously).
                    // This isn't as nice as you'd get from a framework method call, but it gets the job done.
                    ThrowException(searchPatterns, err, path, p, 0);
                }
                do
                {
                    if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY &&
                        findData.cFileName != "." && findData.cFileName != "..")
                    {
                        return(true);
                    }
                } while (FindNextFileW(findHandle, out findData));

                if (searchOption == FastIOSearchOption.TopDirectoryOnly)
                {
                    return(false);
                }
            }

            using (SafeSearchHandle findHandle = FindFirstFileExW(
                       pathC + "*",
                       FINDEX_INFO_LEVELS.FindExInfoBasic,
                       out findData,
                       FINDEX_SEARCH_OPS.FindExSearchNameMatch,
                       IntPtr.Zero,
                       0))
            {
                if (findHandle.IsInvalid)
                {
                    int err = Marshal.GetLastWin32Error();
                    if (err != ERROR_FILE_NOT_FOUND)
                    {
                        ThrowException(searchPatterns, err, path, @"\* [looking for all directories]", 1);
                    }
                }
                do
                {
                    if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY &&
                        findData.cFileName != "." && findData.cFileName != ".." &&
                        FirstFileExists(FastIOSearchOption.AllDirectories, Path.Combine(path, findData.cFileName),
                                        searchPatterns))
                    {
                        return(true);
                    }
                } while (FindNextFileW(findHandle, out findData));

                return(false);
            }
        }
Example #3
0
        private static bool FirstFileExists(FastIOSearchOption searchOption, string path, params string[] searchPatterns)
        {
            // Vital, path must not have a trailing separator
            // We also normalize manually to all backslashes because we use \\?\ which skips normalization
            path = path.Replace('/', '\\').TrimEnd(FMConstants.CA_Backslash);

            bool pathContainsInvalidChars = false;

            char[] invalidChars = Path.GetInvalidPathChars();

            // Dumb loop to avoid LINQ.
            for (int i = 0; i < invalidChars.Length; i++)
            {
                if (path.Contains(invalidChars[i]))
                {
                    pathContainsInvalidChars = true;
                    break;
                }
            }

            if (path.IsWhiteSpace() || pathContainsInvalidChars)
            {
                throw new ArgumentException("The path '" + path + "' is invalid in some, or other, regard.");
            }

            const int FILE_ATTRIBUTE_DIRECTORY = 0x10;
            const int ERROR_FILE_NOT_FOUND     = 0x2;

            // Other relevant errors (though we don't use them specifically at the moment)
            //const int ERROR_PATH_NOT_FOUND = 0x3;
            //const int ERROR_REM_NOT_LIST = 0x33;
            //const int ERROR_BAD_NETPATH = 0x35;

            WIN32_FIND_DATAW findData;

            // Search the base directory first, and only then search subdirectories.
            // TODO: Fix goofy duplicate code

            string pathC = @"\\?\" + path + "\\";

            if (searchOption != FastIOSearchOption.AllDirectoriesSkipTop)
            {
                foreach (string p in searchPatterns)
                {
                    using SafeSearchHandle findHandle = FindFirstFileEx(
                              pathC + p,
                              FINDEX_INFO_LEVELS.FindExInfoBasic,
                              out findData,
                              FINDEX_SEARCH_OPS.FindExSearchNameMatch,
                              IntPtr.Zero,
                              0);

                    if (findHandle.IsInvalid)
                    {
                        int err = Marshal.GetLastWin32Error();
                        if (err == ERROR_FILE_NOT_FOUND)
                        {
                            continue;
                        }

                        // Since the framework isn't here to save us, we should blanket-catch and throw on every
                        // possible error other than file-not-found (as that's an intended scenario, obviously).
                        // This isn't as nice as you'd get from a framework method call, but it gets the job done.
                        ThrowException(searchPatterns, err, path, p, 0);
                    }
                    do
                    {
                        if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY &&
                            findData.cFileName != "." && findData.cFileName != "..")
                        {
                            return(true);
                        }
                    } while (FindNextFileW(findHandle, out findData));

                    if (searchOption == FastIOSearchOption.TopDirectoryOnly)
                    {
                        return(false);
                    }
                }
            }

            using (SafeSearchHandle findHandle = FindFirstFileEx(
                       pathC + "*",
                       FINDEX_INFO_LEVELS.FindExInfoBasic,
                       out findData,
                       FINDEX_SEARCH_OPS.FindExSearchNameMatch,
                       IntPtr.Zero,
                       0))
            {
                if (findHandle.IsInvalid)
                {
                    int err = Marshal.GetLastWin32Error();
                    if (err != ERROR_FILE_NOT_FOUND)
                    {
                        ThrowException(searchPatterns, err, path, @"\* [looking for all directories]", 1);
                    }
                }
                do
                {
                    if ((findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY &&
                        findData.cFileName != "." && findData.cFileName != ".." &&
                        FirstFileExists(FastIOSearchOption.AllDirectories, Path.Combine(path, findData.cFileName),
                                        searchPatterns))
                    {
                        return(true);
                    }
                } while (FindNextFileW(findHandle, out findData));

                return(false);
            }
        }