internal Relocation(RelocationBlock relocBlock, long relocOffset, ushort relocValue) { block = relocBlock; int reloc_type = relocValue >> 12; int reloc_offset = relocValue & 0xFFF; type = (RelocationType)reloc_type; offset = Convert.ToUInt16(reloc_offset); value = relocValue; computed_rva = block.PageRVA; switch (type) { case RelocationType.Absolute: break; case RelocationType.HighLow: computed_rva += offset; break; case RelocationType.Dir64: computed_rva += offset; break; case RelocationType.High: case RelocationType.Low: default: computed_rva = 0; break; } location = new StreamLocation(relocOffset,size); }
internal ImportLookupTableEntry(ImportLookupTable lookupTable, StreamLocation streamLoc, ulong entryAddress, int entryOrdinal) { table = lookupTable; location = streamLoc; address = entryAddress; ordinal = entryOrdinal; }
internal NTHeaders(ExeReader exeReader, StreamLocation streamLoc, FileHeader fileHeader, OptionalHeader optHeader) { reader = exeReader; location = streamLoc; file_header = fileHeader; opt_header = optHeader; }
internal CLRMetaDataHeader(CLRMetaData metaData) { long offset = metaData.Location.Offset; Stream stream = metaData.Content.Section.Sections.Reader.GetStream(); stream.Seek(offset,SeekOrigin.Begin); MetaData = metaData; Signature = Utils.ReadUInt32(stream); if (Signature != CLR_METADATA_SIGNATURE) throw new ExeReaderException("Incorrect signature found in CLR meta-data header."); MajorVersion = Utils.ReadUInt16(stream); MinorVersion = Utils.ReadUInt16(stream); Reserved = Utils.ReadUInt32(stream); VersionLength = Utils.ReadUInt32(stream); Version = Utils.ReadString(stream,VersionLength); Flags = Utils.ReadUInt16(stream); Streams = Utils.ReadUInt16(stream); long size = stream.Position - offset; Location = new StreamLocation(offset,size); }
internal CLRContent(DataDirectory dataDirectory, Section section) : base(dataDirectory,section) { long offset = section.RVAToOffset(dataDirectory.VirtualAddress); location = new StreamLocation(offset,dataDirectory.Size); header = new CLRHeader(this,dataDirectory); meta_data = null; }
internal CLRMetaData(CLRContent clrContent) { long offset = clrContent.Section.RVAToOffset(clrContent.Header.MetaDataAddress); content = clrContent; location = new StreamLocation(offset,clrContent.Header.MetaDataSize); header = null; stream_table = null; streams = null; }
internal CLRHeader(CLRContent clrContent, DataDirectory dataDirectory) { long offset = clrContent.Section.RVAToOffset(dataDirectory.VirtualAddress); Stream stream = clrContent.Section.Sections.Reader.GetStream(); stream.Seek(offset,SeekOrigin.Begin); content = clrContent; location = new StreamLocation(offset,size); header = Utils.Read<IMAGE_COR20_HEADER>(stream); }
public void AssignAtomText(ScanStream ScanStream) { TextLocation wordBx = new StreamLocation(this.Pos).ToTextLocation(ScanStream); int lx = this.MatchLength; TextLocation wordEx = new StreamLocation(this.Pos + lx - 1).ToTextLocation(ScanStream); string scanText = ScanStream.Stream.Substring(this.Pos, lx); this.AtomText = new AtomText( this.MatchPattern.DelimClassification.ToScanAtomCode().Value, scanText, this.MatchPattern.ReplacementValue, wordBx, wordEx, this.MatchPattern.UserCode); }
private static Tuple <TextLocation, TextWord> IsolateWordText( ScanStream ScanStream, TextTraits Traits, LiteralType?LiteralType, string LitText, int Bx, int?NonWordBx) { TextLocation wordBx = null; TextWord wordPart = null; // not a literal. A word that runs from Bx to immed before NonWordBx. if (LiteralType == null) { wordBx = new StreamLocation(Bx).ToTextLocation(ScanStream); int lx; if (NonWordBx == null) { lx = ScanStream.Stream.Length - Bx; } else { lx = NonWordBx.Value - Bx; } wordPart = new TextWord( ScanStream.Substring(Bx, lx), WordClassification.Identifier, Traits); } // a quoted or numeric literal else { wordBx = new StreamLocation(Bx).ToTextLocation(ScanStream); wordPart = new TextWord(LitText, LiteralType.Value, Traits); } return(new Tuple <TextLocation, TextWord>(wordBx, wordPart)); }
internal TLSContent(DataDirectory dataDirectory, Section section) : base(dataDirectory,section) { long offset = section.RVAToOffset(dataDirectory.VirtualAddress); location = new StreamLocation(offset,dataDirectory.Size); }
internal FileHeader(ExeReader exeReader, IMAGE_FILE_HEADER fileHeader, StreamLocation streamLoc) { reader = exeReader; header = fileHeader; location = streamLoc; }
internal DOSStub(ExeReader exeReader, StreamLocation streamLoc) { reader = exeReader; location = streamLoc; }
private FileHeader LoadFileHeader(DOSHeader dosHeader) { IMAGE_FILE_HEADER native_file_header = Utils.Read<IMAGE_FILE_HEADER>(_stream,FileHeader.Size); StreamLocation location = new StreamLocation(dosHeader.FileAddressNewHeader + 4,FileHeader.Size); return new FileHeader(this,native_file_header,location); }
// ------------------------ ScanNextAtom ------------------------- // Scans to the next atom in the string. ( a word being the text bounded by the // delimeter and whitespace characters as spcfd in the TextTraits argument ) // Return null when end of string. public static ScanAtomCursor ScanNextAtom( ScanStream ScanStream, TextTraits Traits, ScanAtomCursor CurrentWord) { // components of the next word. TextLocation wordBx = null; int nonWordIx = -1; int nonWordLx = 0; ScanPattern nonWordPat = null; List <MatchScanPattern> nonWordPatList = null; AtomText atomText = null; List <MatchScanPattern> atomTextList = null; AtomText whitespaceText = null; // ScanAtomCode? priorCode = null; bool?priorCodeIsWhitespaceSignificant = null; // stay at the current location. return copy of the cursor, but with stayatflag // turned off. if (CurrentWord.StayAtFlag == true) { atomText = CurrentWord.AtomText; nonWordPat = CurrentWord.AtomPattern; wordBx = CurrentWord.StartLoc; } else { #region STEP1 setup the begin pos of the next word. // ----------------------------- STEP 1 ------------------------------ // setup the begin pos of the next word. int bx; { // save the ScanAtomCode of the prior word. if ((CurrentWord.Position == RelativePosition.At) || (CurrentWord.Position == RelativePosition.After)) { priorCodeIsWhitespaceSignificant = CurrentWord.WhitespaceIsSignificant; // priorCode = CurrentWord.AtomText.AtomCode; } // calc scan start position bx = ScanAtom.CalcScanNextStart(ScanStream, Traits, CurrentWord); // advance past whitespace if (bx != -1) { int saveBx = bx; bx = Scanner.ScanNotEqual(ScanStream.Stream, Traits.WhitespacePatterns, bx); // there is some whitespace. depending on what preceeds and follows, may // return this as the atom. if ((priorCodeIsWhitespaceSignificant != null) && (priorCodeIsWhitespaceSignificant.Value == true)) { if (bx != saveBx) { int whitespaceEx = -1; if (bx == -1) { whitespaceEx = ScanStream.Stream.Length - 1; } else { whitespaceEx = bx - 1; } int whitespaceLx = whitespaceEx - saveBx + 1; whitespaceText = new AtomText( ScanAtomCode.Whitespace, ScanStream.Stream.Substring(saveBx, whitespaceLx), " ", new StreamLocation(saveBx).ToTextLocation(ScanStream), new StreamLocation(whitespaceEx).ToTextLocation(ScanStream)); } } } } // end STEP 1. #endregion #region STEP 2. Isolate either numeric lib, quoted lit or scan to non word pattern // ------------------------------- STEP 2 ---------------------------------- // Isolate either numeric literal, quoted literal or scan to the next non word // pattern. LiteralType?litType = null; string litText = null; { // got a decimal digit. isolate the numeric literal string. if ((bx != -1) && (Char.IsDigit(ScanStream.Stream[bx]) == true)) { var rv = Scanner.IsolateNumericLiteral(ScanStream, Traits, bx); litType = rv.Item1; litText = rv.Item2; nonWordPat = rv.Item3; // the non word pattern immed after numeric literal nonWordIx = rv.Item4; // pos of foundPat } // got something. now scan forward for the pattern that delimits the word. else if (bx != -1) { { var rv = Scanner.ScanEqualAny(ScanStream.Stream, bx, Traits.DelimPatterns); nonWordPat = rv.Item1; nonWordIx = rv.Item2; nonWordLx = rv.Item3; nonWordPatList = rv.Item4; } // got a quote char. Isolate the quoted string, then find the delim that follows // the quoted string. if ((nonWordPat != null) && (nonWordPat.DelimClassification == DelimClassification.Quote) && (nonWordIx == bx)) { var rv = Scanner.IsolateQuotedWord(ScanStream, Traits, nonWordIx); litType = rv.Item1; litText = rv.Item2; nonWordPat = rv.Item3; // the non word pattern immed after quoted literal nonWordIx = rv.Item4; // pos of foundPat. } } } // end STEP 2. #endregion #region STEP 3 - setup wordBx and wordPart with the found word. { // got nothing. if (bx == -1) { } // no delim found. word text all the way to the end. else if (nonWordIx == -1) { if (whitespaceText != null) { atomText = whitespaceText; nonWordPat = null; nonWordPatList = null; } else { var rv = Scanner.IsolateWordText( ScanStream, Traits, litType, litText, bx, null); atomText = rv.Item3; wordBx = atomText.StartLoc; } } // got a word and a non word pattern. else if (nonWordIx > bx) { if (whitespaceText != null) { atomText = whitespaceText; nonWordPat = null; nonWordPatList = null; } else { var rv = Scanner.IsolateWordText( ScanStream, Traits, litType, litText, bx, nonWordIx); atomText = rv.Item3; wordBx = atomText.StartLoc; } } // no word. just delim. else { // the delim is comment to end. store as a word. if (nonWordPat.DelimClassification == DelimClassification.CommentToEnd) { var rv = Scanner.ScanEqualAny(ScanStream.Stream, bx, Traits.NewLinePatterns); var eolPat = rv.Item1; var eolIx = rv.Item2; if (eolPat == null) { int ex = ScanStream.Stream.Length - 1; wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); TextLocation wordEx = new StreamLocation(ex).ToTextLocation(ScanStream); string commentText = ScanStream.Substring(nonWordIx); atomText = new AtomText( ScanAtomCode.CommentToEnd, commentText, null, wordBx, wordEx); nonWordPat = null; nonWordPatList = null; } else { wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); int lx = eolIx - nonWordIx; TextLocation wordEx = new StreamLocation(nonWordIx + lx - 1).ToTextLocation(ScanStream); string commentText = ScanStream.Substring(nonWordIx, lx); atomText = new AtomText( ScanAtomCode.CommentToEnd, commentText, null, wordBx, wordEx); var sloc = wordBx.ToStreamLocation(ScanStream); nonWordPat = eolPat; nonWordPatList = null; } } // the word found is a non word or keyword pattern. else { // got whitespace followed by keyword. Return the whitespace. if ((nonWordPat.DelimClassification == DelimClassification.Keyword) && (whitespaceText != null)) { atomText = whitespaceText; nonWordPat = null; nonWordPatList = null; } // there are more than one scan patterns that match. else if (nonWordPatList != null) { atomTextList = new List <MatchScanPattern>(); foreach (var pat in nonWordPatList) { wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); int lx = pat.MatchLength; TextLocation wordEx = new StreamLocation(nonWordIx + lx - 1).ToTextLocation(ScanStream); string scanText = ScanStream.Stream.Substring(nonWordIx, lx); atomText = new AtomText( pat.MatchPattern.DelimClassification.ToScanAtomCode().Value, scanText, pat.MatchPattern.ReplacementValue, wordBx, wordEx); pat.AtomText = atomText; atomTextList.Add(pat); } } else { wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); int lx = nonWordLx; TextLocation wordEx = new StreamLocation(nonWordIx + lx - 1).ToTextLocation(ScanStream); string scanText = ScanStream.Stream.Substring(nonWordIx, lx); atomText = new AtomText( nonWordPat.DelimClassification.ToScanAtomCode().Value, scanText, nonWordPat.ReplacementValue, wordBx, wordEx); } } } } #endregion } // store the results in the return cursor. ScanAtomCursor nx = null; if (atomText == null) { nx = new ScanAtomCursor( ); nx.Position = RelativePosition.End; } else if (atomTextList != null) { nx = new ScanAtomCursor(atomTextList); } else { nx = new ScanAtomCursor(atomText, nonWordPat); nx.Position = RelativePosition.At; } return(nx); }
internal DebugDirectory(DebugContent debugContent, long directoryOffset, IMAGE_DEBUG_DIRECTORY debugDirectory) { content = debugContent; location = new StreamLocation(directoryOffset,DebugDirectory.Size); directory = debugDirectory; }
internal OptionalHeader64(ExeReader exeReader, IMAGE_OPTIONAL_HEADER64 optHeader, StreamLocation streamLoc) : base(exeReader,streamLoc) { header = optHeader; List<DataDirectory> dirs = new List<DataDirectory>(); dirs.AddRange(new DataDirectory[] { new DataDirectory(DataDirectoryType.ExportTable,header.ExportTable), new DataDirectory(DataDirectoryType.ImportTable,header.ImportTable), new DataDirectory(DataDirectoryType.ResourceTable,header.ResourceTable), new DataDirectory(DataDirectoryType.ExceptionTable,header.ExceptionTable), new DataDirectory(DataDirectoryType.CertificateTable,header.CertificateTable), new DataDirectory(DataDirectoryType.BaseRelocationTable,header.BaseRelocationTable), new DataDirectory(DataDirectoryType.Debug,header.Debug), new DataDirectory(DataDirectoryType.Architecture,header.Architecture), new DataDirectory(DataDirectoryType.GlobalPtr,header.GlobalPtr), new DataDirectory(DataDirectoryType.TLSTable,header.TLSTable), new DataDirectory(DataDirectoryType.LoadConfigTable,header.LoadConfigTable), new DataDirectory(DataDirectoryType.BoundImport,header.BoundImport), new DataDirectory(DataDirectoryType.ImportAddressTable,header.IAT), new DataDirectory(DataDirectoryType.DelayImportDescriptor,header.DelayImportDescriptor), new DataDirectory(DataDirectoryType.CLRRuntimeHeader,header.CLRRuntimeHeader) }); long dir_size = 16 * DataDirectories.EntrySize; StreamLocation location = new StreamLocation((streamLoc.Offset + streamLoc.Size) - dir_size,dir_size); data_dirs = new DataDirectories(this,location,dirs.Where(dir => dir.DirectoryType != DataDirectoryType.None).ToDictionary(dir => dir.DirectoryType)); }
private void LoadDOSStub() { if (_dos_header == null) LoadDOSHeader(); long offset = _dos_header.Location.Offset + _dos_header.Location.Size; int size = _dos_header.FileAddressNewHeader - DOSHeader.Size; if ((offset + size) > _stream.Length) throw new ExeReaderException("Cannot read beyond end of stream."); StreamLocation location = new StreamLocation(offset,size); _dos_stub = new DOSStub(this,location); }
internal TLSDirectory32(TLSContent tlsContent, long directoryOffset, IMAGE_TLS_DIRECTORY32 tlsDirectory) : base(tlsContent) { location = new StreamLocation(directoryOffset,TLSDirectory.Size32); directory = tlsDirectory; }
internal ExportDirectory(ExportContent exportContent, IMAGE_EXPORT_DIRECTORY exportDir, StreamLocation streamLoc) { content = exportContent; directory = exportDir; location = streamLoc; }
// ------------------------ ScanNextWord ------------------------- // Scans to the next word in the string. ( a word being the text bounded by the // delimeter and whitespace characters as spcfd in the TextTraits argument ) // Return null when end of string. public static ScanWordCursor ScanNextWord( ScanStream ScanStream, TextTraits Traits, ScanWordCursor CurrentWord) { // components of the next word. TextWord wordPart = null; TextLocation wordBx = null; ScanPattern nonWordPat = null; TextLocation nonWordLoc = null; int nonWordIx = -1; // stay at the current location. return copy of the cursor, but with stayatflag // turned off. if (CurrentWord.StayAtFlag == true) { nonWordPat = CurrentWord.DelimPattern; nonWordLoc = CurrentWord.DelimBx; wordPart = CurrentWord.Word; wordBx = CurrentWord.WordBx; } else { #region STEP1 setup the begin pos of the next word. // ----------------------------- STEP 1 ------------------------------ // setup the begin pos of the next word. int bx; { // calc scan start position bx = ScanWord.CalcScanNextStart(ScanStream, Traits, CurrentWord); // advance past whitespace if (bx != -1) { bx = Scanner.ScanNotEqual(ScanStream.Stream, Traits.WhitespacePatterns, bx); } } // end STEP 1. #endregion #region STEP 2. Isolate either numeric lib, quoted lit or scan to non word pattern // ------------------------------- STEP 2 ---------------------------------- // Isolate either numeric literal, quoted literal or scan to the next non word // pattern. LiteralType?litType = null; string litText = null; { // got a decimal digit. isolate the numeric literal string. if ((bx != -1) && (Char.IsDigit(ScanStream.Stream[bx]) == true)) { var rv = ScanWord.IsolateNumericLiteral(ScanStream, Traits, bx); litType = rv.Item1; litText = rv.Item2; nonWordPat = rv.Item3; // the non word pattern immed after numeric literal nonWordIx = rv.Item4; // pos of foundPat } // got something. now scan forward for the pattern that delimits the word. else if (bx != -1) { { var rv = Scanner.ScanEqualAny(ScanStream.Stream, bx, Traits.DelimPatterns); nonWordPat = rv.Item1; nonWordIx = rv.Item2; } // got a quote char. Isolate the quoted string, then find the delim that follows // the quoted string. if ((nonWordPat != null) && (nonWordPat.DelimClassification == DelimClassification.Quote) && (nonWordIx == bx)) { var rv = IsolateQuotedWord(ScanStream, Traits, nonWordIx); litType = rv.Item1; litText = rv.Item2; nonWordPat = rv.Item3; // the non word pattern immed after quoted literal nonWordIx = rv.Item4; // pos of foundPat. } } } // end STEP 2. #endregion #region STEP 3 - setup wordBx and wordPart with the found word. { // got nothing. if (bx == -1) { } // no delim found. word text all the way to the end. else if (nonWordIx == -1) { var rv = ScanWord.IsolateWordText( ScanStream, Traits, litType, litText, bx, null); wordBx = rv.Item1; wordPart = rv.Item2; #if skip wordBx = new StreamLocation(bx).ToTextLocation(ScanStream); if (litType != null) { wordPart = new TextWord(litText, WordClassification.Quoted, Traits); } else { wordPart = new TextWord( ScanStream.Substring(bx), WordClassification.Identifier, Traits); } #endif } // got a word and a non word pattern. else if (nonWordIx > bx) { var rv = ScanWord.IsolateWordText( ScanStream, Traits, litType, litText, bx, nonWordIx); wordBx = rv.Item1; wordPart = rv.Item2; #if skip wordBx = new StreamLocation(bx).ToTextLocation(ScanStream); int lx = foundIx - bx; wordPart = new TextWord( ScanStream.Substring(bx, lx), WordClassification.Identifier, Traits); #endif nonWordLoc = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); } // no word. just delim. else { nonWordLoc = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); // the delim is comment to end. store as a word. if (nonWordPat.DelimClassification == DelimClassification.CommentToEnd) { var rv = Scanner.ScanEqualAny(ScanStream.Stream, bx, Traits.NewLinePatterns); var eolPat = rv.Item1; var eolIx = rv.Item2; if (eolPat == null) { wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); wordPart = new TextWord( ScanStream.Substring(nonWordIx), WordClassification.CommentToEnd, Traits); nonWordLoc = null; nonWordPat = null; } else { wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); int lx = eolIx - nonWordIx; var sloc = wordBx.ToStreamLocation(ScanStream); wordPart = new TextWord( ScanStream.Substring(sloc.Value, lx), WordClassification.CommentToEnd, Traits); nonWordLoc = new StreamLocation(eolIx).ToTextLocation(ScanStream); nonWordPat = eolPat; } } // if the delim pattern is not non word ( a divider ), store the pattern also // as the word. else if (Traits.DelimPatternsThatAreNonWords.Contains(nonWordPat) == false) { wordBx = nonWordLoc; wordPart = new TextWord( nonWordPat.PatternValue, nonWordPat.DelimClassification.ToWordClassification().Value, Traits); } } } #endregion // delim is whitespace. scan ahead for something more meaningful than whitespace. if ((nonWordPat != null) && (Traits.IsWhitespace(nonWordPat))) { StreamLocation dx = nonWordLoc.ToStreamLocation(ScanStream); int fx = Scanner.ScanNotEqual( ScanStream.Stream, Traits.WhitespacePatterns, dx.Value + nonWordPat.Length); var pat = Traits.DelimPatterns.MatchAt(ScanStream.Stream, fx); if (pat != null) { nonWordLoc = new StreamLocation(fx).ToTextLocation(ScanStream); nonWordPat = pat; } } } // store the results in the return cursor. ScanWordCursor nx = null; if ((wordPart == null) && (nonWordPat == null)) { nx = new ScanWordCursor( ); nx.Position = RelativePosition.End; } else { nx = new ScanWordCursor(wordPart, wordBx, nonWordLoc, nonWordPat); nx.Position = RelativePosition.At; } return(nx); }
private void LoadSectionTable() { if (_nt_headers == null) LoadNTHeaders(); long offset = _nt_headers.Location.Offset + _nt_headers.Location.Size; _stream.Seek(offset,SeekOrigin.Begin); List<IMAGE_SECTION_HEADER> headers = new List<IMAGE_SECTION_HEADER>(); for(var i = 0; i < _nt_headers.FileHeader.NumberOfSections; i++) { IMAGE_SECTION_HEADER header = Utils.Read<IMAGE_SECTION_HEADER>(_stream,SectionTableEntry.Size); headers.Add(header); } long size = headers.Count * SectionTableEntry.Size; StreamLocation location = new StreamLocation(offset,size); _section_table = new SectionTable(this,location,headers); }
private OptionalHeader LoadOptionalHeader(FileHeader fileHeader) { CharacteristicsType characteristics = fileHeader.GetCharacteristics(); bool is_x64 = !((characteristics & CharacteristicsType.Supports32Bit) == CharacteristicsType.Supports32Bit); IMAGE_OPTIONAL_HEADER32 opt_header_32 = new IMAGE_OPTIONAL_HEADER32(); IMAGE_OPTIONAL_HEADER64 opt_header_64 = new IMAGE_OPTIONAL_HEADER64(); StreamLocation location = null; OptionalHeader opt_header = null; if (!is_x64) { opt_header_32 = Utils.Read<IMAGE_OPTIONAL_HEADER32>(_stream,OptionalHeader.Size32); location = new StreamLocation(fileHeader.Location.Offset + fileHeader.Location.Size,OptionalHeader.Size32); opt_header = new OptionalHeader32(this,opt_header_32,location); } else { opt_header_64 = Utils.Read<IMAGE_OPTIONAL_HEADER64>(_stream,OptionalHeader.Size64); location = new StreamLocation(fileHeader.Location.Offset + fileHeader.Location.Size,OptionalHeader.Size64); opt_header = new OptionalHeader64(this,opt_header_64,location); } return opt_header; }
internal LoadConfigDirectory64(LoadConfigContent lcContent, long directoryOffset, IMAGE_LOAD_CONFIG_DIRECTORY64 lcDirectory) : base(lcContent) { location = new StreamLocation(directoryOffset,LoadConfigDirectory.Size64); directory = lcDirectory; }
// ------------------------ ScanNextAtom ------------------------- // Scans to the next atom in the string. ( a word being the text bounded by the // delimiter and whitespace characters as spcfd in the TextTraits argument ) // Return null when end of string. public static ScanAtomCursor OrigScanNextAtom( ScanStream ScanStream, TextTraits Traits, ScanAtomCursor CurrentWord) { // components of the next word. TextLocation wordBx = null; int nonWordIx = -1; int nonWordLx = 0; ScanPattern nonWordPat = null; PatternScanResults nonWord = null; AtomText atomText = null; List <MatchScanPattern> atomTextList = null; AtomText whitespaceText = null; ScanAtomCode?tokenCode = null; // ScanAtomCode of this token. int? tokenLx = null; ScanAtomCode?priorTokenCode = null; // ScanAtomCode? priorCode = null; bool?priorCodeIsWhitespaceSignificant = null; // stay at the current location. return copy of the cursor, but with stayatflag // turned off. if (CurrentWord.StayAtFlag == true) { atomText = CurrentWord.AtomText; tokenCode = atomText.AtomCode; priorTokenCode = null; nonWordPat = CurrentWord.AtomPattern; wordBx = CurrentWord.StartLoc; } else { #region STEP1 setup the begin pos of the next word. // ----------------------------- STEP 1 ------------------------------ // setup the begin pos of the next word. int bx; { // save the ScanAtomCode of the prior word. if ((CurrentWord.Position == RelativePosition.At) || (CurrentWord.Position == RelativePosition.After)) { priorTokenCode = CurrentWord.AtomCode; priorCodeIsWhitespaceSignificant = CurrentWord.WhitespaceIsSignificant; } // calc scan start position bx = ScanAtom.CalcScanNextStart(ScanStream, Traits, CurrentWord); // advance past whitespace if (bx != -1) { int saveBx = bx; bx = Scanner.ScanNotEqual(ScanStream.Stream, Traits.WhitespacePatterns, bx); // there is some whitespace. Isolate it as AtomText. // This method will return the whitespace as the token. But need to look at // the token before and after to classify the whitespace as significant or // not. ( whitespace between identifiers or keywords is significant. // Whitespace between symbols is not significant. // note: even insignificant whitespace is returned as a token because the // whitespace is needed when redisplaying the statement text. if (bx != saveBx) { int whitespaceEx = -1; if (bx == -1) { whitespaceEx = ScanStream.Stream.Length - 1; } else { whitespaceEx = bx - 1; } int whitespaceLx = whitespaceEx - saveBx + 1; string userCode = null; whitespaceText = new AtomText( ScanAtomCode.Whitespace, ScanStream.Stream.Substring(saveBx, whitespaceLx), " ", new StreamLocation(saveBx).ToTextLocation(ScanStream), new StreamLocation(whitespaceEx).ToTextLocation(ScanStream), userCode); } } } // end STEP 1. #endregion #region STEP 2. Isolate either numeric lit, quoted lit or identifier/keyword. // ------------------------------- STEP 2 ---------------------------------- // Isolate either numeric literal, quoted literal or scan to the next non word // pattern. LiteralType?litType = null; string litText = null; { // got a decimal digit. isolate the numeric literal string. if ((bx != -1) && (Char.IsDigit(ScanStream.Stream[bx]) == true)) { var rv = Scanner.IsolateNumericLiteral(ScanStream, Traits, bx); litType = rv.Item1; litText = rv.Item2; nonWord = rv.Item3; // nonWordPat = rv.Item4; // the non word pattern immed after numeric literal // nonWordIx = rv.Item5; // pos of foundPat tokenCode = ScanAtomCode.Numeric; } // got something. now scan forward for the pattern that delimits the word. else if (bx != -1) { { nonWord = Scanner.ScanEqualAny(ScanStream.Stream, bx, Traits.DelimPatterns); // nonWordPat = rv.Item1; // nonWordIx = rv.Item2; // nonWordLx = rv.Item3; // nonWord = rv.Item3; } // a special value starter. scan further for the spcval word. var startPat = nonWord.FindPattern(DelimClassification.SpecialValueStarter); if (startPat != null) { } // word chars all the way to the end. // if (nonWordPat == null) if (nonWord == null) { tokenCode = ScanAtomCode.Identifier; tokenLx = ScanStream.Stream.Length - bx; } else if (nonWord.FoundAtPosition(DelimClassification.Quote, bx)) { var rv = Scanner.IsolateQuotedWord(ScanStream, Traits, bx); litType = rv.Item1; litText = rv.Item2; // nonWordPat = rv.Item3; // the non word pattern immed after quoted literal // nonWordIx = rv.Item4; // pos of foundPat. nonWord = rv.Item3; tokenCode = ScanAtomCode.Quoted; } #if skip // got a quote char. Isolate the quoted string, then find the delim that follows // the quoted string. else if ((nonWordPat.DelimClassification == DelimClassification.Quote) && (nonWordIx == bx)) { var rv = Scanner.IsolateQuotedWord(ScanStream, Traits, nonWordIx); litType = rv.Item1; litText = rv.Item2; nonWordPat = rv.Item3; // the non word pattern immed after quoted literal nonWordIx = rv.Item4; // pos of foundPat. nonWord = rv.Item5; tokenCode = ScanAtomCode.Quoted; } #endif // delim pattern found past the start of the scan. That means there are // identifier chars from the start of the scan to the found delim. else if (bx != nonWord.Position) // else if (bx != nonWordIx) { tokenCode = ScanAtomCode.Identifier; tokenLx = nonWord.Position - bx; // tokenLx = nonWordIx - bx; } else if (nonWordPat != null) { tokenCode = nonWordPat.DelimClassification.ToScanAtomCode(); } // should never get here. else { tokenCode = null; } } // attempt to classify the identifier token as a keyword. if ((tokenCode != null) && (tokenCode.Value == ScanAtomCode.Identifier)) { var rv = Traits.KeywordPatterns.MatchPatternToSubstring( ScanStream.Stream, bx, tokenLx.Value); var kwdResults = rv.Item3; var kwdPat = kwdResults.FirstFoundPattern; if (kwdPat != null) { tokenCode = kwdPat.MatchPattern.DelimClassification.ToScanAtomCode(); nonWordPat = kwdPat.MatchPattern; nonWord = kwdResults; nonWordIx = bx; nonWordLx = kwdPat.MatchLength; } #if skip var matchPat = rv.Item1; var keywordTextLx = rv.Item2; // the actual lgth of matched text. if (matchPat != null) { tokenCode = matchPat.DelimClassification.ToScanAtomCode(); nonWordPat = matchPat; nonWordPatList = null; nonWord = null; nonWordIx = bx; nonWordLx = keywordTextLx; } #endif } } // end STEP 2. #endregion #region STEP 3 - setup wordBx and wordPart with the found word. { // got whitespace. if (whitespaceText != null) { ScanAtomCode wstc = ScanAtomCode.Whitespace; if (priorTokenCode == null) { wstc = ScanAtomCode.InsignificantWhitespace; } else if (tokenCode == null) { wstc = ScanAtomCode.InsignificantWhitespace; } else if ((priorTokenCode.Value.WhitespaceIsSignificant() == true) && (tokenCode.Value.WhitespaceIsSignificant() == true)) { wstc = ScanAtomCode.Whitespace; } else { wstc = ScanAtomCode.InsignificantWhitespace; } atomText = whitespaceText; atomText.AtomCode = wstc; } // got nothing. else if (bx == -1) { } // no delim found. word text all the way to the end. else if (nonWord.IsEmpty == true) // else if (nonWordIx == -1) { if (whitespaceText != null) { atomText = whitespaceText; nonWordPat = null; } else { // get the text from start of scan to end of string. var rv = Scanner.IsolateWordText( ScanStream, Traits, litType, litText, bx, null); atomText = rv.Item3; wordBx = atomText.StartLoc; } } // got a word and a non word pattern. else if (nonWord.Position > bx) // else if (nonWordIx > bx) { if (whitespaceText != null) { atomText = whitespaceText; nonWord = new PatternScanResults(); nonWordPat = null; } else { var rv = Scanner.IsolateWordText( ScanStream, Traits, litType, litText, bx, nonWord.Position); // var rv = Scanner.IsolateWordText( // ScanStream, Traits, litType, litText, bx, nonWordIx); atomText = rv.Item3; wordBx = atomText.StartLoc; } } // no word. just delim. else { // the delim is comment to end. store as a word. if (nonWordPat.DelimClassification == DelimClassification.CommentToEnd) { var rv = ScanAtom.ClassifyAsComment(ScanStream, Traits, bx); wordBx = rv.Item1; atomText = rv.Item2; nonWordPat = rv.Item3; nonWord = rv.Item4; #if skip var rv = Scanner.ScanEqualAny(ScanStream.Stream, bx, Traits.NewLinePatterns); var eolPat = rv.Item1; var eolIx = rv.Item2; // no newline pattern found. Comment to the end of the text stream. if (eolPat == null) { int ex = ScanStream.Stream.Length - 1; wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); TextLocation wordEx = new StreamLocation(ex).ToTextLocation(ScanStream); string commentText = ScanStream.Substring(nonWordIx); string userCode = null; atomText = new AtomText( ScanAtomCode.CommentToEnd, commentText, null, wordBx, wordEx, userCode); nonWordPat = null; nonWordPatList = null; } else { wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); int lx = eolIx - nonWordIx; TextLocation wordEx = new StreamLocation(nonWordIx + lx - 1).ToTextLocation(ScanStream); string commentText = ScanStream.Substring(nonWordIx, lx); string userCode = null; atomText = new AtomText( ScanAtomCode.CommentToEnd, commentText, null, wordBx, wordEx, userCode); var sloc = wordBx.ToStreamLocation(ScanStream); nonWordPat = eolPat; nonWordPatList = null; } #endif } // the word found is a non word or keyword pattern. else { // got whitespace followed by keyword. Return the whitespace. if ((nonWordPat.DelimClassification == DelimClassification.Keyword) && (whitespaceText != null)) { atomText = whitespaceText; nonWord = new PatternScanResults(); nonWordPat = null; } // there are more than one scan patterns that match. else if (nonWord.FoundCount > 1) // else if (nonWordPatList != null) { atomTextList = new List <MatchScanPattern>(); foreach (var pat in nonWord) { wordBx = new StreamLocation(nonWord.Position).ToTextLocation(ScanStream); int lx = pat.MatchLength; TextLocation wordEx = new StreamLocation(nonWord.Position + lx - 1).ToTextLocation(ScanStream); string scanText = ScanStream.Stream.Substring(nonWord.Position, lx); atomText = new AtomText( pat.MatchPattern.DelimClassification.ToScanAtomCode().Value, scanText, pat.MatchPattern.ReplacementValue, wordBx, wordEx, pat.MatchPattern.UserCode); pat.AtomText = atomText; atomTextList.Add(pat); } #if skip foreach (var pat in nonWordPatList) { wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); int lx = pat.MatchLength; TextLocation wordEx = new StreamLocation(nonWordIx + lx - 1).ToTextLocation(ScanStream); string scanText = ScanStream.Stream.Substring(nonWordIx, lx); atomText = new AtomText( pat.MatchPattern.DelimClassification.ToScanAtomCode().Value, scanText, pat.MatchPattern.ReplacementValue, wordBx, wordEx, pat.MatchPattern.UserCode); pat.AtomText = atomText; atomTextList.Add(pat); } #endif } else { var foundPat = nonWord.FirstFoundPattern; wordBx = new StreamLocation(nonWord.Position).ToTextLocation(ScanStream); int lx = foundPat.MatchLength; TextLocation wordEx = new StreamLocation(nonWord.Position + lx - 1).ToTextLocation(ScanStream); string scanText = ScanStream.Stream.Substring(nonWord.Position, lx); atomText = new AtomText( foundPat.MatchPattern.DelimClassification.ToScanAtomCode().Value, scanText, foundPat.MatchPattern.ReplacementValue, wordBx, wordEx, foundPat.MatchPattern.UserCode); #if skip wordBx = new StreamLocation(nonWordIx).ToTextLocation(ScanStream); int lx = nonWordLx; TextLocation wordEx = new StreamLocation(nonWordIx + lx - 1).ToTextLocation(ScanStream); string scanText = ScanStream.Stream.Substring(nonWordIx, lx); atomText = new AtomText( nonWordPat.DelimClassification.ToScanAtomCode().Value, scanText, nonWordPat.ReplacementValue, wordBx, wordEx, nonWordPat.UserCode); #endif } } } } #endregion } // store the results in the return cursor. ScanAtomCursor nx = null; if (atomText == null) { nx = new ScanAtomCursor(); nx.Position = RelativePosition.End; } else if (atomTextList != null) { nx = new ScanAtomCursor(atomTextList); } else { // nx = new ScanAtomCursor(atomText, nonWordPat); if ((nonWord == null) || (nonWord.IsEmpty == true)) { nx = new ScanAtomCursor(atomText, nonWordPat); } else { nx = new ScanAtomCursor(atomText, nonWord.FirstFoundPattern.MatchPattern); } nx.Position = RelativePosition.At; } return(nx); }
internal DOSHeader(ExeReader exeReader, IMAGE_DOS_HEADER dosHeader, StreamLocation streamLoc) { reader = exeReader; header = dosHeader; location = streamLoc; }
private void LoadDOSHeader() { _stream.Seek(0,SeekOrigin.Begin); IMAGE_DOS_HEADER native_dos_header = Utils.Read<IMAGE_DOS_HEADER>(_stream,DOSHeader.Size); if (native_dos_header.e_magic != DOSHeader.DOS_MAGIC_MZ) throw new ExeReaderException("Incorrect magic number specified in MS-DOS header."); if (native_dos_header.e_lfanew == 0) throw new ExeReaderException("No new header location specified in MS-DOS header, most likely a 16-bit executable."); if (native_dos_header.e_lfanew >= (256 * (1024 * 1024))) throw new ExeReaderException("New header location specified in MS-DOS header is beyond 256mb boundary (see RtlImageNtHeaderEx)."); if (native_dos_header.e_lfanew % 4 != 0) throw new ExeReaderException("New header location specified in MS-DOS header is not properly aligned."); if (native_dos_header.e_lfanew < DOSHeader.Size) throw new ExeReaderException("New header location specified is invalid."); StreamLocation location = new StreamLocation(0,DOSHeader.Size); _dos_header = new DOSHeader(this,native_dos_header,location); }
private async Task OpenInputStreamAsync() { Debug.Assert( State.OpenInputStream == this.state, "OpenInputStreamAsync called, but state is not OpenInputStream."); this.hasWork = false; await Task.Run(() => { this.NotifyStarting(); this.Controller.CheckCancellation(); if (this.transferJob.Source.Type == TransferLocationType.Stream) { StreamLocation streamLocation = this.transferJob.Source as StreamLocation; this.inputStream = streamLocation.Stream; this.ownsStream = false; if (!this.inputStream.CanRead) { throw new NotSupportedException(string.Format( CultureInfo.CurrentCulture, Resources.StreamMustSupportReadException, "inputStream")); } if (!this.inputStream.CanSeek) { throw new NotSupportedException(string.Format( CultureInfo.CurrentCulture, Resources.StreamMustSupportSeekException, "inputStream")); } } else { FileLocation fileLocation = this.transferJob.Source as FileLocation; Debug.Assert( null != fileLocation, "Initializing StreamedReader instance, but source is neither a stream nor a file"); try { if (fileLocation.RelativePath != null && fileLocation.RelativePath.Length > Constants.MaxRelativePathLength) { string errorMessage = string.Format( CultureInfo.CurrentCulture, Resources.RelativePathTooLong, fileLocation.RelativePath); throw new TransferException(TransferErrorCode.OpenFileFailed, errorMessage); } #if DOTNET5_4 string filePath = fileLocation.FilePath; if (Interop.CrossPlatformHelpers.IsWindows) { filePath = LongPath.ToUncPath(fileLocation.FilePath); } // Attempt to open the file first so that we throw an exception before getting into the async work this.inputStream = new FileStream( filePath, FileMode.Open, FileAccess.Read, FileShare.Read); #else this.inputStream = LongPathFile.Open( fileLocation.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read); #endif this.ownsStream = true; } catch (Exception ex) { if ((ex is NotSupportedException) || (ex is IOException) || (ex is UnauthorizedAccessException) || (ex is SecurityException) || (ex is ArgumentException && !(ex is ArgumentNullException))) { string exceptionMessage = string.Format( CultureInfo.CurrentCulture, Resources.FailedToOpenFileException, fileLocation.FilePath, ex.Message); throw new TransferException( TransferErrorCode.OpenFileFailed, exceptionMessage, ex); } else { throw; } } } }); this.SharedTransferData.TotalLength = this.inputStream.Length; int count = (int)Math.Ceiling((double)(this.SharedTransferData.TotalLength - this.transferJob.CheckPoint.EntryTransferOffset) / this.SharedTransferData.BlockSize); if (null != this.transferJob.CheckPoint.TransferWindow) { count += this.transferJob.CheckPoint.TransferWindow.Count; } this.lastTransferWindow = new Queue <long>(this.transferJob.CheckPoint.TransferWindow); this.md5HashStream = new MD5HashStream( this.inputStream, this.transferJob.CheckPoint.EntryTransferOffset, true); this.PreProcessed = true; // This reader will come into 'Finish' state after all chunks are read and MD5 calculation completes. // So initialize the CountDownEvent to count (number of chunks to read) + 1 (md5 calculation). this.countdownEvent = new CountdownEvent(count + 1); if (0 != count) { // Change the state to 'ReadStream' before awaiting MD5 calculation task to not block the reader. this.state = State.ReadStream; this.hasWork = true; } if (!this.md5HashStream.FinishedSeparateMd5Calculator) { await Task.Run(() => { this.md5HashStream.CalculateMd5(this.Scheduler.MemoryManager, this.Controller.CheckCancellation); }); } this.SetChunkFinish(); }
private async Task OpenInputStreamAsync() { Debug.Assert( State.OpenInputStream == this.state, "OpenInputStreamAsync called, but state is not OpenInputStream."); this.hasWork = false; await Task.Run(() => { this.NotifyStarting(); this.Controller.CheckCancellation(); if (this.transferJob.Source.Type == TransferLocationType.Stream) { StreamLocation streamLocation = this.transferJob.Source as StreamLocation; this.inputStream = streamLocation.Stream; this.ownsStream = false; if (!this.inputStream.CanRead) { throw new NotSupportedException(string.Format( CultureInfo.CurrentCulture, Resources.StreamMustSupportReadException, "inputStream")); } if (!this.inputStream.CanSeek) { throw new NotSupportedException(string.Format( CultureInfo.CurrentCulture, Resources.StreamMustSupportSeekException, "inputStream")); } } else { FileLocation fileLocation = this.transferJob.Source as FileLocation; Debug.Assert( null != fileLocation, "Initializing StreamedReader instance, but source is neither a stream nor a file"); this.SharedTransferData.SourceLocation = fileLocation.ToString(); try { // Attempt to open the file first so that we throw an exception before getting into the async work this.inputStream = new FileStream( fileLocation.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read); this.ownsStream = true; } catch (Exception ex) { if ((ex is NotSupportedException) || (ex is IOException) || (ex is UnauthorizedAccessException) || (ex is SecurityException) || (ex is ArgumentException && !(ex is ArgumentNullException))) { string exceptionMessage = string.Format( CultureInfo.CurrentCulture, Resources.FailedToOpenFileException, fileLocation.FilePath, ex.Message); throw new TransferException( TransferErrorCode.OpenFileFailed, exceptionMessage, ex); } else { throw; } } } }); this.SharedTransferData.TotalLength = this.inputStream.Length; int count = (int)Math.Ceiling((double)(this.SharedTransferData.TotalLength - this.transferJob.CheckPoint.EntryTransferOffset) / this.Scheduler.TransferOptions.BlockSize); if (null != this.transferJob.CheckPoint.TransferWindow) { count += this.transferJob.CheckPoint.TransferWindow.Count; } this.lastTransferWindow = new Queue <long>(this.transferJob.CheckPoint.TransferWindow); this.md5HashStream = new MD5HashStream( this.inputStream, this.transferJob.CheckPoint.EntryTransferOffset, true); this.PreProcessed = true; if (!this.md5HashStream.FinishedSeparateMd5Calculator) { await Task.Run(() => { this.md5HashStream.CalculateMd5(this.Scheduler.MemoryManager, this.Controller.CheckCancellation); }); } if (0 == count) { this.countdownEvent = new CountdownEvent(1); this.SetChunkFinish(); } else { this.countdownEvent = new CountdownEvent(count); this.state = State.ReadStream; this.hasWork = true; } }
public GenericLocationSupport(long offset, long size, object parentObj) { location = new StreamLocation(offset,size); parent = parentObj; }
ClassifyAsComment(ScanStream ScanStream, TextTraits Traits, int Bx) { TextLocation wordBx = null; AtomText atomText = null; ScanPattern nonWordPat = null; PatternScanResults nonWord = null; // look prior to see if this comment to the end of the line is the first non // blank on the line. bool isFirstNonBlankOnLine = false; if (Bx == 0) { isFirstNonBlankOnLine = true; } else { // go back to the first non blank. int ix = Scanner.ScanReverseNotEqual( ScanStream.Stream, Bx - 1, Traits.WhitespaceWithoutNewLinePatterns); if (ix == -1) // nothing but blanks to start of string. { isFirstNonBlankOnLine = true; } else { var rv = Traits.NewLinePatterns.MatchFirstPatternEndsAtStringLocation( ScanStream.Stream, ix); var pat = rv.Item1; var patBx = rv.Item2; // is a new line pattern. there is nothing but spaces between this new line // and the start of the comment. if (pat != null) { isFirstNonBlankOnLine = true; } } } // set the atomCode of this atom depending on if the comment starts the line. ScanAtomCode atomCode = ScanAtomCode.CommentToEnd; if (isFirstNonBlankOnLine == true) { atomCode = ScanAtomCode.EntireLineCommentToEnd; } // scan for a new line. That is the end of the comment. { nonWord = Scanner.ScanEqualAny(ScanStream.Stream, Bx, Traits.NewLinePatterns); // eolPat = rv.Item1; // eolIx = rv.Item2; // nonWord = rv.Item3; } // no newline pattern found. Comment to the end of the text stream. if (nonWord.IsEmpty == true) // if (eolPat == null) { int ex = ScanStream.Stream.Length - 1; wordBx = new StreamLocation(Bx).ToTextLocation(ScanStream); TextLocation wordEx = new StreamLocation(ex).ToTextLocation(ScanStream); string commentText = ScanStream.Substring(Bx); string userCode = null; atomText = new AtomText( atomCode, commentText, null, wordBx, wordEx, userCode); // nonWordPat = eolPat; } else { wordBx = new StreamLocation(Bx).ToTextLocation(ScanStream); int lx = nonWord.Position - Bx; // int lx = eolIx - Bx; TextLocation wordEx = new StreamLocation(Bx + lx - 1).ToTextLocation(ScanStream); string commentText = ScanStream.Substring(Bx, lx); string userCode = null; atomText = new AtomText( atomCode, commentText, null, wordBx, wordEx, userCode); var sloc = wordBx.ToStreamLocation(ScanStream); // nonWordPat = eolPat; } return(new Tuple <TextLocation, AtomText, ScanPattern, PatternScanResults> (wordBx, atomText, nonWordPat, nonWord)); }
internal OptionalHeader(ExeReader exeReader, StreamLocation streamLoc) { reader = exeReader; location = streamLoc; }
private void LoadNTHeaders() { if (_dos_header == null) LoadDOSHeader(); _stream.Seek(_dos_header.FileAddressNewHeader,SeekOrigin.Begin); LoadPESignature(); FileHeader file_header = LoadFileHeader(_dos_header); OptionalHeader opt_header = LoadOptionalHeader(file_header); StreamLocation location = new StreamLocation(_dos_header.FileAddressNewHeader,4 + file_header.Location.Size + opt_header.Location.Size); _nt_headers = new NTHeaders(this,location,file_header,opt_header); if (_nt_headers.FileHeader != null) { CharacteristicsType characteristics = _nt_headers.FileHeader.GetCharacteristics(); is_32bit = ((characteristics & CharacteristicsType.Supports32Bit) == CharacteristicsType.Supports32Bit); is_64bit = !is_32bit; } if (_nt_headers.OptionalHeader != null) { is_32bit = (_nt_headers.OptionalHeader.GetMagic() == MagicType.PE32); is_64bit = !is_32bit; } DataDirectory clr_dir = _nt_headers.OptionalHeader.DataDirectories[DataDirectoryType.CLRRuntimeHeader]; is_clr = (clr_dir != null && clr_dir.VirtualAddress > 0 && clr_dir.Size > 0); }
private async Task OpenInputStreamAsync() { Debug.Assert( State.OpenInputStream == this.state, "OpenInputStreamAsync called, but state is not OpenInputStream."); if (Interlocked.CompareExchange(ref workToken, 0, 1) == 0) { return; } await Task.Yield(); this.NotifyStarting(); this.Controller.CheckCancellation(); if (this.transferJob.Source.Type == TransferLocationType.Stream) { StreamLocation streamLocation = this.transferJob.Source as StreamLocation; this.inputStream = streamLocation.Stream; this.ownsStream = false; if (!this.inputStream.CanRead) { throw new NotSupportedException(string.Format( CultureInfo.CurrentCulture, Resources.StreamMustSupportReadException, "inputStream")); } } else { FileLocation fileLocation = this.transferJob.Source as FileLocation; Debug.Assert( null != fileLocation, "Initializing StreamedReader instance, but source is neither a stream nor a file"); try { if (fileLocation.RelativePath != null && fileLocation.RelativePath.Length > Constants.MaxRelativePathLength) { string errorMessage = string.Format( CultureInfo.CurrentCulture, Resources.RelativePathTooLong, fileLocation.RelativePath); throw new TransferException(TransferErrorCode.OpenFileFailed, errorMessage); } this.filePath = fileLocation.FilePath.ToLongPath(); #if DOTNET5_4 // Attempt to open the file first so that we throw an exception before getting into the async work this.inputStream = new FileStream( filePath, FileMode.Open, FileAccess.Read, FileShare.Read); #else this.inputStream = LongPathFile.Open( this.filePath, FileMode.Open, FileAccess.Read, FileShare.Read); #endif this.ownsStream = true; } catch (Exception ex) { if ((ex is NotSupportedException) || (ex is IOException) || (ex is UnauthorizedAccessException) || (ex is SecurityException) || (ex is ArgumentException && !(ex is ArgumentNullException))) { string exceptionMessage = string.Format( CultureInfo.CurrentCulture, Resources.FailedToOpenFileException, fileLocation.FilePath, ex.Message); throw new TransferException( TransferErrorCode.OpenFileFailed, exceptionMessage, ex); } else { throw; } } } try { this.SharedTransferData.TotalLength = this.inputStream.Length; } catch (NotSupportedException) { this.SharedTransferData.TotalLength = -1; } // Only do calculation related to transfer window when the file contains multiple chunks. if (!this.EnableOneChunkFileOptimization) { var checkpoint = this.transferJob.CheckPoint; checkpoint.TransferWindow.Sort(); this.readLength = checkpoint.EntryTransferOffset; if (checkpoint.TransferWindow.Any()) { // The size of last block can be smaller than BlockSize. this.readLength -= Math.Min(checkpoint.EntryTransferOffset - checkpoint.TransferWindow.Last(), this.SharedTransferData.BlockSize); this.readLength -= (checkpoint.TransferWindow.Count - 1) * this.SharedTransferData.BlockSize; } if (this.readLength < 0) { throw new InvalidOperationException(Resources.RestartableInfoCorruptedException); } else if ((checkpoint.EntryTransferOffset > 0) && (!this.inputStream.CanSeek)) { throw new NotSupportedException(string.Format( CultureInfo.CurrentCulture, Resources.StreamMustSupportSeekException, "inputStream")); } this.lastTransferWindow = new Queue <long>(this.transferJob.CheckPoint.TransferWindow); } this.md5HashStream = new MD5HashStream( this.inputStream, this.transferJob.CheckPoint.EntryTransferOffset, true); this.PreProcessed = true; if (this.readLength != this.SharedTransferData.TotalLength) { // Change the state to 'ReadStream' before awaiting MD5 calculation task to not block the reader. this.state = State.ReadStream; this.workToken = 1; } else { Interlocked.Exchange(ref this.readCompleted, 1); } if (!this.md5HashStream.FinishedSeparateMd5Calculator) { await Task.Run(() => { this.md5HashStream.CalculateMd5(this.Scheduler.MemoryManager, this.Controller.CheckCancellation); }); } this.SetChunkFinish(); }
private async Task OpenInputStreamAsync() { Debug.Assert( State.OpenInputStream == this.state, "OpenInputStreamAsync called, but state is not OpenInputStream."); if (Interlocked.CompareExchange(ref workToken, 0, 1) == 0) { return; } await Task.Yield(); this.NotifyStarting(); this.Controller.CheckCancellation(); if (this.transferJob.Source.Type == TransferLocationType.Stream) { StreamLocation streamLocation = this.transferJob.Source as StreamLocation; this.inputStream = streamLocation.Stream; this.ownsStream = false; if (!this.inputStream.CanRead) { throw new NotSupportedException(string.Format( CultureInfo.CurrentCulture, Resources.StreamMustSupportReadException, "inputStream")); } } else { FileLocation fileLocation = this.transferJob.Source as FileLocation; Debug.Assert( null != fileLocation, "Initializing StreamedReader instance, but source is neither a stream nor a file"); try { if (fileLocation.RelativePath != null && fileLocation.RelativePath.Length > Constants.MaxRelativePathLength) { string errorMessage = string.Format( CultureInfo.CurrentCulture, Resources.RelativePathTooLong, fileLocation.RelativePath); throw new TransferException(TransferErrorCode.OpenFileFailed, errorMessage); } #if DOTNET5_4 string filePath = fileLocation.FilePath; if (Interop.CrossPlatformHelpers.IsWindows) { filePath = LongPath.ToUncPath(fileLocation.FilePath); } // Attempt to open the file first so that we throw an exception before getting into the async work this.inputStream = new FileStream( filePath, FileMode.Open, FileAccess.Read, FileShare.Read); #else this.inputStream = LongPathFile.Open( fileLocation.FilePath, FileMode.Open, FileAccess.Read, FileShare.Read); #endif this.ownsStream = true; } catch (Exception ex) { if ((ex is NotSupportedException) || (ex is IOException) || (ex is UnauthorizedAccessException) || (ex is SecurityException) || (ex is ArgumentException && !(ex is ArgumentNullException))) { string exceptionMessage = string.Format( CultureInfo.CurrentCulture, Resources.FailedToOpenFileException, fileLocation.FilePath, ex.Message); throw new TransferException( TransferErrorCode.OpenFileFailed, exceptionMessage, ex); } else { throw; } } } }).ConfigureAwait(false);