diff --git a/dll/windivert.c b/dll/windivert.c index f882bfe..1fefba8 100644 --- a/dll/windivert.c +++ b/dll/windivert.c @@ -219,10 +219,25 @@ static BOOLEAN WinDivertGetDriverFileName(LPWSTR sys_str) */ static SC_HANDLE WinDivertDriverInstall(VOID) { - DWORD err, retries = 2; + DWORD err; SC_HANDLE manager = NULL, service = NULL; wchar_t windivert_sys[MAX_PATH+1]; - SERVICE_STATUS status; + HANDLE mutex = NULL; + + // Create & lock a named mutex. This is to stop two processes trying + // to start the driver at the same time. + mutex = CreateMutex(NULL, FALSE, L"WinDivertDriverInstallMutex"); + if (mutex == NULL) + { + return NULL; + } + switch (WaitForSingleObject(mutex, INFINITE)) + { + case WAIT_OBJECT_0: case WAIT_ABANDONED: + break; + default: + return NULL; + } // Open the service manager: manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); @@ -232,7 +247,6 @@ static SC_HANDLE WinDivertDriverInstall(VOID) } // Check if the WinDivert service already exists; if so, start it. -WinDivertDriverInstallReTry: service = OpenService(manager, WINDIVERT_DEVICE_NAME, SERVICE_ALL_ACCESS); if (service != NULL) { @@ -254,11 +268,8 @@ WinDivertDriverInstallReTry: { if (GetLastError() == ERROR_SERVICE_EXISTS) { - if (retries != 0) - { - retries--; - goto WinDivertDriverInstallReTry; - } + service = OpenService(manager, WINDIVERT_DEVICE_NAME, + SERVICE_ALL_ACCESS); } goto WinDivertDriverInstallExit; } @@ -278,8 +289,6 @@ WinDivertDriverInstallExit: else { // Failed to start service; clean-up: - ControlService(service, SERVICE_CONTROL_STOP, &status); - DeleteService(service); CloseServiceHandle(service); service = NULL; SetLastError(err); @@ -292,6 +301,8 @@ WinDivertDriverInstallExit: { CloseServiceHandle(manager); } + ReleaseMutex(mutex); + CloseHandle(mutex); SetLastError(err); return service; @@ -442,7 +453,6 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer, INVALID_HANDLE_VALUE); // Schedule the service to be deleted (once all handles are closed). - DeleteService(service); CloseServiceHandle(service); if (handle == INVALID_HANDLE_VALUE) @@ -492,14 +502,14 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer, * Receive a WinDivert packet. */ extern BOOL WinDivertRecv(HANDLE handle, PVOID pPacket, UINT packetLen, - PWINDIVERT_ADDRESS addr, UINT *readlen) + UINT *readLen, PWINDIVERT_ADDRESS addr) { WINDIVERT_IOCTL ioctl; memset(&ioctl, 0, sizeof(ioctl)); ioctl.recv.addr = addr; ioctl.recv.addr_len_ptr = NULL; return WinDivertIoControl(handle, IOCTL_WINDIVERT_RECV, &ioctl, - pPacket, packetLen, readlen); + pPacket, packetLen, readLen); } /* @@ -534,14 +544,14 @@ extern BOOL WinDivertRecvEx(HANDLE handle, PVOID pPacket, UINT packetLen, * Send a WinDivert packet. */ extern BOOL WinDivertSend(HANDLE handle, const VOID *pPacket, UINT packetLen, - const WINDIVERT_ADDRESS *addr, UINT *writelen) + UINT *writeLen, const WINDIVERT_ADDRESS *addr) { WINDIVERT_IOCTL ioctl; memset(&ioctl, 0, sizeof(ioctl)); ioctl.send.addr = addr; ioctl.send.addr_len = sizeof(WINDIVERT_ADDRESS); return WinDivertIoControl(handle, IOCTL_WINDIVERT_SEND, &ioctl, - (PVOID)pPacket, packetLen, writelen); + (PVOID)pPacket, packetLen, writeLen); } /* diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c index 9bf73ea..4bec8e0 100644 --- a/dll/windivert_helper.c +++ b/dll/windivert_helper.c @@ -2460,7 +2460,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet, return FALSE; } if (!WinDivertHelperParsePacket((PVOID)packet, packet_len, - &protocol, &iphdr, &ipv6hdr, &icmphdr, &icmpv6hdr, + &iphdr, &ipv6hdr, &protocol, &icmphdr, &icmpv6hdr, &tcphdr, &udphdr, NULL, &payload_len, NULL, NULL)) { SetLastError(ERROR_INVALID_PARAMETER); @@ -4642,9 +4642,9 @@ extern UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen, PWINDIVERT_TCPHDR tcp_header = NULL; PWINDIVERT_UDPHDR udp_header = NULL; - if (!WinDivertHelperParsePacket((PVOID)pPacket, packetLen, NULL, - &ip_header, &ipv6_header, &icmp_header, &icmpv6_header, - &tcp_header, &udp_header, NULL, NULL, NULL, NULL)) + if (!WinDivertHelperParsePacket((PVOID)pPacket, packetLen, &ip_header, + &ipv6_header, NULL, &icmp_header, &icmpv6_header, &tcp_header, + &udp_header, NULL, NULL, NULL, NULL)) { return 0; } diff --git a/dll/windivert_shared.c b/dll/windivert_shared.c index ba9c4c9..43e0a94 100644 --- a/dll/windivert_shared.c +++ b/dll/windivert_shared.c @@ -284,7 +284,7 @@ static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len) * Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet. */ extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen, - UINT8 *pProtocol, PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr, + PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr, UINT8 *pProtocol, PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr, PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData, UINT *pDataLen, PVOID *ppNext, UINT *pNextLen) @@ -491,8 +491,8 @@ extern BOOL WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen, PWINDIVERT_UDPHDR udp_header; UINT payload_len, checksum_len; - if (!WinDivertHelperParsePacket(pPacket, packetLen, NULL, &ip_header, - &ipv6_header, &icmp_header, &icmpv6_header, &tcp_header, + if (!WinDivertHelperParsePacket(pPacket, packetLen, &ip_header, + &ipv6_header, NULL, &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, &payload_len, NULL, NULL)) { return FALSE; diff --git a/doc/windivert.html b/doc/windivert.html index 7190709..560cbbf 100644 --- a/doc/windivert.html +++ b/doc/windivert.html @@ -61,15 +61,16 @@
-WinDivert is a user-mode +WinDivert is a powerful user-mode capture/sniffing/modification/blocking/re-injection package for Windows 7, Windows 8 and Windows 10. WinDivert can be used to implement user-mode packet filters, packet sniffers, @@ -93,8 +94,8 @@ The main features of the WinDivert are:
WinDivert provides similar functionality to
-divert sockets from FreeBSD/MacOS, NETLINK sockets from
-Linux.
+divert sockets from FreeBSD/MacOS, NETLINK sockets
+from Linux.
WinDivert.dll,
WinDivert32.sys, and WinDivert64.sys files.
If already running, the WinDivert driver will be automatically
uninstalled during the next machine reboot.
-The WinDivert driver can also be manually removed by issuing the following
+The WinDivert driver can also be manually removed by (1) terminating
+all processes that are using WinDivert, and (2) issuing the following
commands at the command prompt
-sc stop WinDivert -sc delete WinDivert + sc stop WinDivert + sc delete WinDivert
-Note that this is not recommended as it will interfere with other
-applications that depend on WinDivert.
+Alternatively, the WinDivert driver can be removed by using the
+windivertctl.exe sample program by
+issuing the following command:
+ windivertctl uninstall +
priority values represent higher priorities, with
+Higher priority values represent higher priorities, with
WINDIVERT_PRIORITY_HIGHEST being the highest priority,
0 the middle (and a good default) priority,
and WINDIVERT_PRIORITY_LOWEST the lowest priority.
@@ -1180,8 +1186,8 @@ BOOL WinDivertRecv(
__in HANDLE handle,
__out_opt PVOID pPacket,
__in UINT packetLen,
- __out_opt WINDIVERT_ADDRESS *pAddr,
- __out_opt UINT *recvLen
+ __out_opt UINT *pRecvLen,
+ __out_opt WINDIVERT_ADDRESS *pAddr
);
@@ -1192,10 +1198,10 @@ BOOL WinDivertRecv(
WinDivertOpen().
pPacket: An optional buffer for the captured packet.packetLen: The length of the pPacket buffer.pRecvLen: The total number of bytes written to pPacket.
+ Can be NULL if this information is not required.pAddr: An optional buffer for the
address of the captured packet/event.recvLen: The total number of bytes written to pPacket.
- Can be NULL if this information is not required.
Return Value
@@ -1307,7 +1313,7 @@ Data?
For layers that do support capturing, the captured packet will be written to
the pPacket buffer.
If non-NULL, then the total number of bytes
-written to pPacket will be written to recvLen.
+written to pPacket will be written to pRecvLen.
If the pPacket buffer is too small, the packet will be
truncated and the operation will fail with the
ERROR_INSUFFICIENT_BUFFER error code.
@@ -1347,7 +1353,7 @@ BOOL WinDivertRecvEx(
__in HANDLE handle,
__out VOID *pPacket,
__in UINT packetLen,
- __out_opt UINT *recvLen,
+ __out_opt UINT *pRecvLen,
__in UINT64 flags,
__out_opt WINDIVERT_ADDRESS *pAddr,
__inout_opt UINT *pAddrLen,
@@ -1363,7 +1369,7 @@ BOOL WinDivertRecvEx(
pPacket: A buffer for the captured packet(s).packetLen: The length of the pPacket buffer in
bytes.recvLen: The total number of bytes written to pPacket.
+pRecvLen: The total number of bytes written to pPacket.
Can be NULL if this information is not required.flags: Reserved, set to zero.pAddr: The
@@ -1437,8 +1443,8 @@ BOOL WinDivertSend(
__in HANDLE handle,
__in const VOID *pPacket,
__in UINT packetLen,
- __in const WINDIVERT_ADDRESS *pAddr,
- __out_opt UINT *sendLen
+ __out_opt UINT *pSendLen,
+ __in const WINDIVERT_ADDRESS *pAddr
);
@@ -1449,10 +1455,10 @@ BOOL WinDivertSend(
WinDivertOpen().pPacket: A buffer containing a packet to be injected.packetLen: The total length of the pPacket buffer.pSendLen: The total number of bytes injected.
+ Can be NULL if this information is not required.pAddr: The
address of the injected packet.sendLen: The total number of bytes injected.
- Can be NULL if this information is not required.
Return Value
@@ -1608,7 +1614,7 @@ BOOL WinDivertSendEx(
__in HANDLE handle,
__in const VOID *pPacket,
__in UINT packetLen,
- __out_opt UINT *sendLen,
+ __out_opt UINT *pSendLen,
__in UINT64 flags,
__in const WINDIVERT_ADDRESS *pAddr,
__in UINT addrLen,
@@ -1623,7 +1629,7 @@ BOOL WinDivertSendEx(
WinDivertOpen().
pPacket: A buffer containing the packet(s) to be injected.packetLen: The total length of the buffer pPacket.sendLen: The total number of bytes injected.
+pSendLen: The total number of bytes injected.
Can be NULL if this information is not required.flags: Reserved, set to zero.pAddr: The
@@ -2105,9 +2111,9 @@ UDP header definition.
BOOL WinDivertHelperParsePacket(
__in PVOID pPacket,
__in UINT packetLen,
- __out_opt UINT8 *pProtocol,
__out_opt PWINDIVERT_IPHDR *ppIpHdr,
__out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
+ __out_opt UINT8 *pProtocol,
__out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr,
__out_opt PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
__out_opt PWINDIVERT_TCPHDR *ppTcpHdr,
@@ -2124,9 +2130,9 @@ BOOL WinDivertHelperParsePacket(
pPacket: The packet(s) to be parsed.packetLen: The total length of the packet(s) pPacket.pProtocol: Output transport protocol.ppIpHdr: Output pointer to a WINDIVERT_IPHDR.ppIpv6Hdr: Output pointer to a WINDIVERT_IPV6HDR.pProtocol: Output transport protocol.ppIcmpHdr: Output pointer to a WINDIVERT_ICMPHDR.ppIcmpv6Hdr: Output pointer to a WINDIVERT_ICMPV6HDR.ppTcpHdr: Output pointer to a WINDIVERT_TCPHDR.
BOOL WinDivertHelperCalcChecksums(
- __inout PVOID pPacket,
+ __inout VOID *pPacket,
__in UINT packetLen,
__out_opt WINDIVERT_ADDRESS *pAddr,
__in UINT64 flags
@@ -2874,7 +2880,65 @@ find the optimal solution.
passthru.exe: A simple program that simply re-injects every
packet it captures.
- This example is multi-threaded, where multiple threads are processing
- packets from a single handle.
- This example is useful for performance testing, and as a starting point
+ This example has a configurable batch-size and thread count,
+ and so is useful for performance testing or as a starting point
for more interesting applications.streamdump.exe: A simple program that demonstrates how to
handle streams using WinDivert.
@@ -2924,9 +2987,11 @@ The sample programs are:
The socketdump sample demonstrates the
WINDIVERT_LAYER_SOCKET layer.windivertctl.exe allows the user to query which processes
- are using WinDivert via the list or monitor
+ are using WinDivert via the list or watch
commands, or to terminate all such processes using the
- killall command.
+ kill command.
+ The windivertctl.exe can also forcibly remove the
+ WinDivert driver using the uninstall command.
The windivertctl sample demonstrates the
WINDIVERT_LAYER_REFLECT layer.netdump.exe sample program for an example of this usage.
- 9. Known Issues+10. Known Issues
WinDivert has some known limitations listed below:
@@ -3038,8 +3103,8 @@ WinDivert has some known limitations listed below:
- 10. License+11. License |