diff --git a/renderdoc/core/crash_handler.h b/renderdoc/core/crash_handler.h index 2df792888..f6fa8537c 100644 --- a/renderdoc/core/crash_handler.h +++ b/renderdoc/core/crash_handler.h @@ -89,7 +89,7 @@ public: wstring cmdline = L"\""; cmdline += radpath; - cmdline += L"/renderdoccmd.exe\" --crashhandle"; + cmdline += L"/renderdoccmd.exe\" crashhandle"; wchar_t *paramsAlloc = new wchar_t[512]; diff --git a/renderdoc/os/win32/win32_process.cpp b/renderdoc/os/win32/win32_process.cpp index 2395fcd10..8dde052c6 100644 --- a/renderdoc/os/win32/win32_process.cpp +++ b/renderdoc/os/win32/win32_process.cpp @@ -647,8 +647,9 @@ void Process::StartGlobalHook(const char *pathmatch, const char *logfile, const wstring wlogfile = logfile == NULL ? L"" : StringFormat::UTF82Wide(string(logfile)); wstring wpathmatch = StringFormat::UTF82Wide(string(pathmatch)); - _snwprintf_s(paramsAlloc, 2047, 2047, L"\"%ls\" --globalhook \"%ls\" \"%ls\" \"%hs\"", - renderdocPath, wpathmatch.c_str(), wlogfile.c_str(), optstr.c_str()); + _snwprintf_s(paramsAlloc, 2047, 2047, + L"\"%ls\" globalhook --match \"%ls\" --log \"%ls\" --capopts \"%hs\"", renderdocPath, + wpathmatch.c_str(), wlogfile.c_str(), optstr.c_str()); paramsAlloc[2047] = 0; @@ -665,8 +666,9 @@ void Process::StartGlobalHook(const char *pathmatch, const char *logfile, const wcscat_s(renderdocPath, L"\\x86\\renderdoccmd.exe"); - _snwprintf_s(paramsAlloc, 2047, 2047, L"\"%ls\" --globalhook \"%ls\" \"%ls\" \"%hs\"", - renderdocPath, wpathmatch.c_str(), wlogfile.c_str(), optstr.c_str()); + _snwprintf_s(paramsAlloc, 2047, 2047, + L"\"%ls\" globalhook --match \"%ls\" --log \"%ls\" --capopts \"%hs\"", renderdocPath, + wpathmatch.c_str(), wlogfile.c_str(), optstr.c_str()); paramsAlloc[2047] = 0; diff --git a/renderdoccmd/renderdoccmd_win32.cpp b/renderdoccmd/renderdoccmd_win32.cpp index a6a05829a..a5b553ae8 100644 --- a/renderdoccmd/renderdoccmd_win32.cpp +++ b/renderdoccmd/renderdoccmd_win32.cpp @@ -274,117 +274,16 @@ void DisplayRendererPreview(ReplayRenderer *renderer, TextureDisplay &displayCfg DestroyWindow(wnd); } -// from http://stackoverflow.com/q/29939893/4070143 -// and http://stackoverflow.com/a/4570213/4070143 - -std::string getParentExe() +struct UpgradeCommand : public Command { - DWORD pid = GetCurrentProcessId(); - HANDLE h = NULL; - PROCESSENTRY32 pe = {0}; - DWORD ppid = 0; - pe.dwSize = sizeof(PROCESSENTRY32); - h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if(Process32First(h, &pe)) + virtual void AddOptions(cmdline::parser &parser) { parser.add("path", 0, ""); } + virtual const char *Description() { return "Internal use only!"; } + virtual bool IsInternalOnly() { return true; } + virtual bool IsCaptureCommand() { return false; } + virtual int Execute(cmdline::parser &parser, const CaptureOptions &) { - do - { - if(pe.th32ProcessID == pid) - { - ppid = pe.th32ParentProcessID; - break; - } - } while(Process32Next(h, &pe)); - } - CloseHandle(h); + string originalpath = parser.get("path"); - if(ppid == 0) - return ""; - - h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ppid); - if(h) - { - char buf[MAX_PATH]; - if(GetModuleFileNameExA(h, 0, buf, MAX_PATH)) - { - CloseHandle(h); - return buf; - } - CloseHandle(h); - } - - return ""; -} - -int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, - _In_ int nShowCmd) -{ - LPWSTR *wargv; - int argc; - - wargv = CommandLineToArgvW(GetCommandLine(), &argc); - - std::vector argv; - - argv.resize(argc); - for(size_t i = 0; i < argv.size(); i++) - { - size_t len = wcslen(wargv[i]); - len *= 4; // worst case, every UTF-8 character takes 4 bytes - argv[i].resize(len + 1); - argv[i][len] = 0; - char *cstr = (char *)&argv[i][0]; - - WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, cstr, (int)len + 1, NULL, NULL); - - argv[i].resize(strlen(cstr)); - } - - if(argv.empty()) - argv.push_back("renderdoccmd"); - - LocalFree(wargv); - - // if launched from cmd.exe, be friendly and redirect output - std::string parent = getParentExe(); - for(size_t i = 0; i < parent.length(); i++) - { - parent[i] = tolower(parent[i]); - if(parent[i] == '\\') - parent[i] = '/'; - } - - if(strstr(parent.c_str(), "/cmd.exe") && AttachConsole(ATTACH_PARENT_PROCESS)) - { - freopen("CONOUT$", "w", stdout); - freopen("CONOUT$", "w", stderr); - } - - hInstance = hInst; - - WNDCLASSEX wc; - wc.cbSize = sizeof(WNDCLASSEX); - wc.style = 0; - wc.lpfnWndProc = WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON)); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wc.lpszMenuName = NULL; - wc.lpszClassName = L"renderdoccmd"; - wc.hIconSm = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON)); - - if(!RegisterClassEx(&wc)) - { - return 1; - } - - // special WIN32 option for launching the crash handler - if(argv.size() == 3 && argequal(argv[1], "--update")) - { - string originalpath = argv[2]; wstring wide_path; { @@ -579,13 +478,19 @@ int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ return 0; } +}; #if defined(RELEASE) - CrashGenerationServer *crashServer = NULL; - - // special WIN32 option for launching the crash handler - if(argv.size() == 2 && argequal(argv[1], "--crashhandle")) +struct CrashHandlerCommand : public Command +{ + virtual void AddOptions(cmdline::parser &parser) {} + virtual const char *Description() { return "Internal use only!"; } + virtual bool IsInternalOnly() { return true; } + virtual bool IsCaptureCommand() { return false; } + virtual int Execute(cmdline::parser &parser, const CaptureOptions &) { + CrashGenerationServer *crashServer = NULL; + wchar_t tempPath[MAX_PATH] = {0}; GetTempPathW(MAX_PATH - 1, tempPath); @@ -758,15 +663,27 @@ int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ return 0; } +}; #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(argv.size() == 5 && argequal(argv[1], "--globalhook")) +struct GlobalHookCommand : public Command +{ + virtual void AddOptions(cmdline::parser &parser) { - std::string &pathmatch = argv[2]; - std::string &log = argv[3]; + parser.add("match", 0, ""); + parser.add("log", 0, ""); + parser.add("capopts", 0, ""); + } + virtual const char *Description() { return "Internal use only!"; } + virtual bool IsInternalOnly() { return true; } + virtual bool IsCaptureCommand() { return false; } + virtual int Execute(cmdline::parser &parser, const CaptureOptions &) + { + string pathmatch = parser.get("match"); + string log = parser.get("log"); + + CaptureOptions cmdopts; + readCapOpts(parser.get("capopts").c_str(), &cmdopts); size_t len = pathmatch.length(); wstring wpathmatch; @@ -774,16 +691,13 @@ int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ MultiByteToWideChar(CP_UTF8, 0, pathmatch.c_str(), -1, &wpathmatch[0], (int)len); wpathmatch.resize(wcslen(wpathmatch.c_str())); - CaptureOptions cmdopts; - readCapOpts(argv[4], &cmdopts); - // 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(wpathmatch.length() < 4) { - fprintf( - stderr, - "--globalhook path match is too short/general. Danger of matching too many processes!\n"); + std::cerr + << "globalhook path match is too short/general. Danger of matching too many processes!" + << std::endl; return 1; } @@ -794,7 +708,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ if(rdoc == NULL) { - fprintf(stderr, "--globalhook couldn't find renderdoc.dll!\n"); + std::cerr << "globalhook couldn't find renderdoc.dll!" << std::endl; return 1; } @@ -814,7 +728,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ if(pipe == INVALID_HANDLE_VALUE) { - fprintf(stderr, "--globalhook couldn't open control pipe.\n"); + std::cerr << "globalhook couldn't open control pipe.\n" << std::endl; return 1; } @@ -824,8 +738,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ { CloseHandle(pipe); CloseHandle(datahandle); - fprintf(stderr, - "--globalhook found pre-existing global data, not creating second global hook.\n"); + std::cerr << "globalhook found pre-existing global data, not creating second global hook." + << std::endl; return 1; } @@ -858,20 +772,141 @@ int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ } else { - fprintf(stderr, "--globalhook couldn't map global data store.\n"); + std::cerr << "globalhook couldn't map global data store." << std::endl; } CloseHandle(datahandle); } else { - fprintf(stderr, "--globalhook couldn't create global data store.\n"); + std::cerr << "globalhook couldn't create global data store." << std::endl; } CloseHandle(pipe); return 0; } +}; + +// from http://stackoverflow.com/q/29939893/4070143 +// and http://stackoverflow.com/a/4570213/4070143 + +std::string getParentExe() +{ + DWORD pid = GetCurrentProcessId(); + HANDLE h = NULL; + PROCESSENTRY32 pe = {0}; + DWORD ppid = 0; + pe.dwSize = sizeof(PROCESSENTRY32); + h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if(Process32First(h, &pe)) + { + do + { + if(pe.th32ProcessID == pid) + { + ppid = pe.th32ParentProcessID; + break; + } + } while(Process32Next(h, &pe)); + } + CloseHandle(h); + + if(ppid == 0) + return ""; + + h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ppid); + if(h) + { + char buf[MAX_PATH]; + if(GetModuleFileNameExA(h, 0, buf, MAX_PATH)) + { + CloseHandle(h); + return buf; + } + CloseHandle(h); + } + + return ""; +} + +int WINAPI wWinMain(_In_ HINSTANCE hInst, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, + _In_ int nShowCmd) +{ + LPWSTR *wargv; + int argc; + + wargv = CommandLineToArgvW(GetCommandLine(), &argc); + + std::vector argv; + + argv.resize(argc); + for(size_t i = 0; i < argv.size(); i++) + { + size_t len = wcslen(wargv[i]); + len *= 4; // worst case, every UTF-8 character takes 4 bytes + argv[i].resize(len + 1); + argv[i][len] = 0; + char *cstr = (char *)&argv[i][0]; + + WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, cstr, (int)len + 1, NULL, NULL); + + argv[i].resize(strlen(cstr)); + } + + if(argv.empty()) + argv.push_back("renderdoccmd"); + + LocalFree(wargv); + + // if launched from cmd.exe, be friendly and redirect output + std::string parent = getParentExe(); + for(size_t i = 0; i < parent.length(); i++) + { + parent[i] = tolower(parent[i]); + if(parent[i] == '\\') + parent[i] = '/'; + } + + if(strstr(parent.c_str(), "/cmd.exe") && AttachConsole(ATTACH_PARENT_PROCESS)) + { + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + } + + hInstance = hInst; + + WNDCLASSEX wc; + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = 0; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON)); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = L"renderdoccmd"; + wc.hIconSm = LoadIcon(NULL, MAKEINTRESOURCE(IDI_ICON)); + + if(!RegisterClassEx(&wc)) + { + return 1; + } + + // perform an upgrade of the UI + add_command("upgrade", new UpgradeCommand()); + +#if defined(RELEASE) + // special WIN32 option for launching the crash handler + add_command("crashhandle", new CrashHandlerCommand()); +#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 + add_command("globalhook", new GlobalHookCommand()); return renderdoccmd(argv); } diff --git a/renderdocui/Windows/Dialogs/UpdateDialog.cs b/renderdocui/Windows/Dialogs/UpdateDialog.cs index f00d3404b..633aa08d4 100644 --- a/renderdocui/Windows/Dialogs/UpdateDialog.cs +++ b/renderdocui/Windows/Dialogs/UpdateDialog.cs @@ -171,7 +171,7 @@ namespace renderdocui.Windows.Dialogs File.Copy(Path.Combine(srcpath, "renderdoccmd.exe"), Path.Combine(dstpath, "renderdoccmd.exe"), true); var process = new Process(); - process.StartInfo = new ProcessStartInfo(Path.Combine(dstpath, "renderdoccmd.exe"), "--update \"" + srcpath.Replace('\\', '/') + "/\""); + process.StartInfo = new ProcessStartInfo(Path.Combine(dstpath, "renderdoccmd.exe"), "upgrade --path \"" + srcpath.Replace('\\', '/') + "/\""); process.StartInfo.WorkingDirectory = dstpath; process.StartInfo.Verb = "runas"; // need to run as admin to have write permissions