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:
baldurk
2016-08-18 15:03:37 +02:00
parent 71cca06683
commit b5e6f8bef2
20 changed files with 1132 additions and 78 deletions
+11 -3
View File
@@ -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);
+15
View File
@@ -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,
};
+53 -4
View File
@@ -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,
+8 -8
View File
@@ -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();
+19 -2
View File
@@ -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 = "";
+70 -5
View File
@@ -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)
+30 -2
View File
@@ -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);
}