]> git.cworth.org Git - apitrace/blobdiff - common/os_win32.cpp
Don't call overridden virtual methods from the base destructor.
[apitrace] / common / os_win32.cpp
index f33e175aac4916cc4baa296c219ab2b622c55a0a..13dd4f890a7f5b8ea2788eb4a2dc9182697ecc58 100644 (file)
 #include <string.h>
 #include <stdio.h>
 
+#include <string>
+
 #include "os.hpp"
-#include "os_path.hpp"
+#include "os_string.hpp"
 
 
 namespace os {
@@ -59,10 +61,10 @@ releaseMutex(void)
 }
 
 
-Path
+String
 getProcessName(void)
 {
-    Path path;
+    String path;
     size_t size = MAX_PATH;
     char *buf = path.buf(size);
 
@@ -74,10 +76,10 @@ getProcessName(void)
     return path;
 }
 
-Path
+String
 getCurrentDir(void)
 {
-    Path path;
+    String path;
     size_t size = MAX_PATH;
     char *buf = path.buf(size);
     
@@ -90,6 +92,123 @@ getCurrentDir(void)
     return path;
 }
 
+bool
+String::exists(void) const
+{
+    DWORD attrs = GetFileAttributesA(str());
+    return attrs != INVALID_FILE_ATTRIBUTES;
+}
+
+/**
+ * Determine whether an argument should be quoted.
+ */
+static bool
+needsQuote(const char *arg)
+{
+    char c;
+    while (true) {
+        c = *arg++;
+        if (c == '\0') {
+            break;
+        }
+        if (c == ' ' || c == '\t' || c == '\"') {
+            return true;
+        }
+        if (c == '\\') {
+            c = *arg++;
+            if (c == '\0') {
+                break;
+            }
+            if (c == '"') {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+static void
+quoteArg(std::string &s, const char *arg)
+{
+    char c;
+    unsigned backslashes = 0;
+    
+    s.push_back('"');
+    while (true) {
+        c = *arg++;
+        switch (c)
+        if (c == '\0') {
+            break;
+        } else if (c == '"') {
+            while (backslashes) {
+                s.push_back('\\');
+                --backslashes;
+            }
+            s.push_back('\\');
+        } else {
+            if (c == '\\') {
+                ++backslashes;
+            } else {
+                backslashes = 0;
+            }
+        }
+        s.push_back(c);
+    }
+    s.push_back('"');
+}
+
+int execute(char * const * args)
+{
+    std::string commandLine;
+   
+    const char *arg0 = *args;
+    const char *arg;
+    char sep = 0;
+    while ((arg = *args++) != NULL) {
+        if (sep) {
+            commandLine.push_back(sep);
+        }
+
+        if (needsQuote(arg)) {
+            quoteArg(commandLine, arg);
+        } else {
+            commandLine.append(arg);
+        }
+
+        sep = ' ';
+    }
+
+    STARTUPINFO startupInfo;
+    memset(&startupInfo, 0, sizeof(startupInfo));
+    startupInfo.cb = sizeof(startupInfo);
+
+    PROCESS_INFORMATION processInformation;
+
+    if (!CreateProcessA(NULL,
+                        const_cast<char *>(commandLine.c_str()), // only modified by CreateProcessW
+                        0, // process attributes
+                        0, // thread attributes
+                        FALSE, // inherit handles
+                        0, // creation flags,
+                        NULL, // environment
+                        NULL, // current directory
+                        &startupInfo,
+                        &processInformation
+                        )) {
+        log("error: failed to execute %s\n", arg0);
+    }
+
+    WaitForSingleObject(processInformation.hProcess, INFINITE);
+
+    DWORD exitCode = ~0;
+    GetExitCodeProcess(processInformation.hProcess, &exitCode);
+
+    CloseHandle(processInformation.hProcess);
+    CloseHandle(processInformation.hThread);
+
+    return (int)exitCode;
+}
+
 void
 log(const char *format, ...)
 {