Manually clean up ugly corners
This commit is contained in:
parent
5ec565c7e8
commit
de481cdb12
@ -91,6 +91,7 @@ StatementMacros: [
|
|||||||
'_Acquires_shared_lock_',
|
'_Acquires_shared_lock_',
|
||||||
'_Releases_shared_lock_',
|
'_Releases_shared_lock_',
|
||||||
'_Requires_lock_held_',
|
'_Requires_lock_held_',
|
||||||
|
'_Requires_lock_not_held_',
|
||||||
'_Use_decl_annotations_',
|
'_Use_decl_annotations_',
|
||||||
'_Guarded_by_',
|
'_Guarded_by_',
|
||||||
'__drv_preferredFunction',
|
'__drv_preferredFunction',
|
||||||
|
@ -37,6 +37,7 @@ ZwQuerySystemInformation(
|
|||||||
PVOID SystemInformation,
|
PVOID SystemInformation,
|
||||||
ULONG SystemInformationLength,
|
ULONG SystemInformationLength,
|
||||||
ULONG *ReturnLength);
|
ULONG *ReturnLength);
|
||||||
|
|
||||||
extern NDIS_HANDLE
|
extern NDIS_HANDLE
|
||||||
NdisWdfGetAdapterContextFromAdapterHandle(PVOID DeviceExtension);
|
NdisWdfGetAdapterContextFromAdapterHandle(PVOID DeviceExtension);
|
||||||
|
|
||||||
|
389
wintun.c
389
wintun.c
@ -18,6 +18,7 @@
|
|||||||
#pragma warning(disable : 4204) // nonstandard extension used: non-constant aggregate initializer
|
#pragma warning(disable : 4204) // nonstandard extension used: non-constant aggregate initializer
|
||||||
#pragma warning(disable : 4221) // nonstandard extension used: <member>: cannot be initialized using address of
|
#pragma warning(disable : 4221) // nonstandard extension used: <member>: cannot be initialized using address of
|
||||||
// automatic variable <variable>
|
// automatic variable <variable>
|
||||||
|
#pragma warning(disable : 6320) // exception-filter expression is the constant EXCEPTION_EXECUTE_HANDLER
|
||||||
|
|
||||||
#define NDIS_MINIPORT_VERSION_MIN ((NDIS_MINIPORT_MINIMUM_MAJOR_VERSION << 16) | NDIS_MINIPORT_MINIMUM_MINOR_VERSION)
|
#define NDIS_MINIPORT_VERSION_MIN ((NDIS_MINIPORT_MINIMUM_MAJOR_VERSION << 16) | NDIS_MINIPORT_MINIMUM_MINOR_VERSION)
|
||||||
#define NDIS_MINIPORT_VERSION_MAX ((NDIS_MINIPORT_MAJOR_VERSION << 16) | NDIS_MINIPORT_MINOR_VERSION)
|
#define NDIS_MINIPORT_VERSION_MAX ((NDIS_MINIPORT_MAJOR_VERSION << 16) | NDIS_MINIPORT_MINOR_VERSION)
|
||||||
@ -28,15 +29,15 @@
|
|||||||
#define TUN_VENDOR_ID 0xFFFFFF00
|
#define TUN_VENDOR_ID 0xFFFFFF00
|
||||||
#define TUN_LINK_SPEED 100000000000ULL // 100gbps
|
#define TUN_LINK_SPEED 100000000000ULL // 100gbps
|
||||||
|
|
||||||
#define TUN_EXCH_MAX_PACKETS \
|
// Maximum number of full-sized exchange packets that can be exchanged in a single read/write.
|
||||||
256 // Maximum number of full-sized exchange packets that can be exchanged in a single read/write
|
#define TUN_EXCH_MAX_PACKETS 256
|
||||||
#define TUN_EXCH_MAX_PACKET_SIZE \
|
// Maximum exchange packet size - empirically determined by net buffer list (pool) limitations
|
||||||
0xF000 // Maximum exchange packet size - empirically determined by net buffer list (pool) limitations
|
#define TUN_EXCH_MAX_PACKET_SIZE 0xF000
|
||||||
#define TUN_EXCH_ALIGNMENT 16 // Memory alignment in exchange buffers
|
#define TUN_EXCH_ALIGNMENT 16 // Memory alignment in exchange buffers
|
||||||
#define TUN_EXCH_MAX_IP_PACKET_SIZE \
|
// Maximum IP packet size (headers + payload)
|
||||||
(TUN_EXCH_MAX_PACKET_SIZE - sizeof(TUN_PACKET)) // Maximum IP packet size (headers + payload)
|
#define TUN_EXCH_MAX_IP_PACKET_SIZE (TUN_EXCH_MAX_PACKET_SIZE - sizeof(TUN_PACKET))
|
||||||
#define TUN_EXCH_MAX_BUFFER_SIZE \
|
// Maximum size of read/write exchange buffer
|
||||||
(TUN_EXCH_MAX_PACKETS * TUN_EXCH_MAX_PACKET_SIZE) // Maximum size of read/write exchange buffer
|
#define TUN_EXCH_MAX_BUFFER_SIZE (TUN_EXCH_MAX_PACKETS * TUN_EXCH_MAX_PACKET_SIZE)
|
||||||
#define TUN_EXCH_MIN_BUFFER_SIZE_READ TUN_EXCH_MAX_PACKET_SIZE // Minimum size of read exchange buffer
|
#define TUN_EXCH_MIN_BUFFER_SIZE_READ TUN_EXCH_MAX_PACKET_SIZE // Minimum size of read exchange buffer
|
||||||
#define TUN_EXCH_MIN_BUFFER_SIZE_WRITE (sizeof(TUN_PACKET)) // Minimum size of write exchange buffer
|
#define TUN_EXCH_MIN_BUFFER_SIZE_WRITE (sizeof(TUN_PACKET)) // Minimum size of write exchange buffer
|
||||||
#define TUN_QUEUE_MAX_NBLS 1000
|
#define TUN_QUEUE_MAX_NBLS 1000
|
||||||
@ -48,10 +49,10 @@
|
|||||||
# define TUN_HTONS(x) ((USHORT)(x))
|
# define TUN_HTONS(x) ((USHORT)(x))
|
||||||
# define TUN_HTONL(x) ((ULONG)(x))
|
# define TUN_HTONL(x) ((ULONG)(x))
|
||||||
#elif REG_DWORD == REG_DWORD_LITTLE_ENDIAN
|
#elif REG_DWORD == REG_DWORD_LITTLE_ENDIAN
|
||||||
# define TUN_HTONS(x) (((USHORT)(x)&0x00ff) << 8 | ((USHORT)(x)&0xff00) >> 8)
|
# define TUN_HTONS(x) ((((USHORT)(x)&0x00ff) << 8) | (((USHORT)(x)&0xff00) >> 8))
|
||||||
# define TUN_HTONL(x) \
|
# define TUN_HTONL(x) \
|
||||||
(((ULONG)(x)&0x000000ff) << 24 | ((ULONG)(x)&0x0000ff00) << 8 | ((ULONG)(x)&0x00ff0000) >> 8 | \
|
((((ULONG)(x)&0x000000ff) << 24) | (((ULONG)(x)&0x0000ff00) << 8) | (((ULONG)(x)&0x00ff0000) >> 8) | \
|
||||||
((ULONG)(x)&0xff000000) >> 24)
|
(((ULONG)(x)&0xff000000) >> 24))
|
||||||
#else
|
#else
|
||||||
# error "Unable to determine endianess"
|
# error "Unable to determine endianess"
|
||||||
#endif
|
#endif
|
||||||
@ -77,8 +78,7 @@ typedef struct _TUN_CTX
|
|||||||
* atomic and then releasing. It's similar to setting the atomic and then calling rcu_barrier(). */
|
* atomic and then releasing. It's similar to setting the atomic and then calling rcu_barrier(). */
|
||||||
EX_SPIN_LOCK TransitionLock;
|
EX_SPIN_LOCK TransitionLock;
|
||||||
|
|
||||||
/* This is actually a pointer to NDIS_MINIPORT_BLOCK struct. */
|
NDIS_HANDLE MiniportAdapterHandle; // This is actually a pointer to NDIS_MINIPORT_BLOCK struct.
|
||||||
NDIS_HANDLE MiniportAdapterHandle;
|
|
||||||
NDIS_STATISTICS_INFO Statistics;
|
NDIS_STATISTICS_INFO Statistics;
|
||||||
|
|
||||||
volatile LONG64 ActiveNBLCount;
|
volatile LONG64 ActiveNBLCount;
|
||||||
@ -166,22 +166,22 @@ TunIndicateStatus(_In_ NDIS_HANDLE MiniportAdapterHandle, _In_ NDIS_MEDIA_CONNEC
|
|||||||
|
|
||||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
static void
|
static void
|
||||||
TunCompleteRequest(_Inout_ TUN_CTX *ctx, _Inout_ IRP *irp, _In_ NTSTATUS status, _In_ CCHAR priority_boost)
|
TunCompleteRequest(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp, _In_ NTSTATUS Status, _In_ CCHAR PriorityBoost)
|
||||||
{
|
{
|
||||||
irp->IoStatus.Status = status;
|
Irp->IoStatus.Status = Status;
|
||||||
IoCompleteRequest(irp, priority_boost);
|
IoCompleteRequest(Irp, PriorityBoost);
|
||||||
IoReleaseRemoveLock(&ctx->Device.RemoveLock, irp);
|
IoReleaseRemoveLock(&Ctx->Device.RemoveLock, Irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
static NDIS_STATUS
|
static NDIS_STATUS
|
||||||
TunCompletePause(_Inout_ TUN_CTX *ctx, _In_ BOOLEAN async_completion)
|
TunCompletePause(_Inout_ TUN_CTX *Ctx, _In_ BOOLEAN AsyncCompletion)
|
||||||
{
|
{
|
||||||
ASSERT(InterlockedGet64(&ctx->ActiveNBLCount) > 0);
|
ASSERT(InterlockedGet64(&Ctx->ActiveNBLCount) > 0);
|
||||||
if (InterlockedDecrement64(&ctx->ActiveNBLCount) <= 0)
|
if (InterlockedDecrement64(&Ctx->ActiveNBLCount) <= 0)
|
||||||
{
|
{
|
||||||
if (async_completion)
|
if (AsyncCompletion)
|
||||||
NdisMPauseComplete(ctx->MiniportAdapterHandle);
|
NdisMPauseComplete(Ctx->MiniportAdapterHandle);
|
||||||
return NDIS_STATUS_SUCCESS;
|
return NDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,27 +264,26 @@ TunCsqCompleteCanceledIrp(IO_CSQ *Csq, IRP *Irp)
|
|||||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
TunGetIrpBuffer(_In_ IRP *Irp, _Out_ UCHAR **buffer, _Out_ ULONG *size)
|
TunGetIrpBuffer(_In_ IRP *Irp, _Out_ UCHAR **buffer, _Out_ ULONG *Size)
|
||||||
{
|
{
|
||||||
TUN_MAPPED_UBUFFER *ubuffer = NULL;
|
TUN_MAPPED_UBUFFER *ubuffer;
|
||||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp);
|
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
TUN_FILE_CTX *file_ctx = (TUN_FILE_CTX *)stack->FileObject->FsContext;
|
TUN_FILE_CTX *file_ctx = (TUN_FILE_CTX *)stack->FileObject->FsContext;
|
||||||
|
|
||||||
switch (stack->MajorFunction)
|
switch (stack->MajorFunction)
|
||||||
{
|
{
|
||||||
case IRP_MJ_READ:
|
case IRP_MJ_READ:
|
||||||
*size = stack->Parameters.Read.Length;
|
*Size = stack->Parameters.Read.Length;
|
||||||
ubuffer = &file_ctx->ReadBuffer;
|
ubuffer = &file_ctx->ReadBuffer;
|
||||||
break;
|
break;
|
||||||
case IRP_MJ_WRITE:
|
case IRP_MJ_WRITE:
|
||||||
*size = stack->Parameters.Write.Length;
|
*Size = stack->Parameters.Write.Length;
|
||||||
ubuffer = &file_ctx->WriteBuffer;
|
ubuffer = &file_ctx->WriteBuffer;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ASSERT(FALSE);
|
return STATUS_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
_Analysis_assume_(ubuffer != NULL);
|
if (*Size > ubuffer->Size)
|
||||||
if (*size > ubuffer->Size)
|
|
||||||
return STATUS_INVALID_USER_BUFFER;
|
return STATUS_INVALID_USER_BUFFER;
|
||||||
ASSERT(ubuffer->KernelAddress != NULL);
|
ASSERT(ubuffer->KernelAddress != NULL);
|
||||||
*buffer = ubuffer->KernelAddress;
|
*buffer = ubuffer->KernelAddress;
|
||||||
@ -302,7 +301,7 @@ TunMapUbuffer(_Inout_ TUN_MAPPED_UBUFFER *MappedBuffer, _In_ VOID *UserAddress,
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
return STATUS_ALREADY_INITIALIZED;
|
return STATUS_ALREADY_INITIALIZED;
|
||||||
}
|
}
|
||||||
__try
|
try
|
||||||
{
|
{
|
||||||
ProbeForWrite(UserAddress, Size, 1);
|
ProbeForWrite(UserAddress, Size, 1);
|
||||||
ProbeForRead(UserAddress, Size, 1);
|
ProbeForRead(UserAddress, Size, 1);
|
||||||
@ -322,7 +321,7 @@ TunMapUbuffer(_Inout_ TUN_MAPPED_UBUFFER *MappedBuffer, _In_ VOID *UserAddress,
|
|||||||
MappedBuffer->UserAddress = UserAddress;
|
MappedBuffer->UserAddress = UserAddress;
|
||||||
MappedBuffer->Size = Size;
|
MappedBuffer->Size = Size;
|
||||||
}
|
}
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
except(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
if (MappedBuffer->Mdl)
|
if (MappedBuffer->Mdl)
|
||||||
{
|
{
|
||||||
@ -381,48 +380,48 @@ TunMapIrp(_In_ IRP *Irp)
|
|||||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static _Return_type_success_(
|
static _Return_type_success_(
|
||||||
return != NULL) IRP *TunRemoveNextIrp(_Inout_ TUN_CTX *ctx, _Out_ UCHAR **buffer, _Out_ ULONG *size)
|
return != NULL) IRP *TunRemoveNextIrp(_Inout_ TUN_CTX *Ctx, _Out_ UCHAR **Buffer, _Out_ ULONG *Size)
|
||||||
{
|
{
|
||||||
IRP *irp;
|
IRP *irp;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, NULL);
|
irp = IoCsqRemoveNextIrp(&Ctx->Device.ReadQueue.Csq, NULL);
|
||||||
if (!irp)
|
if (!irp)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
NTSTATUS status = TunGetIrpBuffer(irp, buffer, size);
|
NTSTATUS status = TunGetIrpBuffer(irp, Buffer, Size);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
TunCompleteRequest(ctx, irp, status, IO_NO_INCREMENT);
|
TunCompleteRequest(Ctx, irp, status, IO_NO_INCREMENT);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(irp->IoStatus.Information <= (ULONG_PTR)*size);
|
ASSERT(irp->IoStatus.Information <= (ULONG_PTR)*Size);
|
||||||
|
|
||||||
return irp;
|
return irp;
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_same_ static BOOLEAN
|
_IRQL_requires_same_ static BOOLEAN
|
||||||
TunWontFitIntoIrp(_In_ IRP *Irp, _In_ ULONG size, _In_ NET_BUFFER *nb)
|
TunWontFitIntoIrp(_In_ IRP *Irp, _In_ ULONG Size, _In_ NET_BUFFER *Nb)
|
||||||
{
|
{
|
||||||
return (ULONG_PTR)size <
|
return (ULONG_PTR)Size <
|
||||||
Irp->IoStatus.Information + TunPacketAlign(sizeof(TUN_PACKET) + NET_BUFFER_DATA_LENGTH(nb));
|
Irp->IoStatus.Information + TunPacketAlign(sizeof(TUN_PACKET) + NET_BUFFER_DATA_LENGTH(Nb));
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
TunWriteIntoIrp(_Inout_ IRP *Irp, _Inout_ UCHAR *buffer, _In_ NET_BUFFER *nb, _Inout_ NDIS_STATISTICS_INFO *statistics)
|
TunWriteIntoIrp(_Inout_ IRP *Irp, _Inout_ UCHAR *Buffer, _In_ NET_BUFFER *Nb, _Inout_ NDIS_STATISTICS_INFO *Statistics)
|
||||||
{
|
{
|
||||||
ULONG p_size = NET_BUFFER_DATA_LENGTH(nb);
|
ULONG p_size = NET_BUFFER_DATA_LENGTH(Nb);
|
||||||
TUN_PACKET *p = (TUN_PACKET *)(buffer + Irp->IoStatus.Information);
|
TUN_PACKET *p = (TUN_PACKET *)(Buffer + Irp->IoStatus.Information);
|
||||||
|
|
||||||
p->Size = p_size;
|
p->Size = p_size;
|
||||||
void *ptr = NdisGetDataBuffer(nb, p_size, p->Data, 1, 0);
|
void *ptr = NdisGetDataBuffer(Nb, p_size, p->Data, 1, 0);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
{
|
{
|
||||||
if (statistics)
|
if (Statistics)
|
||||||
InterlockedIncrement64((LONG64 *)&statistics->ifOutErrors);
|
InterlockedIncrement64((LONG64 *)&Statistics->ifOutErrors);
|
||||||
return NDIS_STATUS_RESOURCES;
|
return NDIS_STATUS_RESOURCES;
|
||||||
}
|
}
|
||||||
if (ptr != p->Data)
|
if (ptr != p->Data)
|
||||||
@ -430,114 +429,115 @@ TunWriteIntoIrp(_Inout_ IRP *Irp, _Inout_ UCHAR *buffer, _In_ NET_BUFFER *nb, _I
|
|||||||
|
|
||||||
Irp->IoStatus.Information += TunPacketAlign(sizeof(TUN_PACKET) + p_size);
|
Irp->IoStatus.Information += TunPacketAlign(sizeof(TUN_PACKET) + p_size);
|
||||||
|
|
||||||
InterlockedAdd64((LONG64 *)&statistics->ifHCOutOctets, p_size);
|
InterlockedAdd64((LONG64 *)&Statistics->ifHCOutOctets, p_size);
|
||||||
InterlockedAdd64((LONG64 *)&statistics->ifHCOutUcastOctets, p_size);
|
InterlockedAdd64((LONG64 *)&Statistics->ifHCOutUcastOctets, p_size);
|
||||||
InterlockedIncrement64((LONG64 *)&statistics->ifHCOutUcastPkts);
|
InterlockedIncrement64((LONG64 *)&Statistics->ifHCOutUcastPkts);
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NET_BUFFER_LIST_REFCOUNT(nbl) ((volatile LONG64 *)NET_BUFFER_LIST_MINIPORT_RESERVED(nbl))
|
#define NET_BUFFER_LIST_REFCOUNT(nbl) ((volatile LONG64 *)NET_BUFFER_LIST_MINIPORT_RESERVED(nbl))
|
||||||
|
|
||||||
_IRQL_requires_same_ static void
|
_IRQL_requires_same_ static void
|
||||||
TunNBLRefInit(_Inout_ TUN_CTX *ctx, _Inout_ NET_BUFFER_LIST *nbl)
|
TunNBLRefInit(_Inout_ TUN_CTX *Ctx, _Inout_ NET_BUFFER_LIST *Nbl)
|
||||||
{
|
{
|
||||||
InterlockedIncrement64(&ctx->ActiveNBLCount);
|
InterlockedIncrement64(&Ctx->ActiveNBLCount);
|
||||||
InterlockedIncrement(&ctx->PacketQueue.NumNbl);
|
InterlockedIncrement(&Ctx->PacketQueue.NumNbl);
|
||||||
InterlockedExchange64(NET_BUFFER_LIST_REFCOUNT(nbl), 1);
|
InterlockedExchange64(NET_BUFFER_LIST_REFCOUNT(Nbl), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_same_ static void
|
_IRQL_requires_same_ static void
|
||||||
TunNBLRefInc(_Inout_ NET_BUFFER_LIST *nbl)
|
TunNBLRefInc(_Inout_ NET_BUFFER_LIST *Nbl)
|
||||||
{
|
{
|
||||||
ASSERT(InterlockedGet64(NET_BUFFER_LIST_REFCOUNT(nbl)));
|
ASSERT(InterlockedGet64(NET_BUFFER_LIST_REFCOUNT(Nbl)));
|
||||||
InterlockedIncrement64(NET_BUFFER_LIST_REFCOUNT(nbl));
|
InterlockedIncrement64(NET_BUFFER_LIST_REFCOUNT(Nbl));
|
||||||
}
|
}
|
||||||
|
|
||||||
_When_((SendCompleteFlags & NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL), _IRQL_requires_(DISPATCH_LEVEL))
|
_When_((SendCompleteFlags & NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL), _IRQL_requires_(DISPATCH_LEVEL))
|
||||||
_When_(!(SendCompleteFlags & NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL), _IRQL_requires_max_(DISPATCH_LEVEL))
|
_When_(!(SendCompleteFlags & NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL), _IRQL_requires_max_(DISPATCH_LEVEL))
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
TunNBLRefDec(_Inout_ TUN_CTX *ctx, _Inout_ NET_BUFFER_LIST *nbl, _In_ ULONG SendCompleteFlags)
|
TunNBLRefDec(_Inout_ TUN_CTX *Ctx, _Inout_ NET_BUFFER_LIST *Nbl, _In_ ULONG SendCompleteFlags)
|
||||||
{
|
{
|
||||||
ASSERT(InterlockedGet64(NET_BUFFER_LIST_REFCOUNT(nbl)) > 0);
|
ASSERT(InterlockedGet64(NET_BUFFER_LIST_REFCOUNT(Nbl)) > 0);
|
||||||
if (InterlockedDecrement64(NET_BUFFER_LIST_REFCOUNT(nbl)) <= 0)
|
if (InterlockedDecrement64(NET_BUFFER_LIST_REFCOUNT(Nbl)) <= 0)
|
||||||
{
|
{
|
||||||
NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
|
NET_BUFFER_LIST_NEXT_NBL(Nbl) = NULL;
|
||||||
NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, SendCompleteFlags);
|
NdisMSendNetBufferListsComplete(Ctx->MiniportAdapterHandle, Nbl, SendCompleteFlags);
|
||||||
ASSERT(InterlockedGet(&ctx->PacketQueue.NumNbl) > 0);
|
ASSERT(InterlockedGet(&Ctx->PacketQueue.NumNbl) > 0);
|
||||||
InterlockedDecrement(&ctx->PacketQueue.NumNbl);
|
InterlockedDecrement(&Ctx->PacketQueue.NumNbl);
|
||||||
TunCompletePause(ctx, TRUE);
|
TunCompletePause(Ctx, TRUE);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_same_ static void
|
_IRQL_requires_same_ static void
|
||||||
TunAppendNBL(_Inout_ NET_BUFFER_LIST **head, _Inout_ NET_BUFFER_LIST **tail, __drv_aliasesMem _In_ NET_BUFFER_LIST *nbl)
|
TunAppendNBL(_Inout_ NET_BUFFER_LIST **Head, _Inout_ NET_BUFFER_LIST **Tail, __drv_aliasesMem _In_ NET_BUFFER_LIST *Nbl)
|
||||||
{
|
{
|
||||||
*(*tail ? &NET_BUFFER_LIST_NEXT_NBL(*tail) : head) = nbl;
|
*(*Tail ? &NET_BUFFER_LIST_NEXT_NBL(*Tail) : Head) = Nbl;
|
||||||
*tail = nbl;
|
*Tail = Nbl;
|
||||||
NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
|
NET_BUFFER_LIST_NEXT_NBL(Nbl) = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Requires_lock_not_held_(ctx->PacketQueue.Lock) _IRQL_requires_max_(DISPATCH_LEVEL)
|
_Requires_lock_not_held_(Ctx->PacketQueue.Lock)
|
||||||
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
static void
|
static void
|
||||||
TunQueueAppend(_Inout_ TUN_CTX *ctx, _In_ NET_BUFFER_LIST *nbl, _In_ UINT max_nbls)
|
TunQueueAppend(_Inout_ TUN_CTX *Ctx, _In_ NET_BUFFER_LIST *Nbl, _In_ UINT MaxNbls)
|
||||||
{
|
{
|
||||||
for (NET_BUFFER_LIST *nbl_next; nbl; nbl = nbl_next)
|
for (NET_BUFFER_LIST *nbl_next; Nbl; Nbl = nbl_next)
|
||||||
{
|
{
|
||||||
nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl);
|
nbl_next = NET_BUFFER_LIST_NEXT_NBL(Nbl);
|
||||||
if (!NET_BUFFER_LIST_FIRST_NB(nbl))
|
if (!NET_BUFFER_LIST_FIRST_NB(Nbl))
|
||||||
{
|
{
|
||||||
NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
|
NET_BUFFER_LIST_NEXT_NBL(Nbl) = NULL;
|
||||||
NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, 0);
|
NdisMSendNetBufferListsComplete(Ctx->MiniportAdapterHandle, Nbl, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
KLOCK_QUEUE_HANDLE lqh;
|
KLOCK_QUEUE_HANDLE lqh;
|
||||||
KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh);
|
KeAcquireInStackQueuedSpinLock(&Ctx->PacketQueue.Lock, &lqh);
|
||||||
TunNBLRefInit(ctx, nbl);
|
TunNBLRefInit(Ctx, Nbl);
|
||||||
TunAppendNBL(&ctx->PacketQueue.FirstNbl, &ctx->PacketQueue.LastNbl, nbl);
|
TunAppendNBL(&Ctx->PacketQueue.FirstNbl, &Ctx->PacketQueue.LastNbl, Nbl);
|
||||||
|
|
||||||
while ((UINT)InterlockedGet(&ctx->PacketQueue.NumNbl) > max_nbls && ctx->PacketQueue.FirstNbl)
|
while ((UINT)InterlockedGet(&Ctx->PacketQueue.NumNbl) > MaxNbls && Ctx->PacketQueue.FirstNbl)
|
||||||
{
|
{
|
||||||
NET_BUFFER_LIST *nbl_second = NET_BUFFER_LIST_NEXT_NBL(ctx->PacketQueue.FirstNbl);
|
NET_BUFFER_LIST *nbl_second = NET_BUFFER_LIST_NEXT_NBL(Ctx->PacketQueue.FirstNbl);
|
||||||
|
|
||||||
NET_BUFFER_LIST_STATUS(ctx->PacketQueue.FirstNbl) = NDIS_STATUS_SEND_ABORTED;
|
NET_BUFFER_LIST_STATUS(Ctx->PacketQueue.FirstNbl) = NDIS_STATUS_SEND_ABORTED;
|
||||||
TunNBLRefDec(ctx, ctx->PacketQueue.FirstNbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
|
TunNBLRefDec(Ctx, Ctx->PacketQueue.FirstNbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
|
||||||
|
|
||||||
ctx->PacketQueue.NextNb = NULL;
|
Ctx->PacketQueue.NextNb = NULL;
|
||||||
ctx->PacketQueue.FirstNbl = nbl_second;
|
Ctx->PacketQueue.FirstNbl = nbl_second;
|
||||||
if (!ctx->PacketQueue.FirstNbl)
|
if (!Ctx->PacketQueue.FirstNbl)
|
||||||
ctx->PacketQueue.LastNbl = NULL;
|
Ctx->PacketQueue.LastNbl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeReleaseInStackQueuedSpinLock(&lqh);
|
KeReleaseInStackQueuedSpinLock(&lqh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Requires_lock_held_(ctx->PacketQueue.Lock)
|
_Requires_lock_held_(Ctx->PacketQueue.Lock)
|
||||||
_IRQL_requires_(DISPATCH_LEVEL)
|
_IRQL_requires_(DISPATCH_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static _Return_type_success_(return !=
|
static _Return_type_success_(return !=
|
||||||
NULL) NET_BUFFER *TunQueueRemove(_Inout_ TUN_CTX *ctx, _Out_ NET_BUFFER_LIST **nbl)
|
NULL) NET_BUFFER *TunQueueRemove(_Inout_ TUN_CTX *Ctx, _Out_ NET_BUFFER_LIST **Nbl)
|
||||||
{
|
{
|
||||||
NET_BUFFER_LIST *nbl_top;
|
NET_BUFFER_LIST *nbl_top;
|
||||||
NET_BUFFER *ret;
|
NET_BUFFER *ret;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
nbl_top = ctx->PacketQueue.FirstNbl;
|
nbl_top = Ctx->PacketQueue.FirstNbl;
|
||||||
*nbl = nbl_top;
|
*Nbl = nbl_top;
|
||||||
if (!nbl_top)
|
if (!nbl_top)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!ctx->PacketQueue.NextNb)
|
if (!Ctx->PacketQueue.NextNb)
|
||||||
ctx->PacketQueue.NextNb = NET_BUFFER_LIST_FIRST_NB(nbl_top);
|
Ctx->PacketQueue.NextNb = NET_BUFFER_LIST_FIRST_NB(nbl_top);
|
||||||
ret = ctx->PacketQueue.NextNb;
|
ret = Ctx->PacketQueue.NextNb;
|
||||||
ctx->PacketQueue.NextNb = NET_BUFFER_NEXT_NB(ret);
|
Ctx->PacketQueue.NextNb = NET_BUFFER_NEXT_NB(ret);
|
||||||
if (!ctx->PacketQueue.NextNb)
|
if (!Ctx->PacketQueue.NextNb)
|
||||||
{
|
{
|
||||||
ctx->PacketQueue.FirstNbl = NET_BUFFER_LIST_NEXT_NBL(nbl_top);
|
Ctx->PacketQueue.FirstNbl = NET_BUFFER_LIST_NEXT_NBL(nbl_top);
|
||||||
if (!ctx->PacketQueue.FirstNbl)
|
if (!Ctx->PacketQueue.FirstNbl)
|
||||||
ctx->PacketQueue.LastNbl = NULL;
|
Ctx->PacketQueue.LastNbl = NULL;
|
||||||
NET_BUFFER_LIST_NEXT_NBL(nbl_top) = NULL;
|
NET_BUFFER_LIST_NEXT_NBL(nbl_top) = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -546,57 +546,59 @@ retry:
|
|||||||
if (ret && NET_BUFFER_DATA_LENGTH(ret) > TUN_EXCH_MAX_IP_PACKET_SIZE)
|
if (ret && NET_BUFFER_DATA_LENGTH(ret) > TUN_EXCH_MAX_IP_PACKET_SIZE)
|
||||||
{
|
{
|
||||||
NET_BUFFER_LIST_STATUS(nbl_top) = NDIS_STATUS_INVALID_LENGTH;
|
NET_BUFFER_LIST_STATUS(nbl_top) = NDIS_STATUS_INVALID_LENGTH;
|
||||||
TunNBLRefDec(ctx, nbl_top, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
|
TunNBLRefDec(Ctx, nbl_top, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
|
||||||
InterlockedIncrement64((LONG64 *)&ctx->Statistics.ifOutDiscards);
|
InterlockedIncrement64((LONG64 *)&Ctx->Statistics.ifOutDiscards);
|
||||||
goto retry; /* A for (;;) and a break would be fine, but this is clearer actually. */
|
goto retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: Must be called immediately after TunQueueRemove without dropping ctx->PacketQueue.Lock. */
|
// Note: Must be called immediately after TunQueueRemove without dropping ctx->PacketQueue.Lock.
|
||||||
_Requires_lock_held_(ctx->PacketQueue.Lock)
|
_Requires_lock_held_(Ctx->PacketQueue.Lock)
|
||||||
_IRQL_requires_(DISPATCH_LEVEL)
|
_IRQL_requires_(DISPATCH_LEVEL)
|
||||||
static void
|
static void
|
||||||
TunQueuePrepend(_Inout_ TUN_CTX *ctx, _In_ NET_BUFFER *nb, _In_ NET_BUFFER_LIST *nbl)
|
TunQueuePrepend(_Inout_ TUN_CTX *Ctx, _In_ NET_BUFFER *Nb, _In_ NET_BUFFER_LIST *Nbl)
|
||||||
{
|
{
|
||||||
ctx->PacketQueue.NextNb = nb;
|
Ctx->PacketQueue.NextNb = Nb;
|
||||||
|
|
||||||
if (!nbl || nbl == ctx->PacketQueue.FirstNbl)
|
if (!Nbl || Nbl == Ctx->PacketQueue.FirstNbl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TunNBLRefInc(nbl);
|
TunNBLRefInc(Nbl);
|
||||||
if (!ctx->PacketQueue.FirstNbl)
|
if (!Ctx->PacketQueue.FirstNbl)
|
||||||
ctx->PacketQueue.FirstNbl = ctx->PacketQueue.LastNbl = nbl;
|
Ctx->PacketQueue.FirstNbl = Ctx->PacketQueue.LastNbl = Nbl;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NET_BUFFER_LIST_NEXT_NBL(nbl) = ctx->PacketQueue.FirstNbl;
|
NET_BUFFER_LIST_NEXT_NBL(Nbl) = Ctx->PacketQueue.FirstNbl;
|
||||||
ctx->PacketQueue.FirstNbl = nbl;
|
Ctx->PacketQueue.FirstNbl = Nbl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Requires_lock_not_held_(ctx->PacketQueue.Lock) _IRQL_requires_max_(DISPATCH_LEVEL)
|
_Requires_lock_not_held_(Ctx->PacketQueue.Lock)
|
||||||
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
static void
|
static void
|
||||||
TunQueueClear(_Inout_ TUN_CTX *ctx, _In_ NDIS_STATUS status)
|
TunQueueClear(_Inout_ TUN_CTX *Ctx, _In_ NDIS_STATUS Status)
|
||||||
{
|
{
|
||||||
KLOCK_QUEUE_HANDLE lqh;
|
KLOCK_QUEUE_HANDLE lqh;
|
||||||
KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh);
|
KeAcquireInStackQueuedSpinLock(&Ctx->PacketQueue.Lock, &lqh);
|
||||||
for (NET_BUFFER_LIST *nbl = ctx->PacketQueue.FirstNbl, *nbl_next; nbl; nbl = nbl_next)
|
for (NET_BUFFER_LIST *nbl = Ctx->PacketQueue.FirstNbl, *nbl_next; nbl; nbl = nbl_next)
|
||||||
{
|
{
|
||||||
nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl);
|
nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl);
|
||||||
NET_BUFFER_LIST_STATUS(nbl) = status;
|
NET_BUFFER_LIST_STATUS(nbl) = Status;
|
||||||
TunNBLRefDec(ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
|
TunNBLRefDec(Ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
|
||||||
}
|
}
|
||||||
ctx->PacketQueue.FirstNbl = NULL;
|
Ctx->PacketQueue.FirstNbl = NULL;
|
||||||
ctx->PacketQueue.LastNbl = NULL;
|
Ctx->PacketQueue.LastNbl = NULL;
|
||||||
ctx->PacketQueue.NextNb = NULL;
|
Ctx->PacketQueue.NextNb = NULL;
|
||||||
InterlockedExchange(&ctx->PacketQueue.NumNbl, 0);
|
InterlockedExchange(&Ctx->PacketQueue.NumNbl, 0);
|
||||||
KeReleaseInStackQueuedSpinLock(&lqh);
|
KeReleaseInStackQueuedSpinLock(&lqh);
|
||||||
}
|
}
|
||||||
|
|
||||||
_Requires_lock_not_held_(ctx->PacketQueue.Lock) _IRQL_requires_max_(DISPATCH_LEVEL)
|
_Requires_lock_not_held_(Ctx->PacketQueue.Lock)
|
||||||
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
static void
|
static void
|
||||||
TunQueueProcess(_Inout_ TUN_CTX *ctx)
|
TunQueueProcess(_Inout_ TUN_CTX *Ctx)
|
||||||
{
|
{
|
||||||
IRP *irp = NULL;
|
IRP *irp = NULL;
|
||||||
UCHAR *buffer = NULL;
|
UCHAR *buffer = NULL;
|
||||||
@ -608,24 +610,24 @@ TunQueueProcess(_Inout_ TUN_CTX *ctx)
|
|||||||
{
|
{
|
||||||
NET_BUFFER_LIST *nbl;
|
NET_BUFFER_LIST *nbl;
|
||||||
|
|
||||||
KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh);
|
KeAcquireInStackQueuedSpinLock(&Ctx->PacketQueue.Lock, &lqh);
|
||||||
|
|
||||||
/* Get head NB (and IRP). */
|
/* Get head NB (and IRP). */
|
||||||
if (!irp)
|
if (!irp)
|
||||||
{
|
{
|
||||||
nb = TunQueueRemove(ctx, &nbl);
|
nb = TunQueueRemove(Ctx, &nbl);
|
||||||
if (!nb)
|
if (!nb)
|
||||||
{
|
{
|
||||||
KeReleaseInStackQueuedSpinLock(&lqh);
|
KeReleaseInStackQueuedSpinLock(&lqh);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
irp = TunRemoveNextIrp(ctx, &buffer, &size);
|
irp = TunRemoveNextIrp(Ctx, &buffer, &size);
|
||||||
if (!irp)
|
if (!irp)
|
||||||
{
|
{
|
||||||
TunQueuePrepend(ctx, nb, nbl);
|
TunQueuePrepend(Ctx, nb, nbl);
|
||||||
KeReleaseInStackQueuedSpinLock(&lqh);
|
KeReleaseInStackQueuedSpinLock(&lqh);
|
||||||
if (nbl)
|
if (nbl)
|
||||||
TunNBLRefDec(ctx, nbl, 0);
|
TunNBLRefDec(Ctx, nbl, 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,14 +635,14 @@ TunQueueProcess(_Inout_ TUN_CTX *ctx)
|
|||||||
_Analysis_assume_(irp->IoStatus.Information <= size);
|
_Analysis_assume_(irp->IoStatus.Information <= size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nb = TunQueueRemove(ctx, &nbl);
|
nb = TunQueueRemove(Ctx, &nbl);
|
||||||
|
|
||||||
/* If the NB won't fit in the IRP, return it. */
|
/* If the NB won't fit in the IRP, return it. */
|
||||||
if (nb && TunWontFitIntoIrp(irp, size, nb))
|
if (nb && TunWontFitIntoIrp(irp, size, nb))
|
||||||
{
|
{
|
||||||
TunQueuePrepend(ctx, nb, nbl);
|
TunQueuePrepend(Ctx, nb, nbl);
|
||||||
if (nbl)
|
if (nbl)
|
||||||
TunNBLRefDec(ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
|
TunNBLRefDec(Ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
|
||||||
nbl = NULL;
|
nbl = NULL;
|
||||||
nb = NULL;
|
nb = NULL;
|
||||||
}
|
}
|
||||||
@ -650,31 +652,31 @@ TunQueueProcess(_Inout_ TUN_CTX *ctx)
|
|||||||
/* Process NB and IRP. */
|
/* Process NB and IRP. */
|
||||||
if (nb)
|
if (nb)
|
||||||
{
|
{
|
||||||
NTSTATUS status = TunWriteIntoIrp(irp, buffer, nb, &ctx->Statistics);
|
NTSTATUS status = TunWriteIntoIrp(irp, buffer, nb, &Ctx->Statistics);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
if (nbl)
|
if (nbl)
|
||||||
NET_BUFFER_LIST_STATUS(nbl) = status;
|
NET_BUFFER_LIST_STATUS(nbl) = status;
|
||||||
IoCsqInsertIrpEx(&ctx->Device.ReadQueue.Csq, irp, NULL, TUN_CSQ_INSERT_HEAD);
|
IoCsqInsertIrpEx(&Ctx->Device.ReadQueue.Csq, irp, NULL, TUN_CSQ_INSERT_HEAD);
|
||||||
irp = NULL;
|
irp = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TunCompleteRequest(ctx, irp, STATUS_SUCCESS, IO_NETWORK_INCREMENT);
|
TunCompleteRequest(Ctx, irp, STATUS_SUCCESS, IO_NETWORK_INCREMENT);
|
||||||
irp = NULL;
|
irp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbl)
|
if (nbl)
|
||||||
TunNBLRefDec(ctx, nbl, 0);
|
TunNBLRefDec(Ctx, nbl, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_same_ static void
|
_IRQL_requires_same_ static void
|
||||||
TunSetNBLStatus(_Inout_opt_ NET_BUFFER_LIST *nbl, _In_ NDIS_STATUS status)
|
TunSetNBLStatus(_Inout_opt_ NET_BUFFER_LIST *Nbl, _In_ NDIS_STATUS Status)
|
||||||
{
|
{
|
||||||
for (; nbl; nbl = NET_BUFFER_LIST_NEXT_NBL(nbl))
|
for (; Nbl; Nbl = NET_BUFFER_LIST_NEXT_NBL(Nbl))
|
||||||
NET_BUFFER_LIST_STATUS(nbl) = status;
|
NET_BUFFER_LIST_STATUS(Nbl) = Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static MINIPORT_SEND_NET_BUFFER_LISTS TunSendNetBufferLists;
|
static MINIPORT_SEND_NET_BUFFER_LISTS TunSendNetBufferLists;
|
||||||
@ -746,26 +748,26 @@ TunCancelSend(NDIS_HANDLE MiniportAdapterContext, PVOID CancelId)
|
|||||||
_IRQL_requires_max_(APC_LEVEL)
|
_IRQL_requires_max_(APC_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
TunDispatchRead(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp)
|
TunDispatchRead(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
||||||
{
|
{
|
||||||
NTSTATUS status = TunMapIrp(Irp);
|
NTSTATUS status = TunMapIrp(Irp);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
goto cleanup_CompleteRequest;
|
goto cleanup_CompleteRequest;
|
||||||
|
|
||||||
KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock);
|
KIRQL irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
||||||
LONG flags = InterlockedGet(&ctx->Flags);
|
LONG flags = InterlockedGet(&Ctx->Flags);
|
||||||
if ((status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT)) ||
|
if ((status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT)) ||
|
||||||
!NT_SUCCESS(status = IoCsqInsertIrpEx(&ctx->Device.ReadQueue.Csq, Irp, NULL, TUN_CSQ_INSERT_TAIL)))
|
!NT_SUCCESS(status = IoCsqInsertIrpEx(&Ctx->Device.ReadQueue.Csq, Irp, NULL, TUN_CSQ_INSERT_TAIL)))
|
||||||
goto cleanup_ExReleaseSpinLockShared;
|
goto cleanup_ExReleaseSpinLockShared;
|
||||||
|
|
||||||
TunQueueProcess(ctx);
|
TunQueueProcess(Ctx);
|
||||||
ExReleaseSpinLockShared(&ctx->TransitionLock, irql);
|
ExReleaseSpinLockShared(&Ctx->TransitionLock, irql);
|
||||||
return STATUS_PENDING;
|
return STATUS_PENDING;
|
||||||
|
|
||||||
cleanup_ExReleaseSpinLockShared:
|
cleanup_ExReleaseSpinLockShared:
|
||||||
ExReleaseSpinLockShared(&ctx->TransitionLock, irql);
|
ExReleaseSpinLockShared(&Ctx->TransitionLock, irql);
|
||||||
cleanup_CompleteRequest:
|
cleanup_CompleteRequest:
|
||||||
TunCompleteRequest(ctx, Irp, status, IO_NO_INCREMENT);
|
TunCompleteRequest(Ctx, Irp, status, IO_NO_INCREMENT);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -775,17 +777,17 @@ cleanup_CompleteRequest:
|
|||||||
_IRQL_requires_max_(APC_LEVEL)
|
_IRQL_requires_max_(APC_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
TunDispatchWrite(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp)
|
TunDispatchWrite(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
|
||||||
InterlockedIncrement64(&ctx->ActiveNBLCount);
|
InterlockedIncrement64(&Ctx->ActiveNBLCount);
|
||||||
|
|
||||||
if (!NT_SUCCESS(status = TunMapIrp(Irp)))
|
if (!NT_SUCCESS(status = TunMapIrp(Irp)))
|
||||||
goto cleanup_CompleteRequest;
|
goto cleanup_CompleteRequest;
|
||||||
|
|
||||||
KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock);
|
KIRQL irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
||||||
LONG flags = InterlockedGet(&ctx->Flags);
|
LONG flags = InterlockedGet(&Ctx->Flags);
|
||||||
if (status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT))
|
if (status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT))
|
||||||
goto cleanup_ExReleaseSpinLockShared;
|
goto cleanup_ExReleaseSpinLockShared;
|
||||||
|
|
||||||
@ -850,14 +852,14 @@ TunDispatchWrite(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
NET_BUFFER_LIST *nbl =
|
NET_BUFFER_LIST *nbl =
|
||||||
NdisAllocateNetBufferAndNetBufferList(ctx->NBLPool, 0, 0, mdl, (ULONG)(p->Data - buffer), p->Size);
|
NdisAllocateNetBufferAndNetBufferList(Ctx->NBLPool, 0, 0, mdl, (ULONG)(p->Data - buffer), p->Size);
|
||||||
if (!nbl)
|
if (!nbl)
|
||||||
{
|
{
|
||||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
goto cleanup_nbl_queues;
|
goto cleanup_nbl_queues;
|
||||||
}
|
}
|
||||||
|
|
||||||
nbl->SourceHandle = ctx->MiniportAdapterHandle;
|
nbl->SourceHandle = Ctx->MiniportAdapterHandle;
|
||||||
NdisSetNblFlag(nbl, ether_const[idx].nbl_flags);
|
NdisSetNblFlag(nbl, ether_const[idx].nbl_flags);
|
||||||
NET_BUFFER_LIST_INFO(nbl, NetBufferListFrameType) = (PVOID)ether_const[idx].nbl_proto;
|
NET_BUFFER_LIST_INFO(nbl, NetBufferListFrameType) = (PVOID)ether_const[idx].nbl_proto;
|
||||||
NET_BUFFER_LIST_STATUS(nbl) = NDIS_STATUS_SUCCESS;
|
NET_BUFFER_LIST_STATUS(nbl) = NDIS_STATUS_SUCCESS;
|
||||||
@ -882,33 +884,33 @@ TunDispatchWrite(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp)
|
|||||||
}
|
}
|
||||||
if (!(flags & TUN_FLAGS_RUNNING))
|
if (!(flags & TUN_FLAGS_RUNNING))
|
||||||
{
|
{
|
||||||
InterlockedAdd64((LONG64 *)&ctx->Statistics.ifInDiscards, nbl_count);
|
InterlockedAdd64((LONG64 *)&Ctx->Statistics.ifInDiscards, nbl_count);
|
||||||
InterlockedAdd64((LONG64 *)&ctx->Statistics.ifInErrors, nbl_count);
|
InterlockedAdd64((LONG64 *)&Ctx->Statistics.ifInErrors, nbl_count);
|
||||||
status = STATUS_SUCCESS;
|
status = STATUS_SUCCESS;
|
||||||
goto cleanup_nbl_queues;
|
goto cleanup_nbl_queues;
|
||||||
}
|
}
|
||||||
|
|
||||||
InterlockedAdd64(&ctx->ActiveNBLCount, nbl_count);
|
InterlockedAdd64(&Ctx->ActiveNBLCount, nbl_count);
|
||||||
InterlockedExchange(IRP_REFCOUNT(Irp), nbl_count);
|
InterlockedExchange(IRP_REFCOUNT(Irp), nbl_count);
|
||||||
IoMarkIrpPending(Irp);
|
IoMarkIrpPending(Irp);
|
||||||
|
|
||||||
if (nbl_queue[ethtypeidx_ipv4].head)
|
if (nbl_queue[ethtypeidx_ipv4].head)
|
||||||
NdisMIndicateReceiveNetBufferLists(
|
NdisMIndicateReceiveNetBufferLists(
|
||||||
ctx->MiniportAdapterHandle,
|
Ctx->MiniportAdapterHandle,
|
||||||
nbl_queue[ethtypeidx_ipv4].head,
|
nbl_queue[ethtypeidx_ipv4].head,
|
||||||
NDIS_DEFAULT_PORT_NUMBER,
|
NDIS_DEFAULT_PORT_NUMBER,
|
||||||
nbl_queue[ethtypeidx_ipv4].count,
|
nbl_queue[ethtypeidx_ipv4].count,
|
||||||
NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE);
|
NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE);
|
||||||
if (nbl_queue[ethtypeidx_ipv6].head)
|
if (nbl_queue[ethtypeidx_ipv6].head)
|
||||||
NdisMIndicateReceiveNetBufferLists(
|
NdisMIndicateReceiveNetBufferLists(
|
||||||
ctx->MiniportAdapterHandle,
|
Ctx->MiniportAdapterHandle,
|
||||||
nbl_queue[ethtypeidx_ipv6].head,
|
nbl_queue[ethtypeidx_ipv6].head,
|
||||||
NDIS_DEFAULT_PORT_NUMBER,
|
NDIS_DEFAULT_PORT_NUMBER,
|
||||||
nbl_queue[ethtypeidx_ipv6].count,
|
nbl_queue[ethtypeidx_ipv6].count,
|
||||||
NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE);
|
NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE);
|
||||||
|
|
||||||
ExReleaseSpinLockShared(&ctx->TransitionLock, irql);
|
ExReleaseSpinLockShared(&Ctx->TransitionLock, irql);
|
||||||
TunCompletePause(ctx, TRUE);
|
TunCompletePause(Ctx, TRUE);
|
||||||
return STATUS_PENDING;
|
return STATUS_PENDING;
|
||||||
|
|
||||||
cleanup_nbl_queues:
|
cleanup_nbl_queues:
|
||||||
@ -922,10 +924,10 @@ cleanup_nbl_queues:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cleanup_ExReleaseSpinLockShared:
|
cleanup_ExReleaseSpinLockShared:
|
||||||
ExReleaseSpinLockShared(&ctx->TransitionLock, irql);
|
ExReleaseSpinLockShared(&Ctx->TransitionLock, irql);
|
||||||
cleanup_CompleteRequest:
|
cleanup_CompleteRequest:
|
||||||
TunCompleteRequest(ctx, Irp, status, IO_NO_INCREMENT);
|
TunCompleteRequest(Ctx, Irp, status, IO_NO_INCREMENT);
|
||||||
TunCompletePause(ctx, TRUE);
|
TunCompletePause(Ctx, TRUE);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,7 +971,7 @@ TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST Net
|
|||||||
_IRQL_requires_max_(DISPATCH_LEVEL)
|
_IRQL_requires_max_(DISPATCH_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
TunDispatchCreate(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp)
|
TunDispatchCreate(_Inout_ TUN_CTX *Ctx, _Inout_ IRP *Irp)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
TUN_FILE_CTX *file_ctx = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(*file_ctx), TUN_HTONL(TUN_MEMORY_TAG));
|
TUN_FILE_CTX *file_ctx = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(*file_ctx), TUN_HTONL(TUN_MEMORY_TAG));
|
||||||
@ -977,24 +979,24 @@ TunDispatchCreate(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp)
|
|||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
RtlZeroMemory(file_ctx, sizeof(*file_ctx));
|
RtlZeroMemory(file_ctx, sizeof(*file_ctx));
|
||||||
|
|
||||||
KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock);
|
KIRQL irql = ExAcquireSpinLockShared(&Ctx->TransitionLock);
|
||||||
LONG flags = InterlockedGet(&ctx->Flags);
|
LONG flags = InterlockedGet(&Ctx->Flags);
|
||||||
if ((status = STATUS_DELETE_PENDING, !(flags & TUN_FLAGS_PRESENT)))
|
if ((status = STATUS_DELETE_PENDING, !(flags & TUN_FLAGS_PRESENT)))
|
||||||
goto cleanup_ExReleaseSpinLockShared;
|
goto cleanup_ExReleaseSpinLockShared;
|
||||||
|
|
||||||
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp);
|
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
if (!NT_SUCCESS(status = IoAcquireRemoveLock(&ctx->Device.RemoveLock, stack->FileObject)))
|
if (!NT_SUCCESS(status = IoAcquireRemoveLock(&Ctx->Device.RemoveLock, stack->FileObject)))
|
||||||
goto cleanup_ExReleaseSpinLockShared;
|
goto cleanup_ExReleaseSpinLockShared;
|
||||||
stack->FileObject->FsContext = file_ctx;
|
stack->FileObject->FsContext = file_ctx;
|
||||||
|
|
||||||
if (InterlockedIncrement64(&ctx->Device.RefCount) == 1)
|
if (InterlockedIncrement64(&Ctx->Device.RefCount) == 1)
|
||||||
TunIndicateStatus(ctx->MiniportAdapterHandle, MediaConnectStateConnected);
|
TunIndicateStatus(Ctx->MiniportAdapterHandle, MediaConnectStateConnected);
|
||||||
|
|
||||||
status = STATUS_SUCCESS;
|
status = STATUS_SUCCESS;
|
||||||
|
|
||||||
cleanup_ExReleaseSpinLockShared:
|
cleanup_ExReleaseSpinLockShared:
|
||||||
ExReleaseSpinLockShared(&ctx->TransitionLock, irql);
|
ExReleaseSpinLockShared(&Ctx->TransitionLock, irql);
|
||||||
TunCompleteRequest(ctx, Irp, status, IO_NO_INCREMENT);
|
TunCompleteRequest(Ctx, Irp, status, IO_NO_INCREMENT);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
ExFreePoolWithTag(file_ctx, TUN_HTONL(TUN_MEMORY_TAG));
|
ExFreePoolWithTag(file_ctx, TUN_HTONL(TUN_MEMORY_TAG));
|
||||||
return status;
|
return status;
|
||||||
@ -1089,12 +1091,13 @@ TunDispatchPnP(DEVICE_OBJECT *DeviceObject, IRP *Irp)
|
|||||||
switch (stack->MinorFunction)
|
switch (stack->MinorFunction)
|
||||||
{
|
{
|
||||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||||
case IRP_MN_SURPRISE_REMOVAL:
|
case IRP_MN_SURPRISE_REMOVAL: {
|
||||||
KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock);
|
KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock);
|
||||||
InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_PRESENT);
|
InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_PRESENT);
|
||||||
ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql);
|
ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql);
|
||||||
TunQueueClear(ctx, NDIS_STATUS_ADAPTER_REMOVED);
|
TunQueueClear(ctx, NDIS_STATUS_ADAPTER_REMOVED);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||||
InterlockedOr(&ctx->Flags, TUN_FLAGS_PRESENT);
|
InterlockedOr(&ctx->Flags, TUN_FLAGS_PRESENT);
|
||||||
@ -1361,8 +1364,7 @@ TunInitializeEx(
|
|||||||
|
|
||||||
/* A miniport driver can call NdisMIndicateStatusEx after setting its
|
/* A miniport driver can call NdisMIndicateStatusEx after setting its
|
||||||
* registration attributes even if the driver is still in the context
|
* registration attributes even if the driver is still in the context
|
||||||
* of the MiniportInitializeEx function.
|
* of the MiniportInitializeEx function. */
|
||||||
*/
|
|
||||||
TunIndicateStatus(MiniportAdapterHandle, MediaConnectStateDisconnected);
|
TunIndicateStatus(MiniportAdapterHandle, MediaConnectStateDisconnected);
|
||||||
InterlockedIncrement64(&TunAdapterCount);
|
InterlockedIncrement64(&TunAdapterCount);
|
||||||
InterlockedOr(&ctx->Flags, TUN_FLAGS_PRESENT);
|
InterlockedOr(&ctx->Flags, TUN_FLAGS_PRESENT);
|
||||||
@ -1377,7 +1379,7 @@ cleanup_NdisDeregisterDeviceEx:
|
|||||||
|
|
||||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||||
static NTSTATUS
|
static NTSTATUS
|
||||||
TunDeviceSetDenyAllDacl(_In_ DEVICE_OBJECT *device_object)
|
TunDeviceSetDenyAllDacl(_In_ DEVICE_OBJECT *DeviceObject)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
SECURITY_DESCRIPTOR sd;
|
SECURITY_DESCRIPTOR sd;
|
||||||
@ -1390,9 +1392,9 @@ TunDeviceSetDenyAllDacl(_In_ DEVICE_OBJECT *device_object)
|
|||||||
return status;
|
return status;
|
||||||
if (!NT_SUCCESS(status = RtlSetDaclSecurityDescriptor(&sd, TRUE, &acl, FALSE)))
|
if (!NT_SUCCESS(status = RtlSetDaclSecurityDescriptor(&sd, TRUE, &acl, FALSE)))
|
||||||
return status;
|
return status;
|
||||||
if (!NT_SUCCESS(
|
|
||||||
status = ObOpenObjectByPointer(
|
status = ObOpenObjectByPointer(
|
||||||
device_object, OBJ_KERNEL_HANDLE, NULL, WRITE_DAC, *IoDeviceObjectType, KernelMode, &handle)))
|
DeviceObject, OBJ_KERNEL_HANDLE, NULL, WRITE_DAC, *IoDeviceObjectType, KernelMode, &handle);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
status = ZwSetSecurityObject(handle, DACL_SECURITY_INFORMATION, &sd);
|
status = ZwSetSecurityObject(handle, DACL_SECURITY_INFORMATION, &sd);
|
||||||
@ -1403,7 +1405,7 @@ TunDeviceSetDenyAllDacl(_In_ DEVICE_OBJECT *device_object)
|
|||||||
|
|
||||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||||
static void
|
static void
|
||||||
TunForceHandlesClosed(_Inout_ TUN_CTX *ctx)
|
TunForceHandlesClosed(_Inout_ TUN_CTX *Ctx)
|
||||||
{
|
{
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
PEPROCESS process;
|
PEPROCESS process;
|
||||||
@ -1431,9 +1433,9 @@ TunForceHandlesClosed(_Inout_ TUN_CTX *ctx)
|
|||||||
for (ULONG_PTR i = 0; i < table->NumberOfHandles; ++i)
|
for (ULONG_PTR i = 0; i < table->NumberOfHandles; ++i)
|
||||||
{
|
{
|
||||||
FILE_OBJECT *file =
|
FILE_OBJECT *file =
|
||||||
table->Handles[i].Object; // XXX: We should probably first look at table->Handles[i].ObjectTypeIndex, but
|
table->Handles[i].Object; // XXX: We should perhaps first look at table->Handles[i].ObjectTypeIndex, but
|
||||||
// the value changes lots between NT versions.
|
// the value changes lots between NT versions, and it should be implicit anyway.
|
||||||
if (!file || file->Type != 5 || file->DeviceObject != ctx->Device.Object)
|
if (!file || file->Type != 5 || file->DeviceObject != Ctx->Device.Object)
|
||||||
continue;
|
continue;
|
||||||
status = PsLookupProcessByProcessId(table->Handles[i].UniqueProcessId, &process);
|
status = PsLookupProcessByProcessId(table->Handles[i].UniqueProcessId, &process);
|
||||||
if (!NT_SUCCESS(status))
|
if (!NT_SUCCESS(status))
|
||||||
@ -1479,8 +1481,8 @@ TunHaltEx(NDIS_HANDLE MiniportAdapterContext, NDIS_HALT_ACTION HaltAction)
|
|||||||
{
|
{
|
||||||
TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext;
|
TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext;
|
||||||
|
|
||||||
ASSERT(!InterlockedGet64(
|
ASSERT(!InterlockedGet64(&ctx->ActiveNBLCount)); // Adapter should not be halted if there are (potential)
|
||||||
&ctx->ActiveNBLCount)); /* Adapter should not be halted if there are (potential) active NBLs present. */
|
// active NBLs present.
|
||||||
|
|
||||||
KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock);
|
KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock);
|
||||||
InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_PRESENT);
|
InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_PRESENT);
|
||||||
@ -1521,7 +1523,7 @@ TunShutdownEx(NDIS_HANDLE MiniportAdapterContext, NDIS_SHUTDOWN_ACTION ShutdownA
|
|||||||
_IRQL_requires_max_(APC_LEVEL)
|
_IRQL_requires_max_(APC_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static NDIS_STATUS
|
static NDIS_STATUS
|
||||||
TunOidQueryWrite(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG value)
|
TunOidQueryWrite(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG Value)
|
||||||
{
|
{
|
||||||
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG))
|
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG))
|
||||||
{
|
{
|
||||||
@ -1531,14 +1533,14 @@ TunOidQueryWrite(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG);
|
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG);
|
||||||
*(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = value;
|
*(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = Value;
|
||||||
return NDIS_STATUS_SUCCESS;
|
return NDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_max_(APC_LEVEL)
|
_IRQL_requires_max_(APC_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static NDIS_STATUS
|
static NDIS_STATUS
|
||||||
TunOidQueryWrite32or64(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG64 value)
|
TunOidQueryWrite32or64(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG64 Value)
|
||||||
{
|
{
|
||||||
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG))
|
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG))
|
||||||
{
|
{
|
||||||
@ -1551,29 +1553,29 @@ TunOidQueryWrite32or64(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG64 value)
|
|||||||
{
|
{
|
||||||
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64);
|
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64);
|
||||||
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG);
|
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG);
|
||||||
*(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (ULONG)(value & 0xffffffff);
|
*(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (ULONG)(Value & 0xffffffff);
|
||||||
return NDIS_STATUS_SUCCESS;
|
return NDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG64);
|
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG64);
|
||||||
*(ULONG64 *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = value;
|
*(ULONG64 *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = Value;
|
||||||
return NDIS_STATUS_SUCCESS;
|
return NDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
_IRQL_requires_max_(APC_LEVEL)
|
_IRQL_requires_max_(APC_LEVEL)
|
||||||
_Must_inspect_result_
|
_Must_inspect_result_
|
||||||
static NDIS_STATUS
|
static NDIS_STATUS
|
||||||
TunOidQueryWriteBuf(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_bytecount_(size) const void *buf, _In_ UINT size)
|
TunOidQueryWriteBuf(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_bytecount_(Size) const void *Buf, _In_ UINT Size)
|
||||||
{
|
{
|
||||||
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < size)
|
if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < Size)
|
||||||
{
|
{
|
||||||
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = size;
|
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = Size;
|
||||||
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
|
||||||
return NDIS_STATUS_BUFFER_TOO_SHORT;
|
return NDIS_STATUS_BUFFER_TOO_SHORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = size;
|
OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = Size;
|
||||||
NdisMoveMemory(OidRequest->DATA.QUERY_INFORMATION.InformationBuffer, buf, size);
|
NdisMoveMemory(OidRequest->DATA.QUERY_INFORMATION.InformationBuffer, Buf, Size);
|
||||||
return NDIS_STATUS_SUCCESS;
|
return NDIS_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1803,9 +1805,8 @@ DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath)
|
|||||||
.CancelDirectOidRequestHandler = TunCancelDirectOidRequest,
|
.CancelDirectOidRequestHandler = TunCancelDirectOidRequest,
|
||||||
.SynchronousOidRequestHandler = TunSynchronousOidRequest
|
.SynchronousOidRequestHandler = TunSynchronousOidRequest
|
||||||
};
|
};
|
||||||
if (!NT_SUCCESS(
|
status = NdisMRegisterMiniportDriver(DriverObject, RegistryPath, NULL, &miniport, &NdisMiniportDriverHandle);
|
||||||
status =
|
if (!NT_SUCCESS(status))
|
||||||
NdisMRegisterMiniportDriver(DriverObject, RegistryPath, NULL, &miniport, &NdisMiniportDriverHandle)))
|
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
NdisDispatchPnP = DriverObject->MajorFunction[IRP_MJ_PNP];
|
NdisDispatchPnP = DriverObject->MajorFunction[IRP_MJ_PNP];
|
||||||
|
Loading…
Reference in New Issue
Block a user