Files
UnrealEngineUWP/Engine/Source/Programs/CrashReporter/CrashReportCommon/CrashContext.cs
Robert Manuszewski 301e5763c2 Copying //UE4/Dev-Core to //UE4/Dev-Main (Source: //UE4/Dev-Core @ 3228803)
#lockdown Nick.Penwarden
#rb none

==========================
MAJOR FEATURES + CHANGES
==========================

Change 3209807 on 2016/11/24 by Chris.Wood

	CRP now has improved handling of lost comms with website/DB (CRP v.1.2.9)
	[UE-38397] - CrashReportProcess should not lose crashes when the website goes down.

Change 3209936 on 2016/11/24 by Steven.Hutton

	Reconciled offline work. Fixed a number of display bugs with the reports page.

Change 3209938 on 2016/11/24 by Steven.Hutton

	Reconciled offline work

	Adding JQuery UI packages

Change 3210736 on 2016/11/28 by Steve.Robb

	Unset() made protected, which is an implementation details of TFunction and not the way to unbind one (may leak memory).
	Fixes to existing calls.

	https://answers.unrealengine.com/questions/494947/proper-way-to-deal-with-destroying-a-tfunction.html

Change 3211181 on 2016/11/28 by Steve.Robb

	Improved error message when binding a delegate to a pending kill object.

	#jira UE-5232

Change 3211214 on 2016/11/28 by Steve.Robb

	PR #2978: fixed typo in FMallocLeakDetection (Contributed by finap)

	#jira UE-39049

Change 3211301 on 2016/11/28 by Steve.Robb

	PR #2892: Copy bCustomVersionsAreReset when creating an Archive from another Ar. (Contributed by surakin)

	#jira UE-37941

Change 3213387 on 2016/11/29 by Steven.Hutton

	Test of a release note parsed from the changelist

Change 3213553 on 2016/11/29 by Gil.Gribb

	UE4 - Rework dependencies and UStruct creation so that we can create UBlueprintGeneratedClass's without needing the parent class serialized.

Change 3214800 on 2016/11/30 by Robert.Manuszewski

	ModuleManager will now use a critical section instead of FMultiReaderSingleWriterGT to make it really thread safe.

	- removed FMultiReaderSingleWriterGT because it was not fully thread safe

Change 3214926 on 2016/11/30 by Robert.Manuszewski

	Merging using Dev-Core_To_Dev-LoadTimes (reversed)

Change 3214981 on 2016/11/30 by Gil.Gribb

	UE4 - Make sure that subobjects of CDOs are exported even if they don't have any direct references; they might be archetypes.

Change 3215392 on 2016/11/30 by Steve.Robb

	Error out on editor builds when reading a non-boolean value in an archive.

Change 3215674 on 2016/11/30 by Steve.Robb

	Replacement of a custom scope-exit setup with our standard macro.

Change 3215720 on 2016/11/30 by Steve.Robb

	Default constructor for TTuple which value-initializes the elements.

Change 3216777 on 2016/12/01 by Graeme.Thornton

	Add NoRedist and NotForLicensees folders in the game folder to the C# version of config file hierarchy.

Change 3216858 on 2016/12/01 by Graeme.Thornton

	Improvements to pak signing and encryption
	 - Remove compile time defines for encryption key and signing keys
	 - Embed keys in executable by including in the UBT generated UELinkerFixups.cpp file
	 - Add key access core delegate for passing these keys through to pak platform file

Change 3216860 on 2016/12/01 by Graeme.Thornton

	Re-enable pak signing and encryption in ShooterGame

Change 3216861 on 2016/12/01 by Graeme.Thornton

	Re-enable pak signing and encryption in Paragon

Change 3217076 on 2016/12/01 by Gil.Gribb

	UE4 - replaced !GIsIntialLoad with EVENT_DRIVEN_ASYNC_LOAD_ACTIVE_AT_RUNTIME as a first step toward boot time EDL

Change 3221139 on 2016/12/05 by Ben.Woodhouse

	Dummy integrate of CL 3221131 (versioning workarounds) from Dev-LoadTimes4.14 with accept target to prevent those workarounds being merged out of dev-loadtimes4.14.

	Command:
	p4 integrate //UE4/Dev-LoadTimes4.14/...@3221131,3221131

	w/ resolve/accept-target

Change 3221410 on 2016/12/05 by Steve.Robb

	Allow Algo::IsSorted to work on C arrays and initializer_lists.

Change 3221673 on 2016/12/05 by Gil.Gribb

	set up an intentional merge conflict so we can do the right thing when dev-BP and dev-core come together

Change 3223182 on 2016/12/06 by Chris.Wood

	Add EngineModeEx to CrashReportCommon
	[UE-39258] - Update CrashReporter to include whether Engine crashes are from vanilla build or not

Change 3224646 on 2016/12/07 by Robert.Manuszewski

	It's no longer necessary to rebuild the cooked exe to enable the event driven loader. EDL and the new async IO are now controlled with ini settings only.

Change 3224647 on 2016/12/07 by Robert.Manuszewski

	Event Driven Loader is now enabled by default.

Change 3224669 on 2016/12/07 by Chris.Wood

	Compressing some crash files output from CRP to S3 (CRP v1.2.11)
	[UE-37564] - Add compression support for CRP crash files in S3

	Add EngineModeEx to support to CRP (CRP v1.2.10)
	[UE-39258] - Update CrashReporter to include whether Engine crashes are from vanilla build or not

Change 3224873 on 2016/12/07 by Robert.Manuszewski

	A few fixes to the EDL macro refactor.

Change 3224933 on 2016/12/07 by Robert.Manuszewski

	Async Loading settings will now be logged on startup in cooked games

Change 3224984 on 2016/12/07 by Robert.Manuszewski

	Small fix to EDL and new async IO global var init.

Change 3225027 on 2016/12/07 by Robert.Manuszewski

	Re-enabling EDL in ShooterGame since it no longer requires the cooked exe to be re-compiled (and EDL is on by default anyway).

Change 3226702 on 2016/12/08 by Steve.Robb

	UHT can now skip over macro-like identifiers while parsing.
	Correctly handles FTypefaceEntry::Name parsing, which was broken by the workaround in CL# 3219332.
	Syntax workaround reverted in FTypefaceEntry.

	#jira UE-38231

Change 3226756 on 2016/12/08 by Steve.Robb

	LexicalConversion renamed to Lex after #core discussion.
	Lex::ToString overloads added for FString itself.

Change 3226766 on 2016/12/08 by Steve.Robb

	FCookStatsManager::ToString replaced with Lex::ToString, as it now supports the required functionality.

Change 3226949 on 2016/12/08 by Robert.Manuszewski

	Fixing static analysis warnings

Change 3228566 on 2016/12/09 by Robert.Manuszewski

	Making UBT not think it needs to use separate temporary target for non source code projects when EDL settings don't match default.

Change 3228601 on 2016/12/09 by Steve.Robb

	Fix for TSparseArray visualization of types smaller than 8 bytes.

Change 3228654 on 2016/12/09 by Gil.Gribb

	UE4 - Fix very old bug with lock free lists, probably not relevant to anything we currently use.

Change 3228697 on 2016/12/09 by Graeme.Thornton

	Rebuilt UnrealPak

[CL 3228932 by Robert Manuszewski in Main branch]
2016-12-09 11:36:14 -05:00

694 lines
19 KiB
C#

// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.
using System;
using System.IO;
using System.Xml.Serialization;
using System.Collections;
using System.Collections.Generic;
using Tools.DotNETCommon.XmlHandler;
using System.Xml;
using System.Linq;
namespace Tools.CrashReporter.CrashReportCommon
{
/*
Unused Crashes' fields.
Title nchar(20)
Selected bit
Version int
AutoReporterID int
Processed bit
HasDiagnosticsFile bit
HasNewLogFile bit
HasMetaData bit
Fields of Crashes used only by the crash report website.
Status varchar(64) - Status of the crash.
Pattern varchar(800) - Pattern used to group cashes into buggs.
FixedChangeList varchar(64) - Changelist that fixed this crash.
Module varchar(128) - Name of the module where the crash occurred.
UserNameId int - The ID of the user name.
Jira varchar(64) - The Jira.
CrashType smallint NOT NULL - The type of the crash, crash(1), assert(2), ensure(3)
*/
/* PrimaryCrashProperties. Extracted from: FGenericCrashContext::SerializeContentToBuffer */
/*
"CrashVersion"
"CrashGUID"
"ProcessId"
"IsInternalBuild"
"IsPerforceBuild"
"IsSourceDistribution"
"IsEnsure"
"IsAssert"
"CrashType"
"SecondsSinceStart"
"GameName"
"ExecutableName"
"BuildConfiguration"
"GameSessionID"
"PlatformName"
"PlatformNameIni"
"PlatformFullName"
"EngineMode"
"EngineModeEx"
"DeploymentName"
"EngineVersion"
"BuildVersion"
"CommandLine"
"LanguageLCID"
"AppDefaultLocale"
"IsUE4Release"
"UserName"
"BaseDir"
"RootDir"
"MachineId"
"LoginId"
"EpicAccountId"
"CallStack"
"SourceContext"
"UserDescription"
"UserActivityHint"
"ErrorMessage"
"CrashDumpMode"
"FullCrashDumpLocation"
"Misc.NumberOfCores"
"Misc.NumberOfCoresIncludingHyperthreads"
"Misc.Is64bitOperatingSystem"
"Misc.CPUVendor"
"Misc.CPUBrand"
"Misc.PrimaryGPUBrand"
"Misc.OSVersionMajor"
"Misc.OSVersionMinor"
"Misc.AppDiskTotalNumberOfBytes"
"Misc.AppDiskNumberOfFreeBytes"
"MemoryStats.TotalPhysical"
"MemoryStats.TotalVirtual"
"MemoryStats.PageSize"
"MemoryStats.TotalPhysicalGB"
"MemoryStats.AvailablePhysical"
"MemoryStats.AvailableVirtual"
"MemoryStats.UsedPhysical"
"MemoryStats.PeakUsedPhysical"
"MemoryStats.UsedVirtual"
"MemoryStats.PeakUsedVirtual"
"MemoryStats.bIsOOM"
"MemoryStats.OOMAllocationSize"
"MemoryStats.OOMAllocationAlignment"
"TimeofCrash"
"bAllowToBeContacted"
"PlatformCallbackResult"
*/
/// <summary> Enumerates crash description versions. </summary>
public enum ECrashDescVersions
{
/// <summary> Introduces a new crash description format. </summary>
VER_1_NewCrashFormat,
/// <summary> Added misc properties (CPU,GPU,OS,etc), memory related stats and platform specific properties as generic payload. </summary>
VER_2_AddedNewProperties,
/// <summary> Using crash context when available. </summary>
VER_3_CrashContext = 3,
}
/// <summary>
/// GenericCrashContext for managed code. Based on XML file.
/// Holds data from the CrashContext.runtime-xml file
/// Must match FGenericCrashContext::SerializeContentToBuffer
///
/// 1. Generated by FGenericCrashContext::SerializeContentToBuffer via the native code
/// 2. Updated with callstack, source context etc via the crash report client / crash report process
/// 3. Read by the crash report process, verified and forward in the same form to the crash report frontend
/// 4. Basic properties displayed directly in the frontend (already existing in the database), remaining properties are displayed per crash read from the CrashContext.runtime-xml file.
///
/// <RuntimeCrashDescription></RuntimeCrashDescription>
/// <version></version>
/// <PlatformSpecificProperties>
///
/// </PlatformSpecificProperties>
/// </summary>
public class FGenericCrashContext
{
/// <summary> Name of the crash context file. </summary>
public const string CrashContextRuntimeXMLName = "CrashContext.runtime-xml";
/// <summary>Required properties</summary>
[XmlElement( ElementName = "RuntimeProperties" )]
public FPrimaryCrashProperties PrimaryCrashProperties = new FPrimaryCrashProperties();
/// <summary>Optional, platform specific properties</summary>
[XmlElement( ElementName = "PlatformProperties" )]
public object UntypedXMLNodes;
/// <summary> Directory of the crash. </summary>
public string CrashDirectory;
//// <summary> Platform specific properties. </summary>
//[XmlElement]
//public List<KeyValuePair<string, string>> PlatformProperties = new List<KeyValuePair<string, string>>();
/// <summary>A simple default constructor to allow Xml serialization.</summary>
public FGenericCrashContext()
{
}
/// <summary> Creates a new instance of the crash report context from the specified file. </summary>
public static FGenericCrashContext FromFile( string Filepath )
{
// The crash report context contains invalid characters, we need to fix them all in order to parse the XML.
HashSet<string> TagsToIgnore = new HashSet<string>() { "<FGenericCrashContext>", "<RuntimeProperties>", "<PlatformProperties>", "</FGenericCrashContext>", "</RuntimeProperties>", "</PlatformProperties>" };
string[] XMLText = File.ReadAllLines( Filepath );
string CopyText = string.Join( Environment.NewLine, XMLText );
string NodeOpen = "";
string NodeEnd = "";
List<string> Multiline = new List<string>();
List<int> MultiIndex = new List<int>();
int OpenEnd = 0;
int EndStart = 0;
for (int LineIndex = 1; LineIndex < XMLText.Length; LineIndex++)
{
string XMLLine = XMLText[LineIndex].Replace( "\t", "" );
bool bIgnore = TagsToIgnore.Contains( XMLLine );
if (bIgnore)
{
continue;
}
// XML node without data, skip.
if (XMLLine.Contains( "/>" ))
{
continue;
}
if (NodeOpen == "")
{
// Parse the tag.
//<Version>"1"</Version>
//<Version />
int OpenStart = XMLLine.IndexOf( '<' );
OpenEnd = XMLLine.IndexOf( '>', OpenStart );
NodeOpen = XMLLine.Substring( OpenStart + 1, OpenEnd - OpenStart - 1 );
}
EndStart = XMLLine.IndexOf( "</" );
int EndEnd = 0;
if (EndStart != -1)
{
EndEnd = XMLLine.IndexOf( '>', EndStart );
NodeEnd = XMLLine.Substring( EndStart + 2, EndEnd - EndStart - 2 );
}
else
{
Multiline.Add( XMLLine.Substring( OpenEnd != 0 ? OpenEnd + 1 : 0 ) );
MultiIndex.Add( LineIndex );
OpenEnd = 0;
}
// Valid tag, fix invalid characters.
if (NodeOpen == NodeEnd)
{
if (Multiline.Count == 0)
{
string NodeValue = XMLLine.Substring( OpenEnd + 1, EndStart - OpenEnd - 1 );
string EscapedXMLText = EscapeXMLString( UnescapeXMLString( NodeValue ) ); // Required for support old and new type format.
XMLText[LineIndex] = string.Format( "<{0}>{1}</{0}>", NodeOpen, EscapedXMLText );
}
else
{
Multiline.Add( XMLLine.Substring( 0, EndStart ) );
MultiIndex.Add( LineIndex );
for (int Inner = 0; Inner < Multiline.Count; Inner++)
{
string EscapedXMLText = EscapeXMLString( UnescapeXMLString( Multiline[Inner] ) );
if (Inner == 0)
{
XMLText[MultiIndex[Inner]] = string.Format( "<{0}>{1}", NodeOpen, EscapedXMLText );
}
else if (Inner == Multiline.Count - 1)
{
XMLText[MultiIndex[Inner]] = string.Format( "{1}</{0}>", NodeOpen, EscapedXMLText );
}
else
{
XMLText[MultiIndex[Inner]] = EscapedXMLText;
}
}
Multiline.Clear();
MultiIndex.Clear();
}
NodeOpen = NodeEnd = "";
}
}
string XMLTextJoined = string.Join( Environment.NewLine, XMLText );
FGenericCrashContext Context = XmlHandler.FromXmlString<FGenericCrashContext>( XMLTextJoined );
if (Context.UntypedXMLNodes != null)
{
var Typed = ( (IEnumerable)Context.UntypedXMLNodes )
.Cast<XmlNode>()
.Select( X => new KeyValuePair<string, string>( X.Name, X.InnerText ) )
.ToList();
}
return Context;
}
const string NewLineTag = "&nl;";
/// <summary> Escape XML string. </summary>
static public string EscapeXMLString( string Text )
{
return Text
.Replace( "&", "&amp;" )
.Replace( "\"", "&quot;" )
.Replace( "'", "&apos;" )
.Replace( "<", "&lt;" )
.Replace( ">", "&gt;" )
// Ignore return carriage.
.Replace( "\r", "" );
//.Replace( "\n", NewLineTag );
}
/// <summary> Unescape XML string. </summary>
static public string UnescapeXMLString( string Text )
{
return Text
.Replace( "&amp;", "&" )
.Replace( "&quot;", "\"" )
.Replace( "&apos;", "'" )
.Replace( "&lt;", "<" )
.Replace( "&gt;", ">" )
.Replace( NewLineTag, "\n" );
}
/// <summary> Whether this crash contains callstack, error message and source context thus it means that crash is complete. </summary>
public bool HasProcessedData()
{
return !string.IsNullOrEmpty(PrimaryCrashProperties.CallStack) &&
!string.IsNullOrEmpty(PrimaryCrashProperties.ErrorMessage);
}
/// <summary> Writes this instance of the crash report context to the specified file. </summary>
public void ToFile()
{
XmlHandler.WriteXml<FGenericCrashContext>( this, Path.Combine( CrashDirectory, FGenericCrashContext.CrashContextRuntimeXMLName ) );
}
/// <returns>Unique name of this report, can be used as name of file.</returns>
public string GetAsFilename()
{
return Path.GetFileName(CrashDirectory);
}
}
/*
"EngineVersion"
*/
/// <summary> Required properties for the generic crash context. </summary>
public class FPrimaryCrashProperties
{
/// <summary></summary>
[XmlElement]
public int CrashVersion;
/// <summary></summary>
[XmlElement]
public string CrashGUID;
/// <summary></summary>
[XmlElement]
public int ProcessId;
/// <summary></summary>
[XmlElement]
public bool IsInternalBuild;
/// <summary></summary>
[XmlElement]
public bool IsPerforceBuild;
/// <summary></summary>
[XmlElement]
public bool IsSourceDistribution;
/// <summary></summary>
[XmlElement]
public bool IsEnsure;
/// <summary></summary>
[XmlElement]
public bool IsAssert;
/// <summary></summary>
[XmlElement]
public string CrashType;
/// <summary>
/// Get the crash type. Can be empty but we don't want null.
/// </summary>
public string GetCrashType() { return CrashType ?? string.Empty; }
/// <summary></summary>
[XmlElement]
public int SecondsSinceStart;
/// <summary></summary>
[XmlElement]
public string GameName;
/// <summary></summary>
[XmlElement]
public string ExecutableName;
/// <summary></summary>
[XmlElement]
public string BuildConfiguration;
/// <summary></summary>
[XmlElement]
public string GameSessionID;
/// <summary></summary>
[XmlElement]
public string PlatformName;
/// <summary></summary>
[XmlElement]
public string PlatformNameIni;
/// <summary></summary>
[XmlElement]
public string PlatformFullName;
/// <summary>
/// Creates a full platform name, if missing. PlatformName [OS.Major Os.Minor Arch]
/// Must match
/// ...\Engine\Source\Programs\CrashReporter\CrashReportClient\Private\CrashDescription.cpp FCrashContext.FCrashContext
///</summary>
public void SetPlatformFullName()
{
if (string.IsNullOrEmpty( PlatformFullName ))
{
// Create a new one.
string LocalPlatformName = "";
if (BaseDir != "")
{
string[] FolderComponents = BaseDir.Split( new[] { '/' }, StringSplitOptions.RemoveEmptyEntries );
if (FolderComponents.Length != 0)
{
LocalPlatformName = FolderComponents[FolderComponents.Length - 1];
}
}
else
{
LocalPlatformName = PlatformNameIni;
}
if (!string.IsNullOrEmpty( Misc_OSVersionMajor ))
{
PlatformFullName = string.Format( "{0} [{1} {2} {3}]",
LocalPlatformName,
Misc_OSVersionMajor,
string.IsNullOrEmpty( Misc_OSVersionMinor ) ? "" : Misc_OSVersionMinor,
Misc_Is64bitOperatingSystem ? "64b" : "32b" );
}
}
}
/// <summary></summary>
[XmlElement]
public string EngineMode;
/// <summary></summary>
[XmlElement]
public string EngineModeEx;
/// <summary>
/// Get the engine mode ex. Can be empty but we don't want null.
/// </summary>
public string GetEngineModeEx() { return EngineModeEx ?? string.Empty; }
/// <summary></summary>
[XmlElement]
public string DeploymentName;
/// <summary></summary>
[XmlElement]
public string EngineVersion;
/// <summary></summary>
[XmlElement]
public string BuildVersion;
/// <summary></summary>
[XmlElement]
public string CommandLine;
/// <summary></summary>
[XmlElement]
public int LanguageLCID;
/// <summary></summary>
[XmlElement]
public string AppDefaultLocale;
/// <summary></summary>
[XmlElement]
public bool IsUE4Release;
/// <summary></summary>
[XmlElement]
public string UserName;
/// <summary></summary>
[XmlElement]
public string BaseDir;
/// <summary></summary>
[XmlElement]
public string RootDir;
/// <summary></summary>
[XmlElement]
public string MachineId;
/// <summary></summary>
[XmlElement]
public string LoginId;
/// <summary></summary>
[XmlElement]
public string EpicAccountId;
/// <summary></summary>
[XmlElement]
public string CallStack;
/// <summary> Callstack as string[] unescaped. </summary>
public string[] GetCallstack()
{
if (string.IsNullOrWhiteSpace(CallStack)) return new string[0];
string UnescapedValue = FGenericCrashContext.UnescapeXMLString( CallStack );
return UnescapedValue.Split( new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries );
}
/// <summary></summary>
[XmlElement]
public string SourceContext;
/// <summary> SourceContext as string[] unescaped. </summary>
public string[] GetSourceContext()
{
if (string.IsNullOrWhiteSpace(SourceContext)) return new string[0];
string UnescapedValue = FGenericCrashContext.UnescapeXMLString( SourceContext );
return UnescapedValue.Split( new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries );
}
/// <summary></summary>
[XmlElement]
public string UserDescription;
/// <summary> UserDescription as string[] unescaped. </summary>
public string[] GetUserDescription()
{
if (string.IsNullOrWhiteSpace(UserDescription)) return new string[0];
string UnescapedValue = FGenericCrashContext.UnescapeXMLString( UserDescription );
return UnescapedValue.Split( new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries );
}
/// <summary></summary>
[XmlElement]
public string UserActivityHint;
/// <summary></summary>
[XmlElement]
public string ErrorMessage;
/// <summary> ErrorMessage as string[] unescaped. </summary>
public string[] GetErrorMessage()
{
if (string.IsNullOrWhiteSpace(ErrorMessage)) return new string[0];
string UnescapedValue = FGenericCrashContext.UnescapeXMLString( ErrorMessage );
UnescapedValue = UnescapedValue.Substring( 0, Math.Min( 511, UnescapedValue.Length ) ); // Database limitation.
return UnescapedValue.Split( new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries );
}
/// <summary></summary>
[XmlElement]
public int CrashDumpMode;
/// <summary> Location of the full crash dump. Displayed in the crash report frontend, without the filename. </summary>
[XmlElement]
public string FullCrashDumpLocation;
/// <summary> Fullname of the full crash dump.</summary>
public string GetFullCrashDumpLocation()
{
if (string.IsNullOrWhiteSpace(FullCrashDumpLocation)) return string.Empty;
string Fullname = Path.Combine( FullCrashDumpLocation, CrashReporterConstants.UE4MinidumpName );
return Fullname;
}
/// <summary></summary>
[XmlElement( ElementName = "Misc.NumberOfCores" )]
public int Misc_NumberOfCores;
/// <summary></summary>
[XmlElement( ElementName = "Misc.NumberOfCoresIncludingHyperthreads" )]
public int Misc_NumberOfCoresIncludingHyperthreads;
/// <summary></summary>
[XmlElement( ElementName = "Misc.Is64bitOperatingSystem" )]
public bool Misc_Is64bitOperatingSystem;
/// <summary></summary>
[XmlElement( ElementName = "Misc.CPUVendor" )]
public string Misc_CPUVendor;
/// <summary></summary>
[XmlElement( ElementName = "Misc.CPUBrand" )]
public string Misc_CPUBrand;
/// <summary></summary>
[XmlElement( ElementName = "Misc.PrimaryGPUBrand" )]
public string Misc_PrimaryGPUBrand;
/// <summary></summary>
[XmlElement( ElementName = "Misc.OSVersionMajor" )]
public string Misc_OSVersionMajor;
/// <summary></summary>
[XmlElement( ElementName = "Misc.OSVersionMinor" )]
public string Misc_OSVersionMinor;
/// <summary></summary>
[XmlElement( ElementName = "Misc.AppDiskTotalNumberOfBytes")]
public string Misc_AppDiskTotalNumberOfBytes;
/// <summary></summary>
[XmlElement( ElementName = "Misc.AppDiskNumberOfFreeBytes")]
public string Misc_AppDiskNumberOfFreeBytes;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.TotalPhysical")]
public string MemoryStats_TotalPhysical;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.TotalVirtual")]
public string MemoryStats_TotalVirtual;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.PageSize")]
public string MemoryStats_PageSize;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.TotalPhysicalGB")]
public string MemoryStats_TotalPhysicalGB;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.AvailablePhysical")]
public string MemoryStats_AvailablePhysical;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.AvailableVirtual")]
public string MemoryStats_AvailableVirtual;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.UsedPhysical")]
public string MemoryStats_UsedPhysical;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.PeakUsedPhysical")]
public string MemoryStats_PeakUsedPhysical;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.UsedVirtual")]
public string MemoryStats_UsedVirtual;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.PeakUsedVirtual")]
public string MemoryStats_PeakUsedVirtual;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.bIsOOM")]
public string MemoryStats_bIsOOM;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.OOMAllocationSize")]
public string MemoryStats_OOMAllocationSize;
/// <summary></summary>
[XmlElement( ElementName = "MemoryStats.OOMAllocationAlignment")]
public string MemoryStats_OOMAllocationAlignment;
/// <summary>The UTC time the crash occurred.</summary>
[XmlElement]
public DateTime TimeofCrash;
/// <summary> Whether the user allowed us to be contacted. </summary>
[XmlElement]
public bool bAllowToBeContacted = false;
/// <summary> Platform status. </summary>
[XmlElement]
public int PlatformCallbackResult;
/// <summary> CRC version that uploaded the crash. Blank for older builds. </summary>
[XmlElement]
public string CrashReportClientVersion;
/// <summary> An array of module names used by the game that crashed. </summary>
[XmlElement]
public string Modules;
/// <summary> Warning info for missing data or failed processing in the Crash Report Processor. </summary>
[XmlElement]
public string ProcessorFailedMessage;
/// <summary>A simple default constructor to allow Xml serialization.</summary>
public FPrimaryCrashProperties()
{ }
}
}