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]; } } RestartCommandLine = CommandLine.AsString(); 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; } }
FCrashDescription::FCrashDescription( FString WERXMLFilepath ) : // WER XML files are forced to be in the first version CrashDescriptionVersion( ECrashDescVersions::VER_1_NewCrashFormat ), BuiltFromCL( -1 ), TimeOfCrash( FDateTime::UtcNow() ), bHasMiniDumpFile( false ), bHasLogFile( false ), bHasVideoFile( false ), bHasCompleteData( false ) { InitializeIDs(); // This is for the current system that uses files from Windows Error Reporting. // Will be replaced with the unified version soon. FXmlFile XmlFile( WERXMLFilepath ); ReportName = FPaths::GetPath( WERXMLFilepath ); FPaths::NormalizeDirectoryName( ReportName ); // Grab the last component... ReportName = FPaths::GetCleanFilename( ReportName ); const bool bIsValid = XmlFile.IsValid(); if( bIsValid ) { const FXmlNode* OSVersionInformationNode = XmlFile.GetRootNode()->FindChildNode( TEXT( "OSVersionInformation" ) ); const FXmlNode* ProblemSignaturesNode = XmlFile.GetRootNode()->FindChildNode( TEXT( "ProblemSignatures" ) ); const FXmlNode* DynamicSignaturesNode = XmlFile.GetRootNode()->FindChildNode( TEXT( "DynamicSignatures" ) ); FString Product; int EngineVersionComponents = 0; if( OSVersionInformationNode ) { const FXmlNode* ProductNode = OSVersionInformationNode->FindChildNode( TEXT( "Product" ) ); if( ProductNode ) { Product = ProductNode->GetContent(); } } if( ProblemSignaturesNode ) { const FXmlNode* GameNameNode = ProblemSignaturesNode->FindChildNode( TEXT( "Parameter0" ) ); if( GameNameNode ) { GameName = GameNameNode->GetContent(); } const FXmlNode* BuildVersionNode = ProblemSignaturesNode->FindChildNode( TEXT( "Parameter1" ) ); if( BuildVersionNode ) { BuildVersion = BuildVersionNode->GetContent(); EngineVersionComponents++; } const FXmlNode* Parameter8Node = ProblemSignaturesNode->FindChildNode( TEXT( "Parameter8" ) ); if( Parameter8Node ) { const FString Parameter8Value = Parameter8Node->GetContent(); TArray<FString> ParsedParameters8; Parameter8Value.ParseIntoArray( ParsedParameters8, TEXT( "!" ), false ); if( ParsedParameters8.Num() > 1 ) { CommandLine = UnescapeXMLString( ParsedParameters8[1] ); } if( ParsedParameters8.Num() > 2 ) { ErrorMessage.Add( ParsedParameters8[2] ); } } const FXmlNode* Parameter9Node = ProblemSignaturesNode->FindChildNode( TEXT( "Parameter9" ) ); if( Parameter9Node ) { const FString Parameter9Value = Parameter9Node->GetContent(); 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(""); if( Product.Len() > 0 ) { Platform = FString::Printf( TEXT( "%s [%s]" ), *PlatformName, *Product ); } else { Platform = PlatformName; } } if( ParsedParameters9.Num() > 2 ) { EngineMode = ParsedParameters9[2]; } if( ParsedParameters9.Num() > 3 ) { TTypeFromString<uint32>::FromString( BuiltFromCL, *ParsedParameters9[3] ); EngineVersionComponents++; } } } if( DynamicSignaturesNode ) { const FXmlNode* LanguageNode = DynamicSignaturesNode->FindChildNode( TEXT( "Parameter2" ) ); if( LanguageNode ) { LanguageLCID = LanguageNode->GetContent(); } } // We have all three components of the engine version, so initialize it. if( EngineVersionComponents == 3 ) { InitializeEngineVersion(); } bHasCompleteData = true; } else { bHasCompleteData = false; } }