+ os::String wrapperPath = findWrapper(wrapperFilename, verbose);
+ if (!wrapperPath.length()) {
+ std::cerr << "error: failed to find " << wrapperFilename << " wrapper\n";
+ goto exit;
+ }
+
+#if defined(_WIN32)
+ /*
+ * Use DLL injection method on Windows, even for APIs that don't stricly
+ * need it. Except when tracing OpenGL on Windows 8, as the injection
+ * method seems to have troubles tracing the internal
+ * gdi32.dll!SwapBuffers -> opengl32.dll!wglSwapBuffer calls, per github
+ * issue #172.
+ */
+ {
+ OSVERSIONINFO osvi;
+ ZeroMemory(&osvi, sizeof osvi);
+ osvi.dwOSVersionInfoSize = sizeof osvi;
+ GetVersionEx(&osvi);
+ BOOL bIsWindows8orLater =
+ osvi.dwMajorVersion > 6 ||
+ (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion >= 2);
+ if (api != trace::API_GL || !bIsWindows8orLater) {
+ useInject = true;
+ }
+ }
+
+ if (useInject) {
+ args.push_back("inject");
+ args.push_back(wrapperPath);
+ } else {
+ /* On Windows copy the wrapper to the program directory.
+ */
+ if (!copyWrapper(wrapperPath, argv[0], verbose)) {
+ goto exit;
+ }
+ }
+#else /* !_WIN32 */
+ (void)useInject;
+#endif /* !_WIN32 */
+
+#if defined(__APPLE__)
+ /* On Mac OS X, using DYLD_LIBRARY_PATH, we actually set the
+ * directory, not the file. */
+ wrapperPath.trimFilename();
+#endif
+
+ /*
+ * Spawn child process.
+ */
+
+ {
+#if defined(TRACE_VARIABLE)
+ const char *oldEnvVarValue = getenv(TRACE_VARIABLE);
+ if (oldEnvVarValue) {
+ wrapperPath.append(OS_PATH_SEP);
+ wrapperPath.append(oldEnvVarValue);
+ }
+
+ /* FIXME: Don't modify our (ie parent) environment */
+ os::setEnvironment(TRACE_VARIABLE, wrapperPath.str());
+
+ if (verbose) {
+ std::cerr << TRACE_VARIABLE << "=" << wrapperPath.str() << "\n";
+ }
+#endif /* TRACE_VARIABLE */
+
+ if (output) {
+ os::setEnvironment("TRACE_FILE", output);
+ }
+
+ for (char * const * arg = argv; *arg; ++arg) {
+ args.push_back(*arg);
+ }
+
+ if (verbose) {
+ const char *sep = "";
+ for (unsigned i = 0; i < args.size(); ++i) {
+ std::cerr << sep << args[i];
+ sep = " ";
+ }
+ std::cerr << "\n";
+ }
+
+ args.push_back(NULL);
+
+ status = os::execute((char * const *)&args[0]);
+
+#if defined(TRACE_VARIABLE)
+ if (oldEnvVarValue) {
+ os::setEnvironment(TRACE_VARIABLE, oldEnvVarValue);
+ } else {
+ os::unsetEnvironment(TRACE_VARIABLE);
+ }
+#endif
+ }
+
+exit:
+#if defined(_WIN32)
+ if (!useInject) {
+ os::String tmpWrapper(argv[0]);
+ tmpWrapper.trimFilename();
+ tmpWrapper.join(wrapperFilename);
+ os::removeFile(tmpWrapper);
+ }
+#endif
+
+ if (output) {
+ os::unsetEnvironment("TRACE_FILE");
+ }
+
+ return status;
+
+}