Files
UnrealEngineUWP/Engine/Source/Programs/CrashReporter/CrashReportClient/Private/CrashDescription.cpp
Andrew Grant 13a9fa2498 Copying //UE4/Orion-Staging to //UE4/Main (Source: //Orion/Dev-General @ 2845681)
#lockdown Nick.Penwarden

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

Change 2845644 on 2016/01/27 by Martin.Wilson

	Clear marker sync flag after creating tick record, add more information to checks incase issue occurs again

	#Jira OR-13469
	#rb Thomas.Sarkanen
	#tests in editor tests, bot match.

Change 2845613 on 2016/01/27 by John.Pollard

	Latest network profiler binaries

	#rb none
	#tests run profiler

Change 2845595 on 2016/01/27 by Mieszko.Zielinski

	Fixed pathfollowing's block detection using wrong distance when testing for blockage #UE4

	#rb Lukasz.Furman
	#test golden path

Change 2845593 on 2016/01/27 by Jeff.Farris

	Added support for setting and choosing filmbacks and lenses for cinematic cameras.
	- New CineCameraComponent and CineCameraActor classes
	- can define filmback and lens presets via ini file
	- details customizations for filmback and lens selection
	- added prototype set of filmbacks and lenses (primes and zooms)
	- Camera details customization now gracefully handles when CameraSettings category is hidden
	- example sequencer usage is content/developers/jeff.farris/CineCams/CineCamTestMap

	#rb none
	#tests editor

Change 2845585 on 2016/01/27 by Marcus.Wassmer

	Don't fool with connected state if we're early outing from the OS intercepting controller events.  This fixes some missing delegates.
	Fixes cert bug about controller disconnect screen staying up permanently
	#rb Cody.Haskell
	#test Turning off controller, turning on again.
	#lockdown Andrew.Grant

Change 2845528 on 2016/01/27 by Max.Chen

	Sequencer: Fix new spawnables not immediately getting an object binding. This was resulted in a missing +Track->Animation when first creating a spawnable and duplicate transform keys.

	#jira UE-26084
	#tests Add spawnable, +Track->Animation exists
	#rb none

Change 2845483 on 2016/01/27 by Andrew.Rodham

	Sequencer: Fixed MaximizedViewport not getting cleared/restored correctly
	#jria UE-26016
	#rb Max.Chen
	#tests Tested the viewports

Change 2845421 on 2016/01/27 by Max.Preussner

	Sequencer: Implemented go-to feature

	#RB max.chen
	#TESTS Editor

Change 2845407 on 2016/01/27 by Max.Preussner

	Sequencer: Moved SetViewRange() into ISequencer and made it public

	#RB max.chen
	#TESTS none

Change 2845404 on 2016/01/27 by Andrew.Rodham

	Sequencer: Fixed cinematic viewport not updating when dragging transport range
	#jira UE-26003
	#rb Max.Chen
	#tests Scrubbed the timeline

Change 2845396 on 2016/01/27 by David.Nikdel

	#OSS #Purchase #Store #PS4
	- Minor log cleanup
	#RB: none
	#TESTS: compiles

Change 2845375 on 2016/01/27 by Max.Chen

	Sequencer: Implement cinematic shot track thumbnails.

	#jira UE-25125
	#tests Rebuild the trailer with the cinematic shot track
	#rb none

Change 2845359 on 2016/01/27 by Marcus.Wassmer

	Downgrade some checks to ensures.
	#rb none
	#test ps4

Change 2845347 on 2016/01/27 by Nicholas.Davies

	Remove unused EditorStyle dependency from Social. It is not being used, and causes issues for the engine team.
	#RB Antony.Carter
	#TESTS n/a
	#codereview Robert.Manuszewski

Change 2845227 on 2016/01/27 by Robert.Manuszewski

	Adding flags to create callstack map files when building Arxan protection

	#rb none
	#tests Built arxan exe

Change 2844871 on 2016/01/26 by Andrew.Grant

	Prevent enums from being regenerated while cooking (prevents false-positive warning about FText's being regenerated)
	#rb none
	#tests ran editor

[CL 2847722 by Andrew Grant in Main branch]
2016-01-28 16:03:26 -05:00

417 lines
14 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "CrashReportClientApp.h"
#include "GenericPlatformCrashContext.h"
#include "XmlFile.h"
#include "CrashDescription.h"
#include "CrashReportAnalytics.h"
#include "CrashReportUtil.h"
#include "Runtime/Analytics/Analytics/Public/Analytics.h"
#include "Runtime/Analytics/Analytics/Public/Interfaces/IAnalyticsProvider.h"
#include "EngineBuildSettings.h"
// #CrashReport: 2015-07-23 Move crashes from C:\Users\[USER]\AppData\Local\Microsoft\Windows\WER\ReportQueue to C:\Users\[USER]\AppData\Local\CrashReportClient\Saved
/*-----------------------------------------------------------------------------
FCrashProperty
-----------------------------------------------------------------------------*/
FCrashProperty::FCrashProperty( const FString& InMainCategory, const FString& InSecondCategory, FPrimaryCrashProperties* InOwner )
: Owner( InOwner )
, CachedValue( TEXT("") )
, MainCategory( InMainCategory )
, SecondCategory( InSecondCategory )
, bSet( false )
{
}
FCrashProperty& FCrashProperty::operator=(const FString& NewValue)
{
bSet = true;
CachedValue = NewValue;
Owner->SetCrashProperty( MainCategory, SecondCategory, CachedValue );
return *this;
}
FCrashProperty& FCrashProperty::operator=(const TCHAR* NewValue)
{
bSet = true;
CachedValue = NewValue;
Owner->SetCrashProperty( MainCategory, SecondCategory, CachedValue );
return *this;
}
FCrashProperty& FCrashProperty::operator=(const TArray<FString>& NewValue)
{
bSet = true;
CachedValue = Owner->EncodeArrayStringAsXMLString( NewValue );
Owner->SetCrashProperty( MainCategory, SecondCategory, CachedValue );
return *this;
}
FCrashProperty& FCrashProperty::operator=(const bool NewValue)
{
bSet = true;
CachedValue = NewValue ? TEXT( "1" ) : TEXT( "0" );
Owner->SetCrashProperty( MainCategory, SecondCategory, CachedValue );
return *this;
}
FCrashProperty& FCrashProperty::operator=(const int64 NewValue)
{
bSet = true;
CachedValue = LexicalConversion::ToString( NewValue );
Owner->SetCrashProperty( MainCategory, SecondCategory, CachedValue );
return *this;
}
const FString& FCrashProperty::AsString() const
{
if (!bSet)
{
Owner->GetCrashProperty( CachedValue, MainCategory, SecondCategory );
bSet = true;
}
return CachedValue;
}
bool FCrashProperty::AsBool() const
{
return AsString().ToBool();
}
int64 FCrashProperty::AsInt64() const
{
int64 Value = 0;
TTypeFromString<int64>::FromString( Value, *AsString() );
return Value;
}
/*-----------------------------------------------------------------------------
FPrimaryCrashProperties
-----------------------------------------------------------------------------*/
FPrimaryCrashProperties* FPrimaryCrashProperties::Singleton = nullptr;
FPrimaryCrashProperties::FPrimaryCrashProperties()
// At this moment only these properties can be changed by the crash report client.
: PlatformFullName( FGenericCrashContext::RuntimePropertiesTag, TEXT( "PlatformFullName" ), this )
, CommandLine( FGenericCrashContext::RuntimePropertiesTag, TEXT( "CommandLine" ), this )
, UserName( FGenericCrashContext::RuntimePropertiesTag, TEXT("UserName"), this )
, MachineId( FGenericCrashContext::RuntimePropertiesTag, TEXT( "MachineId" ), this )
, EpicAccountId( FGenericCrashContext::RuntimePropertiesTag, TEXT( "EpicAccountId" ), this )
// Multiline properties
, CallStack( FGenericCrashContext::RuntimePropertiesTag, TEXT( "CallStack" ), this )
, SourceContext( FGenericCrashContext::RuntimePropertiesTag, TEXT( "SourceContext" ), this )
, Modules( FGenericCrashContext::RuntimePropertiesTag, TEXT( "Modules" ), this )
, UserDescription( FGenericCrashContext::RuntimePropertiesTag, TEXT( "UserDescription" ), this )
, UserActivityHint( FGenericCrashContext::RuntimePropertiesTag, TEXT( "UserActivityHint" ), this )
, ErrorMessage( FGenericCrashContext::RuntimePropertiesTag, TEXT( "ErrorMessage" ), this )
, FullCrashDumpLocation( FGenericCrashContext::RuntimePropertiesTag, TEXT( "FullCrashDumpLocation" ), this )
, TimeOfCrash( FGenericCrashContext::RuntimePropertiesTag, TEXT( "TimeOfCrash" ), this )
, bAllowToBeContacted( FGenericCrashContext::RuntimePropertiesTag, TEXT( "bAllowToBeContacted" ), this )
, XmlFile( nullptr )
{
CrashVersion = ECrashDescVersions::VER_1_NewCrashFormat;
CrashDumpMode = ECrashDumpMode::Default;
bHasMiniDumpFile = false;
bHasLogFile = false;
bHasPrimaryData = false;
}
void FPrimaryCrashProperties::Shutdown()
{
delete Get();
}
void FPrimaryCrashProperties::UpdateIDs()
{
const bool bAddPersonalData = FCrashReportClientConfig::Get().GetAllowToBeContacted() || FEngineBuildSettings::IsInternalBuild();
bAllowToBeContacted = bAddPersonalData;
if (bAddPersonalData)
{
// The Epic ID can be looked up from this ID.
EpicAccountId = FPlatformMisc::GetEpicAccountId();
}
else
{
EpicAccountId = FString();
}
// Add real user name only if log files were allowed since the user name is in the log file and the user consented to sending this information.
const bool bSendUserName = FCrashReportClientConfig::Get().GetSendLogFile() || FEngineBuildSettings::IsInternalBuild();
if (bSendUserName)
{
// Remove periods from user names to match AutoReporter user names
// The name prefix is read by CrashRepository.AddNewCrash in the website code
UserName = FString( FPlatformProcess::UserName() ).Replace( TEXT( "." ), TEXT( "" ) );
}
else
{
UserName = FString();
}
MachineId = FPlatformMisc::GetMachineId().ToString( EGuidFormats::Digits );
}
void FPrimaryCrashProperties::ReadXML( const FString& CrashContextFilepath )
{
XmlFilepath = CrashContextFilepath;
XmlFile = new FXmlFile( XmlFilepath );
TimeOfCrash = FDateTime::UtcNow().GetTicks();
UpdateIDs();
}
void FPrimaryCrashProperties::SetCrashGUID( const FString& Filepath )
{
FString CrashDirectory = FPaths::GetPath( Filepath );
FPaths::NormalizeDirectoryName( CrashDirectory );
// Grab the last component...
CrashGUID = FPaths::GetCleanFilename( CrashDirectory );
}
FString FPrimaryCrashProperties::EncodeArrayStringAsXMLString( const TArray<FString>& ArrayString ) const
{
const FString Encoded = FString::Join( ArrayString, TEXT("\n") );
return Encoded;
}
void FPrimaryCrashProperties::SendAnalytics()
{
// Connect the crash report client analytics provider.
FCrashReportAnalytics::Initialize();
IAnalyticsProvider& Analytics = FCrashReportAnalytics::GetProvider();
TArray<FAnalyticsEventAttribute> CrashAttributes;
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "bHasPrimaryData" ), bHasPrimaryData ) );
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "CrashVersion" ), (int32)CrashVersion ) );
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "CrashGUID" ), CrashGUID ) );
// AppID = GameName
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "GameName" ), GameName ) );
// AppVersion = EngineVersion
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "EngineVersion" ), EngineVersion.ToString() ) );
// @see UpdateIDs()
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "MachineID" ), MachineId.AsString() ) );
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "UserName" ), UserName.AsString() ) );
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "EpicAccountId" ), EpicAccountId.AsString() ) );
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "Platform" ), PlatformFullName.AsString() ) );
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "TimeOfCrash" ), TimeOfCrash.AsString() ) );
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "EngineMode" ), EngineMode ) );
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "AppDefaultLocale" ), AppDefaultLocale ) );
CrashAttributes.Add( FAnalyticsEventAttribute( TEXT( "UserActivityHint" ), UserActivityHint.AsString() ) );
Analytics.RecordEvent( TEXT( "CrashReportClient.ReportCrash" ), CrashAttributes );
// Shutdown analytics.
FCrashReportAnalytics::Shutdown();
}
void FPrimaryCrashProperties::Save()
{
XmlFile->Save( XmlFilepath );
}
/*-----------------------------------------------------------------------------
FCrashContextReader
-----------------------------------------------------------------------------*/
FCrashContext::FCrashContext( const FString& CrashContextFilepath )
{
ReadXML( CrashContextFilepath );
const bool bIsValid = XmlFile->IsValid();
if (bIsValid)
{
// Setup properties required for the analytics.
GetCrashProperty( CrashVersion, FGenericCrashContext::RuntimePropertiesTag, TEXT( "CrashVersion" ) );
GetCrashProperty( CrashGUID, FGenericCrashContext::RuntimePropertiesTag, TEXT( "CrashGUID" ) );
GetCrashProperty( CrashDumpMode, FGenericCrashContext::RuntimePropertiesTag, TEXT( "CrashDumpMode" ) );
GetCrashProperty( GameName, FGenericCrashContext::RuntimePropertiesTag, TEXT( "GameName" ) );
GetCrashProperty( EngineVersion, FGenericCrashContext::RuntimePropertiesTag, TEXT( "EngineVersion" ) );
GetCrashProperty( BaseDir, FGenericCrashContext::RuntimePropertiesTag, TEXT( "BaseDir" ) );
FString Misc_OSVersionMajor;
GetCrashProperty( Misc_OSVersionMajor, FGenericCrashContext::RuntimePropertiesTag, TEXT( "Misc.OSVersionMajor" ) );
FString Misc_OSVersionMinor;
GetCrashProperty( Misc_OSVersionMinor, FGenericCrashContext::RuntimePropertiesTag, TEXT( "Misc.OSVersionMinor" ) );
bool Misc_Is64bitOperatingSystem = false;
GetCrashProperty( Misc_Is64bitOperatingSystem, FGenericCrashContext::RuntimePropertiesTag, TEXT( "Misc.Is64bitOperatingSystem" ) );
// Extract the Platform component.
TArray<FString> SubDirs;
BaseDir.ParseIntoArray( SubDirs, TEXT( "/" ), true );
const int SubDirsNum = SubDirs.Num();
const FString PlatformName = SubDirsNum > 0 ? SubDirs[SubDirsNum - 1] : TEXT( "" );
if (Misc_OSVersionMajor.Len() > 0)
{
PlatformFullName = FString::Printf( TEXT( "%s [%s %s %s]" ), *PlatformName, *Misc_OSVersionMajor, *Misc_OSVersionMinor, Misc_Is64bitOperatingSystem ? TEXT( "64b" ) : TEXT( "32b" ) );
}
else
{
PlatformFullName = PlatformName;
}
GetCrashProperty( EngineMode, FGenericCrashContext::RuntimePropertiesTag, TEXT( "EngineMode" ) );
GetCrashProperty( AppDefaultLocale, FGenericCrashContext::RuntimePropertiesTag, TEXT( "AppDefaultLocale" ) );
if (CrashDumpMode == ECrashDumpMode::FullDump)
{
// Set the full dump crash location when we have a full dump.
const FString LocationForBranch = FCrashReportClientConfig::Get().GetFullCrashDumpLocationForBranch( EngineVersion.GetBranch() );
if (!LocationForBranch.IsEmpty())
{
FullCrashDumpLocation = LocationForBranch / CrashGUID + TEXT("_") + EngineVersion.ToString();
}
}
bHasPrimaryData = true;
}
}
/*-----------------------------------------------------------------------------
FCrashDescription
-----------------------------------------------------------------------------*/
FCrashWERContext::FCrashWERContext( const FString& WERXMLFilepath )
: FPrimaryCrashProperties()
{
ReadXML( WERXMLFilepath );
CrashGUID = FPaths::GetCleanFilename( FPaths::GetPath( WERXMLFilepath ) );
const bool bIsValid = XmlFile->IsValid();
if (bIsValid)
{
FString BuildVersion;
FString BranchName;
uint32 BuiltFromCL = 0;
int EngineVersionComponents = 0;
GetCrashProperty( GameName, TEXT( "ProblemSignatures" ), TEXT( "Parameter0" ) );
GetCrashProperty( BuildVersion, TEXT( "ProblemSignatures" ), TEXT( "Parameter1" ) );
if (!BuildVersion.IsEmpty())
{
EngineVersionComponents++;
}
FString Parameter8Value;
GetCrashProperty( Parameter8Value, TEXT( "ProblemSignatures" ), TEXT( "Parameter8" ) );
if (!Parameter8Value.IsEmpty())
{
TArray<FString> ParsedParameters8;
Parameter8Value.ParseIntoArray( ParsedParameters8, TEXT( "!" ), false );
if (ParsedParameters8.Num() > 1)
{
CommandLine = FGenericCrashContext::UnescapeXMLString( ParsedParameters8[1] );
CrashDumpMode = CommandLine.AsString().Contains( TEXT( "-fullcrashdump" ) ) ? ECrashDumpMode::FullDump : ECrashDumpMode::Default;
}
if (ParsedParameters8.Num() > 2)
{
ErrorMessage = ParsedParameters8[2];
}
}
FString Parameter9Value;
GetCrashProperty( Parameter9Value, TEXT( "ProblemSignatures" ), TEXT( "Parameter9" ) );
if (!Parameter9Value.IsEmpty())
{
TArray<FString> ParsedParameters9;
Parameter9Value.ParseIntoArray( ParsedParameters9, TEXT( "!" ), false );
if (ParsedParameters9.Num() > 0)
{
BranchName = ParsedParameters9[0].Replace( TEXT( "+" ), TEXT( "/" ) );
const FString DepotRoot = TEXT( "//depot/" );
if (BranchName.StartsWith( DepotRoot ))
{
BranchName = BranchName.Mid( DepotRoot.Len() );
}
EngineVersionComponents++;
}
if (ParsedParameters9.Num() > 1)
{
const FString BaseDirectory = ParsedParameters9[1];
TArray<FString> SubDirs;
BaseDirectory.ParseIntoArray( SubDirs, TEXT( "/" ), true );
const int SubDirsNum = SubDirs.Num();
const FString PlatformName = SubDirsNum > 0 ? SubDirs[SubDirsNum - 1] : TEXT( "" );
FString Product;
GetCrashProperty( Product, TEXT( "OSVersionInformation" ), TEXT( "Product" ) );
if (Product.Len() > 0)
{
PlatformFullName = FString::Printf( TEXT( "%s [%s]" ), *PlatformName, *Product );
}
else
{
PlatformFullName = PlatformName;
}
}
if (ParsedParameters9.Num() > 2)
{
EngineMode = ParsedParameters9[2];
}
if (ParsedParameters9.Num() > 3)
{
TTypeFromString<uint32>::FromString( BuiltFromCL, *ParsedParameters9[3] );
EngineVersionComponents++;
}
}
// We have all three components of the engine version, so initialize it.
if (EngineVersionComponents == 3)
{
InitializeEngineVersion( BuildVersion, BranchName, BuiltFromCL );
}
bHasPrimaryData = true;
}
}
void FCrashWERContext::InitializeEngineVersion( const FString& BuildVersion, const FString& BranchName, uint32 BuiltFromCL )
{
uint16 Major = 0;
uint16 Minor = 0;
uint16 Patch = 0;
TArray<FString> ParsedBuildVersion;
BuildVersion.ParseIntoArray( ParsedBuildVersion, TEXT( "." ), false );
if (ParsedBuildVersion.Num() >= 3)
{
TTypeFromString<uint16>::FromString( Patch, *ParsedBuildVersion[2] );
}
if (ParsedBuildVersion.Num() >= 2)
{
TTypeFromString<uint16>::FromString( Minor, *ParsedBuildVersion[1] );
}
if (ParsedBuildVersion.Num() >= 1)
{
TTypeFromString<uint16>::FromString( Major, *ParsedBuildVersion[0] );
}
EngineVersion = FEngineVersion( Major, Minor, Patch, BuiltFromCL, BranchName );
}