You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Merging Live++ 1.5.0
#rb none #rnx [CL 7277271 by Ben Marsh in Dev-Build branch]
This commit is contained in:
@@ -0,0 +1,231 @@
|
||||
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
|
||||
|
||||
#include "LC_API.h"
|
||||
#include "LC_ClientStartupThread.h"
|
||||
#include "LC_CriticalSection.h"
|
||||
#include "LC_SyncPoint.h"
|
||||
#include "LC_Restart.h"
|
||||
#include "LC_RunMode.h"
|
||||
#include "LC_Logging.h"
|
||||
#include "LPP_API.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
// startup thread
|
||||
static ClientStartupThread* g_startupThread = nullptr;
|
||||
|
||||
// critical section to ensure that startup thread is initialized only once
|
||||
static CriticalSection g_ensureOneTimeStartup;
|
||||
|
||||
// default run mode
|
||||
static RunMode::Enum g_runMode = RunMode::DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
void api::Startup(ClientStartupThread* startupThread)
|
||||
{
|
||||
g_startupThread = startupThread;
|
||||
restart::Startup();
|
||||
}
|
||||
|
||||
|
||||
void api::Shutdown(void)
|
||||
{
|
||||
restart::Shutdown();
|
||||
g_startupThread = nullptr;
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(const char*) LppGetVersion(void)
|
||||
{
|
||||
return LPP_VERSION;
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(int) LppCheckVersion(const char* apiVersion)
|
||||
{
|
||||
if (strcmp(apiVersion, LPP_VERSION) == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
LC_ERROR_USER("Version mismatch detected. API version: %s, DLL version: %s", LPP_VERSION, apiVersion);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppRegisterProcessGroup(const char* groupName)
|
||||
{
|
||||
// now that we have the process group name, start Live++.
|
||||
// ensure that initialization can happen only once, even if the user calls this more than once.
|
||||
{
|
||||
CriticalSection::ScopedLock lock(&g_ensureOneTimeStartup);
|
||||
|
||||
static bool firstTime = true;
|
||||
if (!firstTime)
|
||||
{
|
||||
// this was already called once, bail out
|
||||
return;
|
||||
}
|
||||
|
||||
firstTime = false;
|
||||
}
|
||||
|
||||
g_startupThread->Start(groupName, g_runMode);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppSyncPoint(void)
|
||||
{
|
||||
syncPoint::EnterTarget();
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppWaitForToken(void* token)
|
||||
{
|
||||
if (!token)
|
||||
{
|
||||
// nullptr tokens are returned by Live++ when trying to enable modules which are not loaded into the host process.
|
||||
// therefore, we need to handle this case gracefully.
|
||||
return;
|
||||
}
|
||||
|
||||
g_startupThread->WaitForToken(token);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppTriggerRecompile(void)
|
||||
{
|
||||
g_startupThread->TriggerRecompile();
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppLogMessage(const wchar_t* message)
|
||||
{
|
||||
g_startupThread->LogMessage(message);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppBuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count)
|
||||
{
|
||||
g_startupThread->BuildPatch(moduleNames, objPaths, amalgamatedObjPaths, count);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppInstallExceptionHandler(void)
|
||||
{
|
||||
g_startupThread->InstallExceptionHandler();
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppUseExternalBuildSystem(void)
|
||||
{
|
||||
g_runMode = RunMode::EXTERNAL_BUILD_SYSTEM;
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(int) LppWantsRestart(void)
|
||||
{
|
||||
return restart::WasRequested();
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppRestart(lpp::RestartBehaviour behaviour, unsigned int exitCode)
|
||||
{
|
||||
restart::Execute(behaviour, exitCode);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void*) LppEnableModule(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
return g_startupThread->EnableModule(nameOfExeOrDll);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void*) LppEnableModules(const wchar_t* namesOfExeOrDll[], unsigned int count)
|
||||
{
|
||||
return g_startupThread->EnableModules(namesOfExeOrDll, count);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void*) LppEnableAllModules(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
return g_startupThread->EnableAllModules(nameOfExeOrDll);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void*) LppDisableModule(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
return g_startupThread->DisableModule(nameOfExeOrDll);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void*) LppDisableModules(const wchar_t* namesOfExeOrDll[], unsigned int count)
|
||||
{
|
||||
return g_startupThread->DisableModules(namesOfExeOrDll, count);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void*) LppDisableAllModules(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
return g_startupThread->DisableAllModules(nameOfExeOrDll);
|
||||
}
|
||||
|
||||
|
||||
// BEGIN EPIC MOD - Adding ShowConsole command
|
||||
LPP_DLL_API(void) LppShowConsole()
|
||||
{
|
||||
g_startupThread->ShowConsole();
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
|
||||
// BEGIN EPIC MOD - Adding SetVisible command
|
||||
LPP_DLL_API(void) LppSetVisible(bool visible)
|
||||
{
|
||||
g_startupThread->SetVisible(visible);
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
|
||||
|
||||
// BEGIN EPIC MOD - Adding SetActive command
|
||||
LPP_DLL_API(void) LppSetActive(bool active)
|
||||
{
|
||||
g_startupThread->SetActive(active);
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
|
||||
// BEGIN EPIC MOD - Adding SetBuildArguments command
|
||||
LPP_DLL_API(void) LppSetBuildArguments(const wchar_t* arguments)
|
||||
{
|
||||
g_startupThread->SetBuildArguments(arguments);
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
// BEGIN EPIC MOD - Support for lazy-loading modules
|
||||
LPP_DLL_API(void) LppEnableLazyLoadedModule(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
HMODULE baseAddress = GetModuleHandle(nameOfExeOrDll);
|
||||
g_startupThread->EnableLazyLoadedModule(nameOfExeOrDll, baseAddress);
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppApplySettingBool(const char* settingName, int value)
|
||||
{
|
||||
g_startupThread->ApplySettingBool(settingName, value);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppApplySettingInt(const char* settingName, int value)
|
||||
{
|
||||
g_startupThread->ApplySettingInt(settingName, value);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API(void) LppApplySettingString(const char* settingName, const wchar_t* value)
|
||||
{
|
||||
g_startupThread->ApplySettingString(settingName, value);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LPP_API.h"
|
||||
|
||||
class ClientStartupThread;
|
||||
|
||||
|
||||
// internal API, initialized by entryPoint
|
||||
namespace api
|
||||
{
|
||||
void Startup(ClientStartupThread* startupThread);
|
||||
void Shutdown(void);
|
||||
}
|
||||
|
||||
|
||||
// external Live++ API exported into DLL
|
||||
// BEGIN EPIC MOD - Internalizing API
|
||||
#define LPP_DLL_API(_rv) _rv __cdecl
|
||||
//#define LPP_DLL_API(_rv) extern "C" __declspec(dllexport) _rv __cdecl
|
||||
// END EPIC MOD - Internalizing API
|
||||
|
||||
LPP_DLL_API(const char*) LppGetVersion(void);
|
||||
LPP_DLL_API(int) LppCheckVersion(const char* apiVersion);
|
||||
LPP_DLL_API(void) LppRegisterProcessGroup(const char* groupName);
|
||||
LPP_DLL_API(void) LppSyncPoint(void);
|
||||
LPP_DLL_API(void) LppWaitForToken(void* token);
|
||||
LPP_DLL_API(void) LppTriggerRecompile(void);
|
||||
LPP_DLL_API(void) LppLogMessage(const wchar_t* message);
|
||||
LPP_DLL_API(void) LppBuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count);
|
||||
LPP_DLL_API(void) LppInstallExceptionHandler(void);
|
||||
LPP_DLL_API(void) LppUseExternalBuildSystem(void);
|
||||
LPP_DLL_API(int) LppWantsRestart(void);
|
||||
LPP_DLL_API(void) LppRestart(lpp::RestartBehaviour behaviour, unsigned int exitCode);
|
||||
LPP_DLL_API(void*) LppEnableModule(const wchar_t* nameOfExeOrDll);
|
||||
LPP_DLL_API(void*) LppEnableModules(const wchar_t* namesOfExeOrDll[], unsigned int count);
|
||||
LPP_DLL_API(void*) LppEnableAllModules(const wchar_t* nameOfExeOrDll);
|
||||
LPP_DLL_API(void*) LppDisableModule(const wchar_t* nameOfExeOrDll);
|
||||
LPP_DLL_API(void*) LppDisableModules(const wchar_t* namesOfExeOrDll[], unsigned int count);
|
||||
LPP_DLL_API(void*) LppDisableAllModules(const wchar_t* nameOfExeOrDll);
|
||||
LPP_DLL_API(void) LppApplySettingBool(const char* settingName, int value);
|
||||
LPP_DLL_API(void) LppApplySettingInt(const char* settingName, int value);
|
||||
LPP_DLL_API(void) LppApplySettingString(const char* settingName, const wchar_t* value);
|
||||
+56
-1
@@ -12,6 +12,8 @@
|
||||
#include "LC_Event.h"
|
||||
#include "LC_CriticalSection.h"
|
||||
#include "LC_PrimitiveNames.h"
|
||||
#include "LC_Environment.h"
|
||||
#include "LC_MemoryStream.h"
|
||||
#include "LC_Logging.h"
|
||||
#include "Misc/Paths.h"
|
||||
#include "Misc/ConfigCacheIni.h"
|
||||
@@ -237,6 +239,18 @@ void ClientStartupThread::TriggerRecompile(void)
|
||||
}
|
||||
|
||||
|
||||
void ClientStartupThread::LogMessage(const wchar_t* message)
|
||||
{
|
||||
// wait for the startup thread to finish initialization
|
||||
Join();
|
||||
|
||||
if (m_userCommandThread)
|
||||
{
|
||||
m_userCommandThread->LogMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ClientStartupThread::BuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count)
|
||||
{
|
||||
// wait for the startup thread to finish initialization
|
||||
@@ -488,7 +502,48 @@ unsigned int ClientStartupThread::ThreadFunction(const std::wstring& processGrou
|
||||
m_userCommandThread->Start(processGroupName, m_startEvent, m_pipeClientCS);
|
||||
|
||||
// register this process with Live++
|
||||
m_pipeClient->SendCommandAndWaitForAck(commands::RegisterProcess { process::GetBase(), process::GetId(), commandThreadId, &JumpToSelf }, nullptr, 0u);
|
||||
{
|
||||
// try getting the previous process ID from the environment in case the process was restarted
|
||||
unsigned int restartedProcessId = 0u;
|
||||
const std::wstring& processIdStr = environment::GetVariable(L"LPP_PROCESS_RESTART_ID", nullptr);
|
||||
if (processIdStr.length() != 0u)
|
||||
{
|
||||
restartedProcessId = static_cast<unsigned int>(std::stoi(processIdStr));
|
||||
environment::RemoveVariable(L"LPP_PROCESS_RESTART_ID");
|
||||
}
|
||||
|
||||
// store the current process ID in an environment variable.
|
||||
// upon restart, the environment block is inherited by the new process and can be used to map the process IDs of
|
||||
// restarted processes to their previous IDs.
|
||||
{
|
||||
const unsigned int processID = process::GetId();
|
||||
environment::SetVariable(L"LPP_PROCESS_RESTART_ID", std::to_wstring(processID).c_str());
|
||||
}
|
||||
|
||||
const std::wstring& imagePath = process::GetImagePath();
|
||||
const std::wstring& commandLine = process::GetCommandLine();
|
||||
const std::wstring& workingDirectory = process::GetWorkingDirectory();
|
||||
process::Environment* environment = process::CreateEnvironment(::GetCurrentProcess());
|
||||
|
||||
const commands::RegisterProcess command =
|
||||
{
|
||||
process::GetBase(), process::GetId(), restartedProcessId, commandThreadId, &JumpToSelf,
|
||||
(imagePath.size() + 1u) * sizeof(wchar_t),
|
||||
(commandLine.size() + 1u) * sizeof(wchar_t),
|
||||
(workingDirectory.size() + 1u) * sizeof(wchar_t),
|
||||
environment->size
|
||||
};
|
||||
|
||||
memoryStream::Writer payload(command.imagePathSize + command.commandLineSize + command.workingDirectorySize + command.environmentSize);
|
||||
payload.Write(imagePath.data(), command.imagePathSize);
|
||||
payload.Write(commandLine.data(), command.commandLineSize);
|
||||
payload.Write(workingDirectory.data(), command.workingDirectorySize);
|
||||
payload.Write(environment->data, environment->size);
|
||||
|
||||
m_pipeClient->SendCommandAndWaitForAck(command, payload.GetData(), payload.GetSize());
|
||||
|
||||
process::DestroyEnvironment(environment);
|
||||
}
|
||||
|
||||
// handle commands until registration is finished
|
||||
{
|
||||
|
||||
+1
@@ -37,6 +37,7 @@ public:
|
||||
|
||||
void WaitForToken(void* token);
|
||||
void TriggerRecompile(void);
|
||||
void LogMessage(const wchar_t* message);
|
||||
void BuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count);
|
||||
|
||||
void InstallExceptionHandler(void);
|
||||
|
||||
+12
@@ -361,6 +361,18 @@ void ClientUserCommandThread::TriggerRecompile(void)
|
||||
}
|
||||
|
||||
|
||||
void ClientUserCommandThread::LogMessage(const wchar_t* message)
|
||||
{
|
||||
const size_t lengthWithoutNull = wcslen(message);
|
||||
const size_t payloadSize = sizeof(wchar_t) * (lengthWithoutNull + 1u);
|
||||
|
||||
ProxyCommand<commands::LogMessage>* proxy = new ProxyCommand<commands::LogMessage>(false, payloadSize);
|
||||
proxy->m_payload.Write(message, payloadSize);
|
||||
|
||||
PushUserCommand(proxy);
|
||||
}
|
||||
|
||||
|
||||
void ClientUserCommandThread::BuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count)
|
||||
{
|
||||
const size_t perFileSize = sizeof(wchar_t) * MAX_PATH * 3u;
|
||||
|
||||
+1
@@ -60,6 +60,7 @@ public:
|
||||
|
||||
void WaitForToken(void* token);
|
||||
void TriggerRecompile(void);
|
||||
void LogMessage(const wchar_t* message);
|
||||
void BuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count);
|
||||
|
||||
// BEGIN EPIC MOD - Adding ShowConsole command
|
||||
|
||||
@@ -55,6 +55,7 @@ CommandMap::CommandMap(void)
|
||||
RegisterDefaultAction<commands::CompilationFinished>(m_actions);
|
||||
RegisterDefaultAction<commands::DisconnectClient>(m_actions);
|
||||
RegisterDefaultAction<commands::TriggerRecompile>(m_actions);
|
||||
RegisterDefaultAction<commands::LogMessage>(m_actions);
|
||||
RegisterDefaultAction<commands::BuildPatch>(m_actions);
|
||||
RegisterDefaultAction<commands::HandleException>(m_actions);
|
||||
RegisterDefaultAction<commands::HandleExceptionFinished>(m_actions);
|
||||
|
||||
@@ -37,9 +37,17 @@ namespace commands
|
||||
static const uint32_t ID = Acknowledge::ID + 1u;
|
||||
|
||||
void* processBase;
|
||||
unsigned int processId;
|
||||
unsigned int threadId; // thread ID of Live++ thread running in host
|
||||
const void* jumpToSelf; // address of jump-to-self instruction in host
|
||||
unsigned int processId; // current process ID
|
||||
unsigned int restartedProcessId; // process ID of the previous, restarted process. 0 if non-existent
|
||||
unsigned int threadId; // thread ID of Live++ thread running in host
|
||||
const void* jumpToSelf; // address of jump-to-self instruction in host
|
||||
|
||||
size_t imagePathSize;
|
||||
size_t commandLineSize;
|
||||
size_t workingDirectorySize;
|
||||
size_t environmentSize;
|
||||
|
||||
// image path, command line, working directory and environment follow as payload
|
||||
};
|
||||
|
||||
// tell the DLL that registration has finished
|
||||
@@ -175,10 +183,16 @@ namespace commands
|
||||
static const uint32_t ID = DisconnectClient::ID + 1u;
|
||||
};
|
||||
|
||||
// tell Live++ to log a message
|
||||
struct LogMessage
|
||||
{
|
||||
static const uint32_t ID = TriggerRecompile::ID + 1u;
|
||||
};
|
||||
|
||||
// tell Live++ to build a patch using an array of object files
|
||||
struct BuildPatch
|
||||
{
|
||||
static const uint32_t ID = TriggerRecompile::ID + 1u;
|
||||
static const uint32_t ID = LogMessage::ID + 1u;
|
||||
|
||||
unsigned int fileCount;
|
||||
|
||||
|
||||
+6
-183
@@ -2,20 +2,13 @@
|
||||
|
||||
#include "LC_EntryPoint.h"
|
||||
#include "LC_ClientStartupThread.h"
|
||||
#include "LC_CriticalSection.h"
|
||||
#include "LC_RunMode.h"
|
||||
#include "LPP_API.h"
|
||||
#include "LC_API.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// startup thread. initialized when LppRegisterProcessGroup is called
|
||||
// startup thread
|
||||
static ClientStartupThread* g_startupThread = nullptr;
|
||||
|
||||
// critical section to ensure that startup thread is initialized only once
|
||||
static CriticalSection g_ensureOneTimeStartup;
|
||||
|
||||
static RunMode::Enum g_runMode = RunMode::DEFAULT;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +16,14 @@ namespace
|
||||
void Startup(HINSTANCE instance)
|
||||
{
|
||||
g_startupThread = new ClientStartupThread(instance);
|
||||
api::Startup(g_startupThread);
|
||||
}
|
||||
|
||||
|
||||
void Shutdown(void)
|
||||
{
|
||||
api::Shutdown();
|
||||
|
||||
// wait for the startup thread to finish its work and clean up
|
||||
g_startupThread->Join();
|
||||
delete g_startupThread;
|
||||
@@ -51,179 +47,6 @@ BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD dwReason, _In_ LPVOID /*
|
||||
break;
|
||||
}
|
||||
|
||||
return Windows::TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
// END EPIC MOD
|
||||
|
||||
|
||||
// exported Live++ API
|
||||
// BEGIN EPIC MOD - Internalizing API
|
||||
#define LPP_DLL_API
|
||||
//#define LPP_DLL_API extern "C" __declspec(dllexport)
|
||||
// END EPIC MOD - Internalizing API
|
||||
|
||||
|
||||
LPP_DLL_API void __cdecl LppRegisterProcessGroup(const char* groupName)
|
||||
{
|
||||
// now that we have the process group name, start Live++.
|
||||
// ensure that initialization can happen only once, even if the user calls this more than once.
|
||||
{
|
||||
CriticalSection::ScopedLock lock(&g_ensureOneTimeStartup);
|
||||
|
||||
static bool firstTime = true;
|
||||
if (!firstTime)
|
||||
{
|
||||
// this was already called once, bail out
|
||||
return;
|
||||
}
|
||||
|
||||
firstTime = false;
|
||||
}
|
||||
|
||||
g_startupThread->Start(groupName, g_runMode);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void* __cdecl LppEnableModule(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
// hand command creation to the user command thread
|
||||
return g_startupThread->EnableModule(nameOfExeOrDll);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void* __cdecl LppEnableModules(const wchar_t* namesOfExeOrDll[], unsigned int count)
|
||||
{
|
||||
// hand command creation to the user command thread
|
||||
return g_startupThread->EnableModules(namesOfExeOrDll, count);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void* __cdecl LppEnableAllModules(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
// hand command creation to the user command thread
|
||||
return g_startupThread->EnableAllModules(nameOfExeOrDll);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void* __cdecl LppDisableModule(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
// hand command creation to the user command thread
|
||||
return g_startupThread->DisableModule(nameOfExeOrDll);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void* __cdecl LppDisableModules(const wchar_t* namesOfExeOrDll[], unsigned int count)
|
||||
{
|
||||
// hand command creation to the user command thread
|
||||
return g_startupThread->DisableModules(namesOfExeOrDll, count);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void* __cdecl LppDisableAllModules(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
// hand command creation to the user command thread
|
||||
return g_startupThread->DisableAllModules(nameOfExeOrDll);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void __cdecl LppWaitForToken(void* token)
|
||||
{
|
||||
if (!token)
|
||||
{
|
||||
// nullptr tokens are returned by Live++ when trying to enable modules which are not loaded into the host process.
|
||||
// therefore, we need to handle this case gracefully.
|
||||
return;
|
||||
}
|
||||
|
||||
g_startupThread->WaitForToken(token);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void __cdecl LppTriggerRecompile(void)
|
||||
{
|
||||
g_startupThread->TriggerRecompile();
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void __cdecl LppBuildPatch(const wchar_t* moduleNames[], const wchar_t* objPaths[], const wchar_t* amalgamatedObjPaths[], unsigned int count)
|
||||
{
|
||||
g_startupThread->BuildPatch(moduleNames, objPaths, amalgamatedObjPaths, count);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void __cdecl LppInstallExceptionHandler(void)
|
||||
{
|
||||
g_startupThread->InstallExceptionHandler();
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void __cdecl LppUseExternalBuildSystem(void)
|
||||
{
|
||||
g_runMode = RunMode::EXTERNAL_BUILD_SYSTEM;
|
||||
}
|
||||
|
||||
|
||||
// BEGIN EPIC MOD - Adding ShowConsole command
|
||||
LPP_DLL_API void __cdecl LppShowConsole()
|
||||
{
|
||||
g_startupThread->ShowConsole();
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
|
||||
// BEGIN EPIC MOD - Adding SetVisible command
|
||||
LPP_DLL_API void __cdecl LppSetVisible(bool visible)
|
||||
{
|
||||
g_startupThread->SetVisible(visible);
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
|
||||
|
||||
// BEGIN EPIC MOD - Adding SetActive command
|
||||
LPP_DLL_API void __cdecl LppSetActive(bool active)
|
||||
{
|
||||
g_startupThread->SetActive(active);
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
|
||||
// BEGIN EPIC MOD - Adding SetBuildArguments command
|
||||
LPP_DLL_API void __cdecl LppSetBuildArguments(const wchar_t* arguments)
|
||||
{
|
||||
g_startupThread->SetBuildArguments(arguments);
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
// BEGIN EPIC MOD - Support for lazy-loading modules
|
||||
LPP_DLL_API void __cdecl LppEnableLazyLoadedModule(const wchar_t* nameOfExeOrDll)
|
||||
{
|
||||
HMODULE baseAddress = GetModuleHandle(nameOfExeOrDll);
|
||||
g_startupThread->EnableLazyLoadedModule(nameOfExeOrDll, baseAddress);
|
||||
}
|
||||
// END EPIC MOD
|
||||
|
||||
|
||||
LPP_DLL_API void __cdecl LppApplySettingBool(const char* settingName, int value)
|
||||
{
|
||||
// hand command creation to the user command thread
|
||||
g_startupThread->ApplySettingBool(settingName, value);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void __cdecl LppApplySettingInt(const char* settingName, int value)
|
||||
{
|
||||
// hand command creation to the user command thread
|
||||
g_startupThread->ApplySettingInt(settingName, value);
|
||||
}
|
||||
|
||||
|
||||
LPP_DLL_API void __cdecl LppApplySettingString(const char* settingName, const wchar_t* value)
|
||||
{
|
||||
// hand command creation to the user command thread
|
||||
g_startupThread->ApplySettingString(settingName, value);
|
||||
}
|
||||
|
||||
|
||||
#undef LPP_DLL_API
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
|
||||
|
||||
#include "LC_Environment.h"
|
||||
#include "LC_Logging.h"
|
||||
#include "Windows/WindowsHWrapper.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
static const DWORD MAX_VARIABLE_SIZE = 1024u;
|
||||
}
|
||||
|
||||
|
||||
void environment::RemoveVariable(const wchar_t* variable)
|
||||
{
|
||||
const BOOL result = ::SetEnvironmentVariableW(variable, NULL);
|
||||
if (result == 0)
|
||||
{
|
||||
LC_LOG_DEV("Could not remove environment variable %S (Error: %d)", variable, ::GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void environment::SetVariable(const wchar_t* variable, const wchar_t* value)
|
||||
{
|
||||
const BOOL result = ::SetEnvironmentVariableW(variable, value);
|
||||
if (result == 0)
|
||||
{
|
||||
LC_LOG_DEV("Could not set environment variable %S to value %S (Error: %d)", variable, value, ::GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::wstring environment::GetVariable(const wchar_t* variable, const wchar_t* defaultValue)
|
||||
{
|
||||
std::wstring value;
|
||||
value.resize(MAX_VARIABLE_SIZE);
|
||||
|
||||
const DWORD result = ::GetEnvironmentVariableW(variable, &value[0], MAX_VARIABLE_SIZE);
|
||||
if (result == 0)
|
||||
{
|
||||
// if a default value was provided, return that instead
|
||||
if (defaultValue)
|
||||
{
|
||||
return std::wstring(defaultValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::wstring();
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2011-2019 Molecular Matters GmbH, all rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreTypes.h"
|
||||
#include <string>
|
||||
|
||||
namespace environment
|
||||
{
|
||||
// Removes a variable from the environment of the calling process.
|
||||
void RemoveVariable(const wchar_t* variable);
|
||||
|
||||
// Sets a variable in the environment of the calling process.
|
||||
void SetVariable(const wchar_t* variable, const wchar_t* value);
|
||||
|
||||
// Gets a variable from the environment of the calling process.
|
||||
std::wstring GetVariable(const wchar_t* variable, const wchar_t* defaultValue);
|
||||
}
|
||||
@@ -26,43 +26,21 @@ Event::~Event(void)
|
||||
}
|
||||
|
||||
|
||||
void Event::Signal(void)
|
||||
{
|
||||
::SetEvent(m_event);
|
||||
}
|
||||
|
||||
|
||||
void Event::Reset(void)
|
||||
{
|
||||
::ResetEvent(m_event);
|
||||
}
|
||||
|
||||
|
||||
void Event::Wait(void)
|
||||
void Event::Signal(void)
|
||||
{
|
||||
const DWORD result = ::WaitForSingleObject(m_event, INFINITE);
|
||||
switch (result)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
// event was successfully signaled
|
||||
break;
|
||||
::SetEvent(m_event);
|
||||
}
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
// the operation timed out, which should never happen with a timeout of INFINITE
|
||||
LC_ERROR_DEV("Event timed out.");
|
||||
break;
|
||||
|
||||
case WAIT_ABANDONED:
|
||||
LC_ERROR_DEV("Wait() was called on a stale event which was not released by the owning thread.");
|
||||
break;
|
||||
|
||||
case WAIT_FAILED:
|
||||
LC_ERROR_DEV("Failed to Wait() on an event.");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
bool Event::Wait(void)
|
||||
{
|
||||
return WaitTimeout(INFINITE);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,9 +50,15 @@ bool Event::WaitTimeout(unsigned int milliSeconds)
|
||||
switch (result)
|
||||
{
|
||||
case WAIT_OBJECT_0:
|
||||
// event was successfully signaled
|
||||
return true;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
// the operation timed out, which should never happen with a timeout of INFINITE
|
||||
if (milliSeconds == INFINITE)
|
||||
{
|
||||
LC_ERROR_DEV("Event timed out.");
|
||||
}
|
||||
return false;
|
||||
|
||||
case WAIT_ABANDONED:
|
||||
@@ -89,3 +73,9 @@ bool Event::WaitTimeout(unsigned int milliSeconds)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Event::TryWait(void)
|
||||
{
|
||||
return WaitTimeout(0u);
|
||||
}
|
||||
|
||||
@@ -22,13 +22,22 @@ public:
|
||||
Event(const wchar_t* name, Type::Enum type);
|
||||
~Event(void);
|
||||
|
||||
void Signal(void);
|
||||
// Resets the event.
|
||||
void Reset(void);
|
||||
void Wait(void);
|
||||
|
||||
// returns true if the event was signaled
|
||||
// Signals the event.
|
||||
void Signal(void);
|
||||
|
||||
// Waits until the event becomes signaled, blocking.
|
||||
bool Wait(void);
|
||||
|
||||
// Waits until the event becomes signaled, blocking until the timeout is reached.
|
||||
// Returns whether the event was signaled.
|
||||
bool WaitTimeout(unsigned int milliSeconds);
|
||||
|
||||
// Returns whether the event was signaled, non-blocking.
|
||||
bool TryWait(void);
|
||||
|
||||
private:
|
||||
Windows::HANDLE m_event;
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "LiveCodingLog.h"
|
||||
#include <atomic>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
// we want to be able to dump large things, including environment variable blocks, but 32k on the stack is too much
|
||||
|
||||
+6
@@ -21,6 +21,12 @@ void memoryStream::Reader::Read(void* data, size_t size)
|
||||
}
|
||||
|
||||
|
||||
void memoryStream::Reader::Seek(size_t offset)
|
||||
{
|
||||
m_offset = offset;
|
||||
}
|
||||
|
||||
|
||||
memoryStream::Writer::Writer(size_t capacity)
|
||||
: m_data(new char[capacity])
|
||||
, m_capacity(capacity)
|
||||
|
||||
@@ -22,6 +22,8 @@ namespace memoryStream
|
||||
return data;
|
||||
}
|
||||
|
||||
void Seek(size_t offset);
|
||||
|
||||
private:
|
||||
const void* m_data;
|
||||
size_t m_capacity;
|
||||
|
||||
+17
-10
@@ -6,17 +6,24 @@
|
||||
#include "Misc/AssertionMacros.h"
|
||||
#include "LC_Preprocessor.h"
|
||||
|
||||
#define LC_FILE __FILE__
|
||||
#define LC_LINE __LINE__
|
||||
#define LC_FUNCTION_NAME __FUNCTION__
|
||||
#define LC_FUNCTION_SIGNATURE __FUNCSIG__
|
||||
#define LC_UNUSED(_value) (void)_value
|
||||
#define LC_ASSERT(_condition, _msg) checkf(_condition, TEXT("%s"), TEXT(_msg))
|
||||
#if DO_CHECK
|
||||
# define LC_BREAKPOINT() ((::IsDebuggerPresent() == 0) ? (void)true : __debugbreak())
|
||||
#else
|
||||
# define LC_BREAKPOINT() (void)true
|
||||
#endif
|
||||
|
||||
#define LC_DISABLE_COPY(_name) _name(const _name&) = delete
|
||||
#define LC_DISABLE_MOVE(_name) _name(_name&&) = delete
|
||||
#define LC_DISABLE_ASSIGNMENT(_name) _name& operator=(const _name&) = delete
|
||||
#define LC_DISABLE_MOVE_ASSIGNMENT(_name) _name& operator=(_name&&) = delete
|
||||
#define LC_ASSERT(_condition, _msg) checkf(_condition, TEXT("%s"), TEXT(_msg))
|
||||
|
||||
#define LC_FILE __FILE__
|
||||
#define LC_LINE __LINE__
|
||||
#define LC_FUNCTION_NAME __FUNCTION__
|
||||
#define LC_FUNCTION_SIGNATURE __FUNCSIG__
|
||||
#define LC_UNUSED(_value) (void)(_value)
|
||||
|
||||
#define LC_DISABLE_COPY(_name) _name(const _name&) = delete
|
||||
#define LC_DISABLE_MOVE(_name) _name(_name&&) = delete
|
||||
#define LC_DISABLE_ASSIGNMENT(_name) _name& operator=(const _name&) = delete
|
||||
#define LC_DISABLE_MOVE_ASSIGNMENT(_name) _name& operator=(_name&&) = delete
|
||||
|
||||
#if PLATFORM_64BITS
|
||||
# define LC_64_BIT 1
|
||||
|
||||
@@ -18,6 +18,14 @@ namespace pointer
|
||||
}
|
||||
|
||||
|
||||
template <typename To, typename From>
|
||||
To FromInteger(From integer)
|
||||
{
|
||||
// widen integer to width of pointer type first before converting to pointer
|
||||
return reinterpret_cast<To>(static_cast<uintptr_t>(integer));
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
T AlignBottom(void* anyPointer, size_t alignment)
|
||||
{
|
||||
|
||||
+44
@@ -8,12 +8,16 @@
|
||||
#define LPP_JOB LPP L"_JOB"
|
||||
#define LPP_MUTEX LPP L"_IPM"
|
||||
#define LPP_MEMORY LPP L"_NSM"
|
||||
#define LPP_EVENT LPP L"_EVT"
|
||||
#define LPP_SERVER_READY LPP L"_SR"
|
||||
#define LPP_COMPILE LPP L"_CMP"
|
||||
#define LPP_PIPE L"\\\\.\\pipe\\UE_LC"
|
||||
#define LPP_EXCEPTION_PIPE L"\\\\.\\pipe\\UE_LC_EXC"
|
||||
#define LPP_HEARTBEAT_MUTEX LPP_MUTEX L"_HB"
|
||||
#define LPP_HEARTBEAT_MEMORY LPP_MEMORY L"_HB"
|
||||
#define LPP_RESTART_REQUESTED LPP_EVENT L"_RST_REQ"
|
||||
#define LPP_RESTART_PREPARED LPP_EVENT L"_RST_PREP"
|
||||
#define LPP_RESTART LPP_EVENT L"_RST"
|
||||
|
||||
|
||||
std::wstring primitiveNames::JobGroup(const std::wstring& processGroupName)
|
||||
@@ -126,13 +130,53 @@ std::wstring primitiveNames::HeartBeatNamedSharedMemory(const std::wstring& proc
|
||||
}
|
||||
|
||||
|
||||
std::wstring primitiveNames::RequestRestart(unsigned int processId)
|
||||
{
|
||||
std::wstring name;
|
||||
name.reserve(128u);
|
||||
|
||||
name += LPP_RESTART_REQUESTED;
|
||||
name += std::to_wstring(processId);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
std::wstring primitiveNames::PreparedRestart(unsigned int processId)
|
||||
{
|
||||
std::wstring name;
|
||||
name.reserve(128u);
|
||||
|
||||
name += LPP_RESTART_PREPARED;
|
||||
name += std::to_wstring(processId);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
std::wstring primitiveNames::Restart(unsigned int processId)
|
||||
{
|
||||
std::wstring name;
|
||||
name.reserve(128u);
|
||||
|
||||
name += LPP_RESTART;
|
||||
name += std::to_wstring(processId);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
#undef LPP
|
||||
#undef LPP_JOB
|
||||
#undef LPP_MUTEX
|
||||
#undef LPP_MEMORY
|
||||
#undef LPP_EVENT
|
||||
#undef LPP_SERVER_READY
|
||||
#undef LPP_COMPILE
|
||||
#undef LPP_PIPE
|
||||
#undef LPP_EXCEPTION_PIPE
|
||||
#undef LPP_HEARTBEAT_MUTEX
|
||||
#undef LPP_HEARTBEAT_MEMORY
|
||||
#undef LPP_RESTART_REQUESTED
|
||||
#undef LPP_RESTART_PREPARED
|
||||
#undef LPP_RESTART
|
||||
|
||||
+5
@@ -23,4 +23,9 @@ namespace primitiveNames
|
||||
// heart beat
|
||||
std::wstring HeartBeatMutex(const std::wstring& processGroupName, unsigned int processId);
|
||||
std::wstring HeartBeatNamedSharedMemory(const std::wstring& processGroupName, unsigned int processId);
|
||||
|
||||
// restart
|
||||
std::wstring RequestRestart(unsigned int processId);
|
||||
std::wstring PreparedRestart(unsigned int processId);
|
||||
std::wstring Restart(unsigned int processId);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user