/// <summary>
        /// Initializes a new instance of the <see cref="FileEnumerator"/> class.
        /// </summary>
        /// <param name="path">The directory to search.</param>
        /// <param name="fileExtension">The file extension to search for.</param>
        /// <param name="searchOption">if set to <c>true</c> search the sub directories of <paramref name="path"/>.</param>
        /// <param name="dereferenceLinks">if set to <c>true</c> search the target of shortcuts.</param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="path"/> in null.
        /// -or-
        /// <paramref name="fileExtension"/> is null.
        /// </exception>
        /// <exception cref="ArgumentOutOfRangeException">
        /// <paramref name="searchOption"/> is not a valid <see cref="SearchOption"/> value.
        /// </exception>
        /// <exception cref="PathTooLongException">The specified path, file name, or combined exceed the system-defined maximum length.</exception>
        /// <exception cref="System.Security.SecurityException">The caller does not have the required permission.</exception>
        public FileEnumerator(string path, string fileExtension, SearchOption searchOption, bool dereferenceLinks)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (fileExtension == null)
            {
                throw new ArgumentNullException(nameof(fileExtension));
            }
            if (searchOption < SearchOption.TopDirectoryOnly || searchOption > SearchOption.AllDirectories)
            {
                throw new ArgumentOutOfRangeException(nameof(searchOption));
            }

            string fullPath = Path.GetFullPath(path);
            string demandPath = GetPermissionPath(fullPath, false);
            new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPath).Demand();
            needPathDiscoveryDemand = false;

            searchData = new SearchData(fullPath, false);
            this.fileExtension = fileExtension;
            this.searchOption = searchOption;
            searchDirectories = new Queue<SearchData>();
            if (dereferenceLinks)
            {
                shellLink = new ShellLink();
                this.dereferenceLinks = true;
            }
            else
            {
                shellLink = null;
                this.dereferenceLinks = false;
            }
            shellLinkTarget = null;

            if (OS.IsWindows7OrLater)
            {
                // Suppress the querying of short filenames and use a larger buffer on Windows 7 and later.
                infoLevel = NativeEnums.FindExInfoLevel.Basic;
                additionalFlags = NativeEnums.FindExAdditionalFlags.LargeFetch;
            }
            else
            {
                infoLevel = NativeEnums.FindExInfoLevel.Standard;
                additionalFlags = NativeEnums.FindExAdditionalFlags.None;
            }
            oldErrorMode = SetErrorModeWrapper(NativeConstants.SEM_FAILCRITICALERRORS);
            state = -1;
            current = null;
            disposed = false;
            Init();
        }
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            if (!disposed)
            {
                disposed = true;

                if (handle != null)
                {
                    handle.Dispose();
                    handle = null;
                }

                if (shellLink != null)
                {
                    shellLink.Dispose();
                    shellLink = null;
                }
                current = null;
                state = -1;
                SetErrorModeWrapper(oldErrorMode);
            }
        }