internal static Transaction2FindNext2Response GetSubcommandResponse(SMBHeader header, Transaction2FindNext2Request subcommand, FileSystemShare share, StateObject state) { Transaction2FindNext2Response response = new Transaction2FindNext2Response(); if (!state.OpenSearches.ContainsKey(subcommand.SID)) { header.Status = NTStatus.STATUS_INVALID_HANDLE; return(null); } bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; List <FileSystemEntry> entries = state.OpenSearches[subcommand.SID]; for (int index = 0; index < entries.Count; index++) { FindInformationEntry infoEntry = InfoHelper.FromFileSystemEntry(entries[index], subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys); response.FindInfoList.Add(infoEntry); if (response.FindInfoList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID)) { response.FindInfoList.RemoveAt(response.FindInfoList.Count - 1); break; } } int returnCount = response.FindInfoList.Count; entries.RemoveRange(0, returnCount); state.OpenSearches[subcommand.SID] = entries; response.SearchCount = (ushort)returnCount; response.EndOfSearch = (returnCount == entries.Count) && (entries.Count <= subcommand.SearchCount); return(response); }
internal static Transaction2FindFirst2Response GetSubcommandResponse(SMBHeader header, Transaction2FindFirst2Request subcommand, FileSystemShare share, StateObject state) { IFileSystem fileSystem = share.FileSystem; Transaction2FindFirst2Response response = new Transaction2FindFirst2Response(); string path = subcommand.FileName; // '\Directory' - Get the directory info // '\Directory\*' - List the directory files // '\Directory\s*' - List the directory files starting with s (cmd.exe will use this syntax when entering 's' and hitting tab for autocomplete) // '\Directory\<.inf' (Update driver will use this syntax) // '\Directory\exefile"*' (cmd.exe will use this syntax when entering an exe without its extension, explorer will use this opening a directory from the run menu) bool isDirectoryEnumeration = false; string searchPattern = String.Empty; if (path.Contains("*") || path.Contains("<")) { isDirectoryEnumeration = true; int separatorIndex = path.LastIndexOf('\\'); searchPattern = path.Substring(separatorIndex + 1); path = path.Substring(0, separatorIndex + 1); } bool exactNameWithoutExtension = searchPattern.Contains("\""); FileSystemEntry entry = fileSystem.GetEntry(path); if (entry == null) { header.Status = NTStatus.STATUS_NO_SUCH_FILE; return(null); } List <FileSystemEntry> entries; if (isDirectoryEnumeration) { try { entries = fileSystem.ListEntriesInDirectory(path); } catch (UnauthorizedAccessException) { header.Status = NTStatus.STATUS_ACCESS_DENIED; return(null); } if (searchPattern != String.Empty) { entries = GetFiltered(entries, searchPattern); } if (!exactNameWithoutExtension) { if (IncludeParentDirectoryInResults) { entries.Insert(0, fileSystem.GetEntry(FileSystem.GetParentDirectory(path))); entries[0].Name = ".."; } if (IncludeCurrentDirectoryInResults) { entries.Insert(0, fileSystem.GetEntry(path)); entries[0].Name = "."; } } // 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); } } else { entries = new List <FileSystemEntry>(); entries.Add(entry); } bool returnResumeKeys = (subcommand.Flags & FindFlags.SMB_FIND_RETURN_RESUME_KEYS) > 0; int entriesToReturn = Math.Min(subcommand.SearchCount, entries.Count); // We ignore SearchAttributes for (int index = 0; index < entriesToReturn; index++) { FindInformationEntry infoEntry = InfoHelper.FromFileSystemEntry(entries[index], subcommand.InformationLevel, header.UnicodeFlag, returnResumeKeys); response.FindInfoList.Add(infoEntry); if (response.FindInfoList.GetLength(header.UnicodeFlag) > state.GetMaxDataCount(header.PID)) { response.FindInfoList.RemoveAt(response.FindInfoList.Count - 1); break; } } int returnCount = response.FindInfoList.Count; response.EndOfSearch = (returnCount == entries.Count) && (entries.Count <= subcommand.SearchCount); response.SID = state.AllocateSearchHandle(); entries.RemoveRange(0, returnCount); state.OpenSearches.Add(response.SID, entries); return(response); }