Add a WINDIVERT_FLAG_PARTIAL flag.

This suppresses ERROR_INSUFFICIENT_BUFFER errors
if the passed buffer is too small.  Applications
can set this flag if they want to do partial
reads.
This commit is contained in:
basil00
2018-10-30 08:56:43 +08:00
parent fc868feb3e
commit 3966ec1287
4 changed files with 20 additions and 12 deletions
+5
View File
@@ -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? "|": ""));
+2 -1
View File
@@ -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.
+3 -1
View File
@@ -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))
/*
+10 -10
View File
@@ -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);