Skip to content

Commit

Permalink
Gracefully handle missing Libpcap on Windows
Browse files Browse the repository at this point in the history
Issue a message to the user if WinPcap/Npcap is not found.
Delay load Libpcap on Windows, so that if WinPcap/Npcap is not installed,
the main application will still open.
  • Loading branch information
marcusbirkin committed May 25, 2024
1 parent 0b0e159 commit 5a15b1a
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 15 deletions.
11 changes: 3 additions & 8 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -234,14 +234,9 @@ target_link_libraries(sACNView PRIVATE ${SACNVIEW_QT_LIBRARIES})

# Link PCap/WinPCap libraries
target_link_libraries(sACNView PRIVATE ${PCAP_LIBS})

if(WIN32)
# Copy WinPCap DLLs
foreach(DLLFILE IN LISTS PCAP_LIBS)
add_custom_command (TARGET sACNView POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:${DLLFILE}> $<TARGET_FILE_DIR:sACNView>)
endforeach()
if(MSVC)
target_link_libraries(sACNView PRIVATE delayimp)
target_link_options(sACNView PRIVATE "/DELAYLOAD:wpcap.dll")
endif()

# Blake2
Expand Down
52 changes: 52 additions & 0 deletions src/pcap/pcapplayback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
#include <QThread>
#include <QDebug>

#ifdef Q_OS_WIN
#include <windows.h>
#include <delayimp.h>
#endif

PcapPlayback::PcapPlayback(QWidget *parent) :
QWidget(parent),
ui(new Ui::PcapPlayback),
Expand All @@ -22,6 +27,41 @@ PcapPlayback::~PcapPlayback()
delete ui;
}

bool PcapPlayback::foundLibPcap()
{
#ifdef Q_OS_WIN
const auto checkDelayException = [](int exception_value) {
if (exception_value == VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)
|| exception_value == VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND)) {
return EXCEPTION_EXECUTE_HANDLER;
}
return EXCEPTION_CONTINUE_SEARCH;
};

__try {
HRESULT hr = __HrLoadAllImportsForDll("wpcap.dll");
if (FAILED(hr)) {
return false;
}
} __except (checkDelayException(GetExceptionCode())) {
return false;
}
#endif
return true;
}

std::string PcapPlayback::getLibPcapVersion()
{
if (foundLibPcap()) {
const char *version = pcap_lib_version();
return std::string(version);
}
else
{
return {};
}
}

void PcapPlayback::openThread()
{
if (sender) {
Expand Down Expand Up @@ -59,6 +99,18 @@ void PcapPlayback::playbackThreadClosed()

void PcapPlayback::on_btnOpen_clicked()
{
if (!foundLibPcap()) {
QMessageBox::critical(
this,
tr("Pcap not found"),
#ifdef Q_OS_WIN
tr("Pcap not found, please install Wireshark"));
#else
tr("Libpcap not found, please install"));
#endif
return;
}

/* Select file to open */
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Capture"),
Expand Down
3 changes: 3 additions & 0 deletions src/pcap/pcapplayback.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ class PcapPlayback : public QWidget
explicit PcapPlayback(QWidget *parent = 0);
~PcapPlayback();

static bool foundLibPcap();
static std::string getLibPcapVersion();

private slots:
void on_btnOpen_clicked();
void on_btnStartPause_clicked();
Expand Down
17 changes: 10 additions & 7 deletions src/ui/aboutdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include "aboutdialog.h"
#include "ui_aboutdialog.h"
#include "consts.h"
#include <pcap.h>
#include "pcap/pcapplayback.h"
#include "translations/translations.h"

#include <QTimer>
Expand Down Expand Up @@ -73,12 +73,15 @@ aboutDialog::aboutDialog(QWidget* parent) :
}

{
const char* libpcap = pcap_lib_version();
ui->lblLibs->setText(
tr("<p>This application uses <a href=\"https://www.tcpdump.org/\">libpcap</a><br>"
"%1<br>"
"Licensed under the <a href=\"https://opensource.org/licenses/BSD-3-Clause\">The 3-Clause BSD License</a></p>")
.arg(QString::fromUtf8(libpcap)));
ui->lblLibs->clear();
if (PcapPlayback::foundLibPcap())
{
ui->lblLibs->setText(
tr("<p>This application uses <a href=\"https://www.tcpdump.org/\">libpcap</a><br>"
"%1<br>"
"Licensed under the <a href=\"https://opensource.org/licenses/BSD-3-Clause\">The 3-Clause BSD License</a></p>")
.arg(QString::fromStdString(PcapPlayback::getLibPcapVersion())));
}
ui->lblLibs->setText(ui->lblLibs->text() +
tr("<p>This application uses <a href=\"https://www.blake2.net/\">BLAKE2</a><br>"
"Licensed under the <a href=\"https://creativecommons.org/publicdomain/zero/1.0/\">Creative Commons Zero v1.0 Universal</a></p>"));
Expand Down

0 comments on commit 5a15b1a

Please sign in to comment.