Wintun loader: fix unload() to actually reset all function pointers

This commit is contained in:
Zac Gaetano 2026-05-07 00:14:23 -04:00
parent 06dccbe147
commit 7819b5fbf2

View file

@ -1,4 +1,4 @@
// wintun.h Dynamic-loading wrapper for the Wintun kernel TUN driver. // wintun.h - Dynamic-loading wrapper for the Wintun kernel TUN driver.
// //
// Wintun is distributed as wintun.dll and loaded at runtime via LoadLibraryEx. // Wintun is distributed as wintun.dll and loaded at runtime via LoadLibraryEx.
// All API functions are resolved via GetProcAddress. // All API functions are resolved via GetProcAddress.
@ -10,6 +10,9 @@
// WintunLib wt; // WintunLib wt;
// if (!wt.load()) { /* wintun.dll not found */ } // if (!wt.load()) { /* wintun.dll not found */ }
// WINTUN_ADAPTER_HANDLE adp = wt.CreateAdapter(L"DragonMoonlight", L"WireGuard", nullptr); // WINTUN_ADAPTER_HANDLE adp = wt.CreateAdapter(L"DragonMoonlight", L"WireGuard", nullptr);
// ...
// wt.CloseAdapter(adp);
// wt.unload();
#pragma once #pragma once
@ -17,15 +20,14 @@
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
#include <winternl.h>
#include <stdint.h> #include <stdint.h>
// ─── Wintun opaque types ────────────────────────────────────────────────────── // Wintun opaque types
typedef void *WINTUN_ADAPTER_HANDLE; typedef void *WINTUN_ADAPTER_HANDLE;
typedef void *WINTUN_SESSION_HANDLE; typedef void *WINTUN_SESSION_HANDLE;
// ─── Wintun function pointer types ─────────────────────────────────────────── // Wintun function pointer types
typedef WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_CREATE_ADAPTER_FUNC)( typedef WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_CREATE_ADAPTER_FUNC)(
LPCWSTR Name, LPCWSTR TunnelType, const GUID *RequestedGUID); LPCWSTR Name, LPCWSTR TunnelType, const GUID *RequestedGUID);
@ -60,74 +62,57 @@ typedef BYTE *(WINAPI *WINTUN_ALLOC_SEND_PACKET_FUNC)(WINTUN_SESSION_HANDLE Sess
typedef void(WINAPI *WINTUN_SEND_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session, typedef void(WINAPI *WINTUN_SEND_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session,
const BYTE *Packet); const BYTE *Packet);
// ─── WintunLib — RAII loader ────────────────────────────────────────────────── // WintunLib - RAII loader
class WintunLib { class WintunLib {
public: public:
// Function pointers — public so TunnelManager can call them directly. WINTUN_CREATE_ADAPTER_FUNC CreateAdapter = nullptr;
WINTUN_CREATE_ADAPTER_FUNC CreateAdapter = nullptr; WINTUN_OPEN_ADAPTER_FUNC OpenAdapter = nullptr;
WINTUN_OPEN_ADAPTER_FUNC OpenAdapter = nullptr; WINTUN_CLOSE_ADAPTER_FUNC CloseAdapter = nullptr;
WINTUN_CLOSE_ADAPTER_FUNC CloseAdapter = nullptr; WINTUN_DELETE_DRIVER_FUNC DeleteDriver = nullptr;
WINTUN_DELETE_DRIVER_FUNC DeleteDriver = nullptr; WINTUN_GET_ADAPTER_LUID_FUNC GetAdapterLUID = nullptr;
WINTUN_GET_ADAPTER_LUID_FUNC GetAdapterLUID = nullptr; WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC GetRunningDriverVersion = nullptr;
WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC GetRunningDriverVersion = nullptr; WINTUN_START_SESSION_FUNC StartSession = nullptr;
WINTUN_START_SESSION_FUNC StartSession = nullptr; WINTUN_END_SESSION_FUNC EndSession = nullptr;
WINTUN_END_SESSION_FUNC EndSession = nullptr; WINTUN_GET_READ_WAIT_EVENT_FUNC GetReadWaitEvent = nullptr;
WINTUN_GET_READ_WAIT_EVENT_FUNC GetReadWaitEvent = nullptr; WINTUN_RECEIVE_PACKET_FUNC ReceivePacket = nullptr;
WINTUN_RECEIVE_PACKET_FUNC ReceivePacket = nullptr; WINTUN_RELEASE_RECEIVE_PACKET_FUNC ReleaseReceivePacket = nullptr;
WINTUN_RELEASE_RECEIVE_PACKET_FUNC ReleaseReceivePacket = nullptr; WINTUN_ALLOC_SEND_PACKET_FUNC AllocateSendPacket = nullptr;
WINTUN_ALLOC_SEND_PACKET_FUNC AllocSendPacket = nullptr; WINTUN_SEND_PACKET_FUNC SendPacket = nullptr;
WINTUN_SEND_PACKET_FUNC SendPacket = nullptr;
WintunLib() = default; WintunLib() = default;
~WintunLib() { unload(); } ~WintunLib() { unload(); }
// Non-copyable
WintunLib(const WintunLib &) = delete; WintunLib(const WintunLib &) = delete;
WintunLib &operator=(const WintunLib &) = delete; WintunLib &operator=(const WintunLib &) = delete;
/// Load wintun.dll from the application directory first, then System32.
/// Returns true on success.
bool load() { bool load() {
if (m_module) return true;
m_module = LoadLibraryExW(L"wintun.dll", nullptr, m_module = LoadLibraryExW(L"wintun.dll", nullptr,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!m_module) return false; if (!m_module) return false;
#define WINTUN_RESOLVE(name) \ #define WINTUN_RESOLVE(MEMBER, NAME) \
name = reinterpret_cast<decltype(name)>(GetProcAddress(m_module, #name)); \ MEMBER = reinterpret_cast<decltype(MEMBER)>(GetProcAddress(m_module, #NAME)); \
if (!name) { unload(); return false; } if (!MEMBER) { unload(); return false; }
WINTUN_RESOLVE(WintunCreateAdapter) WINTUN_RESOLVE(CreateAdapter, WintunCreateAdapter)
WINTUN_RESOLVE(WintunOpenAdapter) WINTUN_RESOLVE(OpenAdapter, WintunOpenAdapter)
WINTUN_RESOLVE(WintunCloseAdapter) WINTUN_RESOLVE(CloseAdapter, WintunCloseAdapter)
WINTUN_RESOLVE(WintunDeleteDriver) WINTUN_RESOLVE(DeleteDriver, WintunDeleteDriver)
WINTUN_RESOLVE(WintunGetAdapterLUID) WINTUN_RESOLVE(GetAdapterLUID, WintunGetAdapterLUID)
WINTUN_RESOLVE(WintunGetRunningDriverVersion) WINTUN_RESOLVE(GetRunningDriverVersion, WintunGetRunningDriverVersion)
WINTUN_RESOLVE(WintunStartSession) WINTUN_RESOLVE(StartSession, WintunStartSession)
WINTUN_RESOLVE(WintunEndSession) WINTUN_RESOLVE(EndSession, WintunEndSession)
WINTUN_RESOLVE(WintunGetReadWaitEvent) WINTUN_RESOLVE(GetReadWaitEvent, WintunGetReadWaitEvent)
WINTUN_RESOLVE(WintunReceivePacket) WINTUN_RESOLVE(ReceivePacket, WintunReceivePacket)
WINTUN_RESOLVE(WintunReleaseReceivePacket) WINTUN_RESOLVE(ReleaseReceivePacket, WintunReleaseReceivePacket)
WINTUN_RESOLVE(WintunAllocSendPacket) WINTUN_RESOLVE(AllocateSendPacket, WintunAllocateSendPacket)
WINTUN_RESOLVE(WintunSendPacket) WINTUN_RESOLVE(SendPacket, WintunSendPacket)
#undef WINTUN_RESOLVE #undef WINTUN_RESOLVE
// Remap the struct member names to the exported symbol names
CreateAdapter = WintunCreateAdapter;
OpenAdapter = WintunOpenAdapter;
CloseAdapter = WintunCloseAdapter;
DeleteDriver = WintunDeleteDriver;
GetAdapterLUID = WintunGetAdapterLUID;
GetRunningDriverVersion = WintunGetRunningDriverVersion;
StartSession = WintunStartSession;
EndSession = WintunEndSession;
GetReadWaitEvent = WintunGetReadWaitEvent;
ReceivePacket = WintunReceivePacket;
ReleaseReceivePacket = WintunReleaseReceivePacket;
AllocSendPacket = WintunAllocSendPacket;
SendPacket = WintunSendPacket;
return true; return true;
} }
@ -135,24 +120,21 @@ public:
void unload() { void unload() {
if (m_module) { FreeLibrary(m_module); m_module = nullptr; } if (m_module) { FreeLibrary(m_module); m_module = nullptr; }
CreateAdapter = nullptr; /* etc — reset all to nullptr */ CreateAdapter = nullptr;
OpenAdapter = nullptr;
CloseAdapter = nullptr;
DeleteDriver = nullptr;
GetAdapterLUID = nullptr;
GetRunningDriverVersion = nullptr;
StartSession = nullptr;
EndSession = nullptr;
GetReadWaitEvent = nullptr;
ReceivePacket = nullptr;
ReleaseReceivePacket = nullptr;
AllocateSendPacket = nullptr;
SendPacket = nullptr;
} }
private: private:
HMODULE m_module = nullptr; HMODULE m_module = nullptr;
// Raw resolved symbols (before copying to public members)
WINTUN_CREATE_ADAPTER_FUNC WintunCreateAdapter = nullptr;
WINTUN_OPEN_ADAPTER_FUNC WintunOpenAdapter = nullptr;
WINTUN_CLOSE_ADAPTER_FUNC WintunCloseAdapter = nullptr;
WINTUN_DELETE_DRIVER_FUNC WintunDeleteDriver = nullptr;
WINTUN_GET_ADAPTER_LUID_FUNC WintunGetAdapterLUID = nullptr;
WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC WintunGetRunningDriverVersion = nullptr;
WINTUN_START_SESSION_FUNC WintunStartSession = nullptr;
WINTUN_END_SESSION_FUNC WintunEndSession = nullptr;
WINTUN_GET_READ_WAIT_EVENT_FUNC WintunGetReadWaitEvent = nullptr;
WINTUN_RECEIVE_PACKET_FUNC WintunReceivePacket = nullptr;
WINTUN_RELEASE_RECEIVE_PACKET_FUNC WintunReleaseReceivePacket = nullptr;
WINTUN_ALLOC_SEND_PACKET_FUNC WintunAllocSendPacket = nullptr;
WINTUN_SEND_PACKET_FUNC WintunSendPacket = nullptr;
}; };