diff --git a/dist.sh b/dist.sh
index 310c7ee6e..2c0147e11 100644
--- a/dist.sh
+++ b/dist.sh
@@ -45,9 +45,9 @@ rm -f dist/Release{32,64}/*.{exp,lib,metagen,xml} dist/Release{32,64}/*.vshost.*
# In the 64bit release folder, make an x86 subfolder and copy in renderdoc 32bit
mkdir -p dist/Release64/x86
rm -rf dist/Release32/pdblocate/x64 dist/ReleasePDBs32/pdblocate/x64
-cp -R dist/Release32/{renderdoc.dll,renderdoccmd.exe,pdblocate} dist/Release64/x86/
+cp -R dist/Release32/{renderdoc.dll,renderdocshim32.dll,renderdoccmd.exe,pdblocate} dist/Release64/x86/
mkdir -p dist/ReleasePDBs64/x86
-cp -R dist/ReleasePDBs32/{renderdoc.dll,renderdoc.pdb,renderdoccmd.exe,renderdoccmd.pdb,pdblocate} dist/ReleasePDBs64/x86/
+cp -R dist/ReleasePDBs32/{renderdoc.dll,renderdoc.pdb,renderdocshim32.dll,renderdocshim32.pdb,renderdoccmd.exe,renderdoccmd.pdb,pdblocate} dist/ReleasePDBs64/x86/
if [[ $AUTOBUILD -eq 0 ]]; then
echo "Ready to make installer MSIs - make sure to bump version numbers on package."
diff --git a/docs/FAQ.aml b/docs/FAQ.aml
index 7cda58fc6..c9b5d078a 100644
--- a/docs/FAQ.aml
+++ b/docs/FAQ.aml
@@ -289,5 +289,21 @@
+
+ I can't launch my program for capture directly. Can I capture it anyway?
+
+
+ There is an option for capturing programs using RenderDoc where you can't easily set
+ up a direct launch of the process.
+
+
+ More details can be found in the
+ capture options page which
+ details how to use it, however you should take care to read the warnings! This option
+ isn't without its risks, so you need to be sure you know what you're doing before
+ using it. It should always be used as a last resort when there is no other option.
+
+
+
diff --git a/docs/Layout.content b/docs/Layout.content
index 05ede5f0d..fc5b27247 100644
--- a/docs/Layout.content
+++ b/docs/Layout.content
@@ -126,6 +126,8 @@
+
+
diff --git a/docs/Windows/CaptureDialog.aml b/docs/Windows/CaptureDialog.aml
index f7d23f763..4d1bf8c5a 100644
--- a/docs/Windows/CaptureDialog.aml
+++ b/docs/Windows/CaptureDialog.aml
@@ -201,6 +201,42 @@
+
+ Global Process Hook
+
+
+ This option is risky and should not be used lightly. Know what you're doing and
+ use it as a last resort.
+
+ To expose this option you have to enable it in
+ the settings,
+ to prevent it being used accidentally.
+ When you've entered a path, or filename, in the executable text at the top
+ of the window, this option will then insert a global hook that causes every new
+ process created to load a very small shim dll.
+ The shim dll will load, create a thread that checks to see if the process
+ matches the path or filename specified, and then unload. If the process matches
+ it will also inject RenderDoc and capturing will continue as normal. At this
+ point you should first disable the global hook, then
+ you can use the 'Attach to running instance' menu option to continue as normal.
+ RenderDoc implements this behaviour by modifying the
+
+AppInit_DLLs
+AppInit_DLLs on MSDN
+http://support2.microsoft.com/kb/197571
+ registry key to reference RenderDoc's dlls. This is not a particularly safe
+ method but it's the only reliable method to do what we want. The shim dll is
+ deliberately made as small and thin as possible, referencing only kernel32.dll, to
+ minimise any risks.
+
+ If RenderDoc crashes or something otherwise goes wrong while these registry
+ keys are modified, the shim dll will continue to be injected into every process which
+ is certainly not desireable. Should anything go wrong, RenderDoc writes a .reg
+ file that restores the registry to its previous state in %TEMP%.
+ Again, this method should be a last resort. Given
+ the risks you should always try to capture directly in some way before trying this.
+
+
diff --git a/docs/Windows/Options.aml b/docs/Windows/Options.aml
index b093520a0..94afec63d 100644
--- a/docs/Windows/Options.aml
+++ b/docs/Windows/Options.aml
@@ -96,6 +96,15 @@
recommended that you manually check for updates as new versions will be made available regularly with bugfixes.
Enabled
+
+ Allow global process hooking
+ This option enables the functionality allowing capturing of programs that aren't
+ launched directly from RenderDoc, but are launched from somewhere else.
+ This option can be dangerous which is why you have to deliberately enable it
+ here. Be careful when using this and only do so when necessary - more details can be found in the
+ capture options page.
+ Disabled
+
diff --git a/installer/Installer32.wxs b/installer/Installer32.wxs
index 77f052727..010ae0593 100644
--- a/installer/Installer32.wxs
+++ b/installer/Installer32.wxs
@@ -79,6 +79,7 @@
+
+
+
ToString();
+
+ _snwprintf_s(paramsAlloc, 2047, 2047, L"\"%ls\" --globalhook \"%ls\" \"%ls\" \"%hs\"",
+ renderdocPath, pathmatch, logfile == NULL ? L"" : logfile, optstr.c_str());
+
+ paramsAlloc[2047] = 0;
+
+ BOOL retValue = CreateProcessW(NULL, paramsAlloc, &pSec, &tSec, false, 0, NULL, NULL, &si, &pi);
+
+ if(retValue == FALSE) return;
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+
+#if defined(WIN64)
+ *slash = 0;
+
+ wcscat_s(renderdocPath, L"\\x86\\renderdoccmd.exe");
+
+ _snwprintf_s(paramsAlloc, 2047, 2047, L"\"%ls\" --globalhook \"%ls\" \"%ls\" \"%hs\"",
+ renderdocPath, pathmatch, logfile == NULL ? L"" : logfile, optstr.c_str());
+
+ paramsAlloc[2047] = 0;
+
+ retValue = CreateProcessW(NULL, paramsAlloc, &pSec, &tSec, false, 0, NULL, NULL, &si, &pi);
+
+ if(retValue == FALSE) return;
+
+ CloseHandle(pi.hThread);
+ CloseHandle(pi.hProcess);
+#endif
+}
+
void *Process::GetFunctionAddress(const char *module, const char *function)
{
HMODULE mod = GetModuleHandleA(module);
diff --git a/renderdoc/replay/entry_points.cpp b/renderdoc/replay/entry_points.cpp
index 82cc622b4..b75db27da 100644
--- a/renderdoc/replay/entry_points.cpp
+++ b/renderdoc/replay/entry_points.cpp
@@ -219,6 +219,12 @@ uint32_t RENDERDOC_CC RENDERDOC_ExecuteAndInject(const wchar_t *app, const wchar
return Process::CreateAndInjectIntoProcess(app, workingDir, cmdLine, logfile, opts, waitForExit != 0);
}
+extern "C" RENDERDOC_API
+void RENDERDOC_CC RENDERDOC_StartGlobalHook(const wchar_t *pathmatch, const wchar_t *logfile, const CaptureOptions *opts)
+{
+ Process::StartGlobalHook(pathmatch, logfile, opts);
+}
+
extern "C" RENDERDOC_API
uint32_t RENDERDOC_CC RENDERDOC_InjectIntoProcess(uint32_t pid, const wchar_t *logfile, const CaptureOptions *opts, bool32 waitForExit)
{
diff --git a/renderdoccmd/renderdoccmd.vcxproj b/renderdoccmd/renderdoccmd.vcxproj
index fbe0c0d3d..7d2c6a530 100644
--- a/renderdoccmd/renderdoccmd.vcxproj
+++ b/renderdoccmd/renderdoccmd.vcxproj
@@ -93,7 +93,7 @@
Level3
Disabled
WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- ..\renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\
+ $(SolutionDir)renderdocshim\;$(SolutionDir)renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\
MultiThreadedDLL
true
@@ -109,8 +109,8 @@
Level3
Disabled
- WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
- ..\renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\
+ WIN32;WIN64;RENDERDOC_PLATFORM=win32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ $(SolutionDir)renderdocshim\;$(SolutionDir)renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\
MultiThreadedDLL
true
@@ -129,7 +129,7 @@
true
true
WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;RELEASE;_CONSOLE;%(PreprocessorDefinitions)
- ..\renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\
+ $(SolutionDir)renderdocshim\;$(SolutionDir)renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\
true
@@ -148,8 +148,8 @@
MaxSpeed
true
true
- WIN32;RENDERDOC_PLATFORM=win32;NDEBUG;RELEASE;_CONSOLE;%(PreprocessorDefinitions)
- ..\renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\
+ WIN32;WIN64;RENDERDOC_PLATFORM=win32;NDEBUG;RELEASE;_CONSOLE;%(PreprocessorDefinitions)
+ $(SolutionDir)renderdocshim\;$(SolutionDir)renderdoc\api\;$(SolutionDir)renderdoc\3rdparty\
true
diff --git a/renderdoccmd/renderdoccmd_win32.cpp b/renderdoccmd/renderdoccmd_win32.cpp
index 577cf201f..09b605674 100644
--- a/renderdoccmd/renderdoccmd_win32.cpp
+++ b/renderdoccmd/renderdoccmd_win32.cpp
@@ -29,6 +29,8 @@
#include
#include
+#include
+
#include "resource.h"
#include "miniz/miniz.h"
@@ -293,6 +295,7 @@ void DisplayRendererPreview(ReplayRenderer *renderer)
}
int renderdoccmd(int argc, wchar_t **argv);
+bool argequal(const wchar_t *a, const wchar_t *b);
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd )
{
@@ -499,5 +502,105 @@ int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPWSTR lpCmdLine,
}
#endif
+ // this installs a global windows hook pointing at renderdocshim*.dll that filters all running processes and
+ // loads renderdoc.dll in the target one. In any other process it unloads as soon as possible
+ if(argc == 5 && argequal(argv[1], L"--globalhook"))
+ {
+ wchar_t *pathmatch = argv[2];
+
+ wchar_t *log = argv[3];
+
+ CaptureOptions cmdopts;
+ string optstring(&argv[4][0], &argv[4][0] + wcslen(argv[4]));
+ cmdopts.FromString(optstring);
+
+ // make sure the user doesn't accidentally run this with 'a' as a parameter or something.
+ // "a.exe" is over 4 characters so this limit should not be a problem.
+ if(wcslen(pathmatch) < 4)
+ {
+ fprintf(stderr, "--globalhook path match is too short/general. Danger of matching too many processes!\n");
+ return 1;
+ }
+
+ wchar_t rdocpath[1024];
+
+ // fetch path to our matching renderdoc.dll
+ HMODULE rdoc = GetModuleHandleA("renderdoc.dll");
+
+ if(rdoc == NULL)
+ {
+ fprintf(stderr, "--globalhook couldn't find renderdoc.dll!\n");
+ return 1;
+ }
+
+ GetModuleFileNameW(rdoc, rdocpath, _countof(rdocpath)-1);
+ FreeLibrary(rdoc);
+
+ // Create pipe from control program, to stay open until requested to close
+ HANDLE pipe = CreateFileW(L"\\\\.\\pipe\\"
+#ifdef WIN64
+ L"RenderDoc.GlobalHookControl64"
+#else
+ L"RenderDoc.GlobalHookControl32"
+#endif
+ , GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+ if(pipe == INVALID_HANDLE_VALUE)
+ {
+ fprintf(stderr, "--globalhook couldn't open control pipe.\n");
+ return 1;
+ }
+
+ HANDLE datahandle = OpenFileMappingA(FILE_MAP_READ, FALSE, GLOBAL_HOOK_DATA_NAME);
+
+ if(datahandle != NULL)
+ {
+ CloseHandle(pipe);
+ CloseHandle(datahandle);
+ fprintf(stderr, "--globalhook found pre-existing global data, not creating second global hook.\n");
+ return 1;
+ }
+
+ datahandle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(ShimData), GLOBAL_HOOK_DATA_NAME);
+
+ if(datahandle)
+ {
+ ShimData *shimdata = (ShimData *)MapViewOfFile(datahandle, FILE_MAP_WRITE|FILE_MAP_READ, 0, 0, sizeof(ShimData));
+
+ if(shimdata)
+ {
+ memset(shimdata, 0, sizeof(ShimData));
+
+ wcsncpy_s(shimdata->pathmatchstring, pathmatch, _TRUNCATE);
+ wcsncpy_s(shimdata->rdocpath, rdocpath, _TRUNCATE);
+ wcsncpy_s(shimdata->log, log, _TRUNCATE);
+ memcpy (shimdata->opts, &cmdopts, sizeof(CaptureOptions));
+
+ static_assert(sizeof(CaptureOptions) <= sizeof(shimdata->opts), "ShimData options is too small");
+
+ // wait until a write comes in over the pipe
+ char buf[16];
+ DWORD read = 0;
+ ReadFile(pipe, buf, 16, &read, NULL);
+
+ UnmapViewOfFile(shimdata);
+ }
+ else
+ {
+ fprintf(stderr, "--globalhook couldn't map global data store.\n");
+ }
+
+ CloseHandle(datahandle);
+ }
+ else
+ {
+ fprintf(stderr, "--globalhook couldn't create global data store.\n");
+ }
+
+ CloseHandle(pipe);
+
+ return 0;
+ }
+
return renderdoccmd(argc, argv);
}
diff --git a/renderdocshim/renderdocshim.cpp b/renderdocshim/renderdocshim.cpp
new file mode 100644
index 000000000..6a1522586
--- /dev/null
+++ b/renderdocshim/renderdocshim.cpp
@@ -0,0 +1,169 @@
+/******************************************************************************
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Baldur Karlsson
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+// This project deliberately references only kernel32.dll (ie. not even the CRT)
+// so that when inserted into an application it has as small an overhead/impact
+// as possible. Ideally it would be present only to be a pass-through hook and
+// the first time only to allocate a little, check if this process should be hooked
+// and load the renderdoc dll.
+//
+// The no-CRT restriction causes some awkward bits and pieces but the dll is simple
+// enough that it's not a big issue.
+
+#include
+
+#include "renderdocshim.h"
+
+struct CaptureOptions;
+typedef void (__cdecl *pRENDERDOC_SetCaptureOptions)(const CaptureOptions *opts);
+typedef void (__cdecl *pRENDERDOC_SetLogFile)(const wchar_t *logfile);
+
+#if defined(RELEASE)
+#define LOGPRINT(txt) do { } while (0)
+#else
+// define this to something to get logging
+//#define LOGPRINT(txt) OutputDebugStringW(txt)
+#define LOGPRINT(txt) do { } while (0)
+#endif
+
+void CheckHook()
+{
+ ShimData *data = NULL;
+
+ HANDLE datahandle = OpenFileMappingA(FILE_MAP_READ, FALSE, GLOBAL_HOOK_DATA_NAME);
+
+ if(datahandle == NULL)
+ {
+ LOGPRINT(L"renderdocshim: can't open global data\n");
+ return;
+ }
+
+ data = (ShimData *)MapViewOfFile(datahandle, FILE_MAP_READ, 0, 0, sizeof(ShimData));
+
+ if(data == NULL)
+ {
+ CloseHandle(datahandle);
+ LOGPRINT(L"renderdocshim: can't map global data\n");
+ return;
+ }
+
+ if(data->pathmatchstring[0] == 0 ||
+ data->pathmatchstring[1] == 0 ||
+ data->pathmatchstring[2] == 0 ||
+ data->pathmatchstring[3] == 0)
+ {
+ LOGPRINT(L"renderdocshim: invalid pathmatchstring: '");
+ LOGPRINT(data->pathmatchstring);
+ LOGPRINT(L"'\n");
+
+ UnmapViewOfFile(data);
+ CloseHandle(datahandle);
+ return;
+ }
+
+ // no new[], need to use VirtualAlloc
+ const int exepathLen = 1024;
+ wchar_t *exepath = (wchar_t *)VirtualAlloc(NULL, exepathLen*sizeof(wchar_t), MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
+
+ if(exepath)
+ {
+ // no memset :).
+ for(int i=0; i < exepathLen; i++) exepath[i] = 0;
+
+ GetModuleFileNameW(NULL, exepath, exepathLen - 1);
+
+ // no str*cmp functions
+ int find = FindStringOrdinal(FIND_FROMSTART, exepath, -1, data->pathmatchstring, -1, TRUE);
+
+ if(find >= 0)
+ {
+ LOGPRINT(L"renderdocshim: Hooking into '");
+ LOGPRINT(exepath);
+ LOGPRINT(L"', based on '");
+ LOGPRINT(data->pathmatchstring);
+ LOGPRINT(L"'\n");
+
+ HMODULE mod = LoadLibraryW(data->rdocpath);
+
+ if(mod)
+ {
+ pRENDERDOC_SetCaptureOptions setopts = (pRENDERDOC_SetCaptureOptions)GetProcAddress(mod, "RENDERDOC_SetCaptureOptions");
+ pRENDERDOC_SetLogFile setlog = (pRENDERDOC_SetLogFile)GetProcAddress(mod, "RENDERDOC_SetLogFile");
+
+ if(setopts)
+ setopts( (const CaptureOptions *)data->opts );
+
+ if(setlog && data->log[0])
+ setlog( data->log );
+ }
+ }
+ else
+ {
+ LOGPRINT(L"renderdocshim: NOT Hooking into '");
+ LOGPRINT(data->exepath);
+ LOGPRINT(L"', based on '");
+ LOGPRINT(data->pathmatchstring);
+ LOGPRINT(L"'\n");
+ }
+
+ VirtualFree(exepath, 0, MEM_RELEASE);
+ }
+ else
+ {
+ LOGPRINT(L"renderdocshim: Failed to allocate exepath\n");
+ }
+
+ UnmapViewOfFile(data);
+ CloseHandle(datahandle);
+}
+
+DWORD CheckHookThread(LPVOID param)
+{
+ CheckHook();
+
+ // this makes sure that we remove the reference to the shim dll and unload from
+ // the target process. That minimises the impact of having the dll inserted into
+ // every process
+ FreeLibraryAndExitThread((HMODULE)param, 0);
+ return 0;
+}
+
+BOOL APIENTRY dll_entry(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+{
+ if(ul_reason_for_call == DLL_PROCESS_ATTACH)
+ {
+ DisableThreadLibraryCalls(hModule);
+
+ // create a thread so that we can perform more complex actions (DllMain must be minimal
+ // in size, even this is a bit dodgy).
+ CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&CheckHookThread, (LPVOID)hModule, 0, NULL);
+
+ // Sleep on this thread a bit, as we want to call CheckHook() before any real work is done.
+ // Note it is important we don't try to *synchronise* on CheckHookThread, as that can easily
+ // cause deadlocks, crashes, etc.
+ Sleep(500);
+ }
+
+ return TRUE;
+}
diff --git a/renderdocshim/renderdocshim.h b/renderdocshim/renderdocshim.h
new file mode 100644
index 000000000..5112a8427
--- /dev/null
+++ b/renderdocshim/renderdocshim.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014 Baldur Karlsson
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ ******************************************************************************/
+
+struct ShimData
+{
+ wchar_t pathmatchstring[2048];
+ wchar_t rdocpath[2048];
+ wchar_t log[2048];
+
+ unsigned char opts[512];
+};
+
+#ifdef WIN64
+#define GLOBAL_HOOK_DATA_NAME "RenderDocGlobalHookData64"
+#define SHIM_DLL_NAME "renderdocshim64.dll"
+#else
+#define GLOBAL_HOOK_DATA_NAME "RenderDocGlobalHookData32"
+#define SHIM_DLL_NAME "renderdocshim32.dll"
+#endif
\ No newline at end of file
diff --git a/renderdocshim/renderdocshim.vcxproj b/renderdocshim/renderdocshim.vcxproj
new file mode 100644
index 000000000..4d25ba71a
--- /dev/null
+++ b/renderdocshim/renderdocshim.vcxproj
@@ -0,0 +1,205 @@
+
+
+
+
+ Profile
+ Win32
+
+
+ Profile
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {6DEE3F12-F2F8-42CA-865A-578D0FD11387}
+ Win32Proj
+ renderdocshim
+
+
+
+ DynamicLibrary
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ Unicode
+
+
+ DynamicLibrary
+ false
+ true
+ Unicode
+
+
+ DynamicLibrary
+ false
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(ProjectName)32
+
+
+ true
+ $(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(ProjectName)64
+
+
+ false
+ $(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(ProjectName)32
+
+
+ false
+ $(Platform)\$(Configuration)\
+ $(SolutionDir)$(Platform)\$(Configuration)\
+ $(ProjectName)64
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ Default
+ false
+ false
+ ProgramDatabase
+ MultiThreaded
+ true
+ false
+
+
+ Windows
+ true
+ kernel32.lib;user32.lib
+ true
+ dll_entry
+ Default
+
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;WIN64;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ MultiThreaded
+ Default
+ false
+ false
+ ProgramDatabase
+ true
+ false
+
+
+ Windows
+ true
+ kernel32.lib;user32.lib
+ true
+ dll_entry
+ Default
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;RELEASE;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ Default
+ false
+ false
+ ProgramDatabase
+ MultiThreaded
+ true
+
+
+ Windows
+ true
+ true
+ true
+ kernel32.lib;user32.lib
+ true
+ dll_entry
+ UseLinkTimeCodeGeneration
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;WIN64;RELEASE;NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)
+ MultiThreaded
+ Default
+ false
+ false
+ ProgramDatabase
+ true
+
+
+ Windows
+ true
+ true
+ true
+ kernel32.lib;user32.lib
+ true
+ dll_entry
+ UseLinkTimeCodeGeneration
+
+
+
+
+ kernel32.lib;user32.lib
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/renderdocshim/renderdocshim.vcxproj.filters b/renderdocshim/renderdocshim.vcxproj.filters
new file mode 100644
index 000000000..1de862269
--- /dev/null
+++ b/renderdocshim/renderdocshim.vcxproj.filters
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/renderdocui/Code/PersistantConfig.cs b/renderdocui/Code/PersistantConfig.cs
index 4c177f160..fadf33c17 100644
--- a/renderdocui/Code/PersistantConfig.cs
+++ b/renderdocui/Code/PersistantConfig.cs
@@ -94,6 +94,8 @@ namespace renderdocui.Code
public bool CheckUpdate_UpdateAvailable = false;
public DateTime CheckUpdate_LastUpdate = new DateTime(2012, 06, 27);
+ public bool AllowGlobalHook = false;
+
public void SetupFormatter()
{
Formatter.MinFigures = Formatter_MinFigures;
@@ -124,8 +126,12 @@ namespace renderdocui.Code
RecentCaptureSettings.Clear();
}
+ public bool ReadOnly = false;
+
public void Serialize(string file)
{
+ if (ReadOnly) return;
+
try
{
ReplayHostKeyValues.Clear();
diff --git a/renderdocui/Code/Win32PInvoke.cs b/renderdocui/Code/Win32PInvoke.cs
index 7094b20e7..16b53365c 100644
--- a/renderdocui/Code/Win32PInvoke.cs
+++ b/renderdocui/Code/Win32PInvoke.cs
@@ -91,5 +91,17 @@ namespace renderdocui.Code
[DllImport("shell32.dll")]
public static extern void SHChangeNotify(HChangeNotifyEventID wEventId, HChangeNotifyFlags uFlags, IntPtr dwItem1, IntPtr dwItem2);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern uint GetShortPathName(string lpszLongPath, char[] lpszShortPath, int cchBuffer);
+
+ public static string ShortPath(string longpath)
+ {
+ char[] buffer = new char[256];
+
+ GetShortPathName(longpath, buffer, buffer.Length);
+
+ return new string(buffer);
+ }
}
}
diff --git a/renderdocui/Interop/StaticExports.cs b/renderdocui/Interop/StaticExports.cs
index 50d55e13b..3986d3bb3 100644
--- a/renderdocui/Interop/StaticExports.cs
+++ b/renderdocui/Interop/StaticExports.cs
@@ -36,6 +36,9 @@ namespace renderdoc
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern ReplayCreateStatus RENDERDOC_CreateReplayRenderer(string logfile, ref float progress, ref IntPtr rendPtr);
+ [DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
+ private static extern void RENDERDOC_StartGlobalHook(string pathmatch, string logfile, CaptureOptions opts);
+
[DllImport("renderdoc.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 RENDERDOC_ExecuteAndInject(string app, string workingDir, string cmdLine,
string logfile, CaptureOptions opts, bool waitForExit);
@@ -94,6 +97,11 @@ namespace renderdoc
return new ReplayRenderer(rendPtr);
}
+ public static void StartGlobalHook(string pathmatch, string logfile, CaptureOptions opts)
+ {
+ RENDERDOC_StartGlobalHook(pathmatch, logfile, opts);
+ }
+
public static UInt32 ExecuteAndInject(string app, string workingDir, string cmdLine, string logfile, CaptureOptions opts)
{
return RENDERDOC_ExecuteAndInject(app, workingDir, cmdLine, logfile, opts, false);
diff --git a/renderdocui/Windows/Dialogs/CaptureDialog.Designer.cs b/renderdocui/Windows/Dialogs/CaptureDialog.Designer.cs
index b08369125..5fab8a5bf 100644
--- a/renderdocui/Windows/Dialogs/CaptureDialog.Designer.cs
+++ b/renderdocui/Windows/Dialogs/CaptureDialog.Designer.cs
@@ -34,10 +34,14 @@
System.Windows.Forms.ColumnHeader pid;
System.Windows.Forms.ColumnHeader name;
System.Windows.Forms.Label label5;
- System.Windows.Forms.GroupBox groupBox1;
- this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();
+ this.globalLabel = new System.Windows.Forms.Label();
+ this.actionsGroup = new System.Windows.Forms.GroupBox();
+ this.actionsFlow = new System.Windows.Forms.FlowLayoutPanel();
this.queueFrameCap = new System.Windows.Forms.CheckBox();
this.queuedCapFrame = new System.Windows.Forms.NumericUpDown();
+ this.globalGroup = new System.Windows.Forms.GroupBox();
+ this.globalFlow = new System.Windows.Forms.FlowLayoutPanel();
+ this.toggleGlobalHook = new System.Windows.Forms.CheckBox();
this.capOptsGroup = new System.Windows.Forms.GroupBox();
this.capOptsFlow = new System.Windows.Forms.FlowLayoutPanel();
this.AllowFullscreen = new System.Windows.Forms.CheckBox();
@@ -79,10 +83,11 @@
pid = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
name = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
label5 = new System.Windows.Forms.Label();
- groupBox1 = new System.Windows.Forms.GroupBox();
- groupBox1.SuspendLayout();
- this.flowLayoutPanel2.SuspendLayout();
+ this.actionsGroup.SuspendLayout();
+ this.actionsFlow.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.queuedCapFrame)).BeginInit();
+ this.globalGroup.SuspendLayout();
+ this.globalFlow.SuspendLayout();
this.capOptsGroup.SuspendLayout();
this.capOptsFlow.SuspendLayout();
this.panel3.SuspendLayout();
@@ -128,32 +133,48 @@
| System.Windows.Forms.AnchorStyles.Right)));
label5.Location = new System.Drawing.Point(9, 16);
label5.Name = "label5";
- label5.Size = new System.Drawing.Size(581, 23);
+ label5.Size = new System.Drawing.Size(473, 23);
label5.TabIndex = 3;
label5.Text = "NOTE: Injecting only works when the process has not used the target API";
//
- // groupBox1
+ // globalLabel
//
- groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ this.globalLabel.AutoSize = true;
+ this.globalLabel.ForeColor = System.Drawing.Color.Red;
+ this.globalLabel.Location = new System.Drawing.Point(3, 3);
+ this.globalLabel.Margin = new System.Windows.Forms.Padding(3);
+ this.globalLabel.Name = "globalLabel";
+ this.globalLabel.Size = new System.Drawing.Size(188, 39);
+ this.globalLabel.TabIndex = 2;
+ this.globalLabel.Text = "Text is set by code Text is set by code\r\nText is set by codeText is set by code\r\n" +
+ "Text is set by codeText is set by code";
+ //
+ // actionsGroup
+ //
+ this.actionsGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
- groupBox1.Controls.Add(this.flowLayoutPanel2);
- groupBox1.Location = new System.Drawing.Point(10, 500);
- groupBox1.Margin = new System.Windows.Forms.Padding(10);
- groupBox1.Name = "groupBox1";
- groupBox1.Size = new System.Drawing.Size(603, 49);
- groupBox1.TabIndex = 11;
- groupBox1.TabStop = false;
- groupBox1.Text = "Actions";
+ this.actionsGroup.AutoSize = true;
+ this.actionsGroup.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.actionsGroup.Controls.Add(this.actionsFlow);
+ this.actionsGroup.Location = new System.Drawing.Point(10, 500);
+ this.actionsGroup.Margin = new System.Windows.Forms.Padding(10);
+ this.actionsGroup.Name = "actionsGroup";
+ this.actionsGroup.Size = new System.Drawing.Size(195, 65);
+ this.actionsGroup.TabIndex = 11;
+ this.actionsGroup.TabStop = false;
+ this.actionsGroup.Text = "Actions";
+ this.actionsGroup.Layout += new System.Windows.Forms.LayoutEventHandler(this.actionsGroup_Layout);
//
- // flowLayoutPanel2
+ // actionsFlow
//
- this.flowLayoutPanel2.Controls.Add(this.queueFrameCap);
- this.flowLayoutPanel2.Controls.Add(this.queuedCapFrame);
- this.flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
- this.flowLayoutPanel2.Location = new System.Drawing.Point(3, 16);
- this.flowLayoutPanel2.Name = "flowLayoutPanel2";
- this.flowLayoutPanel2.Size = new System.Drawing.Size(597, 30);
- this.flowLayoutPanel2.TabIndex = 1;
+ this.actionsFlow.AutoSize = true;
+ this.actionsFlow.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.actionsFlow.Controls.Add(this.queueFrameCap);
+ this.actionsFlow.Controls.Add(this.queuedCapFrame);
+ this.actionsFlow.Location = new System.Drawing.Point(3, 16);
+ this.actionsFlow.Name = "actionsFlow";
+ this.actionsFlow.Size = new System.Drawing.Size(283, 30);
+ this.actionsFlow.TabIndex = 1;
//
// queueFrameCap
//
@@ -188,6 +209,45 @@
0,
0});
//
+ // globalGroup
+ //
+ this.globalGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.globalGroup.AutoSize = true;
+ this.globalGroup.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.globalGroup.Controls.Add(this.globalFlow);
+ this.globalGroup.Location = new System.Drawing.Point(10, 585);
+ this.globalGroup.Margin = new System.Windows.Forms.Padding(10);
+ this.globalGroup.Name = "globalGroup";
+ this.globalGroup.Size = new System.Drawing.Size(195, 80);
+ this.globalGroup.TabIndex = 12;
+ this.globalGroup.TabStop = false;
+ this.globalGroup.Text = "Global Process Hook";
+ this.globalGroup.Layout += new System.Windows.Forms.LayoutEventHandler(this.globalGroup_Layout);
+ //
+ // globalFlow
+ //
+ this.globalFlow.AutoSize = true;
+ this.globalFlow.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+ this.globalFlow.Controls.Add(this.globalLabel);
+ this.globalFlow.Controls.Add(this.toggleGlobalHook);
+ this.globalFlow.Location = new System.Drawing.Point(3, 16);
+ this.globalFlow.Name = "globalFlow";
+ this.globalFlow.Size = new System.Drawing.Size(312, 45);
+ this.globalFlow.TabIndex = 0;
+ //
+ // toggleGlobalHook
+ //
+ this.toggleGlobalHook.Appearance = System.Windows.Forms.Appearance.Button;
+ this.toggleGlobalHook.AutoSize = true;
+ this.toggleGlobalHook.Location = new System.Drawing.Point(197, 3);
+ this.toggleGlobalHook.Name = "toggleGlobalHook";
+ this.toggleGlobalHook.Size = new System.Drawing.Size(112, 23);
+ this.toggleGlobalHook.TabIndex = 3;
+ this.toggleGlobalHook.Text = "Enable Global Hook";
+ this.toggleGlobalHook.UseVisualStyleBackColor = true;
+ this.toggleGlobalHook.CheckedChanged += new System.EventHandler(this.toggleGlobalHook_CheckedChanged);
+ //
// capOptsGroup
//
this.capOptsGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
@@ -198,7 +258,7 @@
this.capOptsGroup.Location = new System.Drawing.Point(10, 367);
this.capOptsGroup.Margin = new System.Windows.Forms.Padding(10);
this.capOptsGroup.Name = "capOptsGroup";
- this.capOptsGroup.Size = new System.Drawing.Size(603, 113);
+ this.capOptsGroup.Size = new System.Drawing.Size(195, 113);
this.capOptsGroup.TabIndex = 4;
this.capOptsGroup.TabStop = false;
this.capOptsGroup.Text = "Capture Options";
@@ -312,7 +372,7 @@
//
// HookIntoChildren
//
- this.HookIntoChildren.Location = new System.Drawing.Point(411, 29);
+ this.HookIntoChildren.Location = new System.Drawing.Point(275, 29);
this.HookIntoChildren.Name = "HookIntoChildren";
this.HookIntoChildren.Size = new System.Drawing.Size(130, 20);
this.HookIntoChildren.TabIndex = 14;
@@ -323,7 +383,7 @@
//
// SaveAllInitials
//
- this.SaveAllInitials.Location = new System.Drawing.Point(3, 55);
+ this.SaveAllInitials.Location = new System.Drawing.Point(411, 29);
this.SaveAllInitials.Name = "SaveAllInitials";
this.SaveAllInitials.Size = new System.Drawing.Size(130, 20);
this.SaveAllInitials.TabIndex = 15;
@@ -333,7 +393,7 @@
//
// RefAllResources
//
- this.RefAllResources.Location = new System.Drawing.Point(139, 55);
+ this.RefAllResources.Location = new System.Drawing.Point(3, 55);
this.RefAllResources.Name = "RefAllResources";
this.RefAllResources.Size = new System.Drawing.Size(130, 20);
this.RefAllResources.TabIndex = 16;
@@ -343,7 +403,7 @@
//
// CaptureAllCmdLists
//
- this.CaptureAllCmdLists.Location = new System.Drawing.Point(275, 55);
+ this.CaptureAllCmdLists.Location = new System.Drawing.Point(139, 55);
this.CaptureAllCmdLists.Name = "CaptureAllCmdLists";
this.CaptureAllCmdLists.Size = new System.Drawing.Size(130, 20);
this.CaptureAllCmdLists.TabIndex = 17;
@@ -354,7 +414,7 @@
//
// AutoStart
//
- this.AutoStart.Location = new System.Drawing.Point(411, 55);
+ this.AutoStart.Location = new System.Drawing.Point(275, 55);
this.AutoStart.Name = "AutoStart";
this.AutoStart.Size = new System.Drawing.Size(130, 20);
this.AutoStart.TabIndex = 18;
@@ -371,19 +431,19 @@
this.panel2.Controls.Add(this.save);
this.panel2.Controls.Add(this.close);
this.panel2.Controls.Add(this.capture);
- this.panel2.Location = new System.Drawing.Point(3, 562);
+ this.panel2.Location = new System.Drawing.Point(3, 678);
this.panel2.Name = "panel2";
- this.panel2.Size = new System.Drawing.Size(617, 26);
+ this.panel2.Size = new System.Drawing.Size(209, 26);
this.panel2.TabIndex = 8;
//
// load
//
this.load.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
- this.load.Location = new System.Drawing.Point(104, 3);
+ this.load.Location = new System.Drawing.Point(50, 3);
this.load.Name = "load";
- this.load.Size = new System.Drawing.Size(86, 23);
+ this.load.Size = new System.Drawing.Size(39, 23);
this.load.TabIndex = 24;
- this.load.Text = "Load Settings";
+ this.load.Text = "Load";
this.toolTip.SetToolTip(this.load, "Load a saved set of capture settings");
this.load.UseVisualStyleBackColor = true;
this.load.Click += new System.EventHandler(this.load_Click);
@@ -393,9 +453,9 @@
this.save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.save.Location = new System.Drawing.Point(4, 3);
this.save.Name = "save";
- this.save.Size = new System.Drawing.Size(94, 23);
+ this.save.Size = new System.Drawing.Size(40, 23);
this.save.TabIndex = 23;
- this.save.Text = "Save Settings";
+ this.save.Text = "Save";
this.toolTip.SetToolTip(this.save, "Save these capture settings to file to load later");
this.save.UseVisualStyleBackColor = true;
this.save.Click += new System.EventHandler(this.save_Click);
@@ -403,10 +463,10 @@
// close
//
this.close.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.close.Location = new System.Drawing.Point(540, 3);
+ this.close.Location = new System.Drawing.Point(162, 3);
this.close.Margin = new System.Windows.Forms.Padding(0);
this.close.Name = "close";
- this.close.Size = new System.Drawing.Size(70, 23);
+ this.close.Size = new System.Drawing.Size(41, 23);
this.close.TabIndex = 22;
this.close.Text = "Close";
this.close.UseVisualStyleBackColor = true;
@@ -415,10 +475,10 @@
// capture
//
this.capture.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.capture.Location = new System.Drawing.Point(464, 3);
+ this.capture.Location = new System.Drawing.Point(105, 3);
this.capture.Margin = new System.Windows.Forms.Padding(0);
this.capture.Name = "capture";
- this.capture.Size = new System.Drawing.Size(70, 23);
+ this.capture.Size = new System.Drawing.Size(52, 23);
this.capture.TabIndex = 21;
this.capture.Text = "Capture";
this.toolTip.SetToolTip(this.capture, "Trigger a capture of the selected program");
@@ -466,14 +526,14 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.cmdline.Location = new System.Drawing.Point(137, 71);
this.cmdline.Name = "cmdline";
- this.cmdline.Size = new System.Drawing.Size(460, 20);
+ this.cmdline.Size = new System.Drawing.Size(52, 20);
this.cmdline.TabIndex = 4;
this.toolTip.SetToolTip(this.cmdline, "The command-line that will be passed to the executable on launch");
//
// workDirBrowse
//
this.workDirBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
- this.workDirBrowse.Location = new System.Drawing.Point(573, 45);
+ this.workDirBrowse.Location = new System.Drawing.Point(165, 45);
this.workDirBrowse.Name = "workDirBrowse";
this.workDirBrowse.Size = new System.Drawing.Size(24, 20);
this.workDirBrowse.TabIndex = 3;
@@ -488,7 +548,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.workDirPath.Location = new System.Drawing.Point(137, 45);
this.workDirPath.Name = "workDirPath";
- this.workDirPath.Size = new System.Drawing.Size(430, 20);
+ this.workDirPath.Size = new System.Drawing.Size(22, 20);
this.workDirPath.TabIndex = 2;
this.toolTip.SetToolTip(this.workDirPath, "The working directory the executable will be launched in");
this.workDirPath.TextChanged += new System.EventHandler(this.workDirPath_TextChanged);
@@ -498,7 +558,7 @@
// exeBrowse
//
this.exeBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
- this.exeBrowse.Location = new System.Drawing.Point(573, 19);
+ this.exeBrowse.Location = new System.Drawing.Point(165, 18);
this.exeBrowse.Name = "exeBrowse";
this.exeBrowse.Size = new System.Drawing.Size(24, 20);
this.exeBrowse.TabIndex = 1;
@@ -514,7 +574,7 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.exePath.Location = new System.Drawing.Point(137, 19);
this.exePath.Name = "exePath";
- this.exePath.Size = new System.Drawing.Size(430, 20);
+ this.exePath.Size = new System.Drawing.Size(22, 20);
this.exePath.TabIndex = 0;
this.toolTip.SetToolTip(this.exePath, "The executable file to launch");
this.exePath.TextChanged += new System.EventHandler(this.exePath_TextChanged);
@@ -524,7 +584,7 @@
// pidRefresh
//
this.pidRefresh.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.pidRefresh.Location = new System.Drawing.Point(518, 180);
+ this.pidRefresh.Location = new System.Drawing.Point(410, 180);
this.pidRefresh.Name = "pidRefresh";
this.pidRefresh.Size = new System.Drawing.Size(75, 23);
this.pidRefresh.TabIndex = 6;
@@ -547,7 +607,7 @@
this.pidList.Location = new System.Drawing.Point(6, 42);
this.pidList.MultiSelect = false;
this.pidList.Name = "pidList";
- this.pidList.Size = new System.Drawing.Size(584, 129);
+ this.pidList.Size = new System.Drawing.Size(183, 129);
this.pidList.TabIndex = 5;
this.toolTip.SetToolTip(this.pidList, "Select the process to inject into - must not yet have utilised the target API");
this.pidList.UseCompatibleStateImageBehavior = false;
@@ -555,23 +615,28 @@
//
// tableLayoutPanel2
//
+ this.tableLayoutPanel2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.tableLayoutPanel2.AutoSize = true;
+ this.tableLayoutPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.tableLayoutPanel2.ColumnCount = 1;
this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.tableLayoutPanel2.Controls.Add(this.programGroup, 0, 0);
- this.tableLayoutPanel2.Controls.Add(this.panel2, 0, 4);
+ this.tableLayoutPanel2.Controls.Add(this.panel2, 0, 5);
this.tableLayoutPanel2.Controls.Add(this.capOptsGroup, 0, 2);
this.tableLayoutPanel2.Controls.Add(this.processGroup, 0, 1);
- this.tableLayoutPanel2.Controls.Add(groupBox1, 0, 3);
- this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel2.Controls.Add(this.actionsGroup, 0, 3);
+ this.tableLayoutPanel2.Controls.Add(this.globalGroup, 0, 4);
this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0);
this.tableLayoutPanel2.Name = "tableLayoutPanel2";
- this.tableLayoutPanel2.RowCount = 5;
+ this.tableLayoutPanel2.RowCount = 6;
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
- this.tableLayoutPanel2.Size = new System.Drawing.Size(623, 761);
+ this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ this.tableLayoutPanel2.Size = new System.Drawing.Size(215, 707);
this.tableLayoutPanel2.TabIndex = 8;
//
// programGroup
@@ -589,7 +654,7 @@
this.programGroup.Location = new System.Drawing.Point(10, 10);
this.programGroup.Margin = new System.Windows.Forms.Padding(10);
this.programGroup.Name = "programGroup";
- this.programGroup.Size = new System.Drawing.Size(603, 108);
+ this.programGroup.Size = new System.Drawing.Size(195, 108);
this.programGroup.TabIndex = 10;
this.programGroup.TabStop = false;
this.programGroup.Text = "Program";
@@ -604,7 +669,7 @@
this.processGroup.Location = new System.Drawing.Point(10, 138);
this.processGroup.Margin = new System.Windows.Forms.Padding(10);
this.processGroup.Name = "processGroup";
- this.processGroup.Size = new System.Drawing.Size(603, 209);
+ this.processGroup.Size = new System.Drawing.Size(195, 209);
this.processGroup.TabIndex = 9;
this.processGroup.TabStop = false;
this.processGroup.Text = "Process";
@@ -614,16 +679,22 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoScroll = true;
- this.AutoScrollMinSize = new System.Drawing.Size(360, 0);
- this.ClientSize = new System.Drawing.Size(623, 761);
+ this.AutoScrollMinSize = new System.Drawing.Size(215, 0);
+ this.ClientSize = new System.Drawing.Size(215, 736);
this.Controls.Add(this.tableLayoutPanel2);
this.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.Name = "CaptureDialog";
this.ShowHint = WeifenLuo.WinFormsUI.Docking.DockState.Document;
this.Text = "CaptureDialog";
- groupBox1.ResumeLayout(false);
- this.flowLayoutPanel2.ResumeLayout(false);
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.CaptureDialog_FormClosing);
+ this.actionsGroup.ResumeLayout(false);
+ this.actionsGroup.PerformLayout();
+ this.actionsFlow.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.queuedCapFrame)).EndInit();
+ this.globalGroup.ResumeLayout(false);
+ this.globalGroup.PerformLayout();
+ this.globalFlow.ResumeLayout(false);
+ this.globalFlow.PerformLayout();
this.capOptsGroup.ResumeLayout(false);
this.capOptsGroup.PerformLayout();
this.capOptsFlow.ResumeLayout(false);
@@ -636,6 +707,7 @@
this.programGroup.PerformLayout();
this.processGroup.ResumeLayout(false);
this.ResumeLayout(false);
+ this.PerformLayout();
}
@@ -676,10 +748,15 @@
private System.Windows.Forms.ListView pidList;
private System.Windows.Forms.Button pidRefresh;
private System.Windows.Forms.CheckBox CaptureAllCmdLists;
- private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2;
+ private System.Windows.Forms.FlowLayoutPanel actionsFlow;
private System.Windows.Forms.NumericUpDown queuedCapFrame;
private System.Windows.Forms.CheckBox queueFrameCap;
private System.Windows.Forms.GroupBox capOptsGroup;
+ private System.Windows.Forms.FlowLayoutPanel globalFlow;
+ private System.Windows.Forms.CheckBox toggleGlobalHook;
+ private System.Windows.Forms.GroupBox actionsGroup;
+ private System.Windows.Forms.GroupBox globalGroup;
+ private System.Windows.Forms.Label globalLabel;
}
}
\ No newline at end of file
diff --git a/renderdocui/Windows/Dialogs/CaptureDialog.cs b/renderdocui/Windows/Dialogs/CaptureDialog.cs
index ba214fe9d..4b7b31f04 100644
--- a/renderdocui/Windows/Dialogs/CaptureDialog.cs
+++ b/renderdocui/Windows/Dialogs/CaptureDialog.cs
@@ -28,14 +28,18 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
-using System.Diagnostics;
using System.Text;
+using System.Threading;
using System.IO;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;
+using Microsoft.Win32;
using renderdocui.Code;
using renderdoc;
+using Process = System.Diagnostics.Process;
+using System.IO.Pipes;
+
namespace renderdocui.Windows.Dialogs
{
public partial class CaptureDialog : DockContent
@@ -134,6 +138,8 @@ namespace renderdocui.Windows.Dialogs
processGroup.Visible = true;
programGroup.Visible = false;
+ globalGroup.Visible = false;
+
capture.Text = "Inject";
FillProcessList();
@@ -145,6 +151,8 @@ namespace renderdocui.Windows.Dialogs
processGroup.Visible = false;
programGroup.Visible = true;
+ globalGroup.Visible = m_Core.Config.AllowGlobalHook;
+
capture.Text = "Capture";
Text = "Capture Executable";
@@ -170,6 +178,8 @@ namespace renderdocui.Windows.Dialogs
workDirPath.ForeColor = SystemColors.GrayText;
SetSettings(defaults);
+
+ UpdateGlobalHook();
}
#region Callbacks
@@ -445,6 +455,16 @@ namespace renderdocui.Windows.Dialogs
capOptsFlow.MaximumSize = new Size(capOptsGroup.ClientRectangle.Width - 8, 0);
}
+ private void actionsGroup_Layout(object sender, LayoutEventArgs e)
+ {
+ actionsFlow.MaximumSize = new Size(actionsGroup.ClientRectangle.Width - 8, 0);
+ }
+
+ private void globalGroup_Layout(object sender, LayoutEventArgs e)
+ {
+ globalFlow.MaximumSize = new Size(globalGroup.ClientRectangle.Width - 8, 0);
+ }
+
private void workDirPath_Enter(object sender, EventArgs e)
{
if (workDirHint)
@@ -470,13 +490,14 @@ namespace renderdocui.Windows.Dialogs
private void exePath_TextChanged(object sender, EventArgs e)
{
UpdateWorkDirHint();
+ UpdateGlobalHook();
}
private void UpdateWorkDirHint()
{
if (workDirHint == false) return;
- if(exePath.Text == "")
+ if (exePath.Text == "")
{
workDirPath.Text = "";
return;
@@ -491,5 +512,335 @@ namespace renderdocui.Windows.Dialogs
// invalid path or similar
}
}
+
+ public void UpdateGlobalHook()
+ {
+ globalGroup.Visible = !InjectMode && m_Core.Config.AllowGlobalHook;
+
+ if (exePath.Text.Length >= 4)
+ {
+ toggleGlobalHook.Enabled = true;
+ globalLabel.Text = "Global hooking is risky!" + Environment.NewLine + Environment.NewLine +
+ "Be sure you know what you're doing.";
+
+ if (toggleGlobalHook.Checked)
+ globalLabel.Text += Environment.NewLine + "Emergency restore @ %TEMP%\\RenderDoc_RestoreGlobalHook.reg";
+ }
+ else
+ {
+ toggleGlobalHook.Enabled = false;
+ globalLabel.Text = "Global hooking requires an executable path, or filename";
+ }
+ }
+
+ private string prevAppInit = "";
+ private string prevAppInitWoW64 = "";
+ private int prevAppInitEnabled = 0;
+ private int prevAppInitWoW64Enabled = 0;
+
+ private AutoResetEvent wakeupEvent = new AutoResetEvent(false);
+ private bool pipeExit = false;
+ private Thread pipeThread = null;
+ private NamedPipeServerStream pipe32 = null;
+ private NamedPipeServerStream pipe64 = null;
+
+ private void EnableAppInit(RegistryKey parent, string path, string dllname, out int prevEnabled, out string prevStr)
+ {
+ RegistryKey key = parent.OpenSubKey("Microsoft", true);
+ if (key == null) { prevEnabled = 0; prevStr = ""; return; }
+
+ key = key.OpenSubKey("Windows NT", true);
+ if (key == null) { prevEnabled = 0; prevStr = ""; return; }
+
+ key = key.OpenSubKey("CurrentVersion", true);
+ if (key == null) { prevEnabled = 0; prevStr = ""; return; }
+
+ key = key.OpenSubKey("Windows", true);
+ if (key == null) { prevEnabled = 0; prevStr = ""; return; }
+
+ object o = key.GetValue("LoadAppInit_DLLs");
+ if (o == null || !(o is int)) { prevEnabled = 0; prevStr = ""; return; }
+ prevEnabled = (int)o;
+
+ o = key.GetValue("AppInit_DLLs");
+ if (o == null || !(o is string)) { prevEnabled = 0; prevStr = ""; return; }
+ prevStr = (string)o;
+
+ key.SetValue("AppInit_DLLs", Win32PInvoke.ShortPath(Path.Combine(path, dllname)));
+ key.SetValue("LoadAppInit_DLLs", (int)1);
+ }
+
+ private void RestoreAppInit(RegistryKey parent, int prevEnabled, string prevStr)
+ {
+ RegistryKey key = parent.OpenSubKey("Microsoft", true);
+ if (key == null) { prevEnabled = 0; prevStr = ""; return; }
+
+ key = key.OpenSubKey("Windows NT", true);
+ if (key == null) { prevEnabled = 0; prevStr = ""; return; }
+
+ key = key.OpenSubKey("CurrentVersion", true);
+ if (key == null) { prevEnabled = 0; prevStr = ""; return; }
+
+ key = key.OpenSubKey("Windows", true);
+ if (key == null) { prevEnabled = 0; prevStr = ""; return; }
+
+ key.SetValue("AppInit_DLLs", prevStr);
+ key.SetValue("LoadAppInit_DLLs", prevEnabled);
+ }
+
+ private void PipeTick()
+ {
+ while (!pipeExit)
+ {
+ wakeupEvent.WaitOne(250);
+ }
+
+ if (pipe32 != null)
+ {
+ if (pipe32.IsConnected)
+ {
+ using (StreamWriter writer = new StreamWriter(pipe32))
+ {
+ writer.Write("exit");
+ writer.Flush();
+ }
+ }
+
+ pipe32.Dispose();
+ pipe32 = null;
+ }
+
+ if (pipe64 != null)
+ {
+ if (pipe64.IsConnected)
+ {
+ using (StreamWriter writer = new StreamWriter(pipe64))
+ {
+ writer.Write("exit");
+ writer.Flush();
+ }
+ }
+
+ pipe64.Dispose();
+ pipe64 = null;
+ }
+ }
+
+ private void ExitPipeThread()
+ {
+ pipeExit = true;
+ wakeupEvent.Set();
+
+ if (pipeThread != null)
+ {
+ if (pipeThread.ThreadState != ThreadState.Aborted &&
+ pipeThread.ThreadState != ThreadState.Stopped)
+ {
+ // try to shut down gracefully
+ pipeThread.Join(1000);
+
+ if (pipeThread.ThreadState != ThreadState.Aborted &&
+ pipeThread.ThreadState != ThreadState.Stopped)
+ {
+ pipeThread.Abort();
+ pipeThread.Join();
+ }
+ }
+ }
+
+ pipeThread = null;
+
+ if (pipe32 != null)
+ {
+ pipe32.Dispose();
+ pipe32 = null;
+ }
+
+ if (pipe64 != null)
+ {
+ pipe64.Dispose();
+ pipe64 = null;
+ }
+ }
+
+ private void toggleGlobalHook_CheckedChanged(object sender, EventArgs e)
+ {
+ if (!toggleGlobalHook.Enabled)
+ return;
+
+ toggleGlobalHook.Enabled = false;
+
+ if (toggleGlobalHook.Checked)
+ {
+ if(!Helpers.IsElevated)
+ {
+ DialogResult res = MessageBox.Show("RenderDoc needs to restart with admin privileges. Restart?", "Restart as admin", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
+
+ if (res == DialogResult.Yes)
+ {
+ string capfile = Path.GetTempFileName() + ".cap";
+
+ AutoStart.Checked = false;
+
+ SaveSettings(capfile);
+
+ var process = new Process();
+ process.StartInfo = new System.Diagnostics.ProcessStartInfo(Application.ExecutablePath, capfile);
+ process.StartInfo.Verb = "runas";
+ try
+ {
+ process.Start();
+ }
+ catch (Exception)
+ {
+ // don't restart if it failed for some reason (e.g. user clicked no to UAC)
+ toggleGlobalHook.Checked = false;
+ toggleGlobalHook.Enabled = true;
+ return;
+ }
+
+ m_Core.Config.Serialize(Core.ConfigFilename);
+ m_Core.Config.ReadOnly = true;
+ m_Core.AppWindow.Close();
+ return;
+ }
+ else
+ {
+ toggleGlobalHook.Checked = false;
+ toggleGlobalHook.Enabled = true;
+ return;
+ }
+ }
+
+ exePath.Enabled = exeBrowse.Enabled =
+ workDirPath.Enabled = workDirBrowse.Enabled =
+ cmdline.Enabled =
+ capture.Enabled = save.Enabled = load.Enabled = false;
+
+ foreach (Control c in capOptsFlow.Controls)
+ c.Enabled = false;
+
+ foreach (Control c in actionsFlow.Controls)
+ c.Enabled = false;
+
+ toggleGlobalHook.Text = "Disable Global Hook";
+
+ var path = Path.GetDirectoryName(Path.GetFullPath(Application.ExecutablePath));
+
+ var regfile = Path.Combine(Path.GetTempPath(), "RenderDoc_RestoreGlobalHook.reg");
+
+ if (Environment.Is64BitProcess)
+ {
+ EnableAppInit(Registry.LocalMachine.CreateSubKey("SOFTWARE").CreateSubKey("Wow6432Node"),
+ path, "x86\\renderdocshim32.dll",
+ out prevAppInitWoW64Enabled, out prevAppInitWoW64);
+
+ EnableAppInit(Registry.LocalMachine.CreateSubKey("SOFTWARE"),
+ path, "renderdocshim64.dll",
+ out prevAppInitEnabled, out prevAppInit);
+
+ using (FileStream s = File.OpenWrite(regfile))
+ {
+ using(StreamWriter sw = new StreamWriter(s))
+ {
+ sw.WriteLine("Windows Registry Editor Version 5.00");
+ sw.WriteLine("");
+ sw.WriteLine("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows]");
+ sw.WriteLine(String.Format("\"LoadAppInit_DLLs\"=dword:{0:X8}", prevAppInitWoW64Enabled));
+ sw.WriteLine(String.Format("\"AppInit_DLLs\"=\"{0}\"", prevAppInitWoW64));
+ sw.WriteLine("");
+ sw.WriteLine("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows]");
+ sw.WriteLine(String.Format("\"LoadAppInit_DLLs\"=dword:{0:X8}", prevAppInitEnabled));
+ sw.WriteLine(String.Format("\"AppInit_DLLs\"=\"{0}\"", prevAppInit));
+ sw.Flush();
+ }
+ }
+ }
+ else
+ {
+ // if this is a 64-bit OS, it will re-direct our request to Wow6432Node anyway, so we
+ // don't need to handle that manually
+ EnableAppInit(Registry.LocalMachine.CreateSubKey("SOFTWARE"), path, "renderdocshim32.dll",
+ out prevAppInitEnabled, out prevAppInit);
+
+ using (FileStream s = File.OpenWrite(regfile))
+ {
+ using (StreamWriter sw = new StreamWriter(s))
+ {
+ sw.WriteLine("Windows Registry Editor Version 5.00");
+ sw.WriteLine("");
+ sw.WriteLine("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows]");
+ sw.WriteLine(String.Format("\"LoadAppInit_DLLs\"=dword:{0:X8}", prevAppInitEnabled));
+ sw.WriteLine(String.Format("\"AppInit_DLLs\"=\"{0}\"", prevAppInit));
+ sw.Flush();
+ }
+ }
+ }
+
+ ExitPipeThread();
+
+ pipeExit = false;
+
+ pipe32 = new NamedPipeServerStream("RenderDoc.GlobalHookControl32");
+ pipe64 = new NamedPipeServerStream("RenderDoc.GlobalHookControl64");
+
+ pipeThread = Helpers.NewThread(new ThreadStart(PipeTick));
+
+ pipeThread.Start();
+
+ string exe = exePath.Text;
+
+ string logfile = exe;
+ if (logfile.Contains("/")) logfile = logfile.Substring(logfile.LastIndexOf('/') + 1);
+ if (logfile.Contains("\\")) logfile = logfile.Substring(logfile.LastIndexOf('\\') + 1);
+ if (logfile.Contains(".")) logfile = logfile.Substring(0, logfile.IndexOf('.'));
+ logfile = m_Core.TempLogFilename(logfile);
+
+ StaticExports.StartGlobalHook(exe, logfile, GetSettings().Options);
+ }
+ else
+ {
+ ExitPipeThread();
+
+ exePath.Enabled = exeBrowse.Enabled =
+ workDirPath.Enabled = workDirBrowse.Enabled =
+ cmdline.Enabled =
+ capture.Enabled = save.Enabled = load.Enabled = true;
+
+ foreach (Control c in capOptsFlow.Controls)
+ c.Enabled = true;
+
+ foreach (Control c in actionsFlow.Controls)
+ c.Enabled = true;
+
+ toggleGlobalHook.Text = "Enable Global Hook";
+
+ if (Environment.Is64BitProcess)
+ {
+ RestoreAppInit(Registry.LocalMachine.CreateSubKey("SOFTWARE").CreateSubKey("Wow6432Node"), prevAppInitWoW64Enabled, prevAppInitWoW64);
+ RestoreAppInit(Registry.LocalMachine.CreateSubKey("SOFTWARE"), prevAppInitEnabled, prevAppInit);
+ }
+ else
+ {
+ // if this is a 64-bit OS, it will re-direct our request to Wow6432Node anyway, so we
+ // don't need to handle that manually
+ RestoreAppInit(Registry.LocalMachine.CreateSubKey("SOFTWARE"), prevAppInitEnabled, prevAppInit);
+ }
+
+ var regfile = Path.Combine(Path.GetTempPath(), "RenderDoc_RestoreGlobalHook.reg");
+
+ if (File.Exists(regfile)) File.Delete(regfile);
+ }
+
+ toggleGlobalHook.Enabled = true;
+
+ UpdateGlobalHook();
+ }
+
+ private void CaptureDialog_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (toggleGlobalHook.Checked)
+ toggleGlobalHook.Checked = false;
+ }
}
}
diff --git a/renderdocui/Windows/Dialogs/CaptureDialog.resx b/renderdocui/Windows/Dialogs/CaptureDialog.resx
index 624222232..8e85281e7 100644
--- a/renderdocui/Windows/Dialogs/CaptureDialog.resx
+++ b/renderdocui/Windows/Dialogs/CaptureDialog.resx
@@ -135,9 +135,6 @@
False
-
- False
-
17, 17
@@ -150,4 +147,7 @@
382, 17
+
+ 485, 17
+
\ No newline at end of file
diff --git a/renderdocui/Windows/Dialogs/SettingsDialog.Designer.cs b/renderdocui/Windows/Dialogs/SettingsDialog.Designer.cs
index 029a06111..f6223979e 100644
--- a/renderdocui/Windows/Dialogs/SettingsDialog.Designer.cs
+++ b/renderdocui/Windows/Dialogs/SettingsDialog.Designer.cs
@@ -32,6 +32,7 @@
System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
System.Windows.Forms.GroupBox groupBox1;
System.Windows.Forms.TableLayoutPanel tableLayoutPanel2;
+ System.Windows.Forms.Label label13;
System.Windows.Forms.Label label6;
System.Windows.Forms.Label label4;
System.Windows.Forms.Label label1;
@@ -47,9 +48,13 @@
System.Windows.Forms.GroupBox groupBox4;
System.Windows.Forms.Label label8;
System.Windows.Forms.Label label9;
- TreelistView.TreeListColumn treeListColumn1 = new TreelistView.TreeListColumn("Section", "Section");
+ TreelistView.TreeListColumn treeListColumn1 = ((TreelistView.TreeListColumn)(new TreelistView.TreeListColumn("Section", "Section")));
+ this.ok = new System.Windows.Forms.Button();
+ this.toolTip = new System.Windows.Forms.ToolTip(this.components);
+ this.browserCaptureDialog = new System.Windows.Forms.FolderBrowserDialog();
this.settingsTabs = new renderdocui.Controls.TablessControl();
this.generalTab = new System.Windows.Forms.TabPage();
+ this.AllowGlobalHook = new System.Windows.Forms.CheckBox();
this.Formatter_PosExp = new System.Windows.Forms.NumericUpDown();
this.Formatter_NegExp = new System.Windows.Forms.NumericUpDown();
this.rdcAssoc = new System.Windows.Forms.Button();
@@ -69,12 +74,10 @@
this.EventBrowser_TimeUnit = new System.Windows.Forms.ComboBox();
this.EventBrowser_HideEmpty = new System.Windows.Forms.CheckBox();
this.pagesTree = new TreelistView.TreeListView();
- this.ok = new System.Windows.Forms.Button();
- this.toolTip = new System.Windows.Forms.ToolTip(this.components);
- this.browserCaptureDialog = new System.Windows.Forms.FolderBrowserDialog();
tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
groupBox1 = new System.Windows.Forms.GroupBox();
tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel();
+ label13 = new System.Windows.Forms.Label();
label6 = new System.Windows.Forms.Label();
label4 = new System.Windows.Forms.Label();
label1 = new System.Windows.Forms.Label();
@@ -128,6 +131,21 @@
tableLayoutPanel1.Size = new System.Drawing.Size(580, 353);
tableLayoutPanel1.TabIndex = 1;
//
+ // ok
+ //
+ this.ok.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.ok.Location = new System.Drawing.Point(502, 327);
+ this.ok.Name = "ok";
+ this.ok.Size = new System.Drawing.Size(75, 23);
+ this.ok.TabIndex = 100;
+ this.ok.Text = "OK";
+ this.ok.UseVisualStyleBackColor = true;
+ this.ok.Click += new System.EventHandler(this.ok_Click);
+ //
+ // browserCaptureDialog
+ //
+ this.browserCaptureDialog.RootFolder = System.Environment.SpecialFolder.MyComputer;
+ //
// settingsTabs
//
this.settingsTabs.Alignment = System.Windows.Forms.TabAlignment.Left;
@@ -170,6 +188,8 @@
tableLayoutPanel2.ColumnCount = 2;
tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ tableLayoutPanel2.Controls.Add(this.AllowGlobalHook, 1, 7);
+ tableLayoutPanel2.Controls.Add(label13, 0, 7);
tableLayoutPanel2.Controls.Add(this.Formatter_PosExp, 1, 5);
tableLayoutPanel2.Controls.Add(this.Formatter_NegExp, 1, 4);
tableLayoutPanel2.Controls.Add(label6, 0, 3);
@@ -182,14 +202,15 @@
tableLayoutPanel2.Controls.Add(label7, 0, 5);
tableLayoutPanel2.Controls.Add(this.Formatter_MaxFigures, 1, 3);
tableLayoutPanel2.Controls.Add(this.Formatter_MinFigures, 1, 2);
- tableLayoutPanel2.Controls.Add(label3, 0, 7);
- tableLayoutPanel2.Controls.Add(this.CheckUpdate_AllowChecks, 1, 7);
+ tableLayoutPanel2.Controls.Add(label3, 0, 8);
+ tableLayoutPanel2.Controls.Add(this.CheckUpdate_AllowChecks, 1, 8);
tableLayoutPanel2.Controls.Add(label11, 0, 6);
tableLayoutPanel2.Controls.Add(this.browseCaptureDirectory, 1, 6);
tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill;
tableLayoutPanel2.Location = new System.Drawing.Point(3, 16);
tableLayoutPanel2.Name = "tableLayoutPanel2";
- tableLayoutPanel2.RowCount = 9;
+ tableLayoutPanel2.RowCount = 10;
+ tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle());
@@ -201,6 +222,35 @@
tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
tableLayoutPanel2.Size = new System.Drawing.Size(361, 285);
tableLayoutPanel2.TabIndex = 0;
+ //
+ // AllowGlobalHook
+ //
+ this.AllowGlobalHook.AutoSize = true;
+ this.AllowGlobalHook.Checked = true;
+ this.AllowGlobalHook.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.AllowGlobalHook.Location = new System.Drawing.Point(268, 194);
+ this.AllowGlobalHook.Name = "AllowGlobalHook";
+ this.AllowGlobalHook.Size = new System.Drawing.Size(15, 14);
+ this.AllowGlobalHook.TabIndex = 16;
+ this.toolTip.SetToolTip(this.AllowGlobalHook, "Allow RenderDoc to insert a global hook into all processes to catch the execution" +
+ " of the desired process, without directly launching it.");
+ this.AllowGlobalHook.UseVisualStyleBackColor = true;
+ this.AllowGlobalHook.CheckedChanged += new System.EventHandler(this.AllowGlobalHook_CheckedChanged);
+ //
+ // label13
+ //
+ label13.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ label13.AutoSize = true;
+ label13.Location = new System.Drawing.Point(3, 191);
+ label13.Name = "label13";
+ label13.Size = new System.Drawing.Size(259, 20);
+ label13.TabIndex = 15;
+ label13.Text = "Allow global process hooking - be careful!";
+ label13.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ this.toolTip.SetToolTip(label13, "Allows RenderDoc to phone home to http://renderdoc.org to anonymously check for n" +
+ "ew versions.");
//
// Formatter_PosExp
//
@@ -408,7 +458,7 @@
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
label3.AutoSize = true;
- label3.Location = new System.Drawing.Point(3, 191);
+ label3.Location = new System.Drawing.Point(3, 211);
label3.Name = "label3";
label3.Size = new System.Drawing.Size(259, 20);
label3.TabIndex = 12;
@@ -422,7 +472,7 @@
this.CheckUpdate_AllowChecks.AutoSize = true;
this.CheckUpdate_AllowChecks.Checked = true;
this.CheckUpdate_AllowChecks.CheckState = System.Windows.Forms.CheckState.Checked;
- this.CheckUpdate_AllowChecks.Location = new System.Drawing.Point(268, 194);
+ this.CheckUpdate_AllowChecks.Location = new System.Drawing.Point(268, 214);
this.CheckUpdate_AllowChecks.Name = "CheckUpdate_AllowChecks";
this.CheckUpdate_AllowChecks.Size = new System.Drawing.Size(15, 14);
this.CheckUpdate_AllowChecks.TabIndex = 8;
@@ -701,21 +751,6 @@
this.pagesTree.ViewOptions.ShowPlusMinus = false;
this.pagesTree.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.pagesTree_AfterSelect);
//
- // ok
- //
- this.ok.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
- this.ok.Location = new System.Drawing.Point(502, 327);
- this.ok.Name = "ok";
- this.ok.Size = new System.Drawing.Size(75, 23);
- this.ok.TabIndex = 100;
- this.ok.Text = "OK";
- this.ok.UseVisualStyleBackColor = true;
- this.ok.Click += new System.EventHandler(this.ok_Click);
- //
- // browserCaptureDialog
- //
- this.browserCaptureDialog.RootFolder = System.Environment.SpecialFolder.MyComputer;
- //
// SettingsDialog
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -779,5 +814,6 @@
private System.Windows.Forms.CheckBox EventBrowser_HideEmpty;
private System.Windows.Forms.Button browseCaptureDirectory;
private System.Windows.Forms.FolderBrowserDialog browserCaptureDialog;
+ private System.Windows.Forms.CheckBox AllowGlobalHook;
}
}
\ No newline at end of file
diff --git a/renderdocui/Windows/Dialogs/SettingsDialog.cs b/renderdocui/Windows/Dialogs/SettingsDialog.cs
index 1feb1919b..82e1ed668 100644
--- a/renderdocui/Windows/Dialogs/SettingsDialog.cs
+++ b/renderdocui/Windows/Dialogs/SettingsDialog.cs
@@ -60,6 +60,8 @@ namespace renderdocui.Windows.Dialogs
TextureViewer_ResetRange.Checked = m_Core.Config.TextureViewer_ResetRange;
ShaderViewer_FriendlyNaming.Checked = m_Core.Config.ShaderViewer_FriendlyNaming;
CheckUpdate_AllowChecks.Checked = m_Core.Config.CheckUpdate_AllowChecks;
+
+ AllowGlobalHook.Checked = m_Core.Config.AllowGlobalHook;
{
Type type = m_Core.Config.EventBrowser_TimeUnit.GetType();
@@ -142,6 +144,16 @@ namespace renderdocui.Windows.Dialogs
m_Core.Config.Serialize(Core.ConfigFilename);
}
+ private void AllowGlobalHook_CheckedChanged(object sender, EventArgs e)
+ {
+ m_Core.Config.AllowGlobalHook = AllowGlobalHook.Checked;
+
+ m_Core.Config.Serialize(Core.ConfigFilename);
+
+ if (m_Core.CaptureDialog != null)
+ m_Core.CaptureDialog.UpdateGlobalHook();
+ }
+
private void EventBrowser_TimeUnit_SelectionChangeCommitted(object sender, EventArgs e)
{
m_Core.Config.EventBrowser_TimeUnit = (PersistantConfig.TimeUnit)EventBrowser_TimeUnit.SelectedIndex;
diff --git a/renderdocui/Windows/Dialogs/SettingsDialog.resx b/renderdocui/Windows/Dialogs/SettingsDialog.resx
index 0a75d9349..9338a19db 100644
--- a/renderdocui/Windows/Dialogs/SettingsDialog.resx
+++ b/renderdocui/Windows/Dialogs/SettingsDialog.resx
@@ -129,6 +129,9 @@
17, 17
+
+ False
+
False