// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. using System; using System.IO; using System.Runtime.Serialization; using System.Xml.Serialization; namespace Tools.CrashReporter.CrashReportCommon { /// /// A class to return the result of the CheckReport web request. /// public class CrashReporterResult { /// A bool representing success or failure of the CheckReport web request. [XmlAttribute] public bool bSuccess = false; /// An optional integer value typically representing a unique ID. [XmlAttribute] public int ID = 0; /// A optional message to explain any return values. [XmlAttribute] public string Message = ""; /// A bool representing if a failure was caused by a database timeout. [XmlAttribute] public bool bTimeout = false; } /// /// A class to send to the web service to check to see if the report has already been uploaded. /// public class CheckReportRequest { /// A unique ID, actually the directory name of the WER. [XmlAttribute] public string ReportId = ""; /// LEGACY SUPPORT for crashes reported from clients before CrashReportUploader had been rebuilt [XmlAttribute] public string DirectoryName = ""; /// A simple default constructor to allow Xml serialisation. public CheckReportRequest() { } } /// /// A class to send to the CrashReport website to add a new crash to the database. /// public class CrashDescription { /// The type of the crash e.g. crash, assert or ensure. [XmlElement] public string CrashType = ""; /// The name of the branch this game was built out of. [XmlElement] public string BranchName = ""; /// The name of the game that crashed. [XmlElement] public string GameName = ""; /// The platform that crashed e.g. Win64. [XmlElement] public string Platform = ""; /// The mode the game was in e.g. editor. [XmlElement] public string EngineMode = ""; /// Extended mode info (Vanilla, Dirty, Unset). [XmlElement] public string EngineModeEx = ""; /// The four component version of the app e.g. 4.4.1.0 [XmlElement] public string EngineVersion = ""; /// The four component version of the app e.g. 4.4.1.0 [XmlElement] public string BuildVersion = ""; /// Changelist number. [XmlElement] public int BuiltFromCL = 0; /// The command line of the application that crashed. [XmlElement] public string CommandLine = ""; /// The base directory where the app was running. [XmlElement] public string BaseDir = ""; /// The language code the app was running in e.g. 1033. [XmlElement] public string Language = ""; /// The language code of the system. [XmlElement] public string SystemLanguage = ""; /// /// The name of the user that caused this crash. /// @UserName varchar(64) /// [XmlElement] public string UserName = ""; /// /// The GUID of the machine the crash occurred on. /// @ComputerName varchar(64) /// [XmlElement] public string MachineGuid = ""; /// /// The Epic account ID for the user who last used the Launcher. /// @EpicAccountId varchar(64) /// [XmlElement] public string EpicAccountId = ""; /// An array of strings representing the callstack of the crash. [XmlElement] public string[] CallStack = null; /// An array of strings showing the source code around the crash. [XmlElement] public string[] SourceContext = null; /// An array of strings representing the user description of the crash. [XmlElement] public string[] UserDescription = null; /// A string representing the user activity hint text from the application. [XmlElement] public string UserActivityHint = ""; /// The error message, can be assertion message, ensure message or message from the fatal error. [XmlElement] public string[] ErrorMessage = null; /// Crash GUID from the crash context. [XmlElement] public string CrashGUID = ""; /// The UTC time the crash occurred. [XmlElement] public DateTime TimeofCrash; /// Whether this crash has a minidump. [XmlElement] public bool bHasMiniDump = false; /// Whether this crash has a log file. [XmlElement] public bool bHasLog = false; /// Obsolete. [XmlElement] public bool bHasDiags = false; /// Obsolete. [XmlElement] public bool bHasWERData = false; /// Whether this crash has a video. [XmlElement] public bool bHasVideo = false; /// Whether the user allowed us to be contacted. [XmlElement] public bool bAllowToBeContacted = false; /// Whether the processor generated an error while generating this crash report [XmlElement] public bool bProcessorFailed = false; /// A simple default constructor to allow Xml serialization. public CrashDescription() { } } /// Details about received compressed crash. public class FCompressedCrashInformation { /// Size of the compressed data. public string CompressedSize = ""; /// Size of the data after decompression. public string UncompressedSize = ""; /// Number of files stored in the compressed data. public string NumberOfFiles = ""; /// A simple default constructor to allow Xml serialization. public FCompressedCrashInformation() {} /// Initialization constructor. public FCompressedCrashInformation( string InCompressedSize, string InUncompressedSize, string InNumberOfFiles ) { CompressedSize = InCompressedSize; UncompressedSize = InUncompressedSize; NumberOfFiles = InNumberOfFiles; } /// CompressedSize as int. public int GetCompressedSize() { int Result = 0; int.TryParse( CompressedSize, out Result ); return Result; } /// UncompressedSize as int. public int GetUncompressedSize() { int Result = 0; int.TryParse( UncompressedSize, out Result ); return Result; } /// NumberOfFiles as int. public int GetNumberOfFiles() { int Result = 0; int.TryParse( NumberOfFiles, out Result ); return Result; } } /// Helper class for reading binary data. public class FBinaryReaderHelper { /// Reads FString serialized with SerializeAsANSICharArray. public static string ReadFixedSizeString( BinaryReader BinaryStream ) { uint Length = BinaryStream.ReadUInt32(); string Result = new string( BinaryStream.ReadChars( (int)Length ) ); Result = FixFixedSizeString( Result ); return Result; } static String FixFixedSizeString( string String ) { int RealLength = 0; while( String[RealLength++] != '\0' ) { } string Result = String.Remove( RealLength - 1 ); return Result; } } /// /// Base class for Crash Reporter system exceptions /// [Serializable] public class CrashReporterException : Exception { /// /// Default constructor /// public CrashReporterException() {} /// /// Construct from an error message /// /// The error message public CrashReporterException(string message) : base(message) {} /// /// Construct from an error message and inner exception /// /// The error message /// Inner exception public CrashReporterException(string message, Exception inner) : base(message, inner) {} /// /// Protected constructor for serialization /// /// Serialization info /// Streaming context protected CrashReporterException(SerializationInfo info, StreamingContext context) : base(info, context) {} } /// /// Helper class for checking the available space on a storage medium /// public static class StorageSpaceHelper { /// /// Attempts to extract the drive letter including colon and first slash from a file or folder path. Will not throw exceptions on /// malformed or illegal paths. Does not currently support UNC paths. /// /// A folder or file path that starts with a regular drive letter /// (out) If the path starts with a valid drive letter, contains the drive letter, colon and first slash. /// True if the drive letter was return successfully, false if the method fails for any reason. public static bool TryGetDriveLetter(string InPath, out string OutDriveLetter) { try { OutDriveLetter = Path.GetPathRoot(InPath); return !string.IsNullOrWhiteSpace(OutDriveLetter); } catch (Exception) { OutDriveLetter = String.Empty; return false; } } /// /// This will work for regular drives with letters. Network shares require Win32 calls /// /// Filepath (must be in a regular drive with a letter in this version) /// (out) The number of bytes free /// (out) The percentage of free space /// True if the number of free bytes is retrieved successfully, otherwise false if an error occurs. public static bool TryGetSpaceAvailable(string InPath, out Int64 OutSpaceAvailable, out float OutPercentAvailable) { string PathRoot; if (TryGetDriveLetter(InPath, out PathRoot)) { try { DriveInfo Info = new DriveInfo(PathRoot); OutSpaceAvailable = Info.AvailableFreeSpace; OutPercentAvailable = 100.0f*OutSpaceAvailable/Info.TotalSize; return true; } catch (Exception) { // eat exceptions } } // TODO: fallback on p/invoking platform-specific disk space APIs? OutSpaceAvailable = 0; OutPercentAvailable = 0.0f; return false; } } }