internal static Transaction2FindNext2Response GetSubcommandResponse(SMB1Header header, Transaction2FindNext2Request subcommand, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); OpenSearch openSearch = session.GetOpenSearch(subcommand.SID); if (openSearch == null) { header.Status = NTStatus.STATUS_INVALID_HANDLE; return(null); } bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; int maxLength = (int)state.GetMaxDataCount(header.PID).Value; int maxCount = Math.Min(openSearch.Entries.Count - openSearch.EnumerationLocation, subcommand.SearchCount); List <QueryDirectoryFileInformation> segment = openSearch.Entries.GetRange(openSearch.EnumerationLocation, maxCount); FindInformationList findInformationList; try { findInformationList = SMB1FileStoreHelper.GetFindInformationList(segment, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength); } catch (UnsupportedInformationLevelException) { header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL; return(null); } int returnCount = findInformationList.Count; Transaction2FindNext2Response response = new Transaction2FindNext2Response(); response.SetFindInformationList(findInformationList, header.UnicodeFlag); openSearch.EnumerationLocation += returnCount; response.EndOfSearch = (openSearch.EnumerationLocation == openSearch.Entries.Count); if (response.EndOfSearch) { session.RemoveOpenSearch(subcommand.SID); } return(response); }
internal static Transaction2FindFirst2Response GetSubcommandResponse(SMB1Header header, Transaction2FindFirst2Request subcommand, ISMBShare share, SMB1ConnectionState state) { SMB1Session session = state.GetSession(header.UID); string fileNamePattern = subcommand.FileName; List <QueryDirectoryFileInformation> entries; FileInformationClass informationClass; try { informationClass = GetFileInformationClass(subcommand.InformationLevel); } catch (UnsupportedInformationLevelException) { header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL; return(null); } NTStatus searchStatus = SMB1FileStoreHelper.QueryDirectory(out entries, share.FileStore, fileNamePattern, informationClass, session.SecurityContext); if (searchStatus != NTStatus.STATUS_SUCCESS) { state.LogToServer(Severity.Verbose, "FindFirst2: Searched for '{0}{1}', NTStatus: {2}", share.Name, fileNamePattern, searchStatus.ToString()); header.Status = searchStatus; return(null); } // We ignore SearchAttributes state.LogToServer(Severity.Information, "FindFirst2: Searched for '{0}{1}', found {2} matching entries", share.Name, fileNamePattern, entries.Count); // [MS-CIFS] If no matching entries are found, the server SHOULD fail the request with STATUS_NO_SUCH_FILE. if (entries.Count == 0) { header.Status = NTStatus.STATUS_NO_SUCH_FILE; return(null); } bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count); List <QueryDirectoryFileInformation> segment = entries.GetRange(0, entriesToReturn); int maxLength = (int)state.GetMaxDataCount(header.PID).Value; FindInformationList findInformationList; try { findInformationList = SMB1FileStoreHelper.GetFindInformationList(segment, subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys, maxLength); } catch (UnsupportedInformationLevelException) { header.Status = NTStatus.STATUS_OS2_INVALID_LEVEL; return(null); } int returnCount = findInformationList.Count; Transaction2FindFirst2Response response = new Transaction2FindFirst2Response(); response.SetFindInformationList(findInformationList, header.UnicodeFlag); response.EndOfSearch = (returnCount == entries.Count); // If [..] the search fit within a single response and SMB_FIND_CLOSE_AT_EOS is set in the Flags field, // or if SMB_FIND_CLOSE_AFTER_REQUEST is set in the request, // the server SHOULD return a SID field value of zero. // This indicates that the search has been closed and is no longer active on the server. if ((response.EndOfSearch && subcommand.CloseAtEndOfSearch) || subcommand.CloseAfterRequest) { response.SID = 0; } else { ushort?searchHandle = session.AddOpenSearch(entries, returnCount); if (!searchHandle.HasValue) { header.Status = NTStatus.STATUS_OS2_NO_MORE_SIDS; return(null); } response.SID = searchHandle.Value; } return(response); }