📄 usetupdefinition.cpp
字号:
/*=============================================================================
USetupDefinition.cpp: Unreal installer/filer.
Copyright 1997-1999 Epic Games, Inc. All Rights Reserved.
Revision history:
* Created by Tim Sweeney.
=============================================================================*/
#include "SetupPrivate.h"
/*-----------------------------------------------------------------------------
Helper functions.
-----------------------------------------------------------------------------*/
// Text formatting.
inline const TCHAR* LineFormat( const TCHAR* In )
{
guard(LineFormat);
static TCHAR Result[4069];
TCHAR* Ptr = Result;
while( *In )
*Ptr++ = *In++!='\\' ? In[-1] : *In++=='n' ? '\n' : In[-1];
*Ptr++ = 0;
return Result;
unguard;
}
/*-----------------------------------------------------------------------------
USetupObject.
-----------------------------------------------------------------------------*/
IMPLEMENT_CLASS(USetupObject);
/*-----------------------------------------------------------------------------
USetupProduct.
-----------------------------------------------------------------------------*/
IMPLEMENT_CLASS(USetupProduct);
/*-----------------------------------------------------------------------------
USetupGroup.
-----------------------------------------------------------------------------*/
USetupGroup::USetupGroup()
: File(E_NoInit), Copy(E_NoInit), Group(E_NoInit), Folder(E_NoInit), Backup(E_NoInit), Delete(E_NoInit), Ini(E_NoInit), Requires(E_NoInit)
{
guard(USetupGroup::USetupGroup);
check(Manager);
if( Manager->Uninstalling )
{
Optional = 1;
Visible = 1;
Selected = 0;
}
for( TArray<FString>::TIterator It(Group); It; ++It )
{
Subgroups.AddItem( ConstructObject<USetupGroup>(GetClass(),GetOuter(),**It) );
}
unguard;
}
SQWORD USetupGroup::SpaceRequired()
{
guard(USetupGroup::SpaceRequired);
SQWORD Count=0;
if( Selected )
{
for( TArray<USetupGroup*>::TIterator ItG(Subgroups); ItG; ++ItG )
{
Count += (*ItG)->SpaceRequired();
}
for( TArray<FString>::TIterator ItF(File); ItF; ++ItF )
{
FFileInfo Info(*ItF);
if( Info.Lang==TEXT("") || Info.Lang==UObject::GetLanguage() )
Count += Info.Size + PER_FILE_OVERHEAD;
}
}
return Count;
unguard;
}
USetupDefinition* USetupGroup::Manager;
IMPLEMENT_CLASS(USetupGroup);
/*-----------------------------------------------------------------------------
USetupDefinition.
-----------------------------------------------------------------------------*/
USetupDefinition::USetupDefinition()
: ConfigFile ( MANIFEST_FILE )
, Requires ( E_NoInit )
{}
void USetupDefinition::Init()
{
guard(USetupDefinition::Init);
// Figure out source folder.
SrcPath = appBaseDir();
if( SrcPath.Right(1)==PATH_SEPARATOR )
SrcPath = SrcPath.LeftChop( 1 );
while( SrcPath.Len() && SrcPath.Right(1)!=PATH_SEPARATOR )
SrcPath = SrcPath.LeftChop( 1 );
if( SrcPath.Len() )
SrcPath = SrcPath.LeftChop( 1 );
// See if installing a packed .umod file.
FString Token;
const TCHAR* Cmd = appCmdLine();
ParseToken( Cmd, Token, 0 );
if( Token==TEXT("install") || (Token==TEXT("") && MasterProduct==TEXT("")) )
{
// Installing.
if( Token==TEXT("install") )
{
// Verify that the specified module exists.
ParseToken( Cmd, Token, 0 );
INT RealSize = GFileManager->FileSize(*Token);
if( RealSize<=0 )
appErrorf( TEXT("Can't find module %s"), *Token );
// Read the module's header.
FArchive* Ar = GFileManager->CreateFileReader(*Token);
check(Ar);
FArchiveHeader* Arc = new FArchiveHeader;
INT HeaderPos = Ar->TotalSize()-ARCHIVE_HEADER_SIZE;
Ar->Seek( HeaderPos );
*Ar << *Arc;
// Verify the module's correctness.
if( Ar->IsError() || Arc->Magic!=MOD_MAGIC || Arc->Ver!=ARCHIVE_VERSION || Arc->FileSize!=RealSize )
appErrorf( TEXT("The module %s is incomplete -- probably due to an incomplete or failed download"), *Token );
// Verify the module's CRC, unless we're an executable (in which case the sfx already did that).
if( Token.Right(4)!=TEXT(".exe") )
{
Ar->Seek( 0 );
INT CRC=0;
BYTE Buffer[16384];
for( INT i=0; i<HeaderPos; i+=sizeof(Buffer) )
{
INT Count = Min<INT>( HeaderPos-i, sizeof(Buffer) );
Ar->Serialize( Buffer, Count );
if( Ar->IsError() )
appErrorf( TEXT("The module %s can't be read"), *Token );
CRC = appMemCrc( Buffer, Count, CRC );
}
if( CRC!=Arc->CRC )
appErrorf( TEXT("The module %s is corrupt -- probably due to an incomplete or corrupt download"), *Token );
}
// Read the module's directory.
Ar->Seek( Arc->TableOffset );
*Ar << Arc->Items;
check(!Ar->IsError());
GFileManager = CreateFileManagerArc( GFileManager, *Token, Arc );
Token = TEXT("");
ParseToken( Cmd, Token, 0 );
// Reload config from the new filer manager.
GConfig->Flush(1,MANIFEST_FILE MANIFEST_EXT);
LoadConfig();
LoadLocalized();
}
// Detach configuration file so we can modify it locally.
GConfig->Detach( *ConfigFile );
Manifest = 1;
}
else if( Token==TEXT("reallyuninstall") )
{
// Running uninstaller from temp folder.
ParseToken( Cmd, Product, 0 );
Parse( appCmdLine(), TEXT("PATH="), DestPath );
if( DestPath.Right(1)==PATH_SEPARATOR )
DestPath = DestPath.LeftChop( 1 );
while( DestPath.Len() && DestPath.Right(1)!=PATH_SEPARATOR )
DestPath = DestPath.LeftChop( 1 );
Uninstalling = 1;
}
else if( Token==TEXT("uninstall") || (Token==TEXT("") && MasterProduct!=TEXT("")) )
{
// Running uninstaller for the first time.
NoRun = 1;
if( Token==TEXT("uninstall") )
ParseToken( Cmd, Product, 0 );
else
Product = MasterProduct;
PerformUninstallCopy();
}
else appErrorf(TEXT("Setup: Unknown disposition"));
// Validate everything.
if( !appAtoi(*Version) && !Uninstalling && !NoRun )
appErrorf( TEXT("Setup: Missing version number") );
// Determine whether known to be installed.
Exists
= GetRegisteredProductFolder( Product, RegistryFolder )
&& GFileManager->FileSize(*(RegistryFolder*TEXT("System")*SETUP_INI))>0;
// If this is a mod, find required product's path.
FolderExists = Exists;
if( !Exists && !Uninstalling && !NoRun )
{
FString RequiredProduct, FindFolder;
for( TArray<FString>::TIterator It(Requires); It; ++It )
if
( GConfig->GetString(**It, TEXT("Product"), RequiredProduct, *ConfigFile)
&& GetRegisteredProductFolder(RequiredProduct, FindFolder)
&& GFileManager->FileSize(*(FindFolder*TEXT("System")*SETUP_INI)) )
{
RegistryFolder = FindFolder;
FolderExists = 1;
break;
}
}
// Figure language.
FString Str;
if( GConfig->GetString(TEXT("Engine.Engine"),TEXT("Language"),Str,*(RegistryFolder*TEXT("System\\Default.ini"))) )
UObject::SetLanguage( *Str );
LanguageChange();
unguard;
}
void USetupDefinition::CreateRootGroup()
{
guard(USetupDefinition::CreateRootGroup);
USetupGroup::Manager = this;
RootGroup = new(GetOuter(),TEXT("Setup"))USetupGroup;
unguard;
}
void USetupDefinition::PerformUninstallCopy()
{
guard(USetupDefinition::PerformUninstallCopy);
unguard;
}
UBOOL USetupDefinition::GetRegisteredProductFolder( FString Product, FString& Folder )
{
guard(USetupDefinition::GetRegisteredProductFolder);
return 0;
unguard;
}
UBOOL USetupDefinition::LocateSourceFile( FString& Src )
{
guard(USetupDefinition::LocateSourceFile);
Src = FString(TEXT("..")) * Src;
return GFileManager->FileSize(*Src)>=0;
unguard;
}
void USetupDefinition::Reformat( FString& Msg, TMap<FString,FString>* Map )
{
if( Map )
Msg = appFormat( Msg, *Map );
}
FString USetupDefinition::Format( FString Msg, const TCHAR* Other )
{
guard(USetupDefinition::Format);
if( Manifest )
{
if( Other )
{
Reformat( Msg, GConfig->GetSectionPrivate(Other,0,1,*(FString(MANIFEST_FILE)+TEXT(".")+UObject::GetLanguage())) );
if( FString(UObject::GetLanguage())!=TEXT("INT") )
Reformat( Msg, GConfig->GetSectionPrivate(Other,0,1,*(FString(MANIFEST_FILE)+TEXT(".INT"))) );
}
Reformat( Msg, GConfig->GetSectionPrivate(TEXT("Setup" ),0,1,*(FString(MANIFEST_FILE)+TEXT(".")+UObject::GetLanguage())) );
Reformat( Msg, GConfig->GetSectionPrivate(TEXT("General"),0,1,*(FString(MANIFEST_FILE)+TEXT(".")+UObject::GetLanguage())) );
if( FString(UObject::GetLanguage())!=TEXT("INT") )
{
Reformat( Msg, GConfig->GetSectionPrivate(TEXT("Setup" ),0,1,*(FString(MANIFEST_FILE)+TEXT(".INT"))) );
Reformat( Msg, GConfig->GetSectionPrivate(TEXT("General"),0,1,*(FString(MANIFEST_FILE)+TEXT(".INT"))) );
}
Reformat( Msg, GConfig->GetSectionPrivate(TEXT("Setup"),0,1,*ConfigFile) );
}
return Msg;
unguard;
}
INT USetupDefinition::UpdateRefCount( const TCHAR* Key, const TCHAR* Value, INT Inc )
{
guard(USetupDefinition::UpdateRefCount);
// Increment reference count.
FString RefKey = FString(Key) + TEXT(":") + Value;
FString* CountPtr = RefCounts.Find( *RefKey );
if( CountPtr || Inc>0 )
{
INT Count = (CountPtr ? appAtoi(**CountPtr) : 0) + Inc;
if( Count>0 )
{
RefCounts.Set( *RefKey, *FString::Printf(TEXT("%i"),Count) );
}
else
{
RefCounts.Remove( *RefKey );
Count = 0;
}
return Count;
}
return 0;
unguard;
}
void USetupDefinition::UninstallLogAdd( const TCHAR* Key, const TCHAR* Value, UBOOL Unique, UBOOL RefLog )
{
guard(USetupDefinition::UninstallLogAdd);
// Find in uninstall log.
if( !RootGroup->UninstallLog.FindPair(Key,Value) )
{
// Add to uninstall log.
if( Unique )
RootGroup->UninstallLog.Set( Key, Value );
else
RootGroup->UninstallLog.Add( Key, Value );
if( RefLog )
UpdateRefCount( Key, Value, 1 );
}
unguard;
}
void USetupDefinition::LanguageChange()
{
guard(USetupDefinition::LanguageChange);
Super::LanguageChange();
if( !FolderExists )
RegistryFolder = DefaultFolder;
if( RegistryFolder.Right(1)==PATH_SEPARATOR )
RegistryFolder = RegistryFolder.LeftChop(1);
if( AutoplayWindowTitle==TEXT("") )
AutoplayWindowTitle = SetupWindowTitle;
unguard;
}
FString USetupDefinition::GetFullRef( const FString RefFile )
{
if( RefFile.Left(7)==FString(TEXT("System") PATH_SEPARATOR) )//oldver for Unreal 3dfx version, general multi-reference-path solution?
{
FString Test = RefPath * FString(TEXT("System200") PATH_SEPARATOR) + RefFile.Mid(7);
if( GFileManager->FileSize(*Test)>0 )
return Test;
}
return RefPath * RefFile;
}
void USetupDefinition::DidCancel()
{
guard(DidCancel);
appErrorf( LocalizeGeneral(TEXT("DidCancel"))), LocalizeGeneral(TEXT("InstallCancel") );
unguard;
}
void USetupDefinition::InstallTree( const TCHAR* Action, FInstallPoll* Poll, void (USetupDefinition::*Process)( FString Key, FString Value, UBOOL Selected, FInstallPoll* Poll ), USetupGroup* SetupGroup, UBOOL Selected )
{
guard(USetupDefinition::InstallTree);
if( !SetupGroup )
SetupGroup = RootGroup;
// Update selection status.
Selected = Selected && SetupGroup->Selected;
// Process this item.
(this->*Process)( TEXT("GroupSpecial"), SetupGroup->GetName(), Selected, Poll );
TMap<FString,FString>* Map = GConfig->GetSectionPrivate( SetupGroup->GetName(), 0, 1, *ConfigFile );
check(Map);
for( TMap<FString,FString>::TIterator It(*Map); It; ++It )
{
FString V = Format(It->Value);
(this->*Process)( It->Key, V, Selected, Poll );
}
// Handle all subgroups here.
for( TArray<USetupGroup*>::TIterator ItG(SetupGroup->Subgroups); ItG; ++ItG )
InstallTree( Action, Poll, Process, *ItG, Selected );
unguardf(( TEXT("(%s %s)"), Action, SetupGroup->GetFullName() ));
}
void USetupDefinition::UninstallTree( const TCHAR* Action, FInstallPoll* Poll, void (USetupDefinition::*Process)( FString Key, FString Value, FInstallPoll* Poll ) )
{
guard(USetupDefinition::UninstallTree);
for( TArray<USetupGroup*>::TIterator GroupIt(UninstallComponents); GroupIt; ++GroupIt )
{
for( TMap<FString,FString>::TIterator ItemIt((*GroupIt)->UninstallLog); ItemIt; ++ItemIt )
(this->*Process)( ItemIt->Key, ItemIt->Value, Poll );
}
unguard;
}
void USetupDefinition::SetupFormatStrings()
{
guard(USetupDefinition::SetupFormatStrings);
// Native wildcard strings.
GConfig->SetString( TEXT("Setup"), TEXT("SrcPath"), *SrcPath, *ConfigFile );
GConfig->SetString( TEXT("Setup"), TEXT("DestPath"), *DestPath, *ConfigFile );
GConfig->SetString( TEXT("Setup"), TEXT("RefPath"), *RefPath, *ConfigFile );
GConfig->SetString( TEXT("Setup"), TEXT("CdPath"), Patch ? *RefPath : *SrcPath, *ConfigFile );
unguard;
}
void USetupDefinition::BeginSteps()
{
guard(USetupDefinition::BeginSteps);
// Setup the format strings.
SetupFormatStrings();
// Empty saved .ini log.
SavedIni.Empty();
// Make .ini file.
SetupIniFile = DestPath * TEXT("System") * SETUP_INI;
// Load refcounts, if any.
TMap<FString,FString>* Map = GConfig->GetSectionPrivate( TEXT("RefCounts"), 0, 1, *SetupIniFile );
if( Map )
RefCounts = *Map;
// Load existing log, if any.
if( Uninstalling )//!!can merge?
{
for( TArray<USetupGroup*>::TIterator GroupIt(UninstallComponents); GroupIt; ++GroupIt )
{
TMap<FString,FString>* Map = GConfig->GetSectionPrivate( (*GroupIt)->GetName(), 0, 1, *SetupIniFile );
if( Map )
(*GroupIt)->UninstallLog = *Map;
}
}
else
{
TMap<FString,FString>* Map = GConfig->GetSectionPrivate( *Product, 0, 1, *SetupIniFile );
if( Map )
RootGroup->UninstallLog = *Map;
}
unguard;
}
void USetupDefinition::EndSteps()
{
guard(USetupDefinition::EndSteps);
// Update registry.
if( Uninstalling )
for( TArray<USetupGroup*>::TIterator GroupIt(UninstallComponents); GroupIt; ++GroupIt )
*GConfig->GetSectionPrivate( (*GroupIt)->GetName(), 1, 0, *SetupIniFile ) = (*GroupIt)->UninstallLog;
else//!!can merge?
*GConfig->GetSectionPrivate( *Product, 1, 0, *SetupIniFile ) = RootGroup->UninstallLog;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -