From 795f4eb106d877ba6f2bd30524cc871404e9e42a Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Tue, 13 Dec 2016 10:33:02 -0800 Subject: Qt+Win32: Make software updates more friendly. 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 Petri-Dish: Gerald Combs Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- ui/gtk/main.c | 16 + ui/qt/main_window.cpp | 27 +- ui/qt/main_window.h | 7 + ui/qt/main_window_slots.cpp | 11 + ui/qt/wireshark_application.cpp | 47 +++ ui/qt/wireshark_application.h | 15 + ui/software_update.c | 22 +- ui/software_update.h | 13 + wsutil/file_util.c | 632 ++++++++++++++++++++-------------------- wsutil/file_util.h | 4 + 10 files changed, 471 insertions(+), 323 deletions(-) diff --git a/ui/gtk/main.c b/ui/gtk/main.c index ce5ab50d44..f2631006f1 100644 --- a/ui/gtk/main.c +++ b/ui/gtk/main.c @@ -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 * diff --git a/ui/qt/main_window.cpp b/ui/qt/main_window.cpp index d193dde993..c2cba0c6f1 100644 --- a/ui/qt/main_window.cpp +++ b/ui/qt/main_window.cpp @@ -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(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); diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index cda9116ebb..a020befe12 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -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__"). // // The slots below follow the naming conventaion described in diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 79e8a25433..b1e6526248 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -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() diff --git a/ui/qt/wireshark_application.cpp b/ui/qt/wireshark_application.cpp index 0cc9d8867f..7552dc8377 100644 --- a/ui/qt/wireshark_application.cpp +++ b/ui/qt/wireshark_application.cpp @@ -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 * diff --git a/ui/qt/wireshark_application.h b/ui/qt/wireshark_application.h index 58b489badf..6f26a90f99 100644 --- a/ui/qt/wireshark_application.h +++ b/ui/qt/wireshark_application.h @@ -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 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); diff --git a/ui/software_update.c b/ui/software_update.c index a33dbd5b47..059b409b81 100644 --- a/ui/software_update.c +++ b/ui/software_update.c @@ -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) */ diff --git a/ui/software_update.h b/ui/software_update.h index b3e593b89c..a7ba154960 100644 --- a/ui/software_update.h +++ b/ui/software_update.h @@ -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 } diff --git a/wsutil/file_util.c b/wsutil/file_util.c index cdbe0a4f01..abd4ccab03 100644 --- a/wsutil/file_util.c +++ b/wsutil/file_util.c @@ -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: */ diff --git a/wsutil/file_util.h b/wsutil/file_util.h index 5c8c0c41c6..fc13f4c6c3 100644 --- a/wsutil/file_util.h +++ b/wsutil/file_util.h @@ -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 */ /* -- cgit v1.2.1