public static List <FileInformation> FastFind(string path, string searchPattern, bool getFile, bool getDirectory, bool recurse, int?depth, bool parallel, bool suppressErrors, bool largeFetch, bool getHidden, bool getSystem, bool getReadOnly, bool getCompressed, bool getArchive, bool getReparsePoint, string filterMode)
        {
            object resultListLock = new object();

            Win32Native.WIN32_FIND_DATAW        lpFindFileData;
            Win32Native.FINDEX_ADDITIONAL_FLAGS additionalFlags = 0;
            if (largeFetch)
            {
                additionalFlags = Win32Native.FINDEX_ADDITIONAL_FLAGS.FindFirstExLargeFetch;
            }

            // add prefix to allow for maximum path of up to 32,767 characters
            string prefixedPath;

            if (path.StartsWith(@"\\"))
            {
                prefixedPath = path.Replace(@"\\", uncPrefix);
            }
            else
            {
                prefixedPath = normalPrefix + path;
            }

            var handle = Win32Native.FindFirstFileExW(prefixedPath + @"\*", Win32Native.FINDEX_INFO_LEVELS.FindExInfoBasic, out lpFindFileData, Win32Native.FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, additionalFlags);

            List <FileInformation> resultList       = new List <FileInformation>();
            List <FileInformation> subDirectoryList = new List <FileInformation>();

            if (!handle.IsInvalid)
            {
                do
                {
                    // skip "." and ".."
                    if (lpFindFileData.cFileName != "." && lpFindFileData.cFileName != "..")
                    {
                        // if directory...
                        if ((lpFindFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
                        {
                            // ...and if we are performing a recursive search...
                            if (recurse)
                            {
                                // ... populate the subdirectory list
                                string fullName = Path.Combine(path, lpFindFileData.cFileName);
                                subDirectoryList.Add(new FileInformation {
                                    Path = fullName
                                });
                            }
                        }

                        // skip folders if only the getFile parameter is used
                        if (getFile && !getDirectory)
                        {
                            if ((lpFindFileData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory)
                            {
                                continue;
                            }
                        }

                        // if file matches search pattern and attribute filter, add it to the result list
                        if (MatchesFilter(lpFindFileData.dwFileAttributes, lpFindFileData.cFileName, searchPattern, getFile, getDirectory, getHidden, getSystem, getReadOnly, getCompressed, getArchive, getReparsePoint, filterMode))
                        {
                            string fullName     = Path.Combine(path, lpFindFileData.cFileName);
                            long?  thisFileSize = null;
                            if ((lpFindFileData.dwFileAttributes & FileAttributes.Directory) != FileAttributes.Directory)
                            {
                                thisFileSize = (lpFindFileData.nFileSizeHigh * (2 ^ 32) + lpFindFileData.nFileSizeLow);
                            }
                            resultList.Add(new FileInformation {
                                Name = lpFindFileData.cFileName, Path = Path.Combine(path, lpFindFileData.cFileName), Parent = path, Attributes = lpFindFileData.dwFileAttributes, FileSize = thisFileSize, CreationTime = lpFindFileData.ftCreationTime.ToDateTime(), LastAccessTime = lpFindFileData.ftLastAccessTime.ToDateTime(), LastWriteTime = lpFindFileData.ftLastWriteTime.ToDateTime()
                            });
                        }
                    }
                }while (Win32Native.FindNextFile(handle, out lpFindFileData));

                // close the file handle
                handle.Dispose();

                // handle recursive search
                if (recurse)
                {
                    // handle depth of recursion
                    if (depth > 0)
                    {
                        if (parallel)
                        {
                            subDirectoryList.AsParallel().ForAll(x =>
                            {
                                List <FileInformation> resultSubDirectory = new List <FileInformation>();
                                resultSubDirectory = FastFind(x.Path, searchPattern, getFile, getDirectory, recurse, (depth - 1), false, suppressErrors, largeFetch, getHidden, getSystem, getReadOnly, getCompressed, getArchive, getReparsePoint, filterMode);
                                lock (resultListLock)
                                {
                                    resultList.AddRange(resultSubDirectory);
                                }
                            });
                        }

                        else
                        {
                            foreach (FileInformation directory in subDirectoryList)
                            {
                                foreach (FileInformation result in FastFind(directory.Path, searchPattern, getFile, getDirectory, recurse, (depth - 1), false, suppressErrors, largeFetch, getHidden, getSystem, getReadOnly, getCompressed, getArchive, getReparsePoint, filterMode))
                                {
                                    resultList.Add(result);
                                }
                            }
                        }
                    }

                    // if no depth are specified
                    else if (depth == null)
                    {
                        if (parallel)
                        {
                            subDirectoryList.AsParallel().ForAll(x =>
                            {
                                List <FileInformation> resultSubDirectory = new List <FileInformation>();
                                resultSubDirectory = FastFind(x.Path, searchPattern, getFile, getDirectory, recurse, null, false, suppressErrors, largeFetch, getHidden, getSystem, getReadOnly, getCompressed, getArchive, getReparsePoint, filterMode);
                                lock (resultListLock)
                                {
                                    resultList.AddRange(resultSubDirectory);
                                }
                            });
                        }

                        else
                        {
                            foreach (FileInformation directory in subDirectoryList)
                            {
                                foreach (FileInformation result in FastFind(directory.Path, searchPattern, getFile, getDirectory, recurse, null, false, suppressErrors, largeFetch, getHidden, getSystem, getReadOnly, getCompressed, getArchive, getReparsePoint, filterMode))
                                {
                                    resultList.Add(result);
                                }
                            }
                        }
                    }
                }
            }

            // error handling
            else if (handle.IsInvalid && !suppressErrors)
            {
                int hr = Marshal.GetLastWin32Error();
                if (hr != 2 && hr != 0x12)
                {
                    //throw new Win32Exception(hr);
                    Console.WriteLine("{0}:  {1}", path, (new Win32Exception(hr)).Message);
                }
            }

            return(resultList);
        }
        private static bool MatchesFilter(FileAttributes fileAttributes, string name, string searchPattern, bool aFile, bool aDirectory, bool aHidden, bool aSystem, bool aReadOnly, bool aCompressed, bool aArchive, bool aReparsePoint, string filterMode)
        {
            // first make sure that the name matches the search pattern
            if (Win32Native.PathMatchSpec(name, searchPattern))
            {
                // then we build our filter attributes enumeration
                FileAttributes filterAttributes = new FileAttributes();

                if (aDirectory)
                {
                    filterAttributes |= FileAttributes.Directory;
                }

                if (aHidden)
                {
                    filterAttributes |= FileAttributes.Hidden;
                }

                if (aSystem)
                {
                    filterAttributes |= FileAttributes.System;
                }

                if (aReadOnly)
                {
                    filterAttributes |= FileAttributes.ReadOnly;
                }

                if (aCompressed)
                {
                    filterAttributes |= FileAttributes.Compressed;
                }

                if (aReparsePoint)
                {
                    filterAttributes |= FileAttributes.ReparsePoint;
                }

                if (aArchive)
                {
                    filterAttributes |= FileAttributes.Archive;
                }

                // based on the filtermode, we match the file with our filter attributes a bit differently
                switch (filterMode)
                {
                case "Include":
                    if ((fileAttributes & filterAttributes) == filterAttributes)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }

                case "Exclude":
                    if ((fileAttributes & filterAttributes) != filterAttributes)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }

                case "Strict":
                    if (fileAttributes == filterAttributes)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                return(false);
            }
            else
            {
                return(false);
            }
        }
 protected override bool ReleaseHandle()
 {
     return(Win32Native.FindClose(base.handle));
 }