private SearchResult CreateSearchResult(SearchData localSearchData, Interop.mincore.WIN32_FIND_DATA findData)
        {
            string findData_fileName = findData.cFileName;

            Contract.Requires(findData_fileName.Length != 0 && !Path.IsPathRooted(findData_fileName),
                              "Expected file system enumeration to not have empty file/directory name and not have rooted name");

            String userPathFinal = Path.Combine(localSearchData.userPath, findData_fileName);
            String fullPathFinal = Path.Combine(localSearchData.fullPath, findData_fileName);

            return(new SearchResult(fullPathFinal, userPathFinal, findData));
        }
        internal Win32FileSystemEnumerableIterator(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler <TSource> resultHandler)
        {
            Contract.Requires(path != null);
            Contract.Requires(originalUserPath != null);
            Contract.Requires(searchPattern != null);
            Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
            Contract.Requires(resultHandler != null);

            _oldMode = Interop.mincore.SetErrorMode(Interop.mincore.SEM_FAILCRITICALERRORS);

            _searchStack = new List <SearchData>();

            String normalizedSearchPattern = NormalizeSearchPattern(searchPattern);

            if (normalizedSearchPattern.Length == 0)
            {
                _empty = true;
            }
            else
            {
                _resultHandler     = resultHandler;
                this._searchOption = searchOption;

                _fullPath = Path.GetFullPath(path);
                String fullSearchString = GetFullSearchString(_fullPath, normalizedSearchPattern);
                _normalizedSearchPath = Path.GetDirectoryName(fullSearchString);

                // normalize search criteria
                _searchCriteria = GetNormalizedSearchCriteria(fullSearchString, _normalizedSearchPath);

                // fix up user path
                String searchPatternDirName = Path.GetDirectoryName(normalizedSearchPattern);
                String userPathTemp         = originalUserPath;
                if (searchPatternDirName != null && searchPatternDirName.Length != 0)
                {
                    userPathTemp = Path.Combine(userPathTemp, searchPatternDirName);
                }
                this._userPath = userPathTemp;

                _searchData = new SearchData(_normalizedSearchPath, this._userPath, searchOption);

                CommonInit();
            }
        }
        private Win32FileSystemEnumerableIterator(String fullPath, String normalizedSearchPath, String searchCriteria, String userPath, SearchOption searchOption, SearchResultHandler <TSource> resultHandler)
        {
            this._fullPath             = fullPath;
            this._normalizedSearchPath = normalizedSearchPath;
            this._searchCriteria       = searchCriteria;
            this._resultHandler        = resultHandler;
            this._userPath             = userPath;
            this._searchOption         = searchOption;

            _searchStack = new List <SearchData>();

            if (searchCriteria != null)
            {
                PathHelpers.CheckInvalidPathChars(fullPath, true);

                _searchData = new SearchData(normalizedSearchPath, userPath, searchOption);
                CommonInit();
            }
            else
            {
                _empty = true;
            }
        }
        public override bool MoveNext()
        {
            Interop.mincore.WIN32_FIND_DATA data = new Interop.mincore.WIN32_FIND_DATA();
            switch (state)
            {
            case STATE_INIT:
            {
                if (_empty)
                {
                    state = STATE_FINISH;
                    goto case STATE_FINISH;
                }
                if (_searchData.searchOption == SearchOption.TopDirectoryOnly)
                {
                    state = STATE_FIND_NEXT_FILE;
                    if (current != null)
                    {
                        return(true);
                    }
                    else
                    {
                        goto case STATE_FIND_NEXT_FILE;
                    }
                }
                else
                {
                    state = STATE_SEARCH_NEXT_DIR;
                    goto case STATE_SEARCH_NEXT_DIR;
                }
            }

            case STATE_SEARCH_NEXT_DIR:
            {
                Debug.Assert(_searchData.searchOption != SearchOption.TopDirectoryOnly, "should not reach this code path if searchOption == TopDirectoryOnly");
                // Traverse directory structure. We need to get '*'
                while (_searchStack.Count > 0)
                {
                    _searchData = _searchStack[0];
                    Debug.Assert((_searchData.fullPath != null), "fullpath can't be null!");
                    _searchStack.RemoveAt(0);

                    // Traverse the subdirs
                    AddSearchableDirsToStack(_searchData);

                    // Execute searchCriteria against the current directory
                    String searchPath = Path.Combine(_searchData.fullPath, _searchCriteria);

                    // Open a Find handle
                    _hnd = Interop.mincore.FindFirstFile(searchPath, ref data);
                    if (_hnd.IsInvalid)
                    {
                        int errorCode = Marshal.GetLastWin32Error();
                        if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_NO_MORE_FILES || errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND)
                        {
                            continue;
                        }

                        _hnd.Dispose();
                        HandleError(errorCode, _searchData.fullPath);
                    }

                    state = STATE_FIND_NEXT_FILE;

                    SearchResult searchResult = CreateSearchResult(_searchData, data);
                    if (_resultHandler.IsResultIncluded(searchResult))
                    {
                        current = _resultHandler.CreateObject(searchResult);
                        return(true);
                    }
                    else
                    {
                        goto case STATE_FIND_NEXT_FILE;
                    }
                }
                state = STATE_FINISH;
                goto case STATE_FINISH;
            }

            case STATE_FIND_NEXT_FILE:
            {
                if (_searchData != null && _hnd != null)
                {
                    // Keep asking for more matching files/dirs, add it to the list
                    while (Interop.mincore.FindNextFile(_hnd, ref data))
                    {
                        SearchResult searchResult = CreateSearchResult(_searchData, data);
                        if (_resultHandler.IsResultIncluded(searchResult))
                        {
                            current = _resultHandler.CreateObject(searchResult);
                            return(true);
                        }
                    }

                    // Make sure we quit with a sensible error.
                    int errorCode = Marshal.GetLastWin32Error();

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

                    // ERROR_FILE_NOT_FOUND is valid here because if the top level
                    // dir doesn't contain any subdirs and matching files then
                    // we will get here with this errorcode from the searchStack walk
                    if ((errorCode != 0) && (errorCode != Interop.mincore.Errors.ERROR_NO_MORE_FILES) &&
                        (errorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND))
                    {
                        HandleError(errorCode, _searchData.fullPath);
                    }
                }
                if (_searchData.searchOption == SearchOption.TopDirectoryOnly)
                {
                    state = STATE_FINISH;
                    goto case STATE_FINISH;
                }
                else
                {
                    state = STATE_SEARCH_NEXT_DIR;
                    goto case STATE_SEARCH_NEXT_DIR;
                }
            }

            case STATE_FINISH:
            {
                Dispose();
                break;
            }
            }
            return(false);
        }