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 @@
  • 7.2 Filter Usage
  • -
  • 8. Samples
  • -
  • 9. Known Issues
  • -
  • 10. License
  • +
  • 8. Performance
  • +
  • 9. Samples
  • +
  • 10. Known Issues
  • +
  • 11. License

  • 1. Introduction

    -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.


    @@ -231,17 +232,22 @@ To uninstall, simply delete the 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
    +

    5. Programming API

    @@ -1031,7 +1037,7 @@ and so on, provided the packet matches the handle's filter. A packet is only diverted once per priority level, so handles should not share priority levels unless they use mutually exclusive filters. Otherwise it is not defined which handle will receive the packet first. -Lower 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(