// wintun.h — Dynamic-loading wrapper for the Wintun kernel TUN driver. // // Wintun is distributed as wintun.dll and loaded at runtime via LoadLibraryEx. // All API functions are resolved via GetProcAddress. // // Reference: https://git.zx2c4.com/wintun // License : Wintun is (C) WireGuard LLC; the header bindings here are MIT. // // Usage: // WintunLib wt; // if (!wt.load()) { /* wintun.dll not found */ } // WINTUN_ADAPTER_HANDLE adp = wt.CreateAdapter(L"DragonMoonlight", L"WireGuard", nullptr); #pragma once #ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN #endif #include #include #include // ─── Wintun opaque types ────────────────────────────────────────────────────── typedef void *WINTUN_ADAPTER_HANDLE; typedef void *WINTUN_SESSION_HANDLE; // ─── Wintun function pointer types ─────────────────────────────────────────── typedef WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_CREATE_ADAPTER_FUNC)( LPCWSTR Name, LPCWSTR TunnelType, const GUID *RequestedGUID); typedef WINTUN_ADAPTER_HANDLE(WINAPI *WINTUN_OPEN_ADAPTER_FUNC)(LPCWSTR Name); typedef void(WINAPI *WINTUN_CLOSE_ADAPTER_FUNC)(WINTUN_ADAPTER_HANDLE Adapter); typedef BOOL(WINAPI *WINTUN_DELETE_DRIVER_FUNC)(void); typedef void(WINAPI *WINTUN_GET_ADAPTER_LUID_FUNC)(WINTUN_ADAPTER_HANDLE Adapter, NET_LUID *Luid); typedef DWORD(WINAPI *WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC)(void); typedef WINTUN_SESSION_HANDLE(WINAPI *WINTUN_START_SESSION_FUNC)( WINTUN_ADAPTER_HANDLE Adapter, DWORD Capacity); typedef void(WINAPI *WINTUN_END_SESSION_FUNC)(WINTUN_SESSION_HANDLE Session); typedef HANDLE(WINAPI *WINTUN_GET_READ_WAIT_EVENT_FUNC)(WINTUN_SESSION_HANDLE Session); typedef BYTE *(WINAPI *WINTUN_RECEIVE_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session, DWORD *PacketSize); typedef void(WINAPI *WINTUN_RELEASE_RECEIVE_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session, const BYTE *Packet); typedef BYTE *(WINAPI *WINTUN_ALLOC_SEND_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session, DWORD PacketSize); typedef void(WINAPI *WINTUN_SEND_PACKET_FUNC)(WINTUN_SESSION_HANDLE Session, const BYTE *Packet); // ─── WintunLib — RAII loader ────────────────────────────────────────────────── class WintunLib { public: // Function pointers — public so TunnelManager can call them directly. WINTUN_CREATE_ADAPTER_FUNC CreateAdapter = nullptr; WINTUN_OPEN_ADAPTER_FUNC OpenAdapter = nullptr; WINTUN_CLOSE_ADAPTER_FUNC CloseAdapter = nullptr; WINTUN_DELETE_DRIVER_FUNC DeleteDriver = nullptr; WINTUN_GET_ADAPTER_LUID_FUNC GetAdapterLUID = nullptr; WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC GetRunningDriverVersion = nullptr; WINTUN_START_SESSION_FUNC StartSession = nullptr; WINTUN_END_SESSION_FUNC EndSession = nullptr; WINTUN_GET_READ_WAIT_EVENT_FUNC GetReadWaitEvent = nullptr; WINTUN_RECEIVE_PACKET_FUNC ReceivePacket = nullptr; WINTUN_RELEASE_RECEIVE_PACKET_FUNC ReleaseReceivePacket = nullptr; WINTUN_ALLOC_SEND_PACKET_FUNC AllocSendPacket = nullptr; WINTUN_SEND_PACKET_FUNC SendPacket = nullptr; WintunLib() = default; ~WintunLib() { unload(); } // Non-copyable WintunLib(const WintunLib &) = delete; WintunLib &operator=(const WintunLib &) = delete; /// Load wintun.dll from the application directory first, then System32. /// Returns true on success. bool load() { m_module = LoadLibraryExW(L"wintun.dll", nullptr, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); if (!m_module) return false; #define WINTUN_RESOLVE(name) \ name = reinterpret_cast(GetProcAddress(m_module, #name)); \ if (!name) { unload(); return false; } WINTUN_RESOLVE(WintunCreateAdapter) WINTUN_RESOLVE(WintunOpenAdapter) WINTUN_RESOLVE(WintunCloseAdapter) WINTUN_RESOLVE(WintunDeleteDriver) WINTUN_RESOLVE(WintunGetAdapterLUID) WINTUN_RESOLVE(WintunGetRunningDriverVersion) WINTUN_RESOLVE(WintunStartSession) WINTUN_RESOLVE(WintunEndSession) WINTUN_RESOLVE(WintunGetReadWaitEvent) WINTUN_RESOLVE(WintunReceivePacket) WINTUN_RESOLVE(WintunReleaseReceivePacket) WINTUN_RESOLVE(WintunAllocSendPacket) WINTUN_RESOLVE(WintunSendPacket) #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; } bool isLoaded() const { return m_module != nullptr; } void unload() { if (m_module) { FreeLibrary(m_module); m_module = nullptr; } CreateAdapter = nullptr; /* etc — reset all to nullptr */ } private: 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; };