Files
UnrealEngineUWP/Engine/Source/Programs/Windows/BootstrapPackagedGame/Private/BootstrapPackagedGame.cpp
Ben Marsh 92ec2b8239 Copying //UE4/Dev-Build to Dev-Main (//UE4/Dev-Main)
==========================
MAJOR FEATURES + CHANGES
==========================

Change 2718441 on 2015/10/06 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Allow nodes to be added with an "explicit" frequency, meaning that they'll only be part of manually triggered builds (not CIS).

Change 2718698 on 2015/10/06 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Add a type of node that can execute an arbitrary sequence of tasks, and allow constructing graphs of such nodes from an XML file.

Change 2723013 on 2015/10/09 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Small utility to quickly capture a workspace, or delete files to restore the workspace to a previously captured state (and output a p4 sync list to restore it)

Change 2744521 on 2015/10/28 by Matthew.Griffin@Matthew.Griffin_G5772_BuildStream

	Adding config entries to determine which platforms/configurations are available

	Currently only written out as part of the Rocket Build process but could be done elsewhere for other types of installed build.

	A near identical singleton class is used in both C++ and C# to load the config section and check whether configuration/platform combinations are valid.

Change 2773723 on 2015/11/19 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Copying UnrealGameSync into Engine/Source/Programs.

Change 2773914 on 2015/11/19 by Ben.Marsh@Ben.Marsh_T3245_Stream

	PR #1687: [GitDependencies] New feature: ignore file support (.gitdepsignore) (Contributed by nbjk667)

Change 2775317 on 2015/11/20 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Add a -listtps option to UBT, which will find all the TPS files in any directory that's compiled into a target.

Change 2780832 on 2015/11/25 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Allow compiling a single file in UBT. Pass -singlefile=<Path> on command line to UBT to use.

Change 2781071 on 2015/11/25 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Precompile all valid engine modules for Rocket by default. Modules may set the PrecompileForTargets field to control which configurations they should be compiled for. Modules which currently fail to compile have this set to
PrecompileTargetsType.None.

	#codereview Matthew.Griffin

Change 2784469 on 2015/12/01 by Matthew.Griffin@Matthew.Griffin_G5772_BuildStream

	Added -FastPDB commandline parameter for UBT, so that we can make use of the /DEBUG:FASTLINK option in VS2015

Change 2784722 on 2015/12/01 by Matthew.Griffin@Matthew.Griffin_G5772_BuildStream

	Made -FastPDB option part of BuildConfiguration instead of checking commandline at each place it's used. Also added option to override if someone doesn't want it automatically added to their project files.

Change 2787501 on 2015/12/02 by Ben.Marsh@Ben.Marsh_T3245_Stream

	Restore change to gather VC environment directly from registry.

#lockdown Nick.Penwarden

[CL 2790002 by Ben Marsh in Main branch]
2015-12-04 09:32:58 -05:00

176 lines
5.1 KiB
C++

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#include "BootstrapPackagedGame.h"
#define IDI_EXEC_FILE 201
#define IDI_EXEC_ARGS 202
WCHAR* ReadResourceString(HMODULE ModuleHandle, LPCWSTR Name)
{
WCHAR* Result = NULL;
HRSRC ResourceHandle = FindResource(ModuleHandle, Name, RT_RCDATA);
if(ResourceHandle != NULL)
{
HGLOBAL AllocHandle = LoadResource(ModuleHandle, ResourceHandle);
if(AllocHandle != NULL)
{
WCHAR* Data = (WCHAR*)LockResource(AllocHandle);
DWORD DataLen = SizeofResource(ModuleHandle, ResourceHandle) / sizeof(WCHAR);
Result = new WCHAR[DataLen + 1];
memcpy(Result, Data, DataLen * sizeof(WCHAR));
Result[DataLen] = 0;
}
}
return Result;
}
int InstallMissingPrerequisites(const WCHAR* BaseDirectory)
{
// Look for missing prerequisites
WCHAR MissingPrerequisites[1024] = { 0, };
if(LoadLibrary(L"MSVCP120.DLL") == NULL || LoadLibrary(L"MSVCR120.DLL") == NULL)
{
wcscat_s(MissingPrerequisites, TEXT("Microsoft Visual C++ 2013 Runtime\n"));
}
if(LoadLibrary(L"MSVCP140.DLL") == NULL || LoadLibrary(L"ucrtbase.dll") == NULL)
{
wcscat_s(MissingPrerequisites, TEXT("Microsoft Visual C++ 2015 Runtime\n"));
}
if(LoadLibrary(L"XINPUT1_3.DLL") == NULL)
{
wcscat_s(MissingPrerequisites, TEXT("DirectX Runtime\n"));
}
// Check if there's anything missing
if(MissingPrerequisites[0] != 0)
{
WCHAR MissingPrerequisitesMsg[1024];
wsprintf(MissingPrerequisitesMsg, L"The following component(s) are required to run this program:\n\n%s", MissingPrerequisites);
// If we don't have the installer, just notify the user and quit
WCHAR PrereqInstaller[MAX_PATH];
#ifdef _M_X64
PathCombine(PrereqInstaller, BaseDirectory, L"Engine\\Extras\\Redist\\en-us\\UE4PrereqSetup_x64.exe");
#else
PathCombine(PrereqInstaller, BaseDirectory, L"Engine\\Extras\\Redist\\en-us\\UE4PrereqSetup_x86.exe");
#endif
if(GetFileAttributes(PrereqInstaller) == INVALID_FILE_ATTRIBUTES)
{
MessageBox(NULL, MissingPrerequisitesMsg, NULL, MB_OK);
return 9001;
}
// Otherwise ask them if they want to install them
wcscat_s(MissingPrerequisitesMsg, L"\nWould you like to install them now?");
if(MessageBox(NULL, MissingPrerequisitesMsg, NULL, MB_YESNO) == IDNO)
{
return 9002;
}
// Start the installer
SHELLEXECUTEINFO ShellExecuteInfo;
ZeroMemory(&ShellExecuteInfo, sizeof(ShellExecuteInfo));
ShellExecuteInfo.cbSize = sizeof(ShellExecuteInfo);
ShellExecuteInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShellExecuteInfo.nShow = SW_SHOWNORMAL;
ShellExecuteInfo.lpFile = PrereqInstaller;
if(!ShellExecuteExW(&ShellExecuteInfo))
{
return 9003;
}
// Wait for the process to complete, then get its exit code
DWORD ExitCode = 0;
WaitForSingleObject(ShellExecuteInfo.hProcess, INFINITE);
GetExitCodeProcess(ShellExecuteInfo.hProcess, &ExitCode);
CloseHandle(ShellExecuteInfo.hProcess);
if(ExitCode != 0)
{
return 9004;
}
}
return 0;
}
int SpawnTarget(WCHAR* CmdLine)
{
STARTUPINFO StartupInfo;
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
PROCESS_INFORMATION ProcessInfo;
ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
if(!CreateProcess(NULL, CmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
{
DWORD ErrorCode = GetLastError();
WCHAR* Buffer = new WCHAR[wcslen(CmdLine) + 50];
wsprintf(Buffer, L"Couldn't start:\n%s\nCreateProcess() returned %x.", CmdLine, ErrorCode);
MessageBoxW(NULL, Buffer, NULL, MB_OK);
delete Buffer;
return 9005;
}
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
DWORD ExitCode = 9006;
GetExitCodeProcess(ProcessInfo.hProcess, &ExitCode);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
return (int)ExitCode;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, TCHAR* CmdLine, int ShowCmd)
{
(void)hPrevInstance;
(void)ShowCmd;
// Get the current module filename
WCHAR CurrentModuleFile[MAX_PATH];
GetModuleFileNameW(hInstance, CurrentModuleFile, sizeof(CurrentModuleFile));
// Get the base directory from the current module filename
WCHAR BaseDirectory[MAX_PATH];
PathCanonicalize(BaseDirectory, CurrentModuleFile);
PathRemoveFileSpec(BaseDirectory);
// Get the executable to run
WCHAR* ExecFile = ReadResourceString(hInstance, MAKEINTRESOURCE(IDI_EXEC_FILE));
if(ExecFile == NULL)
{
MessageBoxW(NULL, L"This program is used for packaged games and is not meant to be run directly.", NULL, MB_OK);
return 9000;
}
// Create a full command line for the program to run
WCHAR* BaseArgs = ReadResourceString(hInstance, MAKEINTRESOURCE(IDI_EXEC_ARGS));
WCHAR* ChildCmdLine = new WCHAR[wcslen(BaseDirectory) + wcslen(ExecFile) + wcslen(BaseArgs) + wcslen(CmdLine) + 20];
wsprintf(ChildCmdLine, L"\"%s\\%s\" %s %s", BaseDirectory, ExecFile, BaseArgs, CmdLine);
delete BaseArgs;
delete ExecFile;
// Install the prerequisites
int ExitCode = InstallMissingPrerequisites(BaseDirectory);
if(ExitCode != 0)
{
delete ChildCmdLine;
return ExitCode;
}
// Spawn the target executable
ExitCode = SpawnTarget(ChildCmdLine);
if(ExitCode != 0)
{
delete ChildCmdLine;
return ExitCode;
}
delete ChildCmdLine;
return ExitCode;
}