Skip to content

Commit 5a15b1a

Browse files
committed
Gracefully handle missing Libpcap on Windows
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.
1 parent 0b0e159 commit 5a15b1a

File tree

4 files changed

+68
-15
lines changed

4 files changed

+68
-15
lines changed

CMakeLists.txt

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,9 @@ target_link_libraries(sACNView PRIVATE ${SACNVIEW_QT_LIBRARIES})
234234

235235
# Link PCap/WinPCap libraries
236236
target_link_libraries(sACNView PRIVATE ${PCAP_LIBS})
237-
238-
if(WIN32)
239-
# Copy WinPCap DLLs
240-
foreach(DLLFILE IN LISTS PCAP_LIBS)
241-
add_custom_command (TARGET sACNView POST_BUILD
242-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
243-
$<TARGET_FILE:${DLLFILE}> $<TARGET_FILE_DIR:sACNView>)
244-
endforeach()
237+
if(MSVC)
238+
target_link_libraries(sACNView PRIVATE delayimp)
239+
target_link_options(sACNView PRIVATE "/DELAYLOAD:wpcap.dll")
245240
endif()
246241

247242
# Blake2

src/pcap/pcapplayback.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
#include <QThread>
99
#include <QDebug>
1010

11+
#ifdef Q_OS_WIN
12+
#include <windows.h>
13+
#include <delayimp.h>
14+
#endif
15+
1116
PcapPlayback::PcapPlayback(QWidget *parent) :
1217
QWidget(parent),
1318
ui(new Ui::PcapPlayback),
@@ -22,6 +27,41 @@ PcapPlayback::~PcapPlayback()
2227
delete ui;
2328
}
2429

30+
bool PcapPlayback::foundLibPcap()
31+
{
32+
#ifdef Q_OS_WIN
33+
const auto checkDelayException = [](int exception_value) {
34+
if (exception_value == VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND)
35+
|| exception_value == VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND)) {
36+
return EXCEPTION_EXECUTE_HANDLER;
37+
}
38+
return EXCEPTION_CONTINUE_SEARCH;
39+
};
40+
41+
__try {
42+
HRESULT hr = __HrLoadAllImportsForDll("wpcap.dll");
43+
if (FAILED(hr)) {
44+
return false;
45+
}
46+
} __except (checkDelayException(GetExceptionCode())) {
47+
return false;
48+
}
49+
#endif
50+
return true;
51+
}
52+
53+
std::string PcapPlayback::getLibPcapVersion()
54+
{
55+
if (foundLibPcap()) {
56+
const char *version = pcap_lib_version();
57+
return std::string(version);
58+
}
59+
else
60+
{
61+
return {};
62+
}
63+
}
64+
2565
void PcapPlayback::openThread()
2666
{
2767
if (sender) {
@@ -59,6 +99,18 @@ void PcapPlayback::playbackThreadClosed()
5999

60100
void PcapPlayback::on_btnOpen_clicked()
61101
{
102+
if (!foundLibPcap()) {
103+
QMessageBox::critical(
104+
this,
105+
tr("Pcap not found"),
106+
#ifdef Q_OS_WIN
107+
tr("Pcap not found, please install Wireshark"));
108+
#else
109+
tr("Libpcap not found, please install"));
110+
#endif
111+
return;
112+
}
113+
62114
/* Select file to open */
63115
QString fileName = QFileDialog::getOpenFileName(this,
64116
tr("Open Capture"),

src/pcap/pcapplayback.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ class PcapPlayback : public QWidget
1616
explicit PcapPlayback(QWidget *parent = 0);
1717
~PcapPlayback();
1818

19+
static bool foundLibPcap();
20+
static std::string getLibPcapVersion();
21+
1922
private slots:
2023
void on_btnOpen_clicked();
2124
void on_btnStartPause_clicked();

src/ui/aboutdialog.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "aboutdialog.h"
1717
#include "ui_aboutdialog.h"
1818
#include "consts.h"
19-
#include <pcap.h>
19+
#include "pcap/pcapplayback.h"
2020
#include "translations/translations.h"
2121

2222
#include <QTimer>
@@ -73,12 +73,15 @@ aboutDialog::aboutDialog(QWidget* parent) :
7373
}
7474

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

0 commit comments

Comments
 (0)