diff --git a/examples/windivertctl/windivertctl.c b/examples/windivertctl/windivertctl.c index 88e004d..b2abceb 100644 --- a/examples/windivertctl/windivertctl.c +++ b/examples/windivertctl/windivertctl.c @@ -365,6 +365,11 @@ usage: printf("%sDEBUG", (or? "|": "")); or = TRUE; } + if ((addr.Reflect.Flags & WINDIVERT_FLAG_PARTIAL) != 0) + { + printf("%sPARTIAL", (or? "|": "")); + or = TRUE; + } if ((addr.Reflect.Flags & WINDIVERT_FLAG_NO_INSTALL) != 0) { printf("%sNO_INSTALL", (or? "|": "")); diff --git a/include/windivert.h b/include/windivert.h index 8b1afc4..b3baab0 100644 --- a/include/windivert.h +++ b/include/windivert.h @@ -191,7 +191,8 @@ typedef enum #define WINDIVERT_FLAG_SEND_ONLY 0x08 #define WINDIVERT_FLAG_WRITE_ONLY WINDIVERT_FLAG_SEND_ONLY #define WINDIVERT_FLAG_DEBUG 0x10 -#define WINDIVERT_FLAG_NO_INSTALL 0x20 +#define WINDIVERT_FLAG_PARTIAL 0x20 +#define WINDIVERT_FLAG_NO_INSTALL 0x40 /* * WinDivert parameters. diff --git a/include/windivert_device.h b/include/windivert_device.h index f945db2..1444da8 100644 --- a/include/windivert_device.h +++ b/include/windivert_device.h @@ -163,7 +163,7 @@ #define WINDIVERT_FLAGS_ALL \ (WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP | WINDIVERT_FLAG_RECV_ONLY |\ WINDIVERT_FLAG_SEND_ONLY | WINDIVERT_FLAG_DEBUG | \ - WINDIVERT_FLAG_NO_INSTALL) + WINDIVERT_FLAG_PARTIAL | WINDIVERT_FLAG_NO_INSTALL) #define WINDIVERT_FLAGS_EXCLUDE(flags, flag1, flag2) \ (((flags) & ((flag1) | (flag2))) != ((flag1) | (flag2))) #define WINDIVERT_FLAGS_VALID(flags) \ @@ -171,6 +171,8 @@ WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_SNIFF, \ WINDIVERT_FLAG_DROP) && \ WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_RECV_ONLY, \ + WINDIVERT_FLAG_SEND_ONLY) && \ + WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_PARTIAL, \ WINDIVERT_FLAG_SEND_ONLY)) /* diff --git a/sys/windivert.c b/sys/windivert.c index 24f028b..3f52a18 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -1919,7 +1919,8 @@ static NTSTATUS windivert_read(context_t context, WDFREQUEST request) /* * WinDivert service a single read request. */ -static void windivert_read_service_request(packet_t packet, WDFREQUEST request) +static void windivert_read_service_request(packet_t packet, BOOL partial, + WDFREQUEST request) { PMDL dst_mdl; UINT8 *layer_data, *src, *dst; @@ -1963,6 +1964,10 @@ static void windivert_read_service_request(packet_t packet, WDFREQUEST request) } src_len = packet->packet_len; dst_len = MmGetMdlByteCount(dst_mdl); + if (!partial && src_len > dst_len) + { + status = STATUS_BUFFER_TOO_SMALL; + } dst_len = (src_len < dst_len? src_len: dst_len); RtlCopyMemory(dst, src, dst_len); break; @@ -2027,14 +2032,7 @@ static void windivert_read_service_request(packet_t packet, WDFREQUEST request) windivert_read_service_request_exit: - if (NT_SUCCESS(status)) - { - WdfRequestCompleteWithInformation(request, status, dst_len); - } - else - { - WdfRequestComplete(request, status); - } + WdfRequestCompleteWithInformation(request, status, dst_len); } /* @@ -2049,6 +2047,7 @@ static void windivert_read_service(context_t context) PVOID dst, src; ULONG dst_len, src_len; LONGLONG timestamp; + BOOL partial; BOOL timeout; NTSTATUS status; packet_t packet; @@ -2057,6 +2056,7 @@ static void windivert_read_service(context_t context) timestamp = KeQueryPerformanceCounter(NULL).QuadPart; KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle); + partial = ((context->flags & WINDIVERT_FLAG_PARTIAL) != 0); while (context->state == WINDIVERT_CONTEXT_STATE_OPEN && !IsListEmpty(&context->packet_queue)) { @@ -2080,7 +2080,7 @@ static void windivert_read_service(context_t context) if (!timeout) { - windivert_read_service_request(packet, request); + windivert_read_service_request(packet, partial, request); } windivert_free_packet(packet);