mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 10:00:40 +00:00
Allow specifying environment variable modifications
* This works for local and remote invocations of programs, but is mostly useful on unix systems (Windows programs use env vars less often)
This commit is contained in:
@@ -487,7 +487,7 @@ struct IRemoteServer
|
||||
virtual rdctype::array<DirectoryFile> ListFolder(const char *path) = 0;
|
||||
|
||||
virtual uint32_t ExecuteAndInject(const char *app, const char *workingDir, const char *cmdLine,
|
||||
const CaptureOptions *opts) = 0;
|
||||
void *env, const CaptureOptions *opts) = 0;
|
||||
|
||||
virtual void TakeOwnershipCapture(const char *filename) = 0;
|
||||
virtual rdctype::str CopyCaptureToRemote(const char *filename, float *progress) = 0;
|
||||
@@ -529,7 +529,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_ListFolder(
|
||||
|
||||
extern "C" RENDERDOC_API uint32_t RENDERDOC_CC
|
||||
RemoteServer_ExecuteAndInject(RemoteServer *remote, const char *app, const char *workingDir,
|
||||
const char *cmdLine, const CaptureOptions *opts);
|
||||
const char *cmdLine, void *env, const CaptureOptions *opts);
|
||||
|
||||
extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_TakeOwnershipCapture(RemoteServer *remote,
|
||||
const char *filename);
|
||||
@@ -628,7 +628,7 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_StartGlobalHook(const char
|
||||
const char *logfile,
|
||||
const CaptureOptions *opts);
|
||||
extern "C" RENDERDOC_API uint32_t RENDERDOC_CC
|
||||
RENDERDOC_ExecuteAndInject(const char *app, const char *workingDir, const char *cmdLine,
|
||||
RENDERDOC_ExecuteAndInject(const char *app, const char *workingDir, const char *cmdLine, void *env,
|
||||
const char *logfile, const CaptureOptions *opts, bool32 waitForExit);
|
||||
extern "C" RENDERDOC_API uint32_t RENDERDOC_CC RENDERDOC_InjectIntoProcess(
|
||||
uint32_t pid, const char *logfile, const CaptureOptions *opts, bool32 waitForExit);
|
||||
@@ -647,3 +647,11 @@ extern "C" RENDERDOC_API const char *RENDERDOC_CC RENDERDOC_GetCommitHash();
|
||||
extern "C" RENDERDOC_API const char *RENDERDOC_CC RENDERDOC_GetConfigSetting(const char *name);
|
||||
extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetConfigSetting(const char *name,
|
||||
const char *value);
|
||||
|
||||
extern "C" RENDERDOC_API void *RENDERDOC_CC RENDERDOC_MakeEnvironmentModificationList(int numElems);
|
||||
|
||||
extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetEnvironmentModification(
|
||||
void *mem, int idx, const char *variable, const char *value, EnvironmentModificationType type,
|
||||
EnvironmentSeparator separator);
|
||||
|
||||
extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_FreeEnvironmentModificationList(void *mem);
|
||||
|
||||
@@ -523,3 +523,18 @@ enum TargetControlMessageType
|
||||
eTargetControlMsg_RegisterAPI,
|
||||
eTargetControlMsg_NewChild,
|
||||
};
|
||||
|
||||
enum EnvironmentModificationType
|
||||
{
|
||||
eEnvMod_Set,
|
||||
eEnvMod_Append,
|
||||
eEnvMod_Prepend,
|
||||
};
|
||||
|
||||
enum EnvironmentSeparator
|
||||
{
|
||||
eEnvSep_Platform,
|
||||
eEnvSep_SemiColon,
|
||||
eEnvSep_Colon,
|
||||
eEnvSep_None,
|
||||
};
|
||||
|
||||
@@ -50,6 +50,22 @@ void Serialiser::Serialise(const char *name, DirectoryFile &el)
|
||||
Serialise("flags", el.flags);
|
||||
}
|
||||
|
||||
template <>
|
||||
string ToStrHelper<false, Process::ModificationType>::Get(const Process::ModificationType &el)
|
||||
{
|
||||
return "<...>";
|
||||
}
|
||||
|
||||
template <>
|
||||
void Serialiser::Serialise(const char *name, Process::EnvironmentModification &el)
|
||||
{
|
||||
ScopedContext scope(this, name, "Process::EnvironmentModification", 0, true);
|
||||
|
||||
Serialise("type", el.type);
|
||||
Serialise("name", el.name);
|
||||
Serialise("value", el.value);
|
||||
}
|
||||
|
||||
enum RemoteServerPacket
|
||||
{
|
||||
eRemoteServer_Noop,
|
||||
@@ -372,18 +388,27 @@ static void ActiveRemoteClientThread(void *data)
|
||||
recvser->Serialise("cmdLine", cmdLine);
|
||||
recvser->Serialise("opts", opts);
|
||||
|
||||
uint64_t envListSize = 0;
|
||||
Process::EnvironmentModification *env = NULL;
|
||||
recvser->Serialise("envListSize", envListSize);
|
||||
|
||||
if(envListSize > 0)
|
||||
recvser->SerialiseComplexArray("env", env, envListSize);
|
||||
|
||||
uint32_t ident = eReplayCreate_NetworkIOFailed;
|
||||
|
||||
if(threadData->allowExecution)
|
||||
{
|
||||
ident = Process::LaunchAndInjectIntoProcess(app.c_str(), workingDir.c_str(),
|
||||
cmdLine.c_str(), "", &opts, false);
|
||||
cmdLine.c_str(), env, "", &opts, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDCWARN("Requested to execute program - disallowing based on configuration");
|
||||
}
|
||||
|
||||
SAFE_DELETE_ARRAY(env);
|
||||
|
||||
sendType = eRemoteServer_ExecuteAndInject;
|
||||
sendSer.Serialise("ident", ident);
|
||||
}
|
||||
@@ -769,7 +794,7 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t ExecuteAndInject(const char *app, const char *workingDir, const char *cmdLine,
|
||||
uint32_t ExecuteAndInject(const char *app, const char *workingDir, const char *cmdLine, void *env,
|
||||
const CaptureOptions *opts)
|
||||
{
|
||||
CaptureOptions capopts = opts ? *opts : CaptureOptions();
|
||||
@@ -778,11 +803,35 @@ public:
|
||||
string workstr = workingDir && workingDir[0] ? workingDir : "";
|
||||
string cmdstr = cmdLine && cmdLine[0] ? cmdLine : "";
|
||||
|
||||
Process::EnvironmentModification *envList = (Process::EnvironmentModification *)env;
|
||||
|
||||
Serialiser sendData("", Serialiser::WRITING, false);
|
||||
sendData.Serialise("app", appstr);
|
||||
sendData.Serialise("workingDir", workstr);
|
||||
sendData.Serialise("cmdLine", cmdstr);
|
||||
sendData.Serialise("opts", capopts);
|
||||
|
||||
uint64_t envListSize = 0;
|
||||
if(envList)
|
||||
{
|
||||
Process::EnvironmentModification *it = envList;
|
||||
for(;;)
|
||||
{
|
||||
if(it->name == "")
|
||||
break;
|
||||
envListSize++;
|
||||
it++;
|
||||
}
|
||||
|
||||
// include terminator
|
||||
envListSize++;
|
||||
}
|
||||
|
||||
sendData.Serialise("envListSize", envListSize);
|
||||
|
||||
if(envListSize > 0)
|
||||
sendData.SerialiseComplexArray("env", envList, envListSize);
|
||||
|
||||
Send(eRemoteServer_ExecuteAndInject, sendData);
|
||||
|
||||
RemoteServerPacket type = eRemoteServer_ExecuteAndInject;
|
||||
@@ -1019,9 +1068,9 @@ RemoteServer_RemoteSupportedReplays(RemoteServer *remote, rdctype::array<rdctype
|
||||
|
||||
extern "C" RENDERDOC_API uint32_t RENDERDOC_CC
|
||||
RemoteServer_ExecuteAndInject(RemoteServer *remote, const char *app, const char *workingDir,
|
||||
const char *cmdLine, const CaptureOptions *opts)
|
||||
const char *cmdLine, void *env, const CaptureOptions *opts)
|
||||
{
|
||||
return remote->ExecuteAndInject(app, workingDir, cmdLine, opts);
|
||||
return remote->ExecuteAndInject(app, workingDir, cmdLine, env, opts);
|
||||
}
|
||||
|
||||
extern "C" RENDERDOC_API void RENDERDOC_CC RemoteServer_TakeOwnershipCapture(RemoteServer *remote,
|
||||
|
||||
@@ -52,17 +52,17 @@ enum ModificationType
|
||||
eEnvModification_Replace = 0,
|
||||
|
||||
// prepend/append options will replace if there is no existing variable
|
||||
eEnvModification_Append, // append with no separators
|
||||
eEnvModification_AppendColon, // append, separated by colons
|
||||
eEnvModification_AppendSemiColon, // append, separated by semi-colons
|
||||
eEnvModification_AppendPlatform, // append, separated by colons for linux & semi-colons for
|
||||
// windows
|
||||
eEnvModification_AppendSemiColon, // append, separated by semi-colons
|
||||
eEnvModification_AppendColon, // append, separated by colons
|
||||
eEnvModification_Append, // append with no separators
|
||||
|
||||
eEnvModification_Prepend, // prepend with no separators
|
||||
eEnvModification_PrependColon, // prepend, separated by colons
|
||||
eEnvModification_PrependSemiColon, // prepend, separated by semi-colons
|
||||
eEnvModification_PrependPlatform, // prepend, separated by colons for linux & semi-colons for
|
||||
// windows
|
||||
eEnvModification_PrependSemiColon, // prepend, separated by semi-colons
|
||||
eEnvModification_PrependColon, // prepend, separated by colons
|
||||
eEnvModification_Prepend, // prepend with no separators
|
||||
};
|
||||
struct EnvironmentModification
|
||||
{
|
||||
@@ -84,8 +84,8 @@ uint32_t InjectIntoProcess(uint32_t pid, const char *logfile, const CaptureOptio
|
||||
bool waitForExit);
|
||||
uint32_t LaunchProcess(const char *app, const char *workingDir, const char *cmdLine);
|
||||
uint32_t LaunchAndInjectIntoProcess(const char *app, const char *workingDir, const char *cmdLine,
|
||||
const char *logfile, const CaptureOptions *opts,
|
||||
bool waitForExit);
|
||||
EnvironmentModification *env, const char *logfile,
|
||||
const CaptureOptions *opts, bool waitForExit);
|
||||
void *LoadModule(const char *module);
|
||||
void *GetFunctionAddress(void *module, const char *function);
|
||||
uint32_t GetCurrentPID();
|
||||
|
||||
@@ -361,8 +361,9 @@ uint32_t Process::LaunchProcess(const char *app, const char *workingDir, const c
|
||||
}
|
||||
|
||||
uint32_t Process::LaunchAndInjectIntoProcess(const char *app, const char *workingDir,
|
||||
const char *cmdLine, const char *logfile,
|
||||
const CaptureOptions *opts, bool waitForExit)
|
||||
const char *cmdLine, EnvironmentModification *envList,
|
||||
const char *logfile, const CaptureOptions *opts,
|
||||
bool waitForExit)
|
||||
{
|
||||
if(app == NULL || app[0] == 0)
|
||||
{
|
||||
@@ -375,6 +376,22 @@ uint32_t Process::LaunchAndInjectIntoProcess(const char *app, const char *workin
|
||||
map<string, string> env = EnvStringToEnvMap((const char **)currentEnvironment);
|
||||
vector<EnvironmentModification> &modifications = GetEnvModifications();
|
||||
|
||||
if(envList)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
EnvironmentModification e = *envList;
|
||||
e.name = trim(e.name);
|
||||
|
||||
if(e.name == "")
|
||||
break;
|
||||
|
||||
modifications.push_back(e);
|
||||
|
||||
envList++;
|
||||
}
|
||||
}
|
||||
|
||||
if(logfile == NULL)
|
||||
logfile = "";
|
||||
|
||||
|
||||
@@ -171,6 +171,35 @@ extern "C" __declspec(dllexport) void __cdecl RENDERDOC_SetLogFile(const char *l
|
||||
if(log)
|
||||
RenderDoc::Inst().SetLogFile(log);
|
||||
}
|
||||
|
||||
static Process::EnvironmentModification tempEnvMod;
|
||||
|
||||
extern "C" __declspec(dllexport) void __cdecl RENDERDOC_EnvModName(const char *name)
|
||||
{
|
||||
if(name)
|
||||
tempEnvMod.name = name;
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) void __cdecl RENDERDOC_EnvModValue(const char *value)
|
||||
{
|
||||
if(value)
|
||||
tempEnvMod.value = value;
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) void __cdecl RENDERDOC_EnvMod(Process::ModificationType *type)
|
||||
{
|
||||
if(type)
|
||||
{
|
||||
tempEnvMod.type = *type;
|
||||
Process::RegisterEnvironmentModification(tempEnvMod);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) void __cdecl RENDERDOC_ApplyEnvMods(void *ignored)
|
||||
{
|
||||
Process::ApplyEnvironmentModification();
|
||||
}
|
||||
|
||||
void InjectDLL(HANDLE hProcess, wstring libName)
|
||||
{
|
||||
wchar_t dllPath[MAX_PATH + 1] = {0};
|
||||
@@ -591,8 +620,9 @@ uint32_t Process::LaunchProcess(const char *app, const char *workingDir, const c
|
||||
}
|
||||
|
||||
uint32_t Process::LaunchAndInjectIntoProcess(const char *app, const char *workingDir,
|
||||
const char *cmdLine, const char *logfile,
|
||||
const CaptureOptions *opts, bool waitForExit)
|
||||
const char *cmdLine, EnvironmentModification *env,
|
||||
const char *logfile, const CaptureOptions *opts,
|
||||
bool waitForExit)
|
||||
{
|
||||
void *func = GetProcAddress(GetModuleHandleA("renderdoc.dll"), "RENDERDOC_SetLogFile");
|
||||
|
||||
@@ -607,18 +637,53 @@ uint32_t Process::LaunchAndInjectIntoProcess(const char *app, const char *workin
|
||||
if(pi.dwProcessId == 0)
|
||||
return 0;
|
||||
|
||||
// don't need it
|
||||
CloseHandle(pi.hProcess);
|
||||
|
||||
uint32_t ret = InjectIntoProcess(pi.dwProcessId, logfile, opts, false);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
ResumeThread(pi.hThread);
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(env)
|
||||
{
|
||||
uintptr_t loc = FindRemoteDLL(pi.dwProcessId, L"renderdoc.dll");
|
||||
|
||||
if(loc == 0)
|
||||
{
|
||||
RDCERR("Can't locate renderdoc.dll in remote PID %d", pi.dwProcessId);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
string name = trim(env->name);
|
||||
string value = env->value;
|
||||
ModificationType type = env->type;
|
||||
|
||||
if(name == "")
|
||||
break;
|
||||
|
||||
InjectFunctionCall(pi.hProcess, loc, "RENDERDOC_EnvModName", (void *)name.c_str(),
|
||||
name.size() + 1);
|
||||
InjectFunctionCall(pi.hProcess, loc, "RENDERDOC_EnvModValue", (void *)value.c_str(),
|
||||
value.size() + 1);
|
||||
InjectFunctionCall(pi.hProcess, loc, "RENDERDOC_EnvMod", &type, sizeof(type));
|
||||
|
||||
env++;
|
||||
}
|
||||
|
||||
// parameter is unused
|
||||
InjectFunctionCall(pi.hProcess, loc, "RENDERDOC_ApplyEnvMods", env,
|
||||
sizeof(EnvironmentModification));
|
||||
}
|
||||
}
|
||||
|
||||
// done with it
|
||||
CloseHandle(pi.hProcess);
|
||||
|
||||
ResumeThread(pi.hThread);
|
||||
|
||||
if(waitForExit)
|
||||
|
||||
@@ -252,6 +252,33 @@ extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetConfigSetting(const char
|
||||
RenderDoc::Inst().SetConfigSetting(name, value);
|
||||
}
|
||||
|
||||
extern "C" RENDERDOC_API void *RENDERDOC_CC RENDERDOC_MakeEnvironmentModificationList(int numElems)
|
||||
{
|
||||
return new Process::EnvironmentModification[numElems + 1]; // last one is a terminator
|
||||
}
|
||||
|
||||
extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_SetEnvironmentModification(
|
||||
void *mem, int idx, const char *variable, const char *value, EnvironmentModificationType type,
|
||||
EnvironmentSeparator separator)
|
||||
{
|
||||
Process::EnvironmentModification *mods = (Process::EnvironmentModification *)mem;
|
||||
|
||||
Process::ModificationType modType = Process::eEnvModification_Replace;
|
||||
|
||||
if(type == eEnvMod_Append)
|
||||
modType = Process::ModificationType(Process::eEnvModification_AppendPlatform + (int)separator);
|
||||
if(type == eEnvMod_Prepend)
|
||||
modType = Process::ModificationType(Process::eEnvModification_PrependPlatform + (int)separator);
|
||||
|
||||
mods[idx] = Process::EnvironmentModification(modType, variable, value);
|
||||
}
|
||||
|
||||
extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_FreeEnvironmentModificationList(void *mem)
|
||||
{
|
||||
Process::EnvironmentModification *mods = (Process::EnvironmentModification *)mem;
|
||||
delete[] mods;
|
||||
}
|
||||
|
||||
extern "C" RENDERDOC_API void RENDERDOC_CC RENDERDOC_LogText(const char *text)
|
||||
{
|
||||
RDCLOG("%s", text);
|
||||
@@ -336,10 +363,11 @@ RENDERDOC_CreateReplayRenderer(const char *logfile, float *progress, ReplayRende
|
||||
}
|
||||
|
||||
extern "C" RENDERDOC_API uint32_t RENDERDOC_CC
|
||||
RENDERDOC_ExecuteAndInject(const char *app, const char *workingDir, const char *cmdLine,
|
||||
RENDERDOC_ExecuteAndInject(const char *app, const char *workingDir, const char *cmdLine, void *env,
|
||||
const char *logfile, const CaptureOptions *opts, bool32 waitForExit)
|
||||
{
|
||||
return Process::LaunchAndInjectIntoProcess(app, workingDir, cmdLine, logfile, opts,
|
||||
return Process::LaunchAndInjectIntoProcess(app, workingDir, cmdLine,
|
||||
(Process::EnvironmentModification *)env, logfile, opts,
|
||||
waitForExit != 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user