Qt+Win32: Make software updates more friendly.
authorGerald Combs <gerald@wireshark.org>
Tue, 13 Dec 2016 18:33:02 +0000 (10:33 -0800)
committerAnders Broman <a.broman58@gmail.com>
Tue, 20 Dec 2016 14:18:14 +0000 (14:18 +0000)
Add WinSparkle can_shutdown and shutdown_request callbacks which are
called prior to running the installer. Reject updates when we have
unsaved information. Add notes about possible improvements.

Ping-Bug: 9687
Ping-Bug: 12989
Change-Id: Ia126244b311417aa3105ea8136f186adc2745445
Reviewed-on: https://code.wireshark.org/review/19244
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Anders Broman <a.broman58@gmail.com>
ui/gtk/main.c
ui/qt/main_window.cpp
ui/qt/main_window.h
ui/qt/main_window_slots.cpp
ui/qt/wireshark_application.cpp
ui/qt/wireshark_application.h
ui/software_update.c
ui/software_update.h
wsutil/file_util.c
wsutil/file_util.h

index ce5ab50d44636751dd265031ce8d2039eecd99d7..f2631006f18771c9d6a0982ba91dfb20a21182f9 100644 (file)
@@ -3414,6 +3414,22 @@ void redissect_packets(void)
     status_expert_update();
 }
 
+#ifdef HAVE_SOFTWARE_UPDATE
+/** Check to see if Wireshark can shut down safely (e.g. offer to save the
+ *  current capture).
+ * Dummy.
+ */
+int software_update_can_shutdown_callback(void) {
+    return FALSE;
+}
+
+/** Shut down Wireshark in preparation for an upgrade.
+ * Dummy.
+ */
+void software_update_shutdown_request_callback(void) {
+}
+#endif
+
 /*
  * Editor modelines
  *
index d193dde99321e36b68232942f34c51253dec33bb..c2cba0c6f15d3a66b51d8624eb3dce5c9b8e365e 100644 (file)
@@ -320,6 +320,9 @@ MainWindow::MainWindow(QWidget *parent) :
     // iterates over *all* of our children, looking for matching "on_" slots.
     // The fewer children we have at this point the better.
     main_ui_->setupUi(this);
+#ifdef HAVE_SOFTWARE_UPDATE
+    update_action_ = new QAction(tr("Check for Updates" UTF8_HORIZONTAL_ELLIPSIS), main_ui_->menuHelp);
+#endif
     setWindowIcon(wsApp->normalIcon());
     setTitlebarForCaptureFile();
     setMenusForCaptureFile();
@@ -361,6 +364,13 @@ MainWindow::MainWindow(QWidget *parent) :
     connect(wsApp, SIGNAL(updateRecentCaptureStatus(const QString &, qint64, bool)), this, SLOT(updateRecentCaptures()));
     updateRecentCaptures();
 
+#ifdef HAVE_SOFTWARE_UPDATE
+    connect(wsApp, SIGNAL(softwareUpdateRequested()), this, SLOT(softwareUpdateRequested()),
+        Qt::BlockingQueuedConnection);
+    connect(wsApp, SIGNAL(softwareUpdateClose()), this, SLOT(close()),
+        Qt::BlockingQueuedConnection);
+#endif
+
     df_combo_box_ = new DisplayFilterCombo();
     const DisplayFilterEdit *df_edit = dynamic_cast<DisplayFilterEdit *>(df_combo_box_->lineEdit());
     connect(df_edit, SIGNAL(pushFilterSyntaxStatus(const QString&)),
@@ -449,9 +459,8 @@ MainWindow::MainWindow(QWidget *parent) :
 
 #ifdef HAVE_SOFTWARE_UPDATE
     QAction *update_sep = main_ui_->menuHelp->insertSeparator(main_ui_->actionHelpAbout);
-    QAction *update_action = new QAction(tr("Check for Updates" UTF8_HORIZONTAL_ELLIPSIS), main_ui_->menuHelp);
-    main_ui_->menuHelp->insertAction(update_sep, update_action);
-    connect(update_action, SIGNAL(triggered()), this, SLOT(checkForUpdates()));
+    main_ui_->menuHelp->insertAction(update_sep, update_action_);
+    connect(update_action_, SIGNAL(triggered()), this, SLOT(checkForUpdates()));
 #endif
     master_split_.setObjectName("splitterMaster");
     extra_split_.setObjectName("splitterExtra");
@@ -2090,6 +2099,11 @@ void MainWindow::setMenusForCaptureFile(bool force_disable)
     }
 
     main_ui_->actionViewReload->setEnabled(enable);
+
+#ifdef HAVE_SOFTWARE_UPDATE
+    // We might want to enable or disable automatic checks here as well.
+    update_action_->setEnabled(!can_save);
+#endif
 }
 
 void MainWindow::setMenusForCaptureInProgress(bool capture_in_progress) {
@@ -2116,6 +2130,10 @@ void MainWindow::setMenusForCaptureInProgress(bool capture_in_progress) {
 
     main_ui_->menuFileSet->setEnabled(!capture_in_progress);
     main_ui_->actionFileQuit->setEnabled(true);
+#ifdef HAVE_SOFTWARE_UPDATE
+    // We might want to enable or disable automatic checks here as well.
+    update_action_->setEnabled(!capture_in_progress);
+#endif
 
     main_ui_->actionStatisticsCaptureFileProperties->setEnabled(capture_in_progress);
 
@@ -2140,6 +2158,9 @@ void MainWindow::setMenusForCaptureInProgress(bool capture_in_progress) {
 
 void MainWindow::setMenusForCaptureStopping() {
     main_ui_->actionFileQuit->setEnabled(false);
+#ifdef HAVE_SOFTWARE_UPDATE
+    update_action_->setEnabled(false);
+#endif
     main_ui_->actionStatisticsCaptureFileProperties->setEnabled(false);
 #ifdef HAVE_LIBPCAP
     main_ui_->actionCaptureStart->setChecked(false);
index cda9116ebbd5ba259ee2f7df183b62fff349fea1..a020befe12336d2866e45c4b282d5d9451305749 100644 (file)
@@ -182,6 +182,9 @@ private:
     QMenu *dock_menu_;
 #endif
 
+#ifdef HAVE_SOFTWARE_UPDATE
+    QAction *update_action_;
+#endif
 
     QWidget* getLayoutWidget(layout_pane_content_e type);
 
@@ -358,6 +361,10 @@ private slots:
 
     void byteViewTabChanged(int tab_index);
 
+#ifdef HAVE_SOFTWARE_UPDATE
+    void softwareUpdateRequested();
+#endif
+
     // Automatically connected slots ("on_<object>_<signal>").
     //
     // The slots below follow the naming conventaion described in
index 79e8a254338e8ed0f8f57b69dc357f7917a6a4a3..b1e652624884b40e4eef0694cab107e344acb06a 100644 (file)
@@ -1651,6 +1651,17 @@ void MainWindow::byteViewTabChanged(int tab_index)
     }
 }
 
+#ifdef HAVE_SOFTWARE_UPDATE
+void MainWindow::softwareUpdateRequested() {
+    // We could call testCaptureFileClose here, but that would give us yet
+    // another dialog. Just try again later.
+    if (capture_file_.capFile() && capture_file_.capFile()->state != FILE_CLOSED) {
+        wsApp->rejectSoftwareUpdate();
+    }
+}
+#endif
+
+
 // File Menu
 
 void MainWindow::on_actionFileOpen_triggered()
index 0cc9d8867ffb2f2f7f375c49e41a2dc1586a07f0..7552dc83776adeccae50b0cf59a63a81c37f4471 100644 (file)
@@ -196,6 +196,21 @@ extern "C" void menu_recent_file_write_all(FILE *rf) {
     }
 }
 
+#ifdef HAVE_SOFTWARE_UPDATE
+/** Check to see if Wireshark can shut down safely (e.g. offer to save the
+ *  current capture).
+ */
+extern "C" int software_update_can_shutdown_callback(void) {
+    return wsApp->softwareUpdateCanShutdown();
+}
+
+/** Shut down Wireshark in preparation for an upgrade.
+ */
+extern "C" void software_update_shutdown_request_callback(void) {
+    wsApp->softwareUpdateShutdownRequest();
+}
+#endif // HAVE_SOFTWARE_UPDATE
+
 // Check each recent item in a separate thread so that we don't hang while
 // calling stat(). This is called periodically because files and entire
 // volumes can disappear and reappear at any time.
@@ -682,6 +697,9 @@ WiresharkApplication::WiresharkApplication(int &argc,  char **argv) :
 #endif
     qApp->setStyleSheet(app_style_sheet);
 
+#ifdef HAVE_SOFTWARE_UPDATE
+    connect(this, SIGNAL(softwareUpdateQuit()), this, SLOT(quit()), Qt::QueuedConnection);
+#endif
     connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(cleanup()));
 }
 
@@ -1148,6 +1166,35 @@ void WiresharkApplication::doTriggerMenuItem(MainMenuItem menuItem)
     }
 }
 
+#ifdef HAVE_SOFTWARE_UPDATE
+bool WiresharkApplication::softwareUpdateCanShutdown() {
+    software_update_ok_ = true;
+    // At this point the update is ready to install, but WinSparkle has
+    // not yet run the installer. We need to close our "Wireshark is
+    // running" mutexes along with those of our child processes, e.g.
+    // dumpcap.
+
+    // Step 1: See if we have any open files.
+    emit softwareUpdateRequested();
+    if (software_update_ok_ == true) {
+
+        // Step 2: Close the "running" mutexes.
+        emit softwareUpdateClose();
+        close_app_running_mutex();
+    }
+    return software_update_ok_;
+}
+
+void WiresharkApplication::softwareUpdateShutdownRequest() {
+    // At this point the installer has been launched. Neither Wireshark nor
+    // its children should have any "Wireshark is running" mutexes open.
+    // The main window should be closed.
+
+    // Step 3: Quit.
+    emit softwareUpdateQuit();
+}
+#endif
+
 /*
  * Editor modelines
  *
index 58b489badf4142283549a2e5b02cbd17053197ae..6f26a90f99da78e7ecb7cc02a45b6acd74d280fd 100644 (file)
@@ -124,6 +124,11 @@ public:
     const QString windowTitleString(QStringList title_parts);
     const QString windowTitleString(QString title_part) { return windowTitleString(QStringList() << title_part); }
     void applyCustomColorsFromRecent();
+#ifdef HAVE_SOFTWARE_UPDATE
+    void rejectSoftwareUpdate() { software_update_ok_ = false; }
+    bool softwareUpdateCanShutdown();
+    void softwareUpdateShutdownRequest();
+#endif
 
     QTranslator translator;
     QTranslator translatorQt;
@@ -145,6 +150,10 @@ private:
     static QString window_title_separator_;
     QList<AppSignal> app_signals_;
     int active_captures_;
+#ifdef HAVE_SOFTWARE_UPDATE
+    bool software_update_ok_;
+#endif
+
     void storeCustomColorsInRecent();
 
 protected:
@@ -171,6 +180,12 @@ signals:
     void checkDisplayFilter();
     void fieldsChanged();
     void reloadLuaPlugins();
+#ifdef HAVE_SOFTWARE_UPDATE
+    // Each of these are called from a separate thread.
+    void softwareUpdateRequested();
+    void softwareUpdateClose();
+    void softwareUpdateQuit();
+#endif
 
     void openStatCommandDialog(const QString &menu_path, const char *arg, void *userdata);
     void openTapParameterDialog(const QString cfg_str, const QString arg, void *userdata);
index a33dbd5b47087768117c6124380a837847fccece..059b409b81404b025a82d20711f27b6c8ee3ce98 100644 (file)
@@ -103,10 +103,8 @@ software_update_init(void) {
     win_sparkle_set_appcast_url(update_url);
     win_sparkle_set_automatic_check_for_updates(prefs.gui_update_enabled ? 1 : 0);
     win_sparkle_set_update_check_interval(prefs.gui_update_interval);
-    /* Todo: Fix bugs 9687 and 12989.
-     * win_sparkle_set_can_shutdown_callback(...);
-     * win_sparkle_set_shutdown_request_callback(...);
-     */
+    win_sparkle_set_can_shutdown_callback(software_update_can_shutdown_callback);
+    win_sparkle_set_shutdown_request_callback(software_update_shutdown_request_callback);
     win_sparkle_init();
 }
 
@@ -140,10 +138,20 @@ software_update_check(void) {
 }
 
 /** Clean up software update checking.
- *
- * Does nothing on platforms that don't support software updates.
  */
-extern void software_update_cleanup(void) {
+void software_update_cleanup(void) {
+}
+
+/** Check to see if Wireshark can shut down safely (e.g. offer to save the
+ *  current capture).
+ */
+int software_update_can_shutdown_callback(void) {
+    return FALSE;
+}
+
+/** Shut down Wireshark in preparation for an upgrade.
+ */
+void software_update_shutdown_request_callback(void) {
 }
 
 #endif /* defined(HAVE_SOFTWARE_UPDATE) && defined (_WIN32) */
index b3e593b89ca95ed8509a7577d3655e7451359df4..a7ba1549600e1d53411141bd2c6ac463274033bd 100644 (file)
@@ -45,6 +45,19 @@ extern void software_update_check(void);
  */
 extern void software_update_cleanup(void);
 
+/** Check to see if Wireshark can shut down safely (e.g. offer to save the
+ *  current capture). Called from a separate thread.
+ *
+ * Does nothing on platforms that don't support software updates.
+ */
+extern int software_update_can_shutdown_callback(void);
+
+/** Shut down Wireshark in preparation for an upgrade. Called from a separate
+ *  thread.
+ *
+ * Does nothing on platforms that don't support software updates.
+ */
+extern void software_update_shutdown_request_callback(void);
 
 #ifdef __cplusplus
 }
index cdbe0a4f018a778ae00698ac4590d29ec7d6f851..abd4ccab030581e66a0362fc4175407a32a2ccba 100644 (file)
@@ -96,27 +96,25 @@ static gchar *npcap_path = NULL;
  * Since: 2.6
  */
 int
-ws_stdio_open (const gchar *filename,
-        int          flags,
-        int          mode)
+ws_stdio_open (const gchar *filename, int flags, int mode)
 {
-      wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-      int retval;
-      int save_errno;
+    wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+    int retval;
+    int save_errno;
 
-      if (wfilename == NULL)
-        {
-          errno = EINVAL;
-          return -1;
-        }
+    if (wfilename == NULL)
+    {
+        errno = EINVAL;
+        return -1;
+    }
 
-      retval = _wopen (wfilename, flags, mode);
-      save_errno = errno;
+    retval = _wopen (wfilename, flags, mode);
+    save_errno = errno;
 
-      g_free (wfilename);
+    g_free (wfilename);
 
-      errno = save_errno;
-      return retval;
+    errno = save_errno;
+    return retval;
 }
 
 
@@ -138,36 +136,35 @@ ws_stdio_open (const gchar *filename,
  * Since: 2.6
  */
 int
-ws_stdio_rename (const gchar *oldfilename,
-          const gchar *newfilename)
+ws_stdio_rename (const gchar *oldfilename, const gchar *newfilename)
 {
-      wchar_t *woldfilename = g_utf8_to_utf16 (oldfilename, -1, NULL, NULL, NULL);
-      wchar_t *wnewfilename;
-      int retval;
-      int save_errno = 0;
-
-      if (woldfilename == NULL)
-        {
-          errno = EINVAL;
-          return -1;
-        }
-
-      wnewfilename = g_utf8_to_utf16 (newfilename, -1, NULL, NULL, NULL);
-
-      if (wnewfilename == NULL)
-        {
-          g_free (woldfilename);
-          errno = EINVAL;
-          return -1;
-        }
-
-      if (MoveFileExW (woldfilename, wnewfilename, MOVEFILE_REPLACE_EXISTING))
+    wchar_t *woldfilename = g_utf8_to_utf16 (oldfilename, -1, NULL, NULL, NULL);
+    wchar_t *wnewfilename;
+    int retval;
+    int save_errno = 0;
+
+    if (woldfilename == NULL)
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    wnewfilename = g_utf8_to_utf16 (newfilename, -1, NULL, NULL, NULL);
+
+    if (wnewfilename == NULL)
+    {
+        g_free (woldfilename);
+        errno = EINVAL;
+        return -1;
+    }
+
+    if (MoveFileExW (woldfilename, wnewfilename, MOVEFILE_REPLACE_EXISTING))
         retval = 0;
-      else
+    else
+    {
+        retval = -1;
+        switch (GetLastError ())
         {
-          retval = -1;
-          switch (GetLastError ())
-            {
 #define CASE(a,b) case ERROR_##a: save_errno = b; break
             CASE (FILE_NOT_FOUND, ENOENT);
             CASE (PATH_NOT_FOUND, ENOENT);
@@ -179,14 +176,14 @@ ws_stdio_rename (const gchar *oldfilename,
             CASE (ALREADY_EXISTS, EEXIST);
 #undef CASE
             default: save_errno = EIO;
-            }
         }
+    }
 
-      g_free (woldfilename);
-      g_free (wnewfilename);
+    g_free (woldfilename);
+    g_free (wnewfilename);
 
-      errno = save_errno;
-      return retval;
+    errno = save_errno;
+    return retval;
 }
 
 /**
@@ -205,26 +202,25 @@ ws_stdio_rename (const gchar *oldfilename,
  * Since: 2.6
  */
 int
-ws_stdio_mkdir (const gchar *filename,
-         int          mode)
+ws_stdio_mkdir (const gchar *filename, int mode)
 {
-      wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-      int retval;
-      int save_errno;
+    wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+    int retval;
+    int save_errno;
 
-      if (wfilename == NULL)
-        {
-          errno = EINVAL;
-          return -1;
-        }
+    if (wfilename == NULL)
+    {
+        errno = EINVAL;
+        return -1;
+    }
 
-      retval = _wmkdir (wfilename);
-      save_errno = errno;
+    retval = _wmkdir (wfilename);
+    save_errno = errno;
 
-      g_free (wfilename);
+    g_free (wfilename);
 
-      errno = save_errno;
-      return retval;
+    errno = save_errno;
+    return retval;
 }
 
 /**
@@ -244,34 +240,33 @@ ws_stdio_mkdir (const gchar *filename,
  * Since: 2.6
  */
 int
-ws_stdio_stat64 (const gchar *filename,
-        ws_statb64 *buf)
+ws_stdio_stat64 (const gchar *filename, ws_statb64 *buf)
 {
-      wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-      int retval;
-      int save_errno;
-      size_t len;
-
-      if (wfilename == NULL)
-        {
-          errno = EINVAL;
-          return -1;
-        }
-
-      len = wcslen (wfilename);
-      while (len > 0 && G_IS_DIR_SEPARATOR (wfilename[len-1]))
+    wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+    int retval;
+    int save_errno;
+    size_t len;
+
+    if (wfilename == NULL)
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    len = wcslen (wfilename);
+    while (len > 0 && G_IS_DIR_SEPARATOR (wfilename[len-1]))
         len--;
-      if (len > 0 &&
-          (!g_path_is_absolute (filename) || len > (size_t) (g_path_skip_root (filename) - filename)))
+    if (len > 0 &&
+            (!g_path_is_absolute (filename) || len > (size_t) (g_path_skip_root (filename) - filename)))
         wfilename[len] = '\0';
 
-      retval = _wstati64 (wfilename, buf);
-      save_errno = errno;
+    retval = _wstati64 (wfilename, buf);
+    save_errno = errno;
 
-      g_free (wfilename);
+    g_free (wfilename);
 
-      errno = save_errno;
-      return retval;
+    errno = save_errno;
+    return retval;
 }
 /**
  * g_unlink:
@@ -295,23 +290,23 @@ ws_stdio_stat64 (const gchar *filename,
 int
 ws_stdio_unlink (const gchar *filename)
 {
-      wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-      int retval;
-      int save_errno;
+    wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+    int retval;
+    int save_errno;
 
-      if (wfilename == NULL)
-        {
-          errno = EINVAL;
-          return -1;
-        }
+    if (wfilename == NULL)
+    {
+        errno = EINVAL;
+        return -1;
+    }
 
-      retval = _wunlink (wfilename);
-      save_errno = errno;
+    retval = _wunlink (wfilename);
+    save_errno = errno;
 
-      g_free (wfilename);
+    g_free (wfilename);
 
-      errno = save_errno;
-      return retval;
+    errno = save_errno;
+    return retval;
 }
 
 /**
@@ -343,25 +338,25 @@ ws_stdio_unlink (const gchar *filename)
 int
 ws_stdio_remove (const gchar *filename)
 {
-      wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-      int retval;
-      int save_errno;
-
-      if (wfilename == NULL)
-        {
-          errno = EINVAL;
-          return -1;
-        }
-
-      retval = _wremove (wfilename);
-      if (retval == -1)
+    wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+    int retval;
+    int save_errno;
+
+    if (wfilename == NULL)
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    retval = _wremove (wfilename);
+    if (retval == -1)
         retval = _wrmdir (wfilename);
-      save_errno = errno;
+    save_errno = errno;
 
-      g_free (wfilename);
+    g_free (wfilename);
 
-      errno = save_errno;
-      return retval;
+    errno = save_errno;
+    return retval;
 }
 
 /**
@@ -381,37 +376,36 @@ ws_stdio_remove (const gchar *filename)
  * Since: 2.6
  */
 FILE *
-ws_stdio_fopen (const gchar *filename,
-         const gchar *mode)
+ws_stdio_fopen (const gchar *filename, const gchar *mode)
 {
-      wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-      wchar_t *wmode;
-      FILE *retval;
-      int save_errno;
-
-      if (wfilename == NULL)
-        {
-          errno = EINVAL;
-          return NULL;
-        }
-
-      wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
-
-      if (wmode == NULL)
-        {
-          g_free (wfilename);
-          errno = EINVAL;
-          return NULL;
-        }
-
-      retval = _wfopen (wfilename, wmode);
-      save_errno = errno;
-
-      g_free (wfilename);
-      g_free (wmode);
-
-      errno = save_errno;
-      return retval;
+    wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+    wchar_t *wmode;
+    FILE *retval;
+    int save_errno;
+
+    if (wfilename == NULL)
+    {
+        errno = EINVAL;
+        return NULL;
+    }
+
+    wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
+
+    if (wmode == NULL)
+    {
+        g_free (wfilename);
+        errno = EINVAL;
+        return NULL;
+    }
+
+    retval = _wfopen (wfilename, wmode);
+    save_errno = errno;
+
+    g_free (wfilename);
+    g_free (wmode);
+
+    errno = save_errno;
+    return retval;
 }
 
 /**
@@ -432,38 +426,36 @@ ws_stdio_fopen (const gchar *filename,
  * Since: 2.6
  */
 FILE *
-ws_stdio_freopen (const gchar *filename,
-           const gchar *mode,
-           FILE        *stream)
+ws_stdio_freopen (const gchar *filename, const gchar *mode, FILE *stream)
 {
-      wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
-      wchar_t *wmode;
-      FILE *retval;
-      int save_errno;
-
-      if (wfilename == NULL)
-        {
-          errno = EINVAL;
-          return NULL;
-        }
-
-      wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
-
-      if (wmode == NULL)
-        {
-          g_free (wfilename);
-          errno = EINVAL;
-          return NULL;
-        }
-
-      retval = _wfreopen (wfilename, wmode, stream);
-      save_errno = errno;
-
-      g_free (wfilename);
-      g_free (wmode);
-
-      errno = save_errno;
-      return retval;
+    wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+    wchar_t *wmode;
+    FILE *retval;
+    int save_errno;
+
+    if (wfilename == NULL)
+    {
+        errno = EINVAL;
+        return NULL;
+    }
+
+    wmode = g_utf8_to_utf16 (mode, -1, NULL, NULL, NULL);
+
+    if (wmode == NULL)
+    {
+        g_free (wfilename);
+        errno = EINVAL;
+        return NULL;
+    }
+
+    retval = _wfreopen (wfilename, wmode, stream);
+    save_errno = errno;
+
+    g_free (wfilename);
+    g_free (wmode);
+
+    errno = save_errno;
+    return retval;
 }
 
 
@@ -471,74 +463,74 @@ ws_stdio_freopen (const gchar *filename,
 static gboolean
 init_dll_load_paths()
 {
-      TCHAR path_w[MAX_PATH];
+    TCHAR path_w[MAX_PATH];
 
-      if (program_path && system_path && npcap_path)
-            return TRUE;
+    if (program_path && system_path && npcap_path)
+        return TRUE;
 
-      /* XXX - Duplicate code in filesystem.c:init_progfile_dir */
-      if (GetModuleFileName(NULL, path_w, MAX_PATH) == 0 || GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
-            return FALSE;
-      }
+    /* XXX - Duplicate code in filesystem.c:init_progfile_dir */
+    if (GetModuleFileName(NULL, path_w, MAX_PATH) == 0 || GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+        return FALSE;
+    }
 
-      if (!program_path) {
-            gchar *app_path;
-            app_path = g_utf16_to_utf8(path_w, -1, NULL, NULL, NULL);
-            /* We could use PathRemoveFileSpec here but we'd have to link to Shlwapi.dll */
-            program_path = g_path_get_dirname(app_path);
-            g_free(app_path);
-      }
+    if (!program_path) {
+        gchar *app_path;
+        app_path = g_utf16_to_utf8(path_w, -1, NULL, NULL, NULL);
+        /* We could use PathRemoveFileSpec here but we'd have to link to Shlwapi.dll */
+        program_path = g_path_get_dirname(app_path);
+        g_free(app_path);
+    }
 
-      if (GetSystemDirectory(path_w, MAX_PATH) == 0) {
-            return FALSE;
-      }
+    if (GetSystemDirectory(path_w, MAX_PATH) == 0) {
+        return FALSE;
+    }
 
-      if (!system_path) {
-            system_path = g_utf16_to_utf8(path_w, -1, NULL, NULL, NULL);
-      }
+    if (!system_path) {
+        system_path = g_utf16_to_utf8(path_w, -1, NULL, NULL, NULL);
+    }
 
-      _tcscat_s(path_w, MAX_PATH, _T("\\Npcap"));
+    _tcscat_s(path_w, MAX_PATH, _T("\\Npcap"));
 
-      if (!npcap_path) {
-            npcap_path = g_utf16_to_utf8(path_w, -1, NULL, NULL, NULL);
-      }
+    if (!npcap_path) {
+        npcap_path = g_utf16_to_utf8(path_w, -1, NULL, NULL, NULL);
+    }
 
-      if (program_path && system_path && npcap_path)
-            return TRUE;
+    if (program_path && system_path && npcap_path)
+        return TRUE;
 
-      return FALSE;
+    return FALSE;
 }
 
 gboolean
 ws_init_dll_search_path()
 {
-      gboolean dll_dir_set = FALSE;
-      wchar_t *program_path_w;
-      wchar_t npcap_path_w[MAX_PATH];
-      unsigned int retval;
-
-      typedef BOOL (WINAPI *SetDllDirectoryHandler)(LPCTSTR);
-      SetDllDirectoryHandler PSetDllDirectory;
-
-      PSetDllDirectory = (SetDllDirectoryHandler) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "SetDllDirectoryW");
-      if (PSetDllDirectory) {
-            dll_dir_set = PSetDllDirectory(_T(""));
-            if (dll_dir_set) {
-                  retval = GetSystemDirectoryW(npcap_path_w, MAX_PATH);
-                  if (0 < retval && retval <= MAX_PATH) {
-                        wcscat_s(npcap_path_w, MAX_PATH, L"\\Npcap");
-                        dll_dir_set = PSetDllDirectory(npcap_path_w);
-                  }
+    gboolean dll_dir_set = FALSE;
+    wchar_t *program_path_w;
+    wchar_t npcap_path_w[MAX_PATH];
+    unsigned int retval;
+
+    typedef BOOL (WINAPI *SetDllDirectoryHandler)(LPCTSTR);
+    SetDllDirectoryHandler PSetDllDirectory;
+
+    PSetDllDirectory = (SetDllDirectoryHandler) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "SetDllDirectoryW");
+    if (PSetDllDirectory) {
+        dll_dir_set = PSetDllDirectory(_T(""));
+        if (dll_dir_set) {
+            retval = GetSystemDirectoryW(npcap_path_w, MAX_PATH);
+            if (0 < retval && retval <= MAX_PATH) {
+                wcscat_s(npcap_path_w, MAX_PATH, L"\\Npcap");
+                dll_dir_set = PSetDllDirectory(npcap_path_w);
             }
-      }
+        }
+    }
 
-      if (!dll_dir_set && init_dll_load_paths()) {
-            program_path_w = g_utf8_to_utf16(program_path, -1, NULL, NULL, NULL);
-            SetCurrentDirectory(program_path_w);
-            g_free(program_path_w);
-      }
+    if (!dll_dir_set && init_dll_load_paths()) {
+        program_path_w = g_utf8_to_utf16(program_path, -1, NULL, NULL, NULL);
+        SetCurrentDirectory(program_path_w);
+        g_free(program_path_w);
+    }
 
-      return dll_dir_set;
+    return dll_dir_set;
 }
 
 /*
@@ -551,85 +543,85 @@ ws_init_dll_search_path()
 void *
 ws_load_library(const gchar *library_name)
 {
-      gchar   *full_path;
-      wchar_t *full_path_w;
-      HMODULE  dll_h;
-
-      if (!init_dll_load_paths() || !library_name)
-            return NULL;
-
-      /* First try the program directory */
-      full_path = g_module_build_path(program_path, library_name);
-      full_path_w = g_utf8_to_utf16(full_path, -1, NULL, NULL, NULL);
-
-      if (full_path && full_path_w) {
-            dll_h = LoadLibraryW(full_path_w);
-            if (dll_h) {
-                  g_free(full_path);
-                  g_free(full_path_w);
-                  return dll_h;
-            }
-      }
-
-      /* Next try the system directory */
-      full_path = g_module_build_path(system_path, library_name);
-      full_path_w = g_utf8_to_utf16(full_path, -1, NULL, NULL, NULL);
-
-      if (full_path && full_path_w) {
-            dll_h = LoadLibraryW(full_path_w);
-            if (dll_h) {
-                  g_free(full_path);
-                  g_free(full_path_w);
-                  return dll_h;
-            }
-      }
+    gchar   *full_path;
+    wchar_t *full_path_w;
+    HMODULE  dll_h;
+
+    if (!init_dll_load_paths() || !library_name)
+        return NULL;
+
+    /* First try the program directory */
+    full_path = g_module_build_path(program_path, library_name);
+    full_path_w = g_utf8_to_utf16(full_path, -1, NULL, NULL, NULL);
+
+    if (full_path && full_path_w) {
+        dll_h = LoadLibraryW(full_path_w);
+        if (dll_h) {
+            g_free(full_path);
+            g_free(full_path_w);
+            return dll_h;
+        }
+    }
+
+    /* Next try the system directory */
+    full_path = g_module_build_path(system_path, library_name);
+    full_path_w = g_utf8_to_utf16(full_path, -1, NULL, NULL, NULL);
+
+    if (full_path && full_path_w) {
+        dll_h = LoadLibraryW(full_path_w);
+        if (dll_h) {
+            g_free(full_path);
+            g_free(full_path_w);
+            return dll_h;
+        }
+    }
 
-      return NULL;
+    return NULL;
 }
 
 GModule *
 ws_module_open(gchar *module_name, GModuleFlags flags)
 {
-      gchar   *full_path;
-      GModule *mod;
+    gchar   *full_path;
+    GModule *mod;
 
-      if (!init_dll_load_paths() || !module_name)
-            return NULL;
+    if (!init_dll_load_paths() || !module_name)
+        return NULL;
 
-      /* First try the program directory */
-      full_path = g_module_build_path(program_path, module_name);
+    /* First try the program directory */
+    full_path = g_module_build_path(program_path, module_name);
 
-      if (full_path) {
-            mod = g_module_open(full_path, flags);
-            if (mod) {
-                  g_free(full_path);
-                  return mod;
-            }
-      }
+    if (full_path) {
+        mod = g_module_open(full_path, flags);
+        if (mod) {
+            g_free(full_path);
+            return mod;
+        }
+    }
 
-      /* Next try the system directory */
-      full_path = g_module_build_path(system_path, module_name);
+    /* Next try the system directory */
+    full_path = g_module_build_path(system_path, module_name);
 
-      if (full_path) {
-            mod = g_module_open(full_path, flags);
-            if (mod) {
-                  g_free(full_path);
-                  return mod;
-            }
-      }
+    if (full_path) {
+        mod = g_module_open(full_path, flags);
+        if (mod) {
+            g_free(full_path);
+            return mod;
+        }
+    }
 
-      /* At last try the Npcap directory */
-      full_path = g_module_build_path(npcap_path, module_name);
+    /* At last try the Npcap directory */
+    full_path = g_module_build_path(npcap_path, module_name);
 
-      if (full_path) {
-            mod = g_module_open(full_path, flags);
-            if (mod) {
-                  g_free(full_path);
-                  return mod;
-            }
-      }
+    if (full_path) {
+        mod = g_module_open(full_path, flags);
+        if (mod) {
+            g_free(full_path);
+            return mod;
+        }
+    }
 
-      return NULL;
+    return NULL;
 }
 
 /** Create or open a "Wireshark is running" mutex.
@@ -638,38 +630,52 @@ ws_module_open(gchar *module_name, GModuleFlags flags)
 
 static SECURITY_ATTRIBUTES *sec_attributes_;
 
+static HANDLE local_running_mutex = NULL;
+static HANDLE global_running_mutex = NULL;
+
 void create_app_running_mutex() {
-      SECURITY_ATTRIBUTES *sa = NULL;
+    SECURITY_ATTRIBUTES *sa = NULL;
 
-      if (!sec_attributes_) sec_attributes_ = g_new0(SECURITY_ATTRIBUTES, 1);
+    if (!sec_attributes_) sec_attributes_ = g_new0(SECURITY_ATTRIBUTES, 1);
 
-      sec_attributes_->nLength = sizeof(SECURITY_ATTRIBUTES);
-      sec_attributes_->lpSecurityDescriptor = g_new0(SECURITY_DESCRIPTOR, 1);
-      sec_attributes_->bInheritHandle = TRUE;
-      if (InitializeSecurityDescriptor(sec_attributes_->lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) {
-            if (SetSecurityDescriptorDacl(sec_attributes_->lpSecurityDescriptor, TRUE, NULL, FALSE)) {
-                  sa = sec_attributes_;
-            }
-      }
-
-      if (!sa) {
-            g_free(sec_attributes_->lpSecurityDescriptor);
-            g_free(sec_attributes_);
-            sec_attributes_ = NULL;
-      }
-      CreateMutex(sa, FALSE, _T("Wireshark-is-running-{") _T(WIRESHARK_IS_RUNNING_UUID) _T("}"));
-      CreateMutex(sa, FALSE, _T("Global\\Wireshark-is-running-{") _T(WIRESHARK_IS_RUNNING_UUID) _T("}"));
+    sec_attributes_->nLength = sizeof(SECURITY_ATTRIBUTES);
+    sec_attributes_->lpSecurityDescriptor = g_new0(SECURITY_DESCRIPTOR, 1);
+    sec_attributes_->bInheritHandle = TRUE;
+    if (InitializeSecurityDescriptor(sec_attributes_->lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION)) {
+        if (SetSecurityDescriptorDacl(sec_attributes_->lpSecurityDescriptor, TRUE, NULL, FALSE)) {
+            sa = sec_attributes_;
+        }
+    }
+
+    if (!sa) {
+        g_free(sec_attributes_->lpSecurityDescriptor);
+        g_free(sec_attributes_);
+        sec_attributes_ = NULL;
+    }
+    local_running_mutex = CreateMutex(sa, FALSE, _T("Wireshark-is-running-{") _T(WIRESHARK_IS_RUNNING_UUID) _T("}"));
+    global_running_mutex = CreateMutex(sa, FALSE, _T("Global\\Wireshark-is-running-{") _T(WIRESHARK_IS_RUNNING_UUID) _T("}"));
+}
+
+void close_app_running_mutex() {
+    if (local_running_mutex) {
+        CloseHandle(local_running_mutex);
+        local_running_mutex = NULL;
+    }
+    if (global_running_mutex) {
+        CloseHandle(global_running_mutex);
+        global_running_mutex = NULL;
+    }
 }
 
 /*
  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
  *
- * Local variables:
- * c-basic-offset: 6
+ * Local Variables:
+ * c-basic-offset: 4
  * tab-width: 8
  * indent-tabs-mode: nil
  * End:
  *
- * vi: set shiftwidth=6 tabstop=8 expandtab:
- * :indentSize=6:tabSize=8:noTabs=true:
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
  */
index 5c8c0c41c668e56d48dcaaff2c638095c41eef66..fc13f4c6c37c4f599f745866033a588e88d90bd5 100644 (file)
@@ -168,6 +168,10 @@ GModule *ws_module_open(gchar *module_name, GModuleFlags flags);
  */
 WS_DLL_PUBLIC void create_app_running_mutex();
 
+/** Close our "Wireshark is running" mutex.
+ */
+WS_DLL_PUBLIC void close_app_running_mutex();
+
 #else  /* _WIN32 */
 
 /*