aboutsummaryrefslogtreecommitdiffstats
path: root/wintun.c
diff options
context:
space:
mode:
authorSimon Rozman <simon@rozman.si>2020-05-03 09:07:32 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2020-10-30 16:50:58 +0100
commit9b61d0d851300a717618f55dff85b0e38e658d79 (patch)
tree95e3213f18c6f1b7d0a7fc47336f8c33536b6626 /wintun.c
parentinstaller: ARM64 is always Windows 10 (diff)
downloadwintun-9b61d0d851300a717618f55dff85b0e38e658d79.tar.xz
wintun-9b61d0d851300a717618f55dff85b0e38e658d79.zip
Accept WoW64 clients
Signed-off-by: Simon Rozman <simon@rozman.si>
Diffstat (limited to 'wintun.c')
-rw-r--r--wintun.c57
1 files changed, 47 insertions, 10 deletions
diff --git a/wintun.c b/wintun.c
index 04b7206..60eb9dd 100644
--- a/wintun.c
+++ b/wintun.c
@@ -99,6 +99,25 @@ typedef struct _TUN_REGISTER_RINGS
} Send, Receive;
} TUN_REGISTER_RINGS;
+#ifdef _WIN64
+typedef struct _TUN_REGISTER_RINGS_32
+{
+ struct
+ {
+ /* Size of the ring */
+ ULONG RingSize;
+
+ /* 32-bit addres of client allocated ring */
+ ULONG Ring;
+
+ /* On send: An event created by the client the Wintun signals after it moves the Tail member of the send ring.
+ * On receive: An event created by the client the client will signal when it moves the Tail member of
+ * the receive ring if receive ring is alertable. */
+ ULONG TailMoved;
+ } Send, Receive;
+} TUN_REGISTER_RINGS_32;
+#endif
+
/* Register rings hosted by the client.
* The lpInBuffer and nInBufferSize parameters of DeviceIoControl() must point to an TUN_REGISTER_RINGS struct.
* Client must wait for this IOCTL to finish before adding packets to the ring. */
@@ -558,19 +577,37 @@ TunRegisterBuffers(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
goto cleanupMutex;
Ctx->Device.OwningFileObject = Stack->FileObject;
- TUN_REGISTER_RINGS *Rrb = Irp->AssociatedIrp.SystemBuffer;
- if (Status = STATUS_INVALID_PARAMETER, Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(*Rrb))
+ TUN_REGISTER_RINGS Rrb;
+ if (Stack->Parameters.DeviceIoControl.InputBufferLength == sizeof(Rrb))
+ NdisMoveMemory(&Rrb, Irp->AssociatedIrp.SystemBuffer, sizeof(Rrb));
+#ifdef _WIN64
+ else if (
+ IoIs32bitProcess(Irp) && Stack->Parameters.DeviceIoControl.InputBufferLength == sizeof(TUN_REGISTER_RINGS_32))
+ {
+ TUN_REGISTER_RINGS_32 *Rrb32 = Irp->AssociatedIrp.SystemBuffer;
+ Rrb.Send.RingSize = Rrb32->Send.RingSize;
+ Rrb.Send.Ring = (TUN_RING *)Rrb32->Send.Ring;
+ Rrb.Send.TailMoved = (HANDLE)Rrb32->Send.TailMoved;
+ Rrb.Receive.RingSize = Rrb32->Receive.RingSize;
+ Rrb.Receive.Ring = (TUN_RING *)Rrb32->Receive.Ring;
+ Rrb.Receive.TailMoved = (HANDLE)Rrb32->Receive.TailMoved;
+ }
+#endif
+ else
+ {
+ Status = STATUS_INVALID_PARAMETER;
goto cleanupResetOwner;
+ }
- Ctx->Device.Send.Capacity = TUN_RING_CAPACITY(Rrb->Send.RingSize);
+ Ctx->Device.Send.Capacity = TUN_RING_CAPACITY(Rrb.Send.RingSize);
if (Status = STATUS_INVALID_PARAMETER,
(Ctx->Device.Send.Capacity < TUN_MIN_RING_CAPACITY || Ctx->Device.Send.Capacity > TUN_MAX_RING_CAPACITY ||
- !IS_POW2(Ctx->Device.Send.Capacity) || !Rrb->Send.TailMoved || !Rrb->Send.Ring))
+ !IS_POW2(Ctx->Device.Send.Capacity) || !Rrb.Send.TailMoved || !Rrb.Send.Ring))
goto cleanupResetOwner;
if (!NT_SUCCESS(
Status = ObReferenceObjectByHandle(
- Rrb->Send.TailMoved,
+ Rrb.Send.TailMoved,
/* We will not wait on send ring tail moved event. */
EVENT_MODIFY_STATE,
*ExEventObjectType,
@@ -579,7 +616,7 @@ TunRegisterBuffers(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
NULL)))
goto cleanupResetOwner;
- Ctx->Device.Send.Mdl = IoAllocateMdl(Rrb->Send.Ring, Rrb->Send.RingSize, FALSE, FALSE, NULL);
+ Ctx->Device.Send.Mdl = IoAllocateMdl(Rrb.Send.Ring, Rrb.Send.RingSize, FALSE, FALSE, NULL);
if (Status = STATUS_INSUFFICIENT_RESOURCES, !Ctx->Device.Send.Mdl)
goto cleanupSendTailMoved;
try
@@ -598,15 +635,15 @@ TunRegisterBuffers(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
if (Status = STATUS_INVALID_PARAMETER, Ctx->Device.Send.RingTail >= Ctx->Device.Send.Capacity)
goto cleanupSendUnlockPages;
- Ctx->Device.Receive.Capacity = TUN_RING_CAPACITY(Rrb->Receive.RingSize);
+ Ctx->Device.Receive.Capacity = TUN_RING_CAPACITY(Rrb.Receive.RingSize);
if (Status = STATUS_INVALID_PARAMETER,
(Ctx->Device.Receive.Capacity < TUN_MIN_RING_CAPACITY || Ctx->Device.Receive.Capacity > TUN_MAX_RING_CAPACITY ||
- !IS_POW2(Ctx->Device.Receive.Capacity) || !Rrb->Receive.TailMoved || !Rrb->Receive.Ring))
+ !IS_POW2(Ctx->Device.Receive.Capacity) || !Rrb.Receive.TailMoved || !Rrb.Receive.Ring))
goto cleanupSendUnlockPages;
if (!NT_SUCCESS(
Status = ObReferenceObjectByHandle(
- Rrb->Receive.TailMoved,
+ Rrb.Receive.TailMoved,
/* We need to clear receive ring TailMoved event on transition to non-alertable state. */
SYNCHRONIZE | EVENT_MODIFY_STATE,
*ExEventObjectType,
@@ -615,7 +652,7 @@ TunRegisterBuffers(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
NULL)))
goto cleanupSendUnlockPages;
- Ctx->Device.Receive.Mdl = IoAllocateMdl(Rrb->Receive.Ring, Rrb->Receive.RingSize, FALSE, FALSE, NULL);
+ Ctx->Device.Receive.Mdl = IoAllocateMdl(Rrb.Receive.Ring, Rrb.Receive.RingSize, FALSE, FALSE, NULL);
if (Status = STATUS_INSUFFICIENT_RESOURCES, !Ctx->Device.Receive.Mdl)
goto cleanupReceiveTailMoved;
try