void CommonInit() { Contract.Assert(searchCriteria != null && searchData != null, "searchCriteria and searchData should be initialized"); // Execute searchCriteria against the current directory String searchPath = searchData.fullPath + searchCriteria; var data = new FindData(); // Open a Find handle safeFindHandle = Win32Api.IO.FindFirstFile(searchPath, data); if (safeFindHandle.IsInvalid) { int hr = Marshal.GetLastWin32Error(); if (hr != Win32Error.ERROR_FILE_NOT_FOUND && hr != Win32Error.ERROR_NO_MORE_FILES) { HandleError(hr, searchData.fullPath); } else { // flag this as empty only if we're searching just top directory // Used in fast path for top directory only isEmpty = searchData.searchOptions == SearchOption.TopDirectoryOnly; } } // fast path for TopDirectoryOnly. If we have a result, go ahead and set it to // current. If empty, dispose handle. if (searchData.searchOptions == SearchOption.TopDirectoryOnly) { if (isEmpty) { safeFindHandle.Dispose(); } else { SearchResult searchResult = CreateSearchResult(searchData, data); if (resultHandler.IsResultIncluded(searchResult)) { current = resultHandler.CreateObject(searchResult); } } } // for AllDirectories, we first recurse into dirs, so cleanup and add searchData // to the stack else { safeFindHandle.Dispose(); searchStack.Add(searchData); } }
protected override void Dispose(bool disposing) { try { if (safeFindHandle != null) { safeFindHandle.Dispose(); } } finally { Win32Api.SetErrorMode(oldMode); base.Dispose(disposing); } }
[SecurityCritical] // auto-generated void AddSearchableDirsToStack(SearchData localSearchData) { Contract.Requires(localSearchData != null); String searchPath = localSearchData.fullPath + "*"; SafeFindHandle hnd = null; var data = new FindData(); try { // Get all files and dirs hnd = Win32Api.IO.FindFirstFile(searchPath, data); if (hnd.IsInvalid) { int hr = Marshal.GetLastWin32Error(); // This could happen if the dir doesn't contain any files. // Continue with the recursive search though, eventually // searchStack will become empty if (hr == Win32Error.ERROR_ACCESS_DENIED || hr == Win32Error.ERROR_FILE_NOT_FOUND || hr == Win32Error.ERROR_NO_MORE_FILES || hr == Win32Error.ERROR_PATH_NOT_FOUND) { return; } HandleError(hr, localSearchData.fullPath); } // Add subdirs to searchStack. Exempt ReparsePoints as appropriate int incr = 0; do { if (data.IsDir) { // FullPath var pathBuffer = new StringBuilder(localSearchData.fullPath); pathBuffer.Append(data.FileName); String tempFullPath = pathBuffer.ToString(); // UserPath pathBuffer.Length = 0; pathBuffer.Append(localSearchData.userPath); pathBuffer.Append(data.FileName); SearchOption option = localSearchData.searchOptions; #if EXCLUDE_REPARSEPOINTS // Traverse reparse points depending on the searchoption specified if ((searchDataSubDir.searchOption == SearchOption.AllDirectories) && (0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_REPARSE_POINT))) { option = SearchOption.TopDirectoryOnly; } #endif // Setup search data for the sub directory and push it into the stack var searchDataSubDir = new SearchData(tempFullPath, pathBuffer.ToString(), option); searchStack.Insert(incr++, searchDataSubDir); } } while(Win32Api.IO.FindNextFile(hnd, data)); // We don't care about errors here } finally { if (hnd != null) { hnd.Dispose(); } } }
public override bool MoveNext() { var data = new FindData(); switch (state) { case stateInit: { if (isEmpty) { state = stateFinish; goto case stateFinish; } if (searchData.searchOptions == SearchOption.TopDirectoryOnly) { state = stateFindNextFile; if (current != null) { return(true); } goto case stateFindNextFile; } state = stateSearchNextDir; goto case stateSearchNextDir; } case stateSearchNextDir: { Contract.Assert(searchData.searchOptions != 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]; Contract.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 = searchData.fullPath + searchCriteria; // Open a Find handle safeFindHandle = Win32Api.IO.FindFirstFile(searchPath, data); if (safeFindHandle.IsInvalid) { int hr = Marshal.GetLastWin32Error(); if (hr == Win32Error.ERROR_ACCESS_DENIED || hr == Win32Error.ERROR_FILE_NOT_FOUND || hr == Win32Error.ERROR_NO_MORE_FILES || hr == Win32Error.ERROR_PATH_NOT_FOUND) { continue; } safeFindHandle.Dispose(); HandleError(hr, searchData.fullPath); } state = stateFindNextFile; needsParentPathDiscoveryDemand = true; SearchResult searchResult = CreateSearchResult(searchData, data); if (resultHandler.IsResultIncluded(searchResult)) { if (needsParentPathDiscoveryDemand) { DoDemand(searchData.fullPath); needsParentPathDiscoveryDemand = false; } current = resultHandler.CreateObject(searchResult); return(true); } goto case stateFindNextFile; } state = stateFinish; goto case stateFinish; } case stateFindNextFile: { if (searchData != null && safeFindHandle != null) { // Keep asking for more matching files/dirs, add it to the list while (Win32Api.IO.FindNextFile(safeFindHandle, data)) { SearchResult searchResult = CreateSearchResult(searchData, data); if (resultHandler.IsResultIncluded(searchResult)) { if (needsParentPathDiscoveryDemand) { DoDemand(searchData.fullPath); needsParentPathDiscoveryDemand = false; } current = resultHandler.CreateObject(searchResult); return(true); } } // Make sure we quit with a sensible error. int hr = Marshal.GetLastWin32Error(); if (safeFindHandle != null) { safeFindHandle.Dispose(); } // ERROR_FILE_NOT_FOUND is valid here because if the top level // dir doen't contain any subdirs and matching files then // we will get here with this errorcode from the searchStack walk if ((hr != 0) && (hr != Win32Error.ERROR_NO_MORE_FILES) && (hr != Win32Error.ERROR_FILE_NOT_FOUND)) { HandleError(hr, searchData.fullPath); } } if (searchData.searchOptions == SearchOption.TopDirectoryOnly) { state = stateFinish; goto case stateFinish; } state = stateSearchNextDir; goto case stateSearchNextDir; } case stateFinish: { Dispose(); break; } } return(false); }