extcap: Remove g_spawn_helper support
authorRoland Knall <rknall@gmail.com>
Tue, 28 Jun 2016 19:34:46 +0000 (21:34 +0200)
committerRoland Knall <rknall@gmail.com>
Tue, 5 Jul 2016 11:54:43 +0000 (11:54 +0000)
 Move g_spawn to separate file and implement functions to
 use Windows based method of spawning, instead of the glib
 based version

Change-Id: Ibae03d834ec86531eba37dc8768fbf17ddadf57f
Reviewed-on: https://code.wireshark.org/review/16049
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Graham Bloice <graham.bloice@trihedral.com>
Reviewed-by: Roland Knall <rknall@gmail.com>
CMakeLists.txt
Makefile.am
capture_opts.c
capture_opts.h
extcap.c
extcap_spawn.c [new file with mode: 0644]
extcap_spawn.h [new file with mode: 0644]
packaging/nsis/CMakeLists.txt
packaging/wix/CMakeLists.txt
tools/Get-HardenFlags.ps1

index c79ee445fa98632e297018b38159e8202cf9d906..9bfaf689439e5dac3dd7bfcd0ef0361b71127c6b 100644 (file)
@@ -1280,6 +1280,7 @@ if(ENABLE_EXTCAP)
                ${SHARK_COMMON_SRC}
                extcap.c
                extcap_parser.c
+               extcap_spawn.c
        )
 endif()
 
index a4458e0a6d8330825f9ea0e0d53a563bcffc250c..a6149110c1a99fa433ab60d1f4cca576cdd82342 100644 (file)
@@ -383,11 +383,13 @@ GENERATED_FILES = $(GENERATED_C_FILES) $(GENERATED_HEADER_FILES)
 
 EXTCAP_COMMON_SRC = \
        extcap.c                \
-       extcap_parser.c
+       extcap_parser.c \
+       extcap_spawn.c
 
 EXTCAP_COMMON_INCLUDES = \
        extcap.h                \
-       extcap_parser.h
+       extcap_parser.h \
+       extcap_spawn.h
 
 # sources common for wireshark, tshark, and rawshark
 SHARK_COMMON_SRC = \
index f383c82a94a43bb1b41a99523f63389428478092..2eb5b630d141469f6239a8b56922cfc15cd7ac8a 100644 (file)
@@ -685,6 +685,7 @@ capture_opts_add_iface_opt(capture_options *capture_opts, const char *optarg_str
     interface_opts.extcap_fifo = g_strdup(capture_opts->default_options.extcap_fifo);
     interface_opts.extcap_args = NULL;
     interface_opts.extcap_pid = INVALID_EXTCAP_PID;
+    interface_opts.extcap_userdata = NULL;
 #endif
 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
     interface_opts.buffer_size = capture_opts->default_options.buffer_size;
@@ -1111,6 +1112,7 @@ capture_opts_del_iface(capture_options *capture_opts, guint if_index)
         g_hash_table_unref(interface_opts.extcap_args);
     if (interface_opts.extcap_pid != INVALID_EXTCAP_PID)
         g_spawn_close_pid(interface_opts.extcap_pid);
+    g_free(interface_opts.extcap_userdata);
 #endif
 #ifdef HAVE_PCAP_REMOTE
     if (interface_opts.src_type == CAPTURE_IFREMOTE) {
@@ -1160,6 +1162,7 @@ collect_ifaces(capture_options *capture_opts)
             interface_opts.extcap_pid = INVALID_EXTCAP_PID;
             if (interface_opts.extcap_args)
                 g_hash_table_ref(interface_opts.extcap_args);
+            interface_opts.extcap_userdata = NULL;
 #endif
 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
             interface_opts.buffer_size =  device.buffer;
index 4a8bddb1e610d69aef002bed1f1696ef7d7b27db..4fc4d67fd1362f9e5818ff2d009be7379b0e2c88 100644 (file)
@@ -233,6 +233,7 @@ typedef struct interface_options_tag {
     gchar            *extcap_fifo;
     GHashTable       *extcap_args;
     GPid              extcap_pid;           /* pid of running process or INVALID_EXTCAP_PID */
+    gpointer          extcap_userdata;
     guint             extcap_child_watch;
 #endif
 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
index 29f931ac125a81f9c2178044e1e3301a67de4a55..cff843487c50e6ebd94c403153cf038fc65c56d6 100644 (file)
--- a/extcap.c
+++ b/extcap.c
@@ -51,6 +51,7 @@
 
 #include "extcap.h"
 #include "extcap_parser.h"
+#include "extcap_spawn.h"
 
 #ifdef _WIN32
 static HANDLE pipe_h = NULL;
@@ -153,67 +154,28 @@ static void extcap_foreach(gint argc, gchar **args, extcap_cb_t cb,
     GDir *dir;
     const gchar *file;
     gboolean keep_going;
-    gint i;
-    gchar **argv;
-#ifdef _WIN32
-    gchar **dll_search_envp;
-    gchar *progfile_dir;
-#endif
 
     keep_going = TRUE;
 
-    argv = (gchar **) g_malloc0(sizeof(gchar *) * (argc + 2));
-
-#ifdef _WIN32
-    /*
-     * Make sure executables can find dependent DLLs and that they're *our*
-     * DLLs: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586.aspx
-     * Alternatively we could create a simple wrapper exe similar to Create
-     * Hidden Process (http://www.commandline.co.uk/chp/).
-     */
-    dll_search_envp = g_get_environ();
-    progfile_dir = g_strdup_printf("%s;%s", get_progfile_dir(), g_environ_getenv(dll_search_envp, "Path"));
-    dll_search_envp = g_environ_setenv(dll_search_envp, "Path", progfile_dir, TRUE);
-    g_free(progfile_dir);
-#endif
-
     if ((dir = g_dir_open(dirname, 0, NULL)) != NULL) {
         GString *extcap_path = NULL;
 
         extcap_path = g_string_new("");
         while (keep_going && (file = g_dir_read_name(dir)) != NULL ) {
             gchar *command_output = NULL;
-            gboolean status = FALSE;
-            gint exit_status = 0;
-            gchar **envp = NULL;
 
             /* full path to extcap binary */
 #ifdef _WIN32
             g_string_printf(extcap_path, "%s\\%s", dirname, file);
-            envp = dll_search_envp;
 #else
             g_string_printf(extcap_path, "%s/%s", dirname, file);
 #endif
             if ( extcap_if_exists(ifname) && !extcap_if_exists_for_extcap(ifname, extcap_path->str ) )
                 continue;
 
-#ifdef _WIN32
-            argv[0] = g_strescape(extcap_path->str, NULL);
-#else
-            argv[0] = g_strdup(extcap_path->str);
-#endif
-            for (i = 0; i < argc; ++i)
-                argv[i+1] = args[i];
-            argv[argc+1] = NULL;
-
-            status = g_spawn_sync(dirname, argv, envp,
-                (GSpawnFlags) 0, NULL, NULL,
-                    &command_output, NULL, &exit_status, NULL);
-
-            if (status && exit_status == 0)
+            if ( extcap_spawn_sync ( (gchar *) dirname, extcap_path->str, argc, args, &command_output ) )
                 keep_going = cb(extcap_path->str, ifname, command_output, cb_data, err_str);
 
-            g_free(argv[0]);
             g_free(command_output);
         }
 
@@ -221,10 +183,6 @@ static void extcap_foreach(gint argc, gchar **args, extcap_cb_t cb,
         g_string_free(extcap_path, TRUE);
     }
 
-#ifdef _WIN32
-    g_strfreev(dll_search_envp);
-#endif
-    g_free(argv);
 }
 
 static gboolean dlt_cb(const gchar *extcap _U_, const gchar *ifname _U_, gchar *output, void *data,
@@ -644,7 +602,7 @@ void extcap_cleanup(capture_options * capture_opts) {
 
         /* skip native interfaces */
         if (interface_opts.if_type != IF_EXTCAP)
-        continue;
+            continue;
 
         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
                 "Extcap [%s] - Cleaning up fifo: %s; PID: %d", interface_opts.name,
@@ -730,34 +688,20 @@ static void extcap_child_watch_cb(GPid pid, gint status _U_, gpointer user_data)
     }
 }
 
-/* call mkfifo for each extcap,
- * returns FALSE if there's an error creating a FIFO */
-gboolean
-extcap_init_interfaces(capture_options *capture_opts)
+static
+GPtrArray * extcap_prepare_arguments(interface_options interface_opts)
 {
-    guint i;
-    interface_options interface_opts;
-
-    for (i = 0; i < capture_opts->ifaces->len; i++)
-    {
-        GPtrArray *args = NULL;
-        GPid pid = INVALID_EXTCAP_PID;
-        gchar **tmp;
-        int tmp_i;
-
-        interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
-
-        /* skip native interfaces */
-        if (interface_opts.if_type != IF_EXTCAP )
-            continue;
+       GPtrArray *result = NULL;
+#if ARG_DEBUG
+    gchar **tmp;
+    int tmp_i;
+#endif
 
-        /* create pipe for fifo */
-        if ( ! extcap_create_pipe ( &interface_opts.extcap_fifo ) )
-            return FALSE;
+       if (interface_opts.if_type == IF_EXTCAP )
+       {
+               result = g_ptr_array_new();
 
-        /* Create extcap call */
-        args = g_ptr_array_new();
-#define add_arg(X) g_ptr_array_add(args, g_strdup(X))
+#define add_arg(X) g_ptr_array_add(result, g_strdup(X))
 
         add_arg(interface_opts.extcap);
         add_arg(EXTCAP_ARGUMENT_RUN_CAPTURE);
@@ -824,26 +768,62 @@ extcap_init_interfaces(capture_options *capture_opts)
         }
         else
         {
-            g_hash_table_foreach_remove(interface_opts.extcap_args, extcap_add_arg_and_remove_cb, args);
+            g_hash_table_foreach_remove(interface_opts.extcap_args, extcap_add_arg_and_remove_cb, result);
         }
         add_arg(NULL);
 #undef add_arg
 
+#if ARG_DEBUG
         /* Dump commandline parameters sent to extcap. */
-        for (tmp = (gchar **)args->pdata, tmp_i = 0; *tmp && **tmp; ++tmp_i, ++tmp)
+        for (tmp = (gchar **)result->pdata, tmp_i = 0; *tmp && **tmp; ++tmp_i, ++tmp)
         {
             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "argv[%d]: %s", tmp_i, *tmp);
         }
+#endif
+
+       }
 
-        /* Wireshark for windows crashes here sometimes *
-         * Access violation reading location 0x...      */
-        g_spawn_async(NULL, (gchar **)args->pdata, NULL,
-                    (GSpawnFlags) G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
-                    &pid,NULL);
+       return result;
+}
+
+/* call mkfifo for each extcap,
+ * returns FALSE if there's an error creating a FIFO */
+gboolean
+extcap_init_interfaces(capture_options *capture_opts)
+{
+    guint i;
+    interface_options interface_opts;
+
+    for (i = 0; i < capture_opts->ifaces->len; i++)
+    {
+        GPtrArray *args = NULL;
+        GPid pid = INVALID_EXTCAP_PID;
+
+        interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
+
+        /* skip native interfaces */
+        if (interface_opts.if_type != IF_EXTCAP )
+            continue;
+
+        /* create pipe for fifo */
+        if ( ! extcap_create_pipe ( &interface_opts.extcap_fifo ) )
+            return FALSE;
+
+        /* Create extcap call */
+        args = extcap_prepare_arguments(interface_opts);
+
+        interface_opts.extcap_userdata = NULL;
+
+        pid = extcap_spawn_async(&interface_opts, args );
 
         g_ptr_array_foreach(args, (GFunc)g_free, NULL);
         g_ptr_array_free(args, TRUE);
+
+        if ( pid == INVALID_EXTCAP_PID )
+            continue;
+
         interface_opts.extcap_pid = pid;
+
         interface_opts.extcap_child_watch =
             g_child_watch_add(pid, extcap_child_watch_cb, (gpointer)capture_opts);
         capture_opts->ifaces = g_array_remove_index(capture_opts->ifaces, i);
@@ -861,60 +841,7 @@ extcap_init_interfaces(capture_options *capture_opts)
          */
         if (pid != INVALID_EXTCAP_PID)
         {
-            DWORD dw;
-            HANDLE handles[2];
-            OVERLAPPED ov;
-            ov.Pointer = 0;
-            ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
-            ConnectNamedPipe(pipe_h, &ov);
-            handles[0] = ov.hEvent;
-            handles[1] = pid;
-
-            if (GetLastError() == ERROR_PIPE_CONNECTED)
-            {
-                g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap connected to pipe");
-            }
-            else
-            {
-                dw = WaitForMultipleObjects(2, handles, FALSE, 30000);
-                if (dw == WAIT_OBJECT_0)
-                {
-                    /* ConnectNamedPipe finished. */
-                    DWORD code;
-
-                    code = GetLastError();
-                    if (code == ERROR_IO_PENDING)
-                    {
-                        DWORD dummy;
-                        if (!GetOverlappedResult(ov.hEvent, &ov, &dummy, TRUE))
-                        {
-                            code = GetLastError();
-                        }
-                        else
-                        {
-                            code = ERROR_SUCCESS;
-                        }
-                    }
-
-                    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe code: %d", code);
-                }
-                else if (dw == (WAIT_OBJECT_0 + 1))
-                {
-                    /* extcap process terminated. */
-                    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe!");
-                }
-                else if (dw == WAIT_TIMEOUT)
-                {
-                    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds!");
-                }
-                else
-                {
-                    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "WaitForMultipleObjects returned 0x%08X. Error %d", dw, GetLastError());
-                }
-            }
-
-            CloseHandle(ov.hEvent);
+            extcap_wait_for_pipe(pipe_h, pid);
         }
 #endif
     }
diff --git a/extcap_spawn.c b/extcap_spawn.c
new file mode 100644 (file)
index 0000000..555958c
--- /dev/null
@@ -0,0 +1,368 @@
+/* extcap_spawn.c
+ *
+ * Routines to spawn extcap external capture programs
+ * Copyright 2016, Roland Knall <rknall@gmail.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <glib.h>
+#include <string.h>
+
+#include <wsutil/file_util.h>
+#include <wsutil/filesystem.h>
+#ifdef _WIN32
+#include <wsutil/win32-utils.h>
+#endif
+
+#include <log.h>
+
+#include "extcap.h"
+#include "extcap_spawn.h"
+
+#ifdef _WIN32
+
+void win32_readfrompipe(HANDLE read_pipe, gint32 max_buffer, gchar * buffer)
+{
+    gboolean bSuccess = FALSE;
+    gint32 bytes_written = 0;
+    gint32 max_bytes = 0;
+
+    DWORD dwRead;
+    DWORD bytes_avail = 0;
+
+    for (;;)
+    {
+        if (!PeekNamedPipe(read_pipe, NULL, 0, NULL, &bytes_avail, NULL)) break;
+        if (bytes_avail <= 0) break;
+
+        max_bytes = max_buffer - bytes_written - 1;
+
+        bSuccess = ReadFile(read_pipe, &buffer[bytes_written], max_bytes, &dwRead, NULL);
+        if (!bSuccess || dwRead == 0) break;
+
+        bytes_written += dwRead;
+        if ((bytes_written + 1) >= max_buffer) break;
+    }
+
+    buffer[bytes_written] = '\0';
+}
+#endif
+
+gboolean extcap_spawn_sync ( gchar * dirname, gchar * command, gint argc, gchar ** args, gchar ** command_output )
+{
+    gboolean status = FALSE;
+    gboolean result = FALSE;
+    gchar ** argv = NULL;
+    gint cnt = 0;
+    gchar * local_output = NULL;
+#ifdef _WIN32
+
+#define BUFFER_SIZE 4096
+    gchar buffer[BUFFER_SIZE];
+
+    GString *winargs = g_string_sized_new(200);
+    gchar *quoted_arg;
+    gunichar2 *wcommandline;
+
+    STARTUPINFO info;
+    PROCESS_INFORMATION processInfo;
+
+    SECURITY_ATTRIBUTES sa;
+    HANDLE child_stdout_rd = NULL;
+    HANDLE child_stdout_wr = NULL;
+    HANDLE child_stderr_rd = NULL;
+    HANDLE child_stderr_wr = NULL;
+
+    const gchar * oldpath = g_getenv("PATH");
+    gchar * newpath = NULL;
+#else
+    gint exit_status = 0;
+#endif
+
+    argv = (gchar **) g_malloc0(sizeof(gchar *) * (argc + 2));
+
+#ifdef _WIN32
+    newpath = g_strdup_printf("%s;%s", g_strescape(get_progfile_dir(), NULL), oldpath);
+    g_setenv("PATH", newpath, TRUE);
+
+    argv[0] = g_strescape(command, NULL);
+#else
+    argv[0] = g_strdup(command);
+#endif
+
+    for ( cnt = 0; cnt < argc; cnt++ )
+        argv[cnt+1] = args[cnt];
+    argv[argc+1] = NULL;
+
+#ifdef _WIN32
+
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.bInheritHandle = TRUE;
+    sa.lpSecurityDescriptor = NULL;
+
+    if (!CreatePipe(&child_stdout_rd, &child_stdout_wr, &sa, 0))
+    {
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create stdout handle");
+        return FALSE;
+    }
+
+    if (!CreatePipe(&child_stderr_rd, &child_stderr_wr, &sa, 0))
+    {
+        CloseHandle(child_stdout_rd);
+        CloseHandle(child_stdout_wr);
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create stderr handle");
+        return FALSE;
+    }
+
+    /* convert args array into a single string */
+    /* XXX - could change sync_pipe_add_arg() instead */
+    /* there is a drawback here: the length is internally limited to 1024 bytes */
+    for (cnt = 0; argv[cnt] != 0; cnt++) {
+        if (cnt != 0) g_string_append_c(winargs, ' ');    /* don't prepend a space before the path!!! */
+        quoted_arg = protect_arg(argv[cnt]);
+        g_string_append(winargs, quoted_arg);
+        g_free(quoted_arg);
+    }
+
+    wcommandline = g_utf8_to_utf16(winargs->str, (glong)winargs->len, NULL, NULL, NULL);
+
+    memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
+    memset(&info, 0, sizeof(STARTUPINFO));
+
+    info.cb = sizeof(STARTUPINFO);
+    info.hStdError = child_stderr_wr;
+    info.hStdOutput = child_stdout_wr;
+    info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+    info.wShowWindow = SW_HIDE;
+
+    if (CreateProcess(NULL, wcommandline, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &info, &processInfo))
+    {
+        WaitForSingleObject(processInfo.hProcess, INFINITE);
+        win32_readfrompipe(child_stdout_rd, BUFFER_SIZE, buffer);
+        local_output = g_strdup_printf("%s", buffer);
+
+        CloseHandle(child_stdout_rd);
+        CloseHandle(child_stdout_wr);
+        CloseHandle(child_stderr_rd);
+        CloseHandle(child_stderr_wr);
+
+        CloseHandle(processInfo.hProcess);
+        CloseHandle(processInfo.hThread);
+        status = TRUE;
+    }
+    else
+        status = FALSE;
+
+    g_setenv("PATH", oldpath, TRUE);
+#else
+
+    status = g_spawn_sync(dirname, argv, NULL,
+            (GSpawnFlags) 0, NULL, NULL, &local_output, NULL, &exit_status, NULL);
+
+    if (status && exit_status != 0)
+        status = FALSE;
+#endif
+
+    if (status)
+    {
+        if ( command_output != NULL && local_output != NULL )
+            *command_output = g_strdup(local_output);
+
+        result = TRUE;
+    }
+
+    g_free(local_output);
+    g_free(argv);
+
+    return result;
+}
+
+GPid extcap_spawn_async(interface_options * interface, GPtrArray * args)
+{
+    GPid pid = INVALID_EXTCAP_PID;
+
+#ifdef _WIN32
+    gint cnt = 0;
+    gchar ** tmp = NULL;
+
+    GString *winargs = g_string_sized_new(200);
+    gchar *quoted_arg;
+    gunichar2 *wcommandline;
+
+    STARTUPINFO info;
+    PROCESS_INFORMATION processInfo;
+
+    SECURITY_ATTRIBUTES sa;
+    HANDLE child_stdout_rd = NULL;
+    HANDLE child_stdout_wr = NULL;
+    HANDLE child_stderr_rd = NULL;
+    HANDLE child_stderr_wr = NULL;
+
+    const gchar * oldpath = g_getenv("PATH");
+    gchar * newpath = NULL;
+
+#endif
+
+    extcap_userdata * userdata = NULL;
+    userdata = (extcap_userdata *) g_malloc0(sizeof(extcap_userdata));
+
+#ifdef _WIN32
+    newpath = g_strdup_printf("%s;%s", g_strescape(get_progfile_dir(), NULL), oldpath);
+    g_setenv("PATH", newpath, TRUE);
+
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.bInheritHandle = TRUE;
+    sa.lpSecurityDescriptor = NULL;
+
+    if (!CreatePipe(&child_stdout_rd, &child_stdout_wr, &sa, 0))
+    {
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create stdout handle");
+        return FALSE;
+    }
+
+    if (!CreatePipe(&child_stderr_rd, &child_stderr_wr, &sa, 0))
+    {
+        CloseHandle(child_stdout_rd);
+        CloseHandle(child_stdout_wr);
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create stderr handle");
+        return FALSE;
+    }
+
+    /* convert args array into a single string */
+    /* XXX - could change sync_pipe_add_arg() instead */
+    /* there is a drawback here: the length is internally limited to 1024 bytes */
+    for (tmp = (gchar **)args->pdata, cnt = 0; *tmp && **tmp; ++cnt, ++tmp) {
+        if (cnt != 0) g_string_append_c(winargs, ' ');    /* don't prepend a space before the path!!! */
+        quoted_arg = protect_arg(*tmp);
+        g_string_append(winargs, quoted_arg);
+        g_free(quoted_arg);
+    }
+
+    wcommandline = g_utf8_to_utf16(winargs->str, (glong)winargs->len, NULL, NULL, NULL);
+
+    memset(&processInfo, 0, sizeof(PROCESS_INFORMATION));
+    memset(&info, 0, sizeof(STARTUPINFO));
+
+    info.cb = sizeof(STARTUPINFO);
+    info.hStdError = child_stderr_wr;
+    info.hStdOutput = child_stdout_wr;
+    info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
+    info.wShowWindow = SW_HIDE;
+
+    if (CreateProcess(NULL, wcommandline, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &info, &processInfo))
+    {
+        userdata->extcap_stderr_rd = _open_osfhandle((intptr_t)(child_stderr_rd), _O_BINARY);
+        userdata->extcap_stdout_rd = _open_osfhandle((intptr_t)(child_stdout_rd), _O_BINARY);
+        userdata->threadId = processInfo.hThread;
+        pid = processInfo.hProcess;
+    }
+
+    g_setenv("PATH", oldpath, TRUE);
+#else
+    g_spawn_async(NULL, (gchar **)args->pdata, NULL, (GSpawnFlags) G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL,
+            &pid, NULL);
+#endif
+
+    userdata->pid = pid;
+    interface->extcap_userdata = userdata;
+
+    return pid;
+}
+
+#ifdef _WIN32
+gboolean
+extcap_wait_for_pipe(HANDLE pipe_h, HANDLE pid)
+{
+    DWORD dw;
+    HANDLE handles[2];
+    OVERLAPPED ov;
+    ov.Pointer = 0;
+    gboolean success = FALSE;
+    ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+    ConnectNamedPipe(pipe_h, &ov);
+    handles[0] = ov.hEvent;
+    handles[1] = pid;
+
+    if (GetLastError() == ERROR_PIPE_CONNECTED)
+    {
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap connected to pipe");
+    }
+    else
+    {
+        dw = WaitForMultipleObjects(2, handles, FALSE, 30000);
+        if (dw == WAIT_OBJECT_0)
+        {
+            /* ConnectNamedPipe finished. */
+            DWORD code;
+
+            code = GetLastError();
+            if (code == ERROR_IO_PENDING)
+            {
+                DWORD dummy;
+                if (!GetOverlappedResult(ov.hEvent, &ov, &dummy, TRUE))
+                {
+                    code = GetLastError();
+                }
+                else
+                {
+                    code = ERROR_SUCCESS;
+                    success = TRUE;
+                }
+            }
+
+            g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe code: %d", code);
+        }
+        else if (dw == (WAIT_OBJECT_0 + 1))
+        {
+            /* extcap process terminated. */
+            g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe!");
+        }
+        else if (dw == WAIT_TIMEOUT)
+        {
+            g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds!");
+        }
+        else
+        {
+            g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "WaitForMultipleObjects returned 0x%08X. Error %d", dw, GetLastError());
+        }
+    }
+
+    CloseHandle(ov.hEvent);
+
+    return success;
+}
+#endif
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/extcap_spawn.h b/extcap_spawn.h
new file mode 100644 (file)
index 0000000..b9b2ef4
--- /dev/null
@@ -0,0 +1,67 @@
+/* extcap_spawn.h
+ * Helper routines for executing extcap utilities
+ *
+ * Copyright 2016, Roland Knall <rknall@gmail.com>
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __EXTCAP_SPAWN_H__
+#define __EXTCAP_SPAWN_H__
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <extcap.h>
+
+typedef struct _extcap_userdata {
+    GPid pid;
+    gchar * extcap_stderr;
+    gint exitcode;
+    gint extcap_stderr_rd;
+    gint extcap_stdout_rd;
+#ifdef _WIN32
+    HANDLE threadId;
+#endif
+} extcap_userdata;
+
+gboolean extcap_spawn_sync ( gchar * dirname, gchar * command, gint argc, gchar ** argv, gchar ** command_output );
+
+GPid extcap_spawn_async ( interface_options * interface, GPtrArray * args );
+
+#ifdef _WIN32
+gboolean extcap_wait_for_pipe(HANDLE pipe_h, HANDLE pid);
+void win32_readfrompipe(HANDLE read_pipe, gint32 max_buffer, gchar * buffer);
+#endif
+
+#endif
+
+/*
+ * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
+ *
+ * Local variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
index 7ecb927dd838904d1ac36c2ef28f140189f453f8..3452568999be04b5cc11b8c728bfda74d8a922ea 100644 (file)
@@ -125,8 +125,6 @@ foreach(_dll ${GLIB2_DLLS} ${CARES_DLL} ${GCRYPT_DLLS} ${GEOIP_DLL}
        )
        set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\${_dll}\"\n")
 endforeach()
-set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\gspawn-${WIRESHARK_TARGET_PLATFORM}-helper.exe\"\n")
-set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\gspawn-${WIRESHARK_TARGET_PLATFORM}-helper-console.exe\"\n")
 foreach(_script "init.lua" "console.lua" "dtd_gen.lua")
        set(_all_manifest_contents "${_all_manifest_contents}File \"\${STAGING_DIR}\\${_script}\"\n")
 endforeach()
index ed9f035a9cd70e3e70f62c95a782cd48732ba98f..065e279aa6dc86df16b67d32e9b1d4f511fddc83 100644 (file)
@@ -134,12 +134,6 @@ foreach(_dll ${GLIB2_DLLS} ${CARES_DLL} ${GCRYPT_DLLS} ${GEOIP_DLL}
                SET(unique_component ${unique_component} ${_dll})
        ENDIF(NOT "${unique_component}" MATCHES "(^|;)${_dll}(;|$)")
 endforeach()
-file(APPEND "${_all_manifest_wix}" "       <Component Id=\"cmpGSpawn_${WIRESHARK_TARGET_PLATFORM}_helper_exe\" Guid=\"*\">\n")
-file(APPEND "${_all_manifest_wix}" "         <File Id=\"filSpawn_${WIRESHARK_TARGET_PLATFORM}_helper_exe\" KeyPath=\"yes\" Source=\"$(var.Staging.Dir)\\gspawn-${WIRESHARK_TARGET_PLATFORM}-helper.exe\"/>\n")
-file(APPEND "${_all_manifest_wix}" "       </Component>\n")
-file(APPEND "${_all_manifest_wix}" "       <Component Id=\"cmpGSpawn_${WIRESHARK_TARGET_PLATFORM}_helper_console_exe\" Guid=\"*\">\n")
-file(APPEND "${_all_manifest_wix}" "         <File Id=\"filSpawn_${WIRESHARK_TARGET_PLATFORM}_helper_console_exe\" KeyPath=\"yes\" Source=\"$(var.Staging.Dir)\\gspawn-${WIRESHARK_TARGET_PLATFORM}-helper-console.exe\"/>\n")
-file(APPEND "${_all_manifest_wix}" "       </Component>\n")
 foreach(_script "init.lua" "console.lua" "dtd_gen.lua")
        STRING(REGEX REPLACE "[-|\\.]" "_" _wix_name ${_script})
        file(APPEND "${_all_manifest_wix}" "       <Component Id=\"cmp${_wix_name}\" Guid=\"*\">\n")
@@ -162,8 +156,6 @@ foreach(_dll ${GLIB2_DLLS} ${CARES_DLL} ${GCRYPT_DLLS} ${GEOIP_DLL}
                SET(unique_file ${unique_file} ${_dll})
        ENDIF(NOT "${unique_file}" MATCHES "(^|;)${_dll}(;|$)")
 endforeach()
-file(APPEND "${_all_manifest_wix}" "       <ComponentRef Id=\"cmpGSpawn_${WIRESHARK_TARGET_PLATFORM}_helper_exe\" />\n")
-file(APPEND "${_all_manifest_wix}" "       <ComponentRef Id=\"cmpGSpawn_${WIRESHARK_TARGET_PLATFORM}_helper_console_exe\" />\n")
 foreach(_script "init.lua" "console.lua" "dtd_gen.lua")
        STRING(REGEX REPLACE "[-|\\.]" "_" _wix_name ${_script})
        file(APPEND "${_all_manifest_wix}" "       <ComponentRef Id=\"cmp${_wix_name}\" />\n")
index 83c36e509a33918a4dcb71a0de59793d203e7d7d..665d1eb9a910c17ece4cbb7c20a5debf763c271c 100644 (file)
@@ -77,8 +77,6 @@ $SoftBins = (
     "libgail.dll",
     "airpcap.dll",
     "comerr32.dll",
-    "gspawn-win32-helper-console.exe",
-    "gspawn-win32-helper.exe",
     "k5sprt32.dll",
     "krb5_32.dll",
     "libatk-1.0-0.dll",
@@ -159,4 +157,4 @@ $Binaries | ForEach-Object {
     }
 }
 
-exit $Count
\ No newline at end of file
+exit $Count