From 5bbff1026fbec8ba138d7c6ab0626dfadcc6ce2f Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 26 Jun 2019 14:52:38 +0200 Subject: [PATCH] Add NDIS team's clang-format conventions This needs clang-format 9. This reveals a lot of other things we should clean up. Signed-off-by: Jason A. Donenfeld Link: https://community.osr.com/discussion/291376/clang-format-and-driver-code --- .clang-format | 101 ++ .editorconfig | 3 +- undocumented.h | 37 +- wintun.c | 2528 +++++++++++++++++++++++++----------------------- 4 files changed, 1461 insertions(+), 1208 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..4096055 --- /dev/null +++ b/.clang-format @@ -0,0 +1,101 @@ +AccessModifierOffset: -4 +AlignAfterOpenBracket: AlwaysBreak +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: DontAlign +AlignOperands: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterReturnType: TopLevel +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: true +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: false + BeforeCatch: true + BeforeElse: true +BreakBeforeBraces: Custom +BreakBeforeBinaryOperators: None +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +BreakStringLiterals: false +ColumnLimit: 120 +CommentPragmas: '^begin_wpp|^end_wpp|^FUNC |^USESUFFIX |^USESUFFIX ' +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +ExperimentalAutoDetectBinPacking: false +IndentCaseLabels: false +IndentPPDirectives: AfterHash +IndentWidth: 4 +KeepEmptyLinesAtTheStartOfBlocks: false +Language: Cpp +MacroBlockBegin: '^BEGIN_MODULE$|^BEGIN_TEST_CLASS$|^BEGIN_TEST_METHOD$' +MacroBlockEnd: '^END_MODULE$|^END_TEST_CLASS$|^END_TEST_METHOD$' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PointerAlignment: Right +ReflowComments: true +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesInAngles: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +StatementMacros: [ + 'EXTERN_C', + 'PAGED', + 'PAGEDX', + 'NONPAGED', + 'PNPCODE', + 'INITCODE', + '_At_', + '_When_', + '_Success_', + '_Check_return_', + '_Must_inspect_result_', + '_IRQL_requires_', + '_IRQL_requires_max_', + '_IRQL_requires_min_', + '_IRQL_saves_', + '_IRQL_restores_', + '_IRQL_saves_global_', + '_IRQL_restores_global_', + '_IRQL_raises_', + '_IRQL_lowers_', + '_Acquires_lock_', + '_Releases_lock_', + '_Acquires_exclusive_lock_', + '_Releases_exclusive_lock_', + '_Acquires_shared_lock_', + '_Releases_shared_lock_', + '_Requires_lock_held_', + '_Use_decl_annotations_', + '_Guarded_by_', + '__drv_preferredFunction', + '__drv_allocatesMem', + '__drv_freesMem', + ] +TabWidth: '4' +UseTab: Never diff --git a/.editorconfig b/.editorconfig index 3ca70e6..6eee1a2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,6 @@ [*.{c,h,inf,rc,wxs}] -indent_style = tab +indent_style = space +indent_style = 4 [*.{proj,props,vcxproj,wixproj}] indent_style = space diff --git a/undocumented.h b/undocumented.h index 39cc09e..6d8992d 100644 --- a/undocumented.h +++ b/undocumented.h @@ -7,28 +7,37 @@ #include -typedef enum { SystemExtendedHandleInformation = 0x40 } SYSTEM_INFORMATION_CLASS; +typedef enum +{ + SystemExtendedHandleInformation = 0x40 +} SYSTEM_INFORMATION_CLASS; typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX { - PVOID Object; - HANDLE UniqueProcessId; - HANDLE HandleValue; - ACCESS_MASK GrantedAccess; - USHORT CreatorBackTraceIndex; - USHORT ObjectTypeIndex; - ULONG HandleAttributes; - ULONG Reserved; + PVOID Object; + HANDLE UniqueProcessId; + HANDLE HandleValue; + ACCESS_MASK GrantedAccess; + USHORT CreatorBackTraceIndex; + USHORT ObjectTypeIndex; + ULONG HandleAttributes; + ULONG Reserved; } SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; typedef struct _SYSTEM_HANDLE_INFORMATION_EX { - ULONG_PTR NumberOfHandles; - ULONG_PTR Reserved; - SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[ANYSIZE_ARRAY]; + ULONG_PTR NumberOfHandles; + ULONG_PTR Reserved; + SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[ANYSIZE_ARRAY]; } SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; -extern NTSTATUS ZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, ULONG *ReturnLength); -extern NDIS_HANDLE NdisWdfGetAdapterContextFromAdapterHandle(PVOID DeviceExtension); +extern NTSTATUS +ZwQuerySystemInformation( + SYSTEM_INFORMATION_CLASS SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + ULONG *ReturnLength); +extern NDIS_HANDLE +NdisWdfGetAdapterContextFromAdapterHandle(PVOID DeviceExtension); extern POBJECT_TYPE *IoDeviceObjectType; diff --git a/wintun.c b/wintun.c index 9b6b92f..0945bf4 100644 --- a/wintun.c +++ b/wintun.c @@ -16,99 +16,112 @@ #pragma warning(disable : 4100) // unreferenced formal parameter #pragma warning(disable : 4200) // nonstandard extension used: zero-sized array in struct/union #pragma warning(disable : 4204) // nonstandard extension used: non-constant aggregate initializer -#pragma warning(disable : 4221) // nonstandard extension used: : cannot be initialized using address of automatic variable +#pragma warning(disable : 4221) // nonstandard extension used: : cannot be initialized using address of + // automatic variable -#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_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 TUN_DEVICE_NAME L"WINTUN%u" +#define TUN_DEVICE_NAME L"WINTUN%u" -#define TUN_VENDOR_NAME "Wintun Tunnel" -#define TUN_VENDOR_ID 0xFFFFFF00 -#define TUN_LINK_SPEED 100000000000ULL // 100gbps +#define TUN_VENDOR_NAME "Wintun Tunnel" +#define TUN_VENDOR_ID 0xFFFFFF00 +#define TUN_LINK_SPEED 100000000000ULL // 100gbps -#define TUN_EXCH_MAX_PACKETS 256 // Maximum number of full-sized exchange packets that can be exchanged in a single read/write -#define TUN_EXCH_MAX_PACKET_SIZE 0xF000 // Maximum exchange packet size - empirically determined by net buffer list (pool) limitations -#define TUN_EXCH_ALIGNMENT 16 // Memory alignment in exchange buffers -#define TUN_EXCH_MAX_IP_PACKET_SIZE (TUN_EXCH_MAX_PACKET_SIZE - sizeof(TUN_PACKET)) // Maximum IP packet size (headers + payload) -#define TUN_EXCH_MAX_BUFFER_SIZE (TUN_EXCH_MAX_PACKETS * TUN_EXCH_MAX_PACKET_SIZE) // Maximum size of read/write 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_QUEUE_MAX_NBLS 1000 -#define TUN_MEMORY_TAG 'wtun' -#define TUN_CSQ_INSERT_HEAD ((PVOID)TRUE) -#define TUN_CSQ_INSERT_TAIL ((PVOID)FALSE) +#define TUN_EXCH_MAX_PACKETS \ + 256 // Maximum number of full-sized exchange packets that can be exchanged in a single read/write +#define TUN_EXCH_MAX_PACKET_SIZE \ + 0xF000 // Maximum exchange packet size - empirically determined by net buffer list (pool) limitations +#define TUN_EXCH_ALIGNMENT 16 // Memory alignment in exchange buffers +#define TUN_EXCH_MAX_IP_PACKET_SIZE \ + (TUN_EXCH_MAX_PACKET_SIZE - sizeof(TUN_PACKET)) // Maximum IP packet size (headers + payload) +#define TUN_EXCH_MAX_BUFFER_SIZE \ + (TUN_EXCH_MAX_PACKETS * TUN_EXCH_MAX_PACKET_SIZE) // Maximum size of read/write 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_QUEUE_MAX_NBLS 1000 +#define TUN_MEMORY_TAG 'wtun' +#define TUN_CSQ_INSERT_HEAD ((PVOID)TRUE) +#define TUN_CSQ_INSERT_TAIL ((PVOID)FALSE) #if REG_DWORD == REG_DWORD_BIG_ENDIAN -#define TUN_HTONS(x) ((USHORT)(x)) -#define TUN_HTONL(x) ((ULONG)(x)) +# define TUN_HTONS(x) ((USHORT)(x)) +# define TUN_HTONL(x) ((ULONG)(x)) #elif REG_DWORD == REG_DWORD_LITTLE_ENDIAN -#define TUN_HTONS(x) (((USHORT)(x) & 0x00ff) << 8 | ((USHORT)(x) & 0xff00) >> 8) -#define TUN_HTONL(x) (((ULONG)(x) & 0x000000ff) << 24 | ((ULONG)(x) & 0x0000ff00) << 8 | ((ULONG)(x) & 0x00ff0000) >> 8 | ((ULONG)(x) & 0xff000000) >> 24) +# define TUN_HTONS(x) (((USHORT)(x)&0x00ff) << 8 | ((USHORT)(x)&0xff00) >> 8) +# define TUN_HTONL(x) \ + (((ULONG)(x)&0x000000ff) << 24 | ((ULONG)(x)&0x0000ff00) << 8 | ((ULONG)(x)&0x00ff0000) >> 8 | \ + ((ULONG)(x)&0xff000000) >> 24) #else -#error "Unable to determine endianess" +# error "Unable to determine endianess" #endif -typedef struct _TUN_PACKET { - ULONG Size; // Size of packet data (TUN_EXCH_MAX_IP_PACKET_SIZE max) - _Field_size_bytes_(Size) - __declspec(align(TUN_EXCH_ALIGNMENT)) - UCHAR Data[]; // Packet data +typedef struct _TUN_PACKET +{ + ULONG Size; // Size of packet data (TUN_EXCH_MAX_IP_PACKET_SIZE max) + _Field_size_bytes_(Size) __declspec(align(TUN_EXCH_ALIGNMENT)) UCHAR Data[]; // Packet data } TUN_PACKET; -typedef enum _TUN_FLAGS { - TUN_FLAGS_RUNNING = 1 << 0, // Toggles between paused and running state - TUN_FLAGS_PRESENT = 1 << 1, // Toggles between removal pending and being present +typedef enum _TUN_FLAGS +{ + TUN_FLAGS_RUNNING = 1 << 0, // Toggles between paused and running state + TUN_FLAGS_PRESENT = 1 << 1, // Toggles between removal pending and being present } TUN_FLAGS; -typedef struct _TUN_CTX { - volatile LONG Flags; +typedef struct _TUN_CTX +{ + volatile LONG Flags; - /* Used like RCU. When we're making use of queues, we take a shared lock. When we want to - * drain the queues and toggle the state, we take an exclusive lock before toggling the - * atomic and then releasing. It's similar to setting the atomic and then calling rcu_barrier(). */ - EX_SPIN_LOCK TransitionLock; + /* Used like RCU. When we're making use of queues, we take a shared lock. When we want to + * drain the queues and toggle the state, we take an exclusive lock before toggling the + * atomic and then releasing. It's similar to setting the atomic and then calling rcu_barrier(). */ + EX_SPIN_LOCK TransitionLock; - /* This is actually a pointer to NDIS_MINIPORT_BLOCK struct. */ - NDIS_HANDLE MiniportAdapterHandle; - NDIS_STATISTICS_INFO Statistics; + /* This is actually a pointer to NDIS_MINIPORT_BLOCK struct. */ + NDIS_HANDLE MiniportAdapterHandle; + NDIS_STATISTICS_INFO Statistics; - volatile LONG64 ActiveNBLCount; + volatile LONG64 ActiveNBLCount; - struct { - NDIS_HANDLE Handle; - volatile LONG64 RefCount; - IO_REMOVE_LOCK RemoveLock; + struct + { + NDIS_HANDLE Handle; + volatile LONG64 RefCount; + IO_REMOVE_LOCK RemoveLock; - struct { - KSPIN_LOCK Lock; - IO_CSQ Csq; - LIST_ENTRY List; - } ReadQueue; + struct + { + KSPIN_LOCK Lock; + IO_CSQ Csq; + LIST_ENTRY List; + } ReadQueue; - DEVICE_OBJECT *Object; - } Device; + DEVICE_OBJECT *Object; + } Device; - struct { - KSPIN_LOCK Lock; - NET_BUFFER_LIST *FirstNbl, *LastNbl; - NET_BUFFER *NextNb; - LONG NumNbl; - } PacketQueue; + struct + { + KSPIN_LOCK Lock; + NET_BUFFER_LIST *FirstNbl, *LastNbl; + NET_BUFFER *NextNb; + LONG NumNbl; + } PacketQueue; - NDIS_HANDLE NBLPool; + NDIS_HANDLE NBLPool; } TUN_CTX; -typedef struct _TUN_MAPPED_UBUFFER { - VOID *UserAddress, *KernelAddress; - MDL *Mdl; - ULONG Size; - //TODO: ThreadID for checking +typedef struct _TUN_MAPPED_UBUFFER +{ + VOID *UserAddress, *KernelAddress; + MDL *Mdl; + ULONG Size; + // TODO: ThreadID for checking } TUN_MAPPED_UBUFFER; -typedef struct _TUN_FILE_CTX { - TUN_MAPPED_UBUFFER ReadBuffer; - TUN_MAPPED_UBUFFER WriteBuffer; +typedef struct _TUN_FILE_CTX +{ + TUN_MAPPED_UBUFFER ReadBuffer; + TUN_MAPPED_UBUFFER WriteBuffer; } TUN_FILE_CTX; static UINT NdisVersion; @@ -116,1551 +129,1680 @@ static NDIS_HANDLE NdisMiniportDriverHandle; static DRIVER_DISPATCH *NdisDispatchPnP; static volatile LONG64 TunAdapterCount; -#define InterlockedGet(val) (InterlockedAdd((val), 0)) -#define InterlockedGet64(val) (InterlockedAdd64((val), 0)) -#define InterlockedGetPointer(val) (InterlockedCompareExchangePointer((val), NULL, NULL)) -#define TunPacketAlign(size) (((UINT)(size) + (UINT)(TUN_EXCH_ALIGNMENT - 1)) & ~(UINT)(TUN_EXCH_ALIGNMENT - 1)) -#define TunInitUnicodeString(str, buf) { (str)->Length = 0; (str)->MaximumLength = sizeof(buf); (str)->Buffer = buf; } +#define InterlockedGet(val) (InterlockedAdd((val), 0)) +#define InterlockedGet64(val) (InterlockedAdd64((val), 0)) +#define InterlockedGetPointer(val) (InterlockedCompareExchangePointer((val), NULL, NULL)) +#define TunPacketAlign(size) (((UINT)(size) + (UINT)(TUN_EXCH_ALIGNMENT - 1)) & ~(UINT)(TUN_EXCH_ALIGNMENT - 1)) +#define TunInitUnicodeString(str, buf) \ + { \ + (str)->Length = 0; \ + (str)->MaximumLength = sizeof(buf); \ + (str)->Buffer = buf; \ + } _IRQL_requires_max_(DISPATCH_LEVEL) -_IRQL_requires_same_ -static void TunIndicateStatus(_In_ NDIS_HANDLE MiniportAdapterHandle, _In_ NDIS_MEDIA_CONNECT_STATE MediaConnectState) +_IRQL_requires_same_ static void +TunIndicateStatus(_In_ NDIS_HANDLE MiniportAdapterHandle, _In_ NDIS_MEDIA_CONNECT_STATE MediaConnectState) { - NDIS_LINK_STATE state = { - .Header = { - .Type = NDIS_OBJECT_TYPE_DEFAULT, - .Revision = NDIS_LINK_STATE_REVISION_1, - .Size = NDIS_SIZEOF_LINK_STATE_REVISION_1 - }, - .MediaConnectState = MediaConnectState, - .MediaDuplexState = MediaDuplexStateFull, - .XmitLinkSpeed = TUN_LINK_SPEED, - .RcvLinkSpeed = TUN_LINK_SPEED, - .PauseFunctions = NdisPauseFunctionsUnsupported - }; + NDIS_LINK_STATE state = {.Header = {.Type = NDIS_OBJECT_TYPE_DEFAULT, + .Revision = NDIS_LINK_STATE_REVISION_1, + .Size = NDIS_SIZEOF_LINK_STATE_REVISION_1}, + .MediaConnectState = MediaConnectState, + .MediaDuplexState = MediaDuplexStateFull, + .XmitLinkSpeed = TUN_LINK_SPEED, + .RcvLinkSpeed = TUN_LINK_SPEED, + .PauseFunctions = NdisPauseFunctionsUnsupported}; - NDIS_STATUS_INDICATION t = { - .Header = { - .Type = NDIS_OBJECT_TYPE_STATUS_INDICATION, - .Revision = NDIS_STATUS_INDICATION_REVISION_1, - .Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1 - }, - .SourceHandle = MiniportAdapterHandle, - .StatusCode = NDIS_STATUS_LINK_STATE, - .StatusBuffer = &state, - .StatusBufferSize = sizeof(state) - }; + NDIS_STATUS_INDICATION t = {.Header = {.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION, + .Revision = NDIS_STATUS_INDICATION_REVISION_1, + .Size = NDIS_SIZEOF_STATUS_INDICATION_REVISION_1}, + .SourceHandle = MiniportAdapterHandle, + .StatusCode = NDIS_STATUS_LINK_STATE, + .StatusBuffer = &state, + .StatusBufferSize = sizeof(state)}; - NdisMIndicateStatusEx(MiniportAdapterHandle, &t); + NdisMIndicateStatusEx(MiniportAdapterHandle, &t); } _IRQL_requires_max_(DISPATCH_LEVEL) -static void TunCompleteRequest(_Inout_ TUN_CTX *ctx, _Inout_ IRP *irp, _In_ NTSTATUS status, _In_ CCHAR priority_boost) +static void +TunCompleteRequest(_Inout_ TUN_CTX *ctx, _Inout_ IRP *irp, _In_ NTSTATUS status, _In_ CCHAR priority_boost) { - irp->IoStatus.Status = status; - IoCompleteRequest(irp, priority_boost); - IoReleaseRemoveLock(&ctx->Device.RemoveLock, irp); + irp->IoStatus.Status = status; + IoCompleteRequest(irp, priority_boost); + IoReleaseRemoveLock(&ctx->Device.RemoveLock, irp); } _IRQL_requires_max_(DISPATCH_LEVEL) -static NDIS_STATUS TunCompletePause(_Inout_ TUN_CTX *ctx, _In_ BOOLEAN async_completion) +static NDIS_STATUS +TunCompletePause(_Inout_ TUN_CTX *ctx, _In_ BOOLEAN async_completion) { - ASSERT(InterlockedGet64(&ctx->ActiveNBLCount) > 0); - if (InterlockedDecrement64(&ctx->ActiveNBLCount) <= 0) { - if (async_completion) - NdisMPauseComplete(ctx->MiniportAdapterHandle); - return NDIS_STATUS_SUCCESS; - } + ASSERT(InterlockedGet64(&ctx->ActiveNBLCount) > 0); + if (InterlockedDecrement64(&ctx->ActiveNBLCount) <= 0) + { + if (async_completion) + NdisMPauseComplete(ctx->MiniportAdapterHandle); + return NDIS_STATUS_SUCCESS; + } - return NDIS_STATUS_PENDING; + return NDIS_STATUS_PENDING; } static IO_CSQ_INSERT_IRP_EX TunCsqInsertIrpEx; _Use_decl_annotations_ -static NTSTATUS TunCsqInsertIrpEx(IO_CSQ *Csq, IRP *Irp, PVOID InsertContext) +static NTSTATUS +TunCsqInsertIrpEx(IO_CSQ *Csq, IRP *Irp, PVOID InsertContext) { - TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq); - (InsertContext == TUN_CSQ_INSERT_HEAD ? InsertHeadList : InsertTailList)(&ctx->Device.ReadQueue.List, &Irp->Tail.Overlay.ListEntry); - return STATUS_SUCCESS; + TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq); + (InsertContext == TUN_CSQ_INSERT_HEAD ? InsertHeadList + : InsertTailList)(&ctx->Device.ReadQueue.List, &Irp->Tail.Overlay.ListEntry); + return STATUS_SUCCESS; } static IO_CSQ_REMOVE_IRP TunCsqRemoveIrp; _Use_decl_annotations_ -static VOID TunCsqRemoveIrp(IO_CSQ *Csq, IRP *Irp) +static VOID +TunCsqRemoveIrp(IO_CSQ *Csq, IRP *Irp) { - RemoveEntryList(&Irp->Tail.Overlay.ListEntry); + RemoveEntryList(&Irp->Tail.Overlay.ListEntry); } static IO_CSQ_PEEK_NEXT_IRP TunCsqPeekNextIrp; _Use_decl_annotations_ -static IRP *TunCsqPeekNextIrp(IO_CSQ *Csq, IRP *Irp, _In_ PVOID PeekContext) +static IRP * +TunCsqPeekNextIrp(IO_CSQ *Csq, IRP *Irp, _In_ PVOID PeekContext) { - TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq); + TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq); - /* If the IRP is non-NULL, we will start peeking from that IRP onwards, else - * we will start from the listhead. This is done under the assumption that - * new IRPs are always inserted at the tail. */ - for (LIST_ENTRY - *head = &ctx->Device.ReadQueue.List, - *next = Irp ? Irp->Tail.Overlay.ListEntry.Flink : head->Flink; - next != head; - next = next->Flink) - { - IRP *irp_next = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry); - if (!PeekContext) - return irp_next; + /* If the IRP is non-NULL, we will start peeking from that IRP onwards, else + * we will start from the listhead. This is done under the assumption that + * new IRPs are always inserted at the tail. */ + for (LIST_ENTRY *head = &ctx->Device.ReadQueue.List, *next = Irp ? Irp->Tail.Overlay.ListEntry.Flink : head->Flink; + next != head; + next = next->Flink) + { + IRP *irp_next = CONTAINING_RECORD(next, IRP, Tail.Overlay.ListEntry); + if (!PeekContext) + return irp_next; - IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp_next); - if (stack->FileObject == (FILE_OBJECT *)PeekContext) - return irp_next; - } + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp_next); + if (stack->FileObject == (FILE_OBJECT *)PeekContext) + return irp_next; + } - return NULL; + return NULL; } _IRQL_raises_(DISPATCH_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL) _Requires_lock_not_held_(CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq)->Device.ReadQueue.Lock) -_Acquires_lock_(CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq)->Device.ReadQueue.Lock) -static VOID TunCsqAcquireLock(_In_ IO_CSQ *Csq, _Out_ _At_(*Irql, _Post_ _IRQL_saves_) KIRQL *Irql) + _Acquires_lock_(CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq)->Device.ReadQueue.Lock) +static VOID +TunCsqAcquireLock(_In_ IO_CSQ *Csq, _Out_ _At_(*Irql, _Post_ _IRQL_saves_) KIRQL *Irql) { - KeAcquireSpinLock(&CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq)->Device.ReadQueue.Lock, Irql); + KeAcquireSpinLock(&CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq)->Device.ReadQueue.Lock, Irql); } _IRQL_requires_(DISPATCH_LEVEL) _Requires_lock_held_(CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq)->Device.ReadQueue.Lock) _Releases_lock_(CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq)->Device.ReadQueue.Lock) -static VOID TunCsqReleaseLock(_In_ IO_CSQ *Csq, _In_ _IRQL_restores_ KIRQL Irql) +static VOID +TunCsqReleaseLock(_In_ IO_CSQ *Csq, _In_ _IRQL_restores_ KIRQL Irql) { - KeReleaseSpinLock(&CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq)->Device.ReadQueue.Lock, Irql); + KeReleaseSpinLock(&CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq)->Device.ReadQueue.Lock, Irql); } static IO_CSQ_COMPLETE_CANCELED_IRP TunCsqCompleteCanceledIrp; _Use_decl_annotations_ -static VOID TunCsqCompleteCanceledIrp(IO_CSQ *Csq, IRP *Irp) +static VOID +TunCsqCompleteCanceledIrp(IO_CSQ *Csq, IRP *Irp) { - TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq); - TunCompleteRequest(ctx, Irp, STATUS_CANCELLED, IO_NO_INCREMENT); + TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq); + TunCompleteRequest(ctx, Irp, STATUS_CANCELLED, IO_NO_INCREMENT); } _IRQL_requires_max_(DISPATCH_LEVEL) _Must_inspect_result_ -static NTSTATUS TunGetIrpBuffer(_In_ IRP *Irp, _Out_ UCHAR **buffer, _Out_ ULONG *size) +static NTSTATUS +TunGetIrpBuffer(_In_ IRP *Irp, _Out_ UCHAR **buffer, _Out_ ULONG *size) { - TUN_MAPPED_UBUFFER *ubuffer = NULL; - IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); - TUN_FILE_CTX *file_ctx = (TUN_FILE_CTX *)stack->FileObject->FsContext; + TUN_MAPPED_UBUFFER *ubuffer = NULL; + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); + TUN_FILE_CTX *file_ctx = (TUN_FILE_CTX *)stack->FileObject->FsContext; - switch (stack->MajorFunction) { - case IRP_MJ_READ: - *size = stack->Parameters.Read.Length; - ubuffer = &file_ctx->ReadBuffer; - break; - case IRP_MJ_WRITE: - *size = stack->Parameters.Write.Length; - ubuffer = &file_ctx->WriteBuffer; - break; - default: - ASSERT(FALSE); - } - _Analysis_assume_(ubuffer != NULL); - if (*size > ubuffer->Size) - return STATUS_INVALID_USER_BUFFER; - ASSERT(ubuffer->KernelAddress != NULL); - *buffer = ubuffer->KernelAddress; - return STATUS_SUCCESS; + switch (stack->MajorFunction) + { + case IRP_MJ_READ: + *size = stack->Parameters.Read.Length; + ubuffer = &file_ctx->ReadBuffer; + break; + case IRP_MJ_WRITE: + *size = stack->Parameters.Write.Length; + ubuffer = &file_ctx->WriteBuffer; + break; + default: + ASSERT(FALSE); + } + _Analysis_assume_(ubuffer != NULL); + if (*size > ubuffer->Size) + return STATUS_INVALID_USER_BUFFER; + ASSERT(ubuffer->KernelAddress != NULL); + *buffer = ubuffer->KernelAddress; + return STATUS_SUCCESS; } _IRQL_requires_max_(APC_LEVEL) _Must_inspect_result_ -static NTSTATUS TunMapUbuffer(_Inout_ TUN_MAPPED_UBUFFER *MappedBuffer, _In_ VOID *UserAddress, _In_ ULONG Size) +static NTSTATUS +TunMapUbuffer(_Inout_ TUN_MAPPED_UBUFFER *MappedBuffer, _In_ VOID *UserAddress, _In_ ULONG Size) { - if (MappedBuffer->UserAddress) { - if (UserAddress == MappedBuffer->UserAddress) //TODO: Check ThreadID - return STATUS_SUCCESS; - return STATUS_ALREADY_INITIALIZED; - } - __try { - ProbeForWrite(UserAddress, Size, 1); - ProbeForRead(UserAddress, Size, 1); + if (MappedBuffer->UserAddress) + { + if (UserAddress == MappedBuffer->UserAddress) // TODO: Check ThreadID + return STATUS_SUCCESS; + return STATUS_ALREADY_INITIALIZED; + } + __try + { + ProbeForWrite(UserAddress, Size, 1); + ProbeForRead(UserAddress, Size, 1); - MappedBuffer->Mdl = IoAllocateMdl(UserAddress, Size, FALSE, FALSE, NULL); - if (!MappedBuffer->Mdl) - return STATUS_INSUFFICIENT_RESOURCES; - MmProbeAndLockPages(MappedBuffer->Mdl, KernelMode, IoWriteAccess); - MappedBuffer->KernelAddress = MmGetSystemAddressForMdlSafe(MappedBuffer->Mdl, NormalPagePriority | MdlMappingNoExecute); - if (!MappedBuffer->KernelAddress) { - IoFreeMdl(MappedBuffer->Mdl); - MappedBuffer->Mdl = NULL; - return STATUS_INSUFFICIENT_RESOURCES; - } - MappedBuffer->UserAddress = UserAddress; - MappedBuffer->Size = Size; - } __except (EXCEPTION_EXECUTE_HANDLER) { - if (MappedBuffer->Mdl) { - IoFreeMdl(MappedBuffer->Mdl); - MappedBuffer->Mdl = NULL; - } - return STATUS_INVALID_USER_BUFFER; - } - return STATUS_SUCCESS; + MappedBuffer->Mdl = IoAllocateMdl(UserAddress, Size, FALSE, FALSE, NULL); + if (!MappedBuffer->Mdl) + return STATUS_INSUFFICIENT_RESOURCES; + MmProbeAndLockPages(MappedBuffer->Mdl, KernelMode, IoWriteAccess); + MappedBuffer->KernelAddress = + MmGetSystemAddressForMdlSafe(MappedBuffer->Mdl, NormalPagePriority | MdlMappingNoExecute); + if (!MappedBuffer->KernelAddress) + { + IoFreeMdl(MappedBuffer->Mdl); + MappedBuffer->Mdl = NULL; + return STATUS_INSUFFICIENT_RESOURCES; + } + MappedBuffer->UserAddress = UserAddress; + MappedBuffer->Size = Size; + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + if (MappedBuffer->Mdl) + { + IoFreeMdl(MappedBuffer->Mdl); + MappedBuffer->Mdl = NULL; + } + return STATUS_INVALID_USER_BUFFER; + } + return STATUS_SUCCESS; } _IRQL_requires_max_(DISPATCH_LEVEL) -static void TunUnmapUbuffer(_Inout_ TUN_MAPPED_UBUFFER *MappedBuffer) +static void +TunUnmapUbuffer(_Inout_ TUN_MAPPED_UBUFFER *MappedBuffer) { - if (MappedBuffer->Mdl) { - MmUnlockPages(MappedBuffer->Mdl); - IoFreeMdl(MappedBuffer->Mdl); - MappedBuffer->UserAddress = MappedBuffer->KernelAddress = MappedBuffer->Mdl = NULL; - } + if (MappedBuffer->Mdl) + { + MmUnlockPages(MappedBuffer->Mdl); + IoFreeMdl(MappedBuffer->Mdl); + MappedBuffer->UserAddress = MappedBuffer->KernelAddress = MappedBuffer->Mdl = NULL; + } } _IRQL_requires_max_(APC_LEVEL) _Must_inspect_result_ -static NTSTATUS TunMapIrp(_In_ IRP *Irp) +static NTSTATUS +TunMapIrp(_In_ IRP *Irp) { - ULONG size; - TUN_MAPPED_UBUFFER *ubuffer; - IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); - TUN_FILE_CTX *file_ctx = (TUN_FILE_CTX *)stack->FileObject->FsContext; + ULONG size; + TUN_MAPPED_UBUFFER *ubuffer; + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); + TUN_FILE_CTX *file_ctx = (TUN_FILE_CTX *)stack->FileObject->FsContext; - switch (stack->MajorFunction) { - case IRP_MJ_READ: - size = stack->Parameters.Read.Length; - if (size < TUN_EXCH_MIN_BUFFER_SIZE_READ) - return STATUS_INVALID_USER_BUFFER; - ubuffer = &file_ctx->ReadBuffer; - break; - case IRP_MJ_WRITE: - size = stack->Parameters.Write.Length; - if (size < TUN_EXCH_MIN_BUFFER_SIZE_WRITE) - return STATUS_INVALID_USER_BUFFER; - ubuffer = &file_ctx->WriteBuffer; - break; - default: - return STATUS_INVALID_PARAMETER; - } - if (size > TUN_EXCH_MAX_BUFFER_SIZE) - return STATUS_INVALID_USER_BUFFER; - return TunMapUbuffer(ubuffer, Irp->UserBuffer, size); + switch (stack->MajorFunction) + { + case IRP_MJ_READ: + size = stack->Parameters.Read.Length; + if (size < TUN_EXCH_MIN_BUFFER_SIZE_READ) + return STATUS_INVALID_USER_BUFFER; + ubuffer = &file_ctx->ReadBuffer; + break; + case IRP_MJ_WRITE: + size = stack->Parameters.Write.Length; + if (size < TUN_EXCH_MIN_BUFFER_SIZE_WRITE) + return STATUS_INVALID_USER_BUFFER; + ubuffer = &file_ctx->WriteBuffer; + break; + default: + return STATUS_INVALID_PARAMETER; + } + if (size > TUN_EXCH_MAX_BUFFER_SIZE) + return STATUS_INVALID_USER_BUFFER; + return TunMapUbuffer(ubuffer, Irp->UserBuffer, size); } _IRQL_requires_max_(DISPATCH_LEVEL) _Must_inspect_result_ -static _Return_type_success_(return != NULL) IRP *TunRemoveNextIrp(_Inout_ TUN_CTX *ctx, _Out_ UCHAR **buffer, _Out_ ULONG *size) +static _Return_type_success_( + return != NULL) IRP *TunRemoveNextIrp(_Inout_ TUN_CTX *ctx, _Out_ UCHAR **buffer, _Out_ ULONG *size) { - IRP *irp; + IRP *irp; retry: - irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, NULL); - if (!irp) - return NULL; + irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, NULL); + if (!irp) + return NULL; - NTSTATUS status = TunGetIrpBuffer(irp, buffer, size); - if (!NT_SUCCESS(status)) { - TunCompleteRequest(ctx, irp, status, IO_NO_INCREMENT); - goto retry; - } + NTSTATUS status = TunGetIrpBuffer(irp, buffer, size); + if (!NT_SUCCESS(status)) + { + TunCompleteRequest(ctx, irp, status, IO_NO_INCREMENT); + 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 TunWontFitIntoIrp(_In_ IRP *Irp, _In_ ULONG size, _In_ NET_BUFFER *nb) +_IRQL_requires_same_ static BOOLEAN +TunWontFitIntoIrp(_In_ IRP *Irp, _In_ ULONG size, _In_ NET_BUFFER *nb) { - return (ULONG_PTR)size < Irp->IoStatus.Information + TunPacketAlign(sizeof(TUN_PACKET) + NET_BUFFER_DATA_LENGTH(nb)); + return (ULONG_PTR)size < + Irp->IoStatus.Information + TunPacketAlign(sizeof(TUN_PACKET) + NET_BUFFER_DATA_LENGTH(nb)); } _IRQL_requires_max_(DISPATCH_LEVEL) _Must_inspect_result_ -static NTSTATUS TunWriteIntoIrp(_Inout_ IRP *Irp, _Inout_ UCHAR *buffer, _In_ NET_BUFFER *nb, _Inout_ NDIS_STATISTICS_INFO *statistics) +static NTSTATUS +TunWriteIntoIrp(_Inout_ IRP *Irp, _Inout_ UCHAR *buffer, _In_ NET_BUFFER *nb, _Inout_ NDIS_STATISTICS_INFO *statistics) { - ULONG p_size = NET_BUFFER_DATA_LENGTH(nb); - TUN_PACKET *p = (TUN_PACKET *)(buffer + Irp->IoStatus.Information); + ULONG p_size = NET_BUFFER_DATA_LENGTH(nb); + TUN_PACKET *p = (TUN_PACKET *)(buffer + Irp->IoStatus.Information); - p->Size = p_size; - void *ptr = NdisGetDataBuffer(nb, p_size, p->Data, 1, 0); - if (!ptr) { - if (statistics) - InterlockedIncrement64((LONG64 *)&statistics->ifOutErrors); - return NDIS_STATUS_RESOURCES; - } - if (ptr != p->Data) - NdisMoveMemory(p->Data, ptr, p_size); + p->Size = p_size; + void *ptr = NdisGetDataBuffer(nb, p_size, p->Data, 1, 0); + if (!ptr) + { + if (statistics) + InterlockedIncrement64((LONG64 *)&statistics->ifOutErrors); + return NDIS_STATUS_RESOURCES; + } + if (ptr != p->Data) + NdisMoveMemory(p->Data, ptr, p_size); - 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->ifHCOutUcastOctets, p_size); - InterlockedIncrement64((LONG64 *)&statistics->ifHCOutUcastPkts); - return STATUS_SUCCESS; + InterlockedAdd64((LONG64 *)&statistics->ifHCOutOctets, p_size); + InterlockedAdd64((LONG64 *)&statistics->ifHCOutUcastOctets, p_size); + InterlockedIncrement64((LONG64 *)&statistics->ifHCOutUcastPkts); + return STATUS_SUCCESS; } #define NET_BUFFER_LIST_REFCOUNT(nbl) ((volatile LONG64 *)NET_BUFFER_LIST_MINIPORT_RESERVED(nbl)) -_IRQL_requires_same_ -static void TunNBLRefInit(_Inout_ TUN_CTX *ctx, _Inout_ NET_BUFFER_LIST *nbl) +_IRQL_requires_same_ static void +TunNBLRefInit(_Inout_ TUN_CTX *ctx, _Inout_ NET_BUFFER_LIST *nbl) { - InterlockedIncrement64(&ctx->ActiveNBLCount); - InterlockedIncrement(&ctx->PacketQueue.NumNbl); - InterlockedExchange64(NET_BUFFER_LIST_REFCOUNT(nbl), 1); + InterlockedIncrement64(&ctx->ActiveNBLCount); + InterlockedIncrement(&ctx->PacketQueue.NumNbl); + InterlockedExchange64(NET_BUFFER_LIST_REFCOUNT(nbl), 1); } -_IRQL_requires_same_ -static void TunNBLRefInc(_Inout_ NET_BUFFER_LIST *nbl) +_IRQL_requires_same_ static void +TunNBLRefInc(_Inout_ NET_BUFFER_LIST *nbl) { - ASSERT(InterlockedGet64(NET_BUFFER_LIST_REFCOUNT(nbl))); - InterlockedIncrement64(NET_BUFFER_LIST_REFCOUNT(nbl)); + ASSERT(InterlockedGet64(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)) -static BOOLEAN TunNBLRefDec(_Inout_ TUN_CTX *ctx, _Inout_ NET_BUFFER_LIST *nbl, _In_ ULONG SendCompleteFlags) +static BOOLEAN +TunNBLRefDec(_Inout_ TUN_CTX *ctx, _Inout_ NET_BUFFER_LIST *nbl, _In_ ULONG SendCompleteFlags) { - ASSERT(InterlockedGet64(NET_BUFFER_LIST_REFCOUNT(nbl)) > 0); - if (InterlockedDecrement64(NET_BUFFER_LIST_REFCOUNT(nbl)) <= 0) { - NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; - NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, SendCompleteFlags); - ASSERT(InterlockedGet(&ctx->PacketQueue.NumNbl) > 0); - InterlockedDecrement(&ctx->PacketQueue.NumNbl); - TunCompletePause(ctx, TRUE); - return TRUE; - } - return FALSE; + ASSERT(InterlockedGet64(NET_BUFFER_LIST_REFCOUNT(nbl)) > 0); + if (InterlockedDecrement64(NET_BUFFER_LIST_REFCOUNT(nbl)) <= 0) + { + NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; + NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, SendCompleteFlags); + ASSERT(InterlockedGet(&ctx->PacketQueue.NumNbl) > 0); + InterlockedDecrement(&ctx->PacketQueue.NumNbl); + TunCompletePause(ctx, TRUE); + return TRUE; + } + return FALSE; } -_IRQL_requires_same_ -static void TunAppendNBL(_Inout_ NET_BUFFER_LIST **head, _Inout_ NET_BUFFER_LIST **tail, __drv_aliasesMem _In_ NET_BUFFER_LIST *nbl) +_IRQL_requires_same_ static void +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 = nbl; - NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; + *(*tail ? &NET_BUFFER_LIST_NEXT_NBL(*tail) : head) = nbl; + *tail = nbl; + NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; } -_Requires_lock_not_held_(ctx->PacketQueue.Lock) -_IRQL_requires_max_(DISPATCH_LEVEL) -static void TunQueueAppend(_Inout_ TUN_CTX *ctx, _In_ NET_BUFFER_LIST *nbl, _In_ UINT max_nbls) +_Requires_lock_not_held_(ctx->PacketQueue.Lock) _IRQL_requires_max_(DISPATCH_LEVEL) +static void +TunQueueAppend(_Inout_ TUN_CTX *ctx, _In_ NET_BUFFER_LIST *nbl, _In_ UINT max_nbls) { - for (NET_BUFFER_LIST *nbl_next; nbl; nbl = nbl_next) { - nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); - if (!NET_BUFFER_LIST_FIRST_NB(nbl)) { - NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; - NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, 0); - continue; - } + for (NET_BUFFER_LIST *nbl_next; nbl; nbl = nbl_next) + { + nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); + if (!NET_BUFFER_LIST_FIRST_NB(nbl)) + { + NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; + NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, 0); + continue; + } - KLOCK_QUEUE_HANDLE lqh; - KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh); - TunNBLRefInit(ctx, nbl); - TunAppendNBL(&ctx->PacketQueue.FirstNbl, &ctx->PacketQueue.LastNbl, nbl); + KLOCK_QUEUE_HANDLE lqh; + KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh); + TunNBLRefInit(ctx, nbl); + TunAppendNBL(&ctx->PacketQueue.FirstNbl, &ctx->PacketQueue.LastNbl, nbl); - while ((UINT)InterlockedGet(&ctx->PacketQueue.NumNbl) > max_nbls && ctx->PacketQueue.FirstNbl) { - NET_BUFFER_LIST *nbl_second = NET_BUFFER_LIST_NEXT_NBL(ctx->PacketQueue.FirstNbl); + while ((UINT)InterlockedGet(&ctx->PacketQueue.NumNbl) > max_nbls && 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; - TunNBLRefDec(ctx, ctx->PacketQueue.FirstNbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + NET_BUFFER_LIST_STATUS(ctx->PacketQueue.FirstNbl) = NDIS_STATUS_SEND_ABORTED; + TunNBLRefDec(ctx, ctx->PacketQueue.FirstNbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - ctx->PacketQueue.NextNb = NULL; - ctx->PacketQueue.FirstNbl = nbl_second; - if (!ctx->PacketQueue.FirstNbl) - ctx->PacketQueue.LastNbl = NULL; - } + ctx->PacketQueue.NextNb = NULL; + ctx->PacketQueue.FirstNbl = nbl_second; + if (!ctx->PacketQueue.FirstNbl) + ctx->PacketQueue.LastNbl = NULL; + } - KeReleaseInStackQueuedSpinLock(&lqh); - } + KeReleaseInStackQueuedSpinLock(&lqh); + } } _Requires_lock_held_(ctx->PacketQueue.Lock) _IRQL_requires_(DISPATCH_LEVEL) _Must_inspect_result_ -static _Return_type_success_(return != NULL) NET_BUFFER *TunQueueRemove(_Inout_ TUN_CTX *ctx, _Out_ NET_BUFFER_LIST **nbl) +static _Return_type_success_(return != + NULL) NET_BUFFER *TunQueueRemove(_Inout_ TUN_CTX *ctx, _Out_ NET_BUFFER_LIST **nbl) { - NET_BUFFER_LIST *nbl_top; - NET_BUFFER *ret; + NET_BUFFER_LIST *nbl_top; + NET_BUFFER *ret; retry: - nbl_top = ctx->PacketQueue.FirstNbl; - *nbl = nbl_top; - if (!nbl_top) - return NULL; - if (!ctx->PacketQueue.NextNb) - ctx->PacketQueue.NextNb = NET_BUFFER_LIST_FIRST_NB(nbl_top); - ret = ctx->PacketQueue.NextNb; - ctx->PacketQueue.NextNb = NET_BUFFER_NEXT_NB(ret); - if (!ctx->PacketQueue.NextNb) { - ctx->PacketQueue.FirstNbl = NET_BUFFER_LIST_NEXT_NBL(nbl_top); - if (!ctx->PacketQueue.FirstNbl) - ctx->PacketQueue.LastNbl = NULL; - NET_BUFFER_LIST_NEXT_NBL(nbl_top) = NULL; - } else - TunNBLRefInc(nbl_top); + nbl_top = ctx->PacketQueue.FirstNbl; + *nbl = nbl_top; + if (!nbl_top) + return NULL; + if (!ctx->PacketQueue.NextNb) + ctx->PacketQueue.NextNb = NET_BUFFER_LIST_FIRST_NB(nbl_top); + ret = ctx->PacketQueue.NextNb; + ctx->PacketQueue.NextNb = NET_BUFFER_NEXT_NB(ret); + if (!ctx->PacketQueue.NextNb) + { + ctx->PacketQueue.FirstNbl = NET_BUFFER_LIST_NEXT_NBL(nbl_top); + if (!ctx->PacketQueue.FirstNbl) + ctx->PacketQueue.LastNbl = NULL; + NET_BUFFER_LIST_NEXT_NBL(nbl_top) = NULL; + } + else + TunNBLRefInc(nbl_top); - if (ret && NET_BUFFER_DATA_LENGTH(ret) > TUN_EXCH_MAX_IP_PACKET_SIZE) { - NET_BUFFER_LIST_STATUS(nbl_top) = NDIS_STATUS_INVALID_LENGTH; - TunNBLRefDec(ctx, nbl_top, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - InterlockedIncrement64((LONG64 *)&ctx->Statistics.ifOutDiscards); - goto retry; /* A for (;;) and a break would be fine, but this is clearer actually. */ - } + if (ret && NET_BUFFER_DATA_LENGTH(ret) > TUN_EXCH_MAX_IP_PACKET_SIZE) + { + NET_BUFFER_LIST_STATUS(nbl_top) = NDIS_STATUS_INVALID_LENGTH; + TunNBLRefDec(ctx, nbl_top, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + InterlockedIncrement64((LONG64 *)&ctx->Statistics.ifOutDiscards); + goto retry; /* A for (;;) and a break would be fine, but this is clearer actually. */ + } - return ret; + return ret; } /* Note: Must be called immediately after TunQueueRemove without dropping ctx->PacketQueue.Lock. */ _Requires_lock_held_(ctx->PacketQueue.Lock) _IRQL_requires_(DISPATCH_LEVEL) -static void TunQueuePrepend(_Inout_ TUN_CTX *ctx, _In_ NET_BUFFER *nb, _In_ NET_BUFFER_LIST *nbl) +static void +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) - return; + if (!nbl || nbl == ctx->PacketQueue.FirstNbl) + return; - TunNBLRefInc(nbl); - if (!ctx->PacketQueue.FirstNbl) - ctx->PacketQueue.FirstNbl = ctx->PacketQueue.LastNbl = nbl; - else { - NET_BUFFER_LIST_NEXT_NBL(nbl) = ctx->PacketQueue.FirstNbl; - ctx->PacketQueue.FirstNbl = nbl; - } + TunNBLRefInc(nbl); + if (!ctx->PacketQueue.FirstNbl) + ctx->PacketQueue.FirstNbl = ctx->PacketQueue.LastNbl = nbl; + else + { + NET_BUFFER_LIST_NEXT_NBL(nbl) = ctx->PacketQueue.FirstNbl; + ctx->PacketQueue.FirstNbl = nbl; + } } -_Requires_lock_not_held_(ctx->PacketQueue.Lock) -_IRQL_requires_max_(DISPATCH_LEVEL) -static void TunQueueClear(_Inout_ TUN_CTX *ctx, _In_ NDIS_STATUS status) +_Requires_lock_not_held_(ctx->PacketQueue.Lock) _IRQL_requires_max_(DISPATCH_LEVEL) +static void +TunQueueClear(_Inout_ TUN_CTX *ctx, _In_ NDIS_STATUS status) { - KLOCK_QUEUE_HANDLE lqh; - KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh); - for (NET_BUFFER_LIST *nbl = ctx->PacketQueue.FirstNbl, *nbl_next; nbl; nbl = nbl_next) { - nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); - NET_BUFFER_LIST_STATUS(nbl) = status; - TunNBLRefDec(ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - } - ctx->PacketQueue.FirstNbl = NULL; - ctx->PacketQueue.LastNbl = NULL; - ctx->PacketQueue.NextNb = NULL; - InterlockedExchange(&ctx->PacketQueue.NumNbl, 0); - KeReleaseInStackQueuedSpinLock(&lqh); + KLOCK_QUEUE_HANDLE lqh; + KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh); + for (NET_BUFFER_LIST *nbl = ctx->PacketQueue.FirstNbl, *nbl_next; nbl; nbl = nbl_next) + { + nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); + NET_BUFFER_LIST_STATUS(nbl) = status; + TunNBLRefDec(ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + } + ctx->PacketQueue.FirstNbl = NULL; + ctx->PacketQueue.LastNbl = NULL; + ctx->PacketQueue.NextNb = NULL; + InterlockedExchange(&ctx->PacketQueue.NumNbl, 0); + KeReleaseInStackQueuedSpinLock(&lqh); } -_Requires_lock_not_held_(ctx->PacketQueue.Lock) -_IRQL_requires_max_(DISPATCH_LEVEL) -static void TunQueueProcess(_Inout_ TUN_CTX *ctx) +_Requires_lock_not_held_(ctx->PacketQueue.Lock) _IRQL_requires_max_(DISPATCH_LEVEL) +static void +TunQueueProcess(_Inout_ TUN_CTX *ctx) { - IRP *irp = NULL; - UCHAR *buffer = NULL; - ULONG size = 0; - NET_BUFFER *nb; - KLOCK_QUEUE_HANDLE lqh; + IRP *irp = NULL; + UCHAR *buffer = NULL; + ULONG size = 0; + NET_BUFFER *nb; + KLOCK_QUEUE_HANDLE lqh; - for (;;) { - NET_BUFFER_LIST *nbl; + for (;;) + { + NET_BUFFER_LIST *nbl; - KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh); + KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh); - /* Get head NB (and IRP). */ - if (!irp) { - nb = TunQueueRemove(ctx, &nbl); - if (!nb) { - KeReleaseInStackQueuedSpinLock(&lqh); - return; - } - irp = TunRemoveNextIrp(ctx, &buffer, &size); - if (!irp) { - TunQueuePrepend(ctx, nb, nbl); - KeReleaseInStackQueuedSpinLock(&lqh); - if (nbl) - TunNBLRefDec(ctx, nbl, 0); - return; - } + /* Get head NB (and IRP). */ + if (!irp) + { + nb = TunQueueRemove(ctx, &nbl); + if (!nb) + { + KeReleaseInStackQueuedSpinLock(&lqh); + return; + } + irp = TunRemoveNextIrp(ctx, &buffer, &size); + if (!irp) + { + TunQueuePrepend(ctx, nb, nbl); + KeReleaseInStackQueuedSpinLock(&lqh); + if (nbl) + TunNBLRefDec(ctx, nbl, 0); + return; + } - _Analysis_assume_(buffer); - _Analysis_assume_(irp->IoStatus.Information <= size); - } else - nb = TunQueueRemove(ctx, &nbl); + _Analysis_assume_(buffer); + _Analysis_assume_(irp->IoStatus.Information <= size); + } + else + nb = TunQueueRemove(ctx, &nbl); - /* If the NB won't fit in the IRP, return it. */ - if (nb && TunWontFitIntoIrp(irp, size, nb)) { - TunQueuePrepend(ctx, nb, nbl); - if (nbl) - TunNBLRefDec(ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - nbl = NULL; - nb = NULL; - } + /* If the NB won't fit in the IRP, return it. */ + if (nb && TunWontFitIntoIrp(irp, size, nb)) + { + TunQueuePrepend(ctx, nb, nbl); + if (nbl) + TunNBLRefDec(ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + nbl = NULL; + nb = NULL; + } - KeReleaseInStackQueuedSpinLock(&lqh); + KeReleaseInStackQueuedSpinLock(&lqh); - /* Process NB and IRP. */ - if (nb) { - NTSTATUS status = TunWriteIntoIrp(irp, buffer, nb, &ctx->Statistics); - if (!NT_SUCCESS(status)) { - if (nbl) - NET_BUFFER_LIST_STATUS(nbl) = status; - IoCsqInsertIrpEx(&ctx->Device.ReadQueue.Csq, irp, NULL, TUN_CSQ_INSERT_HEAD); - irp = NULL; - } - } else { - TunCompleteRequest(ctx, irp, STATUS_SUCCESS, IO_NETWORK_INCREMENT); - irp = NULL; - } + /* Process NB and IRP. */ + if (nb) + { + NTSTATUS status = TunWriteIntoIrp(irp, buffer, nb, &ctx->Statistics); + if (!NT_SUCCESS(status)) + { + if (nbl) + NET_BUFFER_LIST_STATUS(nbl) = status; + IoCsqInsertIrpEx(&ctx->Device.ReadQueue.Csq, irp, NULL, TUN_CSQ_INSERT_HEAD); + irp = NULL; + } + } + else + { + TunCompleteRequest(ctx, irp, STATUS_SUCCESS, IO_NETWORK_INCREMENT); + irp = NULL; + } - if (nbl) - TunNBLRefDec(ctx, nbl, 0); - } + if (nbl) + TunNBLRefDec(ctx, nbl, 0); + } } -_IRQL_requires_same_ -static void TunSetNBLStatus(_Inout_opt_ NET_BUFFER_LIST *nbl, _In_ NDIS_STATUS status) +_IRQL_requires_same_ static void +TunSetNBLStatus(_Inout_opt_ NET_BUFFER_LIST *nbl, _In_ NDIS_STATUS status) { - for (; nbl; nbl = NET_BUFFER_LIST_NEXT_NBL(nbl)) - NET_BUFFER_LIST_STATUS(nbl) = status; + for (; nbl; nbl = NET_BUFFER_LIST_NEXT_NBL(nbl)) + NET_BUFFER_LIST_STATUS(nbl) = status; } static MINIPORT_SEND_NET_BUFFER_LISTS TunSendNetBufferLists; _Use_decl_annotations_ -static void TunSendNetBufferLists(NDIS_HANDLE MiniportAdapterContext, NET_BUFFER_LIST *NetBufferLists, NDIS_PORT_NUMBER PortNumber, ULONG SendFlags) +static void +TunSendNetBufferLists( + NDIS_HANDLE MiniportAdapterContext, + NET_BUFFER_LIST *NetBufferLists, + NDIS_PORT_NUMBER PortNumber, + ULONG SendFlags) { - TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; + TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; - InterlockedIncrement64(&ctx->ActiveNBLCount); + InterlockedIncrement64(&ctx->ActiveNBLCount); - KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock); - LONG flags = InterlockedGet(&ctx->Flags); - NDIS_STATUS status; - if ((status = NDIS_STATUS_ADAPTER_REMOVED , !(flags & TUN_FLAGS_PRESENT)) || - (status = NDIS_STATUS_PAUSED , !(flags & TUN_FLAGS_RUNNING)) || - (status = NDIS_STATUS_MEDIA_DISCONNECTED, InterlockedGet64(&ctx->Device.RefCount) <= 0)) - { - TunSetNBLStatus(NetBufferLists, status); - NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, NetBufferLists, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - goto cleanup_ExReleaseSpinLockShared; - } + KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock); + LONG flags = InterlockedGet(&ctx->Flags); + NDIS_STATUS status; + if ((status = NDIS_STATUS_ADAPTER_REMOVED, !(flags & TUN_FLAGS_PRESENT)) || + (status = NDIS_STATUS_PAUSED, !(flags & TUN_FLAGS_RUNNING)) || + (status = NDIS_STATUS_MEDIA_DISCONNECTED, InterlockedGet64(&ctx->Device.RefCount) <= 0)) + { + TunSetNBLStatus(NetBufferLists, status); + NdisMSendNetBufferListsComplete( + ctx->MiniportAdapterHandle, NetBufferLists, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + goto cleanup_ExReleaseSpinLockShared; + } - TunQueueAppend(ctx, NetBufferLists, TUN_QUEUE_MAX_NBLS); + TunQueueAppend(ctx, NetBufferLists, TUN_QUEUE_MAX_NBLS); - TunQueueProcess(ctx); + TunQueueProcess(ctx); cleanup_ExReleaseSpinLockShared: - ExReleaseSpinLockShared(&ctx->TransitionLock, irql); - TunCompletePause(ctx, TRUE); + ExReleaseSpinLockShared(&ctx->TransitionLock, irql); + TunCompletePause(ctx, TRUE); } static MINIPORT_CANCEL_SEND TunCancelSend; _Use_decl_annotations_ -static void TunCancelSend(NDIS_HANDLE MiniportAdapterContext, PVOID CancelId) +static void +TunCancelSend(NDIS_HANDLE MiniportAdapterContext, PVOID CancelId) { - TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; - KLOCK_QUEUE_HANDLE lqh; + TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; + KLOCK_QUEUE_HANDLE lqh; - KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh); + KeAcquireInStackQueuedSpinLock(&ctx->PacketQueue.Lock, &lqh); - NET_BUFFER_LIST *nbl_last = NULL, **nbl_last_link = &ctx->PacketQueue.FirstNbl; - for (NET_BUFFER_LIST *nbl = ctx->PacketQueue.FirstNbl, *nbl_next; nbl; nbl = nbl_next) { - nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); - if (NDIS_GET_NET_BUFFER_LIST_CANCEL_ID(nbl) == CancelId) { - NET_BUFFER_LIST_STATUS(nbl) = NDIS_STATUS_SEND_ABORTED; - *nbl_last_link = nbl_next; - TunNBLRefDec(ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); - } else { - nbl_last = nbl; - nbl_last_link = &NET_BUFFER_LIST_NEXT_NBL(nbl); - } - } - ctx->PacketQueue.LastNbl = nbl_last; + NET_BUFFER_LIST *nbl_last = NULL, **nbl_last_link = &ctx->PacketQueue.FirstNbl; + for (NET_BUFFER_LIST *nbl = ctx->PacketQueue.FirstNbl, *nbl_next; nbl; nbl = nbl_next) + { + nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); + if (NDIS_GET_NET_BUFFER_LIST_CANCEL_ID(nbl) == CancelId) + { + NET_BUFFER_LIST_STATUS(nbl) = NDIS_STATUS_SEND_ABORTED; + *nbl_last_link = nbl_next; + TunNBLRefDec(ctx, nbl, NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL); + } + else + { + nbl_last = nbl; + nbl_last_link = &NET_BUFFER_LIST_NEXT_NBL(nbl); + } + } + ctx->PacketQueue.LastNbl = nbl_last; - KeReleaseInStackQueuedSpinLock(&lqh); + KeReleaseInStackQueuedSpinLock(&lqh); } _IRQL_requires_max_(APC_LEVEL) _Must_inspect_result_ -static NTSTATUS TunDispatchRead(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp) +static NTSTATUS +TunDispatchRead(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp) { - NTSTATUS status = TunMapIrp(Irp); - if (!NT_SUCCESS(status)) - goto cleanup_CompleteRequest; + NTSTATUS status = TunMapIrp(Irp); + if (!NT_SUCCESS(status)) + goto cleanup_CompleteRequest; - KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock); - LONG flags = InterlockedGet(&ctx->Flags); - if ((status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT)) || - !NT_SUCCESS(status = IoCsqInsertIrpEx(&ctx->Device.ReadQueue.Csq, Irp, NULL, TUN_CSQ_INSERT_TAIL))) - goto cleanup_ExReleaseSpinLockShared; + KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock); + LONG flags = InterlockedGet(&ctx->Flags); + if ((status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT)) || + !NT_SUCCESS(status = IoCsqInsertIrpEx(&ctx->Device.ReadQueue.Csq, Irp, NULL, TUN_CSQ_INSERT_TAIL))) + goto cleanup_ExReleaseSpinLockShared; - TunQueueProcess(ctx); - ExReleaseSpinLockShared(&ctx->TransitionLock, irql); - return STATUS_PENDING; + TunQueueProcess(ctx); + ExReleaseSpinLockShared(&ctx->TransitionLock, irql); + return STATUS_PENDING; cleanup_ExReleaseSpinLockShared: - ExReleaseSpinLockShared(&ctx->TransitionLock, irql); + ExReleaseSpinLockShared(&ctx->TransitionLock, irql); cleanup_CompleteRequest: - TunCompleteRequest(ctx, Irp, status, IO_NO_INCREMENT); - return status; + TunCompleteRequest(ctx, Irp, status, IO_NO_INCREMENT); + return status; } -#define IRP_REFCOUNT(irp) ((volatile LONG *)&(irp)->Tail.Overlay.DriverContext[0]) +#define IRP_REFCOUNT(irp) ((volatile LONG *)&(irp)->Tail.Overlay.DriverContext[0]) #define NET_BUFFER_LIST_IRP(nbl) (NET_BUFFER_LIST_MINIPORT_RESERVED(nbl)[0]) _IRQL_requires_max_(APC_LEVEL) _Must_inspect_result_ -static NTSTATUS TunDispatchWrite(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp) +static NTSTATUS +TunDispatchWrite(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp) { - NTSTATUS status; + NTSTATUS status; - InterlockedIncrement64(&ctx->ActiveNBLCount); + InterlockedIncrement64(&ctx->ActiveNBLCount); - if (!NT_SUCCESS(status = TunMapIrp(Irp))) - goto cleanup_CompleteRequest; + if (!NT_SUCCESS(status = TunMapIrp(Irp))) + goto cleanup_CompleteRequest; - KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock); - LONG flags = InterlockedGet(&ctx->Flags); - if (status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT)) - goto cleanup_ExReleaseSpinLockShared; + KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock); + LONG flags = InterlockedGet(&ctx->Flags); + if (status = STATUS_FILE_FORCED_CLOSED, !(flags & TUN_FLAGS_PRESENT)) + goto cleanup_ExReleaseSpinLockShared; - UCHAR *buffer; - ULONG size; - if (!NT_SUCCESS(status = TunGetIrpBuffer(Irp, &buffer, &size))) - goto cleanup_ExReleaseSpinLockShared; - IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); - MDL *mdl = ((TUN_FILE_CTX *)stack->FileObject->FsContext)->WriteBuffer.Mdl; - const UCHAR *b = buffer, *b_end = buffer + size; - typedef enum _ethtypeidx_t { - ethtypeidx_ipv4 = 0, ethtypeidx_start = 0, - ethtypeidx_ipv6, - ethtypeidx_end - } ethtypeidx_t; - static const struct { - ULONG nbl_flags; - USHORT nbl_proto; - } ether_const[ethtypeidx_end] = { - { NDIS_NBL_FLAGS_IS_IPV4, TUN_HTONS(NDIS_ETH_TYPE_IPV4) }, - { NDIS_NBL_FLAGS_IS_IPV6, TUN_HTONS(NDIS_ETH_TYPE_IPV6) }, - }; - struct { - NET_BUFFER_LIST *head, *tail; - LONG count; - } nbl_queue[ethtypeidx_end] = { - { NULL, NULL, 0 }, - { NULL, NULL, 0 } - }; - LONG nbl_count = 0; - while (b_end - b >= sizeof(TUN_PACKET)) { - if (nbl_count >= MAXLONG) { - status = STATUS_INVALID_USER_BUFFER; - goto cleanup_nbl_queues; - } + UCHAR *buffer; + ULONG size; + if (!NT_SUCCESS(status = TunGetIrpBuffer(Irp, &buffer, &size))) + goto cleanup_ExReleaseSpinLockShared; + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); + MDL *mdl = ((TUN_FILE_CTX *)stack->FileObject->FsContext)->WriteBuffer.Mdl; + const UCHAR *b = buffer, *b_end = buffer + size; + typedef enum _ethtypeidx_t + { + ethtypeidx_ipv4 = 0, + ethtypeidx_start = 0, + ethtypeidx_ipv6, + ethtypeidx_end + } ethtypeidx_t; + static const struct + { + ULONG nbl_flags; + USHORT nbl_proto; + } ether_const[ethtypeidx_end] = { + {NDIS_NBL_FLAGS_IS_IPV4, TUN_HTONS(NDIS_ETH_TYPE_IPV4)}, + {NDIS_NBL_FLAGS_IS_IPV6, TUN_HTONS(NDIS_ETH_TYPE_IPV6)}, + }; + struct + { + NET_BUFFER_LIST *head, *tail; + LONG count; + } nbl_queue[ethtypeidx_end] = {{NULL, NULL, 0}, {NULL, NULL, 0}}; + LONG nbl_count = 0; + while (b_end - b >= sizeof(TUN_PACKET)) + { + if (nbl_count >= MAXLONG) + { + status = STATUS_INVALID_USER_BUFFER; + goto cleanup_nbl_queues; + } - TUN_PACKET *p = (TUN_PACKET *)b; - if (p->Size > TUN_EXCH_MAX_IP_PACKET_SIZE) { - status = STATUS_INVALID_USER_BUFFER; - goto cleanup_nbl_queues; - } - ULONG p_size = TunPacketAlign(sizeof(TUN_PACKET) + p->Size); - if (b_end - b < (ptrdiff_t)p_size) { - status = STATUS_INVALID_USER_BUFFER; - goto cleanup_nbl_queues; - } + TUN_PACKET *p = (TUN_PACKET *)b; + if (p->Size > TUN_EXCH_MAX_IP_PACKET_SIZE) + { + status = STATUS_INVALID_USER_BUFFER; + goto cleanup_nbl_queues; + } + ULONG p_size = TunPacketAlign(sizeof(TUN_PACKET) + p->Size); + if (b_end - b < (ptrdiff_t)p_size) + { + status = STATUS_INVALID_USER_BUFFER; + goto cleanup_nbl_queues; + } - ethtypeidx_t idx; - if (p->Size >= 20 && p->Data[0] >> 4 == 4) - idx = ethtypeidx_ipv4; - else if (p->Size >= 40 && p->Data[0] >> 4 == 6) - idx = ethtypeidx_ipv6; - else { - status = STATUS_INVALID_USER_BUFFER; - goto cleanup_nbl_queues; - } + ethtypeidx_t idx; + if (p->Size >= 20 && p->Data[0] >> 4 == 4) + idx = ethtypeidx_ipv4; + else if (p->Size >= 40 && p->Data[0] >> 4 == 6) + idx = ethtypeidx_ipv6; + else + { + status = STATUS_INVALID_USER_BUFFER; + goto cleanup_nbl_queues; + } - NET_BUFFER_LIST *nbl = NdisAllocateNetBufferAndNetBufferList(ctx->NBLPool, 0, 0, mdl, (ULONG)(p->Data - buffer), p->Size); - if (!nbl) { - status = STATUS_INSUFFICIENT_RESOURCES; - goto cleanup_nbl_queues; - } + NET_BUFFER_LIST *nbl = + NdisAllocateNetBufferAndNetBufferList(ctx->NBLPool, 0, 0, mdl, (ULONG)(p->Data - buffer), p->Size); + if (!nbl) + { + status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup_nbl_queues; + } - nbl->SourceHandle = ctx->MiniportAdapterHandle; - NdisSetNblFlag(nbl, ether_const[idx].nbl_flags); - NET_BUFFER_LIST_INFO(nbl, NetBufferListFrameType) = (PVOID)ether_const[idx].nbl_proto; - NET_BUFFER_LIST_STATUS(nbl) = NDIS_STATUS_SUCCESS; - NET_BUFFER_LIST_IRP(nbl) = Irp; - TunAppendNBL(&nbl_queue[idx].head, &nbl_queue[idx].tail, nbl); - nbl_queue[idx].count++; - nbl_count++; - b += p_size; - } + nbl->SourceHandle = ctx->MiniportAdapterHandle; + NdisSetNblFlag(nbl, ether_const[idx].nbl_flags); + NET_BUFFER_LIST_INFO(nbl, NetBufferListFrameType) = (PVOID)ether_const[idx].nbl_proto; + NET_BUFFER_LIST_STATUS(nbl) = NDIS_STATUS_SUCCESS; + NET_BUFFER_LIST_IRP(nbl) = Irp; + TunAppendNBL(&nbl_queue[idx].head, &nbl_queue[idx].tail, nbl); + nbl_queue[idx].count++; + nbl_count++; + b += p_size; + } - if ((ULONG)(b - buffer) != size) { - status = STATUS_INVALID_USER_BUFFER; - goto cleanup_nbl_queues; - } - Irp->IoStatus.Information = size; + if ((ULONG)(b - buffer) != size) + { + status = STATUS_INVALID_USER_BUFFER; + goto cleanup_nbl_queues; + } + Irp->IoStatus.Information = size; - if (!nbl_count) { - status = STATUS_SUCCESS; - goto cleanup_ExReleaseSpinLockShared; - } - if (!(flags & TUN_FLAGS_RUNNING)) { - InterlockedAdd64((LONG64 *)&ctx->Statistics.ifInDiscards, nbl_count); - InterlockedAdd64((LONG64 *)&ctx->Statistics.ifInErrors, nbl_count); - status = STATUS_SUCCESS; - goto cleanup_nbl_queues; - } + if (!nbl_count) + { + status = STATUS_SUCCESS; + goto cleanup_ExReleaseSpinLockShared; + } + if (!(flags & TUN_FLAGS_RUNNING)) + { + InterlockedAdd64((LONG64 *)&ctx->Statistics.ifInDiscards, nbl_count); + InterlockedAdd64((LONG64 *)&ctx->Statistics.ifInErrors, nbl_count); + status = STATUS_SUCCESS; + goto cleanup_nbl_queues; + } - InterlockedAdd64(&ctx->ActiveNBLCount, nbl_count); - InterlockedExchange(IRP_REFCOUNT(Irp), nbl_count); - IoMarkIrpPending(Irp); + InterlockedAdd64(&ctx->ActiveNBLCount, nbl_count); + InterlockedExchange(IRP_REFCOUNT(Irp), nbl_count); + IoMarkIrpPending(Irp); - if (nbl_queue[ethtypeidx_ipv4].head) - NdisMIndicateReceiveNetBufferLists(ctx->MiniportAdapterHandle, nbl_queue[ethtypeidx_ipv4].head, NDIS_DEFAULT_PORT_NUMBER, nbl_queue[ethtypeidx_ipv4].count, NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE); - if (nbl_queue[ethtypeidx_ipv6].head) - NdisMIndicateReceiveNetBufferLists(ctx->MiniportAdapterHandle, nbl_queue[ethtypeidx_ipv6].head, NDIS_DEFAULT_PORT_NUMBER, nbl_queue[ethtypeidx_ipv6].count, NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE); + if (nbl_queue[ethtypeidx_ipv4].head) + NdisMIndicateReceiveNetBufferLists( + ctx->MiniportAdapterHandle, + nbl_queue[ethtypeidx_ipv4].head, + NDIS_DEFAULT_PORT_NUMBER, + nbl_queue[ethtypeidx_ipv4].count, + NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE); + if (nbl_queue[ethtypeidx_ipv6].head) + NdisMIndicateReceiveNetBufferLists( + ctx->MiniportAdapterHandle, + nbl_queue[ethtypeidx_ipv6].head, + NDIS_DEFAULT_PORT_NUMBER, + nbl_queue[ethtypeidx_ipv6].count, + NDIS_RECEIVE_FLAGS_SINGLE_ETHER_TYPE); - ExReleaseSpinLockShared(&ctx->TransitionLock, irql); - TunCompletePause(ctx, TRUE); - return STATUS_PENDING; + ExReleaseSpinLockShared(&ctx->TransitionLock, irql); + TunCompletePause(ctx, TRUE); + return STATUS_PENDING; cleanup_nbl_queues: - for (ethtypeidx_t idx = ethtypeidx_start; idx < ethtypeidx_end; idx++) { - for (NET_BUFFER_LIST *nbl = nbl_queue[idx].head, *nbl_next; nbl; nbl = nbl_next) { - nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); - NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; - NdisFreeNetBufferList(nbl); - } - } + for (ethtypeidx_t idx = ethtypeidx_start; idx < ethtypeidx_end; idx++) + { + for (NET_BUFFER_LIST *nbl = nbl_queue[idx].head, *nbl_next; nbl; nbl = nbl_next) + { + nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); + NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; + NdisFreeNetBufferList(nbl); + } + } cleanup_ExReleaseSpinLockShared: - ExReleaseSpinLockShared(&ctx->TransitionLock, irql); + ExReleaseSpinLockShared(&ctx->TransitionLock, irql); cleanup_CompleteRequest: - TunCompleteRequest(ctx, Irp, status, IO_NO_INCREMENT); - TunCompletePause(ctx, TRUE); - return status; + TunCompleteRequest(ctx, Irp, status, IO_NO_INCREMENT); + TunCompletePause(ctx, TRUE); + return status; } static MINIPORT_RETURN_NET_BUFFER_LISTS TunReturnNetBufferLists; _Use_decl_annotations_ -static void TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST NetBufferLists, ULONG ReturnFlags) +static void +TunReturnNetBufferLists(NDIS_HANDLE MiniportAdapterContext, PNET_BUFFER_LIST NetBufferLists, ULONG ReturnFlags) { - TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; + TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; - LONG64 stat_size = 0, stat_p_ok = 0, stat_p_err = 0; - for (NET_BUFFER_LIST *nbl = NetBufferLists, *nbl_next; nbl; nbl = nbl_next) { - nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); - NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; + LONG64 stat_size = 0, stat_p_ok = 0, stat_p_err = 0; + for (NET_BUFFER_LIST *nbl = NetBufferLists, *nbl_next; nbl; nbl = nbl_next) + { + nbl_next = NET_BUFFER_LIST_NEXT_NBL(nbl); + NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; - IRP *irp = NET_BUFFER_LIST_IRP(nbl); - if (NT_SUCCESS(NET_BUFFER_LIST_STATUS(nbl))) { - ULONG p_size = NET_BUFFER_LIST_FIRST_NB(nbl)->DataLength; - stat_size += p_size; - stat_p_ok++; - } else - stat_p_err++; + IRP *irp = NET_BUFFER_LIST_IRP(nbl); + if (NT_SUCCESS(NET_BUFFER_LIST_STATUS(nbl))) + { + ULONG p_size = NET_BUFFER_LIST_FIRST_NB(nbl)->DataLength; + stat_size += p_size; + stat_p_ok++; + } + else + stat_p_err++; - NdisFreeNetBufferList(nbl); - TunCompletePause(ctx, TRUE); + NdisFreeNetBufferList(nbl); + TunCompletePause(ctx, TRUE); - ASSERT(InterlockedGet(IRP_REFCOUNT(irp)) > 0); - if (InterlockedDecrement(IRP_REFCOUNT(irp)) <= 0) - TunCompleteRequest(ctx, irp, STATUS_SUCCESS, IO_NETWORK_INCREMENT); - } + ASSERT(InterlockedGet(IRP_REFCOUNT(irp)) > 0); + if (InterlockedDecrement(IRP_REFCOUNT(irp)) <= 0) + TunCompleteRequest(ctx, irp, STATUS_SUCCESS, IO_NETWORK_INCREMENT); + } - InterlockedAdd64((LONG64 *)&ctx->Statistics.ifHCInOctets, stat_size); - InterlockedAdd64((LONG64 *)&ctx->Statistics.ifHCInUcastOctets, stat_size); - InterlockedAdd64((LONG64 *)&ctx->Statistics.ifHCInUcastPkts, stat_p_ok); - InterlockedAdd64((LONG64 *)&ctx->Statistics.ifInErrors, stat_p_err); + InterlockedAdd64((LONG64 *)&ctx->Statistics.ifHCInOctets, stat_size); + InterlockedAdd64((LONG64 *)&ctx->Statistics.ifHCInUcastOctets, stat_size); + InterlockedAdd64((LONG64 *)&ctx->Statistics.ifHCInUcastPkts, stat_p_ok); + InterlockedAdd64((LONG64 *)&ctx->Statistics.ifInErrors, stat_p_err); } _IRQL_requires_max_(DISPATCH_LEVEL) _Must_inspect_result_ -static NTSTATUS TunDispatchCreate(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp) +static NTSTATUS +TunDispatchCreate(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp) { - NTSTATUS status; - TUN_FILE_CTX *file_ctx = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(*file_ctx), TUN_HTONL(TUN_MEMORY_TAG)); - if (!file_ctx) - return STATUS_INSUFFICIENT_RESOURCES; - RtlZeroMemory(file_ctx, sizeof(*file_ctx)); + NTSTATUS status; + TUN_FILE_CTX *file_ctx = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(*file_ctx), TUN_HTONL(TUN_MEMORY_TAG)); + if (!file_ctx) + return STATUS_INSUFFICIENT_RESOURCES; + RtlZeroMemory(file_ctx, sizeof(*file_ctx)); - KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock); - LONG flags = InterlockedGet(&ctx->Flags); - if ((status = STATUS_DELETE_PENDING, !(flags & TUN_FLAGS_PRESENT))) - goto cleanup_ExReleaseSpinLockShared; + KIRQL irql = ExAcquireSpinLockShared(&ctx->TransitionLock); + LONG flags = InterlockedGet(&ctx->Flags); + if ((status = STATUS_DELETE_PENDING, !(flags & TUN_FLAGS_PRESENT))) + goto cleanup_ExReleaseSpinLockShared; - IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); - if (!NT_SUCCESS(status = IoAcquireRemoveLock(&ctx->Device.RemoveLock, stack->FileObject))) - goto cleanup_ExReleaseSpinLockShared; - stack->FileObject->FsContext = file_ctx; + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); + if (!NT_SUCCESS(status = IoAcquireRemoveLock(&ctx->Device.RemoveLock, stack->FileObject))) + goto cleanup_ExReleaseSpinLockShared; + stack->FileObject->FsContext = file_ctx; - if (InterlockedIncrement64(&ctx->Device.RefCount) == 1) - TunIndicateStatus(ctx->MiniportAdapterHandle, MediaConnectStateConnected); + if (InterlockedIncrement64(&ctx->Device.RefCount) == 1) + TunIndicateStatus(ctx->MiniportAdapterHandle, MediaConnectStateConnected); - status = STATUS_SUCCESS; + status = STATUS_SUCCESS; cleanup_ExReleaseSpinLockShared: - ExReleaseSpinLockShared(&ctx->TransitionLock, irql); - TunCompleteRequest(ctx, Irp, status, IO_NO_INCREMENT); - if (!NT_SUCCESS(status)) - ExFreePoolWithTag(file_ctx, TUN_HTONL(TUN_MEMORY_TAG)); - return status; + ExReleaseSpinLockShared(&ctx->TransitionLock, irql); + TunCompleteRequest(ctx, Irp, status, IO_NO_INCREMENT); + if (!NT_SUCCESS(status)) + ExFreePoolWithTag(file_ctx, TUN_HTONL(TUN_MEMORY_TAG)); + return status; } static DRIVER_DISPATCH TunDispatch; _Use_decl_annotations_ -static NTSTATUS TunDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp) +static NTSTATUS +TunDispatch(DEVICE_OBJECT *DeviceObject, IRP *Irp) { - NTSTATUS status; - KIRQL irql; + NTSTATUS status; + KIRQL irql; - Irp->IoStatus.Information = 0; + Irp->IoStatus.Information = 0; - TUN_CTX *ctx = NdisGetDeviceReservedExtension(DeviceObject); - if (!ctx) { - status = STATUS_INVALID_HANDLE; - goto cleanup_complete_req; - } + TUN_CTX *ctx = NdisGetDeviceReservedExtension(DeviceObject); + if (!ctx) + { + status = STATUS_INVALID_HANDLE; + goto cleanup_complete_req; + } - IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); - switch (stack->MajorFunction) { - case IRP_MJ_READ: - if (!NT_SUCCESS(status = IoAcquireRemoveLock(&ctx->Device.RemoveLock, Irp))) - goto cleanup_complete_req; - return TunDispatchRead(ctx, Irp); + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); + switch (stack->MajorFunction) + { + case IRP_MJ_READ: + if (!NT_SUCCESS(status = IoAcquireRemoveLock(&ctx->Device.RemoveLock, Irp))) + goto cleanup_complete_req; + return TunDispatchRead(ctx, Irp); - case IRP_MJ_WRITE: - if (!NT_SUCCESS(status = IoAcquireRemoveLock(&ctx->Device.RemoveLock, Irp))) - goto cleanup_complete_req; - return TunDispatchWrite(ctx, Irp); + case IRP_MJ_WRITE: + if (!NT_SUCCESS(status = IoAcquireRemoveLock(&ctx->Device.RemoveLock, Irp))) + goto cleanup_complete_req; + return TunDispatchWrite(ctx, Irp); - case IRP_MJ_CREATE: - if (!NT_SUCCESS(status = IoAcquireRemoveLock(&ctx->Device.RemoveLock, Irp))) - goto cleanup_complete_req; - return TunDispatchCreate(ctx, Irp); + case IRP_MJ_CREATE: + if (!NT_SUCCESS(status = IoAcquireRemoveLock(&ctx->Device.RemoveLock, Irp))) + goto cleanup_complete_req; + return TunDispatchCreate(ctx, Irp); - case IRP_MJ_CLOSE: - irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock); - ASSERT(InterlockedGet64(&ctx->Device.RefCount) > 0); - BOOLEAN last_handle = InterlockedDecrement64(&ctx->Device.RefCount) <= 0; - ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql); - if (last_handle) { - NDIS_HANDLE handle = InterlockedGetPointer(&ctx->MiniportAdapterHandle); - if (handle) - TunIndicateStatus(handle, MediaConnectStateDisconnected); - TunQueueClear(ctx, NDIS_STATUS_MEDIA_DISCONNECTED); - } - TUN_FILE_CTX *file_ctx = (TUN_FILE_CTX *)stack->FileObject->FsContext; - TunUnmapUbuffer(&file_ctx->ReadBuffer); - TunUnmapUbuffer(&file_ctx->WriteBuffer); - ExFreePoolWithTag(file_ctx, TUN_HTONL(TUN_MEMORY_TAG)); - IoReleaseRemoveLock(&ctx->Device.RemoveLock, stack->FileObject); + case IRP_MJ_CLOSE: + irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock); + ASSERT(InterlockedGet64(&ctx->Device.RefCount) > 0); + BOOLEAN last_handle = InterlockedDecrement64(&ctx->Device.RefCount) <= 0; + ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql); + if (last_handle) + { + NDIS_HANDLE handle = InterlockedGetPointer(&ctx->MiniportAdapterHandle); + if (handle) + TunIndicateStatus(handle, MediaConnectStateDisconnected); + TunQueueClear(ctx, NDIS_STATUS_MEDIA_DISCONNECTED); + } + TUN_FILE_CTX *file_ctx = (TUN_FILE_CTX *)stack->FileObject->FsContext; + TunUnmapUbuffer(&file_ctx->ReadBuffer); + TunUnmapUbuffer(&file_ctx->WriteBuffer); + ExFreePoolWithTag(file_ctx, TUN_HTONL(TUN_MEMORY_TAG)); + IoReleaseRemoveLock(&ctx->Device.RemoveLock, stack->FileObject); - status = STATUS_SUCCESS; - goto cleanup_complete_req; + status = STATUS_SUCCESS; + goto cleanup_complete_req; - case IRP_MJ_CLEANUP: - for (IRP *pending_irp; (pending_irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, stack->FileObject)) != NULL; ) - TunCompleteRequest(ctx, pending_irp, STATUS_CANCELLED, IO_NO_INCREMENT); + case IRP_MJ_CLEANUP: + for (IRP *pending_irp; + (pending_irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, stack->FileObject)) != NULL;) + TunCompleteRequest(ctx, pending_irp, STATUS_CANCELLED, IO_NO_INCREMENT); - status = STATUS_SUCCESS; - goto cleanup_complete_req; + status = STATUS_SUCCESS; + goto cleanup_complete_req; - default: - status = STATUS_INVALID_PARAMETER; - goto cleanup_complete_req; - } + default: + status = STATUS_INVALID_PARAMETER; + goto cleanup_complete_req; + } cleanup_complete_req: - Irp->IoStatus.Status = status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return status; + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return status; } -_Dispatch_type_(IRP_MJ_PNP) -static DRIVER_DISPATCH TunDispatchPnP; +_Dispatch_type_(IRP_MJ_PNP) static DRIVER_DISPATCH TunDispatchPnP; _Use_decl_annotations_ -static NTSTATUS TunDispatchPnP(DEVICE_OBJECT *DeviceObject, IRP *Irp) +static NTSTATUS +TunDispatchPnP(DEVICE_OBJECT *DeviceObject, IRP *Irp) { - IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); - if (stack->MajorFunction == IRP_MJ_PNP) { - #pragma warning(suppress: 28175) - TUN_CTX *ctx = DeviceObject->Reserved; + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); + if (stack->MajorFunction == IRP_MJ_PNP) + { +#pragma warning(suppress : 28175) + TUN_CTX *ctx = DeviceObject->Reserved; - switch (stack->MinorFunction) { - case IRP_MN_QUERY_REMOVE_DEVICE: - case IRP_MN_SURPRISE_REMOVAL: - KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock); - InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_PRESENT); - ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql); - TunQueueClear(ctx, NDIS_STATUS_ADAPTER_REMOVED); - break; + switch (stack->MinorFunction) + { + case IRP_MN_QUERY_REMOVE_DEVICE: + case IRP_MN_SURPRISE_REMOVAL: + KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock); + InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_PRESENT); + ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql); + TunQueueClear(ctx, NDIS_STATUS_ADAPTER_REMOVED); + break; - case IRP_MN_CANCEL_REMOVE_DEVICE: - InterlockedOr(&ctx->Flags, TUN_FLAGS_PRESENT); - break; - } - } + case IRP_MN_CANCEL_REMOVE_DEVICE: + InterlockedOr(&ctx->Flags, TUN_FLAGS_PRESENT); + break; + } + } - return NdisDispatchPnP(DeviceObject, Irp); + return NdisDispatchPnP(DeviceObject, Irp); } static MINIPORT_RESTART TunRestart; _Use_decl_annotations_ -static NDIS_STATUS TunRestart(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters) +static NDIS_STATUS +TunRestart(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_RESTART_PARAMETERS MiniportRestartParameters) { - TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; + TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; - InterlockedExchange64(&ctx->ActiveNBLCount, 1); - InterlockedOr(&ctx->Flags, TUN_FLAGS_RUNNING); + InterlockedExchange64(&ctx->ActiveNBLCount, 1); + InterlockedOr(&ctx->Flags, TUN_FLAGS_RUNNING); - return NDIS_STATUS_SUCCESS; + return NDIS_STATUS_SUCCESS; } static MINIPORT_PAUSE TunPause; _Use_decl_annotations_ -static NDIS_STATUS TunPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters) +static NDIS_STATUS +TunPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters) { - TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; + TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; - KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock); - InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_RUNNING); - ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql); - TunQueueClear(ctx, NDIS_STATUS_PAUSED); + KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock); + InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_RUNNING); + ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql); + TunQueueClear(ctx, NDIS_STATUS_PAUSED); - return TunCompletePause(ctx, FALSE); + return TunCompletePause(ctx, FALSE); } static MINIPORT_DEVICE_PNP_EVENT_NOTIFY TunDevicePnPEventNotify; _Use_decl_annotations_ -static void TunDevicePnPEventNotify(NDIS_HANDLE MiniportAdapterContext, PNET_DEVICE_PNP_EVENT NetDevicePnPEvent) +static void +TunDevicePnPEventNotify(NDIS_HANDLE MiniportAdapterContext, PNET_DEVICE_PNP_EVENT NetDevicePnPEvent) { } static MINIPORT_INITIALIZE TunInitializeEx; _Use_decl_annotations_ -static NDIS_STATUS TunInitializeEx(NDIS_HANDLE MiniportAdapterHandle, NDIS_HANDLE MiniportDriverContext, PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters) +static NDIS_STATUS +TunInitializeEx( + NDIS_HANDLE MiniportAdapterHandle, + NDIS_HANDLE MiniportDriverContext, + PNDIS_MINIPORT_INIT_PARAMETERS MiniportInitParameters) { - NDIS_STATUS status; + NDIS_STATUS status; - if (!MiniportAdapterHandle) - return NDIS_STATUS_FAILURE; + if (!MiniportAdapterHandle) + return NDIS_STATUS_FAILURE; - /* Register device first. - * Having only one device per adapter allows us to store adapter context inside device extension. */ - WCHAR device_name[sizeof(L"\\Device\\" TUN_DEVICE_NAME) / sizeof(WCHAR) + 10/*MAXULONG as string*/] = { 0 }; - UNICODE_STRING unicode_device_name; - TunInitUnicodeString(&unicode_device_name, device_name); - RtlUnicodeStringPrintf(&unicode_device_name, L"\\Device\\" TUN_DEVICE_NAME, (ULONG)MiniportInitParameters->NetLuid.Info.NetLuidIndex); + /* Register device first. + * Having only one device per adapter allows us to store adapter context inside device extension. */ + WCHAR device_name[sizeof(L"\\Device\\" TUN_DEVICE_NAME) / sizeof(WCHAR) + 10 /*MAXULONG as string*/] = {0}; + UNICODE_STRING unicode_device_name; + TunInitUnicodeString(&unicode_device_name, device_name); + RtlUnicodeStringPrintf( + &unicode_device_name, L"\\Device\\" TUN_DEVICE_NAME, (ULONG)MiniportInitParameters->NetLuid.Info.NetLuidIndex); - WCHAR symbolic_name[sizeof(L"\\DosDevices\\" TUN_DEVICE_NAME) / sizeof(WCHAR) + 10/*MAXULONG as string*/] = { 0 }; - UNICODE_STRING unicode_symbolic_name; - TunInitUnicodeString(&unicode_symbolic_name, symbolic_name); - RtlUnicodeStringPrintf(&unicode_symbolic_name, L"\\DosDevices\\" TUN_DEVICE_NAME, (ULONG)MiniportInitParameters->NetLuid.Info.NetLuidIndex); + WCHAR symbolic_name[sizeof(L"\\DosDevices\\" TUN_DEVICE_NAME) / sizeof(WCHAR) + 10 /*MAXULONG as string*/] = {0}; + UNICODE_STRING unicode_symbolic_name; + TunInitUnicodeString(&unicode_symbolic_name, symbolic_name); + RtlUnicodeStringPrintf( + &unicode_symbolic_name, + L"\\DosDevices\\" TUN_DEVICE_NAME, + (ULONG)MiniportInitParameters->NetLuid.Info.NetLuidIndex); - static PDRIVER_DISPATCH dispatch_table[IRP_MJ_MAXIMUM_FUNCTION + 1] = { - TunDispatch, /* IRP_MJ_CREATE */ - NULL, /* IRP_MJ_CREATE_NAMED_PIPE */ - TunDispatch, /* IRP_MJ_CLOSE */ - TunDispatch, /* IRP_MJ_READ */ - TunDispatch, /* IRP_MJ_WRITE */ - NULL, /* IRP_MJ_QUERY_INFORMATION */ - NULL, /* IRP_MJ_SET_INFORMATION */ - NULL, /* IRP_MJ_QUERY_EA */ - NULL, /* IRP_MJ_SET_EA */ - NULL, /* IRP_MJ_FLUSH_BUFFERS */ - NULL, /* IRP_MJ_QUERY_VOLUME_INFORMATION */ - NULL, /* IRP_MJ_SET_VOLUME_INFORMATION */ - NULL, /* IRP_MJ_DIRECTORY_CONTROL */ - NULL, /* IRP_MJ_FILE_SYSTEM_CONTROL */ - NULL, /* IRP_MJ_DEVICE_CONTROL */ - NULL, /* IRP_MJ_INTERNAL_DEVICE_CONTROL */ - NULL, /* IRP_MJ_SHUTDOWN */ - NULL, /* IRP_MJ_LOCK_CONTROL */ - TunDispatch, /* IRP_MJ_CLEANUP */ - }; - NDIS_DEVICE_OBJECT_ATTRIBUTES t = { - .Header = { - .Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES, - .Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1, - .Size = NDIS_SIZEOF_DEVICE_OBJECT_ATTRIBUTES_REVISION_1 - }, - .DeviceName = &unicode_device_name, - .SymbolicName = &unicode_symbolic_name, - .MajorFunctions = dispatch_table, - .ExtensionSize = sizeof(TUN_CTX), - .DefaultSDDLString = &SDDL_DEVOBJ_SYS_ALL /* Kernel, and SYSTEM: full control. Others: none */ - }; - NDIS_HANDLE handle; - DEVICE_OBJECT *object; - if (!NT_SUCCESS(status = NdisRegisterDeviceEx(NdisMiniportDriverHandle, &t, &object, &handle))) - return NDIS_STATUS_FAILURE; + static PDRIVER_DISPATCH dispatch_table[IRP_MJ_MAXIMUM_FUNCTION + 1] = { + TunDispatch, /* IRP_MJ_CREATE */ + NULL, /* IRP_MJ_CREATE_NAMED_PIPE */ + TunDispatch, /* IRP_MJ_CLOSE */ + TunDispatch, /* IRP_MJ_READ */ + TunDispatch, /* IRP_MJ_WRITE */ + NULL, /* IRP_MJ_QUERY_INFORMATION */ + NULL, /* IRP_MJ_SET_INFORMATION */ + NULL, /* IRP_MJ_QUERY_EA */ + NULL, /* IRP_MJ_SET_EA */ + NULL, /* IRP_MJ_FLUSH_BUFFERS */ + NULL, /* IRP_MJ_QUERY_VOLUME_INFORMATION */ + NULL, /* IRP_MJ_SET_VOLUME_INFORMATION */ + NULL, /* IRP_MJ_DIRECTORY_CONTROL */ + NULL, /* IRP_MJ_FILE_SYSTEM_CONTROL */ + NULL, /* IRP_MJ_DEVICE_CONTROL */ + NULL, /* IRP_MJ_INTERNAL_DEVICE_CONTROL */ + NULL, /* IRP_MJ_SHUTDOWN */ + NULL, /* IRP_MJ_LOCK_CONTROL */ + TunDispatch, /* IRP_MJ_CLEANUP */ + }; + NDIS_DEVICE_OBJECT_ATTRIBUTES t = { + .Header = {.Type = NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES, + .Revision = NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1, + .Size = NDIS_SIZEOF_DEVICE_OBJECT_ATTRIBUTES_REVISION_1}, + .DeviceName = &unicode_device_name, + .SymbolicName = &unicode_symbolic_name, + .MajorFunctions = dispatch_table, + .ExtensionSize = sizeof(TUN_CTX), + .DefaultSDDLString = &SDDL_DEVOBJ_SYS_ALL /* Kernel, and SYSTEM: full control. Others: none */ + }; + NDIS_HANDLE handle; + DEVICE_OBJECT *object; + if (!NT_SUCCESS(status = NdisRegisterDeviceEx(NdisMiniportDriverHandle, &t, &object, &handle))) + return NDIS_STATUS_FAILURE; - object->Flags &= ~(DO_BUFFERED_IO | DO_DIRECT_IO); + object->Flags &= ~(DO_BUFFERED_IO | DO_DIRECT_IO); - TUN_CTX *ctx = NdisGetDeviceReservedExtension(object); - if (!ctx) { - status = NDIS_STATUS_FAILURE; - goto cleanup_NdisDeregisterDeviceEx; - } + TUN_CTX *ctx = NdisGetDeviceReservedExtension(object); + if (!ctx) + { + status = NDIS_STATUS_FAILURE; + goto cleanup_NdisDeregisterDeviceEx; + } - /* Jason reverse engineered and found NdisWdfGetAdapterContextFromAdapterHandle. - * Switch from device object's "Reserved" to this when we drop support for Windows 8.1. */ - DEVICE_OBJECT *functional_device; - NdisMGetDeviceProperty(MiniportAdapterHandle, NULL, &functional_device, NULL, NULL, NULL); + /* Jason reverse engineered and found NdisWdfGetAdapterContextFromAdapterHandle. + * Switch from device object's "Reserved" to this when we drop support for Windows 8.1. */ + DEVICE_OBJECT *functional_device; + NdisMGetDeviceProperty(MiniportAdapterHandle, NULL, &functional_device, NULL, NULL, NULL); - #pragma warning(suppress: 28175) - ASSERT(!functional_device->Reserved); - #pragma warning(suppress: 28175) - functional_device->Reserved = ctx; +#pragma warning(suppress : 28175) + ASSERT(!functional_device->Reserved); +#pragma warning(suppress : 28175) + functional_device->Reserved = ctx; - NdisZeroMemory(ctx, sizeof(*ctx)); - ctx->MiniportAdapterHandle = MiniportAdapterHandle; + NdisZeroMemory(ctx, sizeof(*ctx)); + ctx->MiniportAdapterHandle = MiniportAdapterHandle; - ctx->Statistics.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; - ctx->Statistics.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1; - ctx->Statistics.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1; - ctx->Statistics.SupportedStatistics = - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV | - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV | - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV | - NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV | - NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS | - NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR | - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR | - NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS | - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV | - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV | - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV | - NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT | - NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT; + ctx->Statistics.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; + ctx->Statistics.Header.Revision = NDIS_STATISTICS_INFO_REVISION_1; + ctx->Statistics.Header.Size = NDIS_SIZEOF_STATISTICS_INFO_REVISION_1; + ctx->Statistics.SupportedStatistics = + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV | + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV | NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV | + NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS | NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR | + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT | + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT | NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT | + NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR | NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS | + NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV | NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV | + NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV | NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT | + NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT | NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT; - ctx->Device.Handle = handle; - ctx->Device.Object = object; - IoInitializeRemoveLock(&ctx->Device.RemoveLock, TUN_HTONL(TUN_MEMORY_TAG), 0, 0); - KeInitializeSpinLock(&ctx->Device.ReadQueue.Lock); - IoCsqInitializeEx(&ctx->Device.ReadQueue.Csq, - TunCsqInsertIrpEx, - TunCsqRemoveIrp, - TunCsqPeekNextIrp, - TunCsqAcquireLock, - TunCsqReleaseLock, - TunCsqCompleteCanceledIrp); - InitializeListHead(&ctx->Device.ReadQueue.List); + ctx->Device.Handle = handle; + ctx->Device.Object = object; + IoInitializeRemoveLock(&ctx->Device.RemoveLock, TUN_HTONL(TUN_MEMORY_TAG), 0, 0); + KeInitializeSpinLock(&ctx->Device.ReadQueue.Lock); + IoCsqInitializeEx( + &ctx->Device.ReadQueue.Csq, + TunCsqInsertIrpEx, + TunCsqRemoveIrp, + TunCsqPeekNextIrp, + TunCsqAcquireLock, + TunCsqReleaseLock, + TunCsqCompleteCanceledIrp); + InitializeListHead(&ctx->Device.ReadQueue.List); - KeInitializeSpinLock(&ctx->PacketQueue.Lock); + KeInitializeSpinLock(&ctx->PacketQueue.Lock); - NET_BUFFER_LIST_POOL_PARAMETERS nbl_pool_param = { - .Header = { - .Type = NDIS_OBJECT_TYPE_DEFAULT, - .Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1, - .Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1 - }, - .ProtocolId = NDIS_PROTOCOL_ID_DEFAULT, - .fAllocateNetBuffer = TRUE, - .PoolTag = TUN_HTONL(TUN_MEMORY_TAG) - }; - #pragma warning(suppress: 6014) /* Leaking memory 'ctx->NBLPool'. Note: 'ctx->NBLPool' is freed in TunHaltEx; or on failure. */ - ctx->NBLPool = NdisAllocateNetBufferListPool(MiniportAdapterHandle, &nbl_pool_param); - if (!ctx->NBLPool) { - status = NDIS_STATUS_FAILURE; - goto cleanup_NdisDeregisterDeviceEx; - } + NET_BUFFER_LIST_POOL_PARAMETERS nbl_pool_param = { + .Header = {.Type = NDIS_OBJECT_TYPE_DEFAULT, + .Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1, + .Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1}, + .ProtocolId = NDIS_PROTOCOL_ID_DEFAULT, + .fAllocateNetBuffer = TRUE, + .PoolTag = TUN_HTONL(TUN_MEMORY_TAG)}; +#pragma warning( \ + suppress : 6014) /* Leaking memory 'ctx->NBLPool'. Note: 'ctx->NBLPool' is freed in TunHaltEx; or on failure. */ + ctx->NBLPool = NdisAllocateNetBufferListPool(MiniportAdapterHandle, &nbl_pool_param); + if (!ctx->NBLPool) + { + status = NDIS_STATUS_FAILURE; + goto cleanup_NdisDeregisterDeviceEx; + } - NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES attr = { - .Header = { - .Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES, - .Revision = NdisVersion < NDIS_RUNTIME_VERSION_630 ? NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1 : NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_2, - .Size = NdisVersion < NDIS_RUNTIME_VERSION_630 ? NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1 : NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_2 - }, - .AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND | NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK, - .InterfaceType = NdisInterfaceInternal, - .MiniportAdapterContext = ctx - }; - if (!NT_SUCCESS(status = NdisMSetMiniportAttributes(MiniportAdapterHandle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&attr))) { - status = NDIS_STATUS_FAILURE; - goto cleanup_NdisFreeNetBufferListPool; - } + NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES attr = { + .Header = {.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES, + .Revision = NdisVersion < NDIS_RUNTIME_VERSION_630 + ? NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1 + : NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_2, + .Size = NdisVersion < NDIS_RUNTIME_VERSION_630 + ? NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1 + : NDIS_SIZEOF_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_2}, + .AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND | NDIS_MINIPORT_ATTRIBUTES_SURPRISE_REMOVE_OK, + .InterfaceType = NdisInterfaceInternal, + .MiniportAdapterContext = ctx}; + if (!NT_SUCCESS( + status = NdisMSetMiniportAttributes(MiniportAdapterHandle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&attr))) + { + status = NDIS_STATUS_FAILURE; + goto cleanup_NdisFreeNetBufferListPool; + } - NDIS_PM_CAPABILITIES pmcap = { - .Header = { - .Type = NDIS_OBJECT_TYPE_DEFAULT, - .Revision = NdisVersion < NDIS_RUNTIME_VERSION_630 ? NDIS_PM_CAPABILITIES_REVISION_1 : NDIS_PM_CAPABILITIES_REVISION_2, - .Size = NdisVersion < NDIS_RUNTIME_VERSION_630 ? NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_1 : NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_2 - }, - .MinMagicPacketWakeUp = NdisDeviceStateUnspecified, - .MinPatternWakeUp = NdisDeviceStateUnspecified, - .MinLinkChangeWakeUp = NdisDeviceStateUnspecified - }; - static NDIS_OID suported_oids[] = { - OID_GEN_MAXIMUM_TOTAL_SIZE, - OID_GEN_CURRENT_LOOKAHEAD, - OID_GEN_TRANSMIT_BUFFER_SPACE, - OID_GEN_RECEIVE_BUFFER_SPACE, - OID_GEN_TRANSMIT_BLOCK_SIZE, - OID_GEN_RECEIVE_BLOCK_SIZE, - OID_GEN_VENDOR_DESCRIPTION, - OID_GEN_VENDOR_ID, - OID_GEN_VENDOR_DRIVER_VERSION, - OID_GEN_XMIT_OK, - OID_GEN_RCV_OK, - OID_GEN_CURRENT_PACKET_FILTER, - OID_GEN_STATISTICS, - OID_GEN_INTERRUPT_MODERATION, - OID_GEN_LINK_PARAMETERS, - OID_PNP_SET_POWER, - OID_PNP_QUERY_POWER - }; - NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gen = { - .Header = { - .Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES, - .Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2, - .Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2 - }, - .MediaType = NdisMediumIP, - .PhysicalMediumType = NdisPhysicalMediumUnspecified, - .MtuSize = TUN_EXCH_MAX_IP_PACKET_SIZE, - .MaxXmitLinkSpeed = TUN_LINK_SPEED, - .MaxRcvLinkSpeed = TUN_LINK_SPEED, - .RcvLinkSpeed = TUN_LINK_SPEED, - .XmitLinkSpeed = TUN_LINK_SPEED, - .MediaConnectState = MediaConnectStateDisconnected, - .LookaheadSize = TUN_EXCH_MAX_IP_PACKET_SIZE, - .MacOptions = - NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | - NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | - NDIS_MAC_OPTION_NO_LOOPBACK, - .SupportedPacketFilters = - NDIS_PACKET_TYPE_DIRECTED | - NDIS_PACKET_TYPE_ALL_MULTICAST | - NDIS_PACKET_TYPE_BROADCAST | - NDIS_PACKET_TYPE_ALL_LOCAL | - NDIS_PACKET_TYPE_ALL_FUNCTIONAL, - .AccessType = NET_IF_ACCESS_BROADCAST, - .DirectionType = NET_IF_DIRECTION_SENDRECEIVE, - .ConnectionType = NET_IF_CONNECTION_DEDICATED, - .IfType = IF_TYPE_PROP_VIRTUAL, - .IfConnectorPresent = FALSE, - .SupportedStatistics = ctx->Statistics.SupportedStatistics, - .SupportedPauseFunctions = NdisPauseFunctionsUnsupported, - .AutoNegotiationFlags = - NDIS_LINK_STATE_XMIT_LINK_SPEED_AUTO_NEGOTIATED | - NDIS_LINK_STATE_RCV_LINK_SPEED_AUTO_NEGOTIATED | - NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED | - NDIS_LINK_STATE_PAUSE_FUNCTIONS_AUTO_NEGOTIATED, - .SupportedOidList = suported_oids, - .SupportedOidListLength = sizeof(suported_oids), - .PowerManagementCapabilitiesEx = &pmcap - }; - if (!NT_SUCCESS(status = NdisMSetMiniportAttributes(MiniportAdapterHandle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gen))) { - status = NDIS_STATUS_FAILURE; - goto cleanup_NdisFreeNetBufferListPool; - } + NDIS_PM_CAPABILITIES pmcap = { + .Header = {.Type = NDIS_OBJECT_TYPE_DEFAULT, + .Revision = NdisVersion < NDIS_RUNTIME_VERSION_630 ? NDIS_PM_CAPABILITIES_REVISION_1 + : NDIS_PM_CAPABILITIES_REVISION_2, + .Size = NdisVersion < NDIS_RUNTIME_VERSION_630 ? NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_1 + : NDIS_SIZEOF_NDIS_PM_CAPABILITIES_REVISION_2}, + .MinMagicPacketWakeUp = NdisDeviceStateUnspecified, + .MinPatternWakeUp = NdisDeviceStateUnspecified, + .MinLinkChangeWakeUp = NdisDeviceStateUnspecified}; + static NDIS_OID suported_oids[] = {OID_GEN_MAXIMUM_TOTAL_SIZE, + OID_GEN_CURRENT_LOOKAHEAD, + OID_GEN_TRANSMIT_BUFFER_SPACE, + OID_GEN_RECEIVE_BUFFER_SPACE, + OID_GEN_TRANSMIT_BLOCK_SIZE, + OID_GEN_RECEIVE_BLOCK_SIZE, + OID_GEN_VENDOR_DESCRIPTION, + OID_GEN_VENDOR_ID, + OID_GEN_VENDOR_DRIVER_VERSION, + OID_GEN_XMIT_OK, + OID_GEN_RCV_OK, + OID_GEN_CURRENT_PACKET_FILTER, + OID_GEN_STATISTICS, + OID_GEN_INTERRUPT_MODERATION, + OID_GEN_LINK_PARAMETERS, + OID_PNP_SET_POWER, + OID_PNP_QUERY_POWER}; + NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES gen = { + .Header = {.Type = NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES, + .Revision = NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2, + .Size = NDIS_SIZEOF_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_2}, + .MediaType = NdisMediumIP, + .PhysicalMediumType = NdisPhysicalMediumUnspecified, + .MtuSize = TUN_EXCH_MAX_IP_PACKET_SIZE, + .MaxXmitLinkSpeed = TUN_LINK_SPEED, + .MaxRcvLinkSpeed = TUN_LINK_SPEED, + .RcvLinkSpeed = TUN_LINK_SPEED, + .XmitLinkSpeed = TUN_LINK_SPEED, + .MediaConnectState = MediaConnectStateDisconnected, + .LookaheadSize = TUN_EXCH_MAX_IP_PACKET_SIZE, + .MacOptions = + NDIS_MAC_OPTION_TRANSFERS_NOT_PEND | NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA | NDIS_MAC_OPTION_NO_LOOPBACK, + .SupportedPacketFilters = NDIS_PACKET_TYPE_DIRECTED | NDIS_PACKET_TYPE_ALL_MULTICAST | + NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_ALL_LOCAL | + NDIS_PACKET_TYPE_ALL_FUNCTIONAL, + .AccessType = NET_IF_ACCESS_BROADCAST, + .DirectionType = NET_IF_DIRECTION_SENDRECEIVE, + .ConnectionType = NET_IF_CONNECTION_DEDICATED, + .IfType = IF_TYPE_PROP_VIRTUAL, + .IfConnectorPresent = FALSE, + .SupportedStatistics = ctx->Statistics.SupportedStatistics, + .SupportedPauseFunctions = NdisPauseFunctionsUnsupported, + .AutoNegotiationFlags = + NDIS_LINK_STATE_XMIT_LINK_SPEED_AUTO_NEGOTIATED | NDIS_LINK_STATE_RCV_LINK_SPEED_AUTO_NEGOTIATED | + NDIS_LINK_STATE_DUPLEX_AUTO_NEGOTIATED | NDIS_LINK_STATE_PAUSE_FUNCTIONS_AUTO_NEGOTIATED, + .SupportedOidList = suported_oids, + .SupportedOidListLength = sizeof(suported_oids), + .PowerManagementCapabilitiesEx = &pmcap}; + if (!NT_SUCCESS( + status = NdisMSetMiniportAttributes(MiniportAdapterHandle, (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&gen))) + { + status = NDIS_STATUS_FAILURE; + goto cleanup_NdisFreeNetBufferListPool; + } - /* A miniport driver can call NdisMIndicateStatusEx after setting its - * registration attributes even if the driver is still in the context - * of the MiniportInitializeEx function. - */ - TunIndicateStatus(MiniportAdapterHandle, MediaConnectStateDisconnected); - InterlockedIncrement64(&TunAdapterCount); - InterlockedOr(&ctx->Flags, TUN_FLAGS_PRESENT); - return NDIS_STATUS_SUCCESS; + /* A miniport driver can call NdisMIndicateStatusEx after setting its + * registration attributes even if the driver is still in the context + * of the MiniportInitializeEx function. + */ + TunIndicateStatus(MiniportAdapterHandle, MediaConnectStateDisconnected); + InterlockedIncrement64(&TunAdapterCount); + InterlockedOr(&ctx->Flags, TUN_FLAGS_PRESENT); + return NDIS_STATUS_SUCCESS; cleanup_NdisFreeNetBufferListPool: - NdisFreeNetBufferListPool(ctx->NBLPool); + NdisFreeNetBufferListPool(ctx->NBLPool); cleanup_NdisDeregisterDeviceEx: - NdisDeregisterDeviceEx(handle); - return status; + NdisDeregisterDeviceEx(handle); + return status; } _IRQL_requires_max_(PASSIVE_LEVEL) -static NTSTATUS TunDeviceSetDenyAllDacl(_In_ DEVICE_OBJECT *device_object) +static NTSTATUS +TunDeviceSetDenyAllDacl(_In_ DEVICE_OBJECT *device_object) { - NTSTATUS status; - SECURITY_DESCRIPTOR sd; - ACL acl; - HANDLE handle; + NTSTATUS status; + SECURITY_DESCRIPTOR sd; + ACL acl; + HANDLE handle; - if (!NT_SUCCESS(status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))) - return status; - if (!NT_SUCCESS(status = RtlCreateAcl(&acl, sizeof(ACL), ACL_REVISION))) - return status; - if (!NT_SUCCESS(status = RtlSetDaclSecurityDescriptor(&sd, TRUE, &acl, FALSE))) - return status; - if (!NT_SUCCESS(status = ObOpenObjectByPointer(device_object, OBJ_KERNEL_HANDLE, NULL, WRITE_DAC, *IoDeviceObjectType, KernelMode, &handle))) - return status; + if (!NT_SUCCESS(status = RtlCreateSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))) + return status; + if (!NT_SUCCESS(status = RtlCreateAcl(&acl, sizeof(ACL), ACL_REVISION))) + return status; + if (!NT_SUCCESS(status = RtlSetDaclSecurityDescriptor(&sd, TRUE, &acl, FALSE))) + return status; + if (!NT_SUCCESS( + status = ObOpenObjectByPointer( + device_object, OBJ_KERNEL_HANDLE, NULL, WRITE_DAC, *IoDeviceObjectType, KernelMode, &handle))) + return status; - status = ZwSetSecurityObject(handle, DACL_SECURITY_INFORMATION, &sd); + status = ZwSetSecurityObject(handle, DACL_SECURITY_INFORMATION, &sd); - ZwClose(handle); - return status; + ZwClose(handle); + return status; } _IRQL_requires_max_(PASSIVE_LEVEL) -static void TunForceHandlesClosed(_Inout_ TUN_CTX *ctx) +static void +TunForceHandlesClosed(_Inout_ TUN_CTX *ctx) { - NTSTATUS status; - PEPROCESS process; - KAPC_STATE apc_state; - PVOID object = NULL; - ULONG verifier_flags = 0; - OBJECT_HANDLE_INFORMATION handle_info; - SYSTEM_HANDLE_INFORMATION_EX *table = NULL; + NTSTATUS status; + PEPROCESS process; + KAPC_STATE apc_state; + PVOID object = NULL; + ULONG verifier_flags = 0; + OBJECT_HANDLE_INFORMATION handle_info; + SYSTEM_HANDLE_INFORMATION_EX *table = NULL; - MmIsVerifierEnabled(&verifier_flags); + MmIsVerifierEnabled(&verifier_flags); - for (ULONG size = 0, req; (status = ZwQuerySystemInformation(SystemExtendedHandleInformation, table, size, &req)) == STATUS_INFO_LENGTH_MISMATCH; size = req) { - if (table) - ExFreePoolWithTag(table, TUN_HTONL(TUN_MEMORY_TAG)); - table = ExAllocatePoolWithTag(PagedPool, req, TUN_HTONL(TUN_MEMORY_TAG)); - if (!table) - return; - } - if (!NT_SUCCESS(status) || !table) - goto out; + for (ULONG size = 0, req; (status = ZwQuerySystemInformation(SystemExtendedHandleInformation, table, size, &req)) == + STATUS_INFO_LENGTH_MISMATCH; + size = req) + { + if (table) + ExFreePoolWithTag(table, TUN_HTONL(TUN_MEMORY_TAG)); + table = ExAllocatePoolWithTag(PagedPool, req, TUN_HTONL(TUN_MEMORY_TAG)); + if (!table) + return; + } + if (!NT_SUCCESS(status) || !table) + goto out; - for (ULONG_PTR i = 0; i < table->NumberOfHandles; ++i) { - FILE_OBJECT *file = table->Handles[i].Object; //XXX: We should probably first look at table->Handles[i].ObjectTypeIndex, but the value changes lots between NT versions. - if (!file || file->Type != 5 || file->DeviceObject != ctx->Device.Object) - continue; - status = PsLookupProcessByProcessId(table->Handles[i].UniqueProcessId, &process); - if (!NT_SUCCESS(status)) - continue; - KeStackAttachProcess(process, &apc_state); - if (!verifier_flags) - status = ObReferenceObjectByHandle(table->Handles[i].HandleValue, 0, NULL, UserMode, &object, &handle_info); - if (NT_SUCCESS(status)) { - if (verifier_flags || object == file) - ObCloseHandle(table->Handles[i].HandleValue, UserMode); - if (!verifier_flags) - ObfDereferenceObject(object); - } - KeUnstackDetachProcess(&apc_state); - ObfDereferenceObject(process); - } + for (ULONG_PTR i = 0; i < table->NumberOfHandles; ++i) + { + FILE_OBJECT *file = + table->Handles[i].Object; // XXX: We should probably first look at table->Handles[i].ObjectTypeIndex, but + // the value changes lots between NT versions. + if (!file || file->Type != 5 || file->DeviceObject != ctx->Device.Object) + continue; + status = PsLookupProcessByProcessId(table->Handles[i].UniqueProcessId, &process); + if (!NT_SUCCESS(status)) + continue; + KeStackAttachProcess(process, &apc_state); + if (!verifier_flags) + status = ObReferenceObjectByHandle(table->Handles[i].HandleValue, 0, NULL, UserMode, &object, &handle_info); + if (NT_SUCCESS(status)) + { + if (verifier_flags || object == file) + ObCloseHandle(table->Handles[i].HandleValue, UserMode); + if (!verifier_flags) + ObfDereferenceObject(object); + } + KeUnstackDetachProcess(&apc_state); + ObfDereferenceObject(process); + } out: - if (table) - ExFreePoolWithTag(table, TUN_HTONL(TUN_MEMORY_TAG)); + if (table) + ExFreePoolWithTag(table, TUN_HTONL(TUN_MEMORY_TAG)); } _IRQL_requires_max_(APC_LEVEL) -static void TunWaitForReferencesToDropToZero(_In_ DEVICE_OBJECT *device_object) +static void +TunWaitForReferencesToDropToZero(_In_ DEVICE_OBJECT *device_object) { - /* The sleep loop isn't pretty, but we don't have a choice. This is an NDIS bug we're working around. */ - enum { SleepTime = 50, TotalTime = 2 * 60 * 1000, MaxTries = TotalTime / SleepTime }; - #pragma warning(suppress: 28175) - for (int i = 0; i < MaxTries && device_object->ReferenceCount; ++i) - NdisMSleep(SleepTime); + /* The sleep loop isn't pretty, but we don't have a choice. This is an NDIS bug we're working around. */ + enum + { + SleepTime = 50, + TotalTime = 2 * 60 * 1000, + MaxTries = TotalTime / SleepTime + }; +#pragma warning(suppress : 28175) + for (int i = 0; i < MaxTries && device_object->ReferenceCount; ++i) + NdisMSleep(SleepTime); } static MINIPORT_HALT TunHaltEx; _Use_decl_annotations_ -static void TunHaltEx(NDIS_HANDLE MiniportAdapterContext, NDIS_HALT_ACTION HaltAction) +static void +TunHaltEx(NDIS_HANDLE MiniportAdapterContext, NDIS_HALT_ACTION HaltAction) { - TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; + TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; - ASSERT(!InterlockedGet64(&ctx->ActiveNBLCount)); /* Adapter should not be halted if there are (potential) active NBLs present. */ + ASSERT(!InterlockedGet64( + &ctx->ActiveNBLCount)); /* Adapter should not be halted if there are (potential) active NBLs present. */ - KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock); - InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_PRESENT); - ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql); + KIRQL irql = ExAcquireSpinLockExclusive(&ctx->TransitionLock); + InterlockedAnd(&ctx->Flags, ~TUN_FLAGS_PRESENT); + ExReleaseSpinLockExclusive(&ctx->TransitionLock, irql); - for (IRP *pending_irp; (pending_irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, NULL)) != NULL;) - TunCompleteRequest(ctx, pending_irp, STATUS_FILE_FORCED_CLOSED, IO_NO_INCREMENT); + for (IRP *pending_irp; (pending_irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, NULL)) != NULL;) + TunCompleteRequest(ctx, pending_irp, STATUS_FILE_FORCED_CLOSED, IO_NO_INCREMENT); - /* Setting a deny-all DACL we prevent userspace to open the device by symlink after TunForceHandlesClosed(). */ - TunDeviceSetDenyAllDacl(ctx->Device.Object); + /* Setting a deny-all DACL we prevent userspace to open the device by symlink after TunForceHandlesClosed(). */ + TunDeviceSetDenyAllDacl(ctx->Device.Object); - if (InterlockedGet64(&ctx->Device.RefCount)) - TunForceHandlesClosed(ctx); + if (InterlockedGet64(&ctx->Device.RefCount)) + TunForceHandlesClosed(ctx); - /* Wait for processing IRP(s) to complete. */ - IoAcquireRemoveLock(&ctx->Device.RemoveLock, NULL); - IoReleaseRemoveLockAndWait(&ctx->Device.RemoveLock, NULL); - NdisFreeNetBufferListPool(ctx->NBLPool); + /* Wait for processing IRP(s) to complete. */ + IoAcquireRemoveLock(&ctx->Device.RemoveLock, NULL); + IoReleaseRemoveLockAndWait(&ctx->Device.RemoveLock, NULL); + NdisFreeNetBufferListPool(ctx->NBLPool); - /* MiniportAdapterHandle must not be used in TunDispatch(). After TunHaltEx() returns it is invalidated. */ - InterlockedExchangePointer(&ctx->MiniportAdapterHandle, NULL); + /* MiniportAdapterHandle must not be used in TunDispatch(). After TunHaltEx() returns it is invalidated. */ + InterlockedExchangePointer(&ctx->MiniportAdapterHandle, NULL); - ASSERT(InterlockedGet64(&TunAdapterCount) > 0); - if (InterlockedDecrement64(&TunAdapterCount) <= 0) - TunWaitForReferencesToDropToZero(ctx->Device.Object); + ASSERT(InterlockedGet64(&TunAdapterCount) > 0); + if (InterlockedDecrement64(&TunAdapterCount) <= 0) + TunWaitForReferencesToDropToZero(ctx->Device.Object); - /* Deregister device _after_ we are done using ctx not to risk an UaF. The ctx is hosted by device extension. */ - NdisDeregisterDeviceEx(ctx->Device.Handle); + /* Deregister device _after_ we are done using ctx not to risk an UaF. The ctx is hosted by device extension. */ + NdisDeregisterDeviceEx(ctx->Device.Handle); } static MINIPORT_SHUTDOWN TunShutdownEx; _Use_decl_annotations_ -static void TunShutdownEx(NDIS_HANDLE MiniportAdapterContext, NDIS_SHUTDOWN_ACTION ShutdownAction) +static void +TunShutdownEx(NDIS_HANDLE MiniportAdapterContext, NDIS_SHUTDOWN_ACTION ShutdownAction) { } _IRQL_requires_max_(APC_LEVEL) _Must_inspect_result_ -static NDIS_STATUS TunOidQueryWrite(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG value) +static NDIS_STATUS +TunOidQueryWrite(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG value) { - if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG)) { - OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG); - OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; - return NDIS_STATUS_BUFFER_TOO_SHORT; - } + if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG)) + { + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG); + OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; + return NDIS_STATUS_BUFFER_TOO_SHORT; + } - OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = - OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG); - *(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = value; - return NDIS_STATUS_SUCCESS; + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG); + *(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = value; + return NDIS_STATUS_SUCCESS; } _IRQL_requires_max_(APC_LEVEL) _Must_inspect_result_ -static NDIS_STATUS TunOidQueryWrite32or64(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG64 value) +static NDIS_STATUS +TunOidQueryWrite32or64(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_ ULONG64 value) { - if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG)) { - OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64); - OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; - return NDIS_STATUS_BUFFER_TOO_SHORT; - } + if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG)) + { + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64); + OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; + return NDIS_STATUS_BUFFER_TOO_SHORT; + } - if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG64)) { - OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64); - OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG); - *(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (ULONG)(value & 0xffffffff); - return NDIS_STATUS_SUCCESS; - } + if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < sizeof(ULONG64)) + { + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = sizeof(ULONG64); + OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG); + *(ULONG *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = (ULONG)(value & 0xffffffff); + return NDIS_STATUS_SUCCESS; + } - OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = - OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG64); - *(ULONG64 *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = value; - return NDIS_STATUS_SUCCESS; + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = sizeof(ULONG64); + *(ULONG64 *)OidRequest->DATA.QUERY_INFORMATION.InformationBuffer = value; + return NDIS_STATUS_SUCCESS; } _IRQL_requires_max_(APC_LEVEL) _Must_inspect_result_ -static NDIS_STATUS TunOidQueryWriteBuf(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_bytecount_(size) const void *buf, _In_ UINT size) +static NDIS_STATUS +TunOidQueryWriteBuf(_Inout_ NDIS_OID_REQUEST *OidRequest, _In_bytecount_(size) const void *buf, _In_ UINT size) { - if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < size) { - OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = size; - OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; - return NDIS_STATUS_BUFFER_TOO_SHORT; - } + if (OidRequest->DATA.QUERY_INFORMATION.InformationBufferLength < size) + { + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = size; + OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; + return NDIS_STATUS_BUFFER_TOO_SHORT; + } - OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = - OidRequest->DATA.QUERY_INFORMATION.BytesWritten = size; - NdisMoveMemory(OidRequest->DATA.QUERY_INFORMATION.InformationBuffer, buf, size); - return NDIS_STATUS_SUCCESS; + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = size; + NdisMoveMemory(OidRequest->DATA.QUERY_INFORMATION.InformationBuffer, buf, size); + return NDIS_STATUS_SUCCESS; } _IRQL_requires_max_(APC_LEVEL) _Must_inspect_result_ -static NDIS_STATUS TunOidQuery(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *OidRequest) +static NDIS_STATUS +TunOidQuery(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *OidRequest) { - ASSERT(OidRequest->RequestType == NdisRequestQueryInformation || OidRequest->RequestType == NdisRequestQueryStatistics); + ASSERT( + OidRequest->RequestType == NdisRequestQueryInformation || + OidRequest->RequestType == NdisRequestQueryStatistics); - switch (OidRequest->DATA.QUERY_INFORMATION.Oid) { - case OID_GEN_MAXIMUM_TOTAL_SIZE: - case OID_GEN_TRANSMIT_BLOCK_SIZE: - case OID_GEN_RECEIVE_BLOCK_SIZE: - return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE); + switch (OidRequest->DATA.QUERY_INFORMATION.Oid) + { + case OID_GEN_MAXIMUM_TOTAL_SIZE: + case OID_GEN_TRANSMIT_BLOCK_SIZE: + case OID_GEN_RECEIVE_BLOCK_SIZE: + return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE); - case OID_GEN_TRANSMIT_BUFFER_SPACE: - return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE * TUN_QUEUE_MAX_NBLS); + case OID_GEN_TRANSMIT_BUFFER_SPACE: + return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE * TUN_QUEUE_MAX_NBLS); - case OID_GEN_RECEIVE_BUFFER_SPACE: - return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE * TUN_EXCH_MAX_PACKETS); + case OID_GEN_RECEIVE_BUFFER_SPACE: + return TunOidQueryWrite(OidRequest, TUN_EXCH_MAX_IP_PACKET_SIZE * TUN_EXCH_MAX_PACKETS); - case OID_GEN_VENDOR_ID: - return TunOidQueryWrite(OidRequest, TUN_HTONL(TUN_VENDOR_ID)); + case OID_GEN_VENDOR_ID: + return TunOidQueryWrite(OidRequest, TUN_HTONL(TUN_VENDOR_ID)); - case OID_GEN_VENDOR_DESCRIPTION: - return TunOidQueryWriteBuf(OidRequest, TUN_VENDOR_NAME, (UINT)sizeof(TUN_VENDOR_NAME)); + case OID_GEN_VENDOR_DESCRIPTION: + return TunOidQueryWriteBuf(OidRequest, TUN_VENDOR_NAME, (UINT)sizeof(TUN_VENDOR_NAME)); - case OID_GEN_VENDOR_DRIVER_VERSION: - return TunOidQueryWrite(OidRequest, (WINTUN_VERSION_MAJ << 16) | WINTUN_VERSION_MIN); + case OID_GEN_VENDOR_DRIVER_VERSION: + return TunOidQueryWrite(OidRequest, (WINTUN_VERSION_MAJ << 16) | WINTUN_VERSION_MIN); - case OID_GEN_XMIT_OK: - return TunOidQueryWrite32or64(OidRequest, - InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutUcastPkts ) + - InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutMulticastPkts) + - InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutBroadcastPkts)); + case OID_GEN_XMIT_OK: + return TunOidQueryWrite32or64( + OidRequest, + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutUcastPkts) + + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutMulticastPkts) + + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCOutBroadcastPkts)); - case OID_GEN_RCV_OK: - return TunOidQueryWrite32or64(OidRequest, - InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInUcastPkts ) + - InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInMulticastPkts) + - InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInBroadcastPkts)); + case OID_GEN_RCV_OK: + return TunOidQueryWrite32or64( + OidRequest, + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInUcastPkts) + + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInMulticastPkts) + + InterlockedGet64((LONG64 *)&ctx->Statistics.ifHCInBroadcastPkts)); - case OID_GEN_STATISTICS: - return TunOidQueryWriteBuf(OidRequest, &ctx->Statistics, (UINT)sizeof(ctx->Statistics)); + case OID_GEN_STATISTICS: + return TunOidQueryWriteBuf(OidRequest, &ctx->Statistics, (UINT)sizeof(ctx->Statistics)); - case OID_GEN_INTERRUPT_MODERATION: { - static const NDIS_INTERRUPT_MODERATION_PARAMETERS intp = { - .Header = { - .Type = NDIS_OBJECT_TYPE_DEFAULT, - .Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1, - .Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1 - }, - .InterruptModeration = NdisInterruptModerationNotSupported - }; - return TunOidQueryWriteBuf(OidRequest, &intp, (UINT)sizeof(intp)); - } + case OID_GEN_INTERRUPT_MODERATION: { + static const NDIS_INTERRUPT_MODERATION_PARAMETERS intp = { + .Header = {.Type = NDIS_OBJECT_TYPE_DEFAULT, + .Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1, + .Size = NDIS_SIZEOF_INTERRUPT_MODERATION_PARAMETERS_REVISION_1}, + .InterruptModeration = NdisInterruptModerationNotSupported}; + return TunOidQueryWriteBuf(OidRequest, &intp, (UINT)sizeof(intp)); + } - case OID_PNP_QUERY_POWER: - OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = - OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; - return NDIS_STATUS_SUCCESS; - } + case OID_PNP_QUERY_POWER: + OidRequest->DATA.QUERY_INFORMATION.BytesNeeded = OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; + return NDIS_STATUS_SUCCESS; + } - OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; - return NDIS_STATUS_NOT_SUPPORTED; + OidRequest->DATA.QUERY_INFORMATION.BytesWritten = 0; + return NDIS_STATUS_NOT_SUPPORTED; } _IRQL_requires_max_(PASSIVE_LEVEL) -static NDIS_STATUS TunOidSet(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *OidRequest) +static NDIS_STATUS +TunOidSet(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *OidRequest) { - ASSERT(OidRequest->RequestType == NdisRequestSetInformation); + ASSERT(OidRequest->RequestType == NdisRequestSetInformation); - OidRequest->DATA.SET_INFORMATION.BytesNeeded = OidRequest->DATA.SET_INFORMATION.BytesRead = 0; + OidRequest->DATA.SET_INFORMATION.BytesNeeded = OidRequest->DATA.SET_INFORMATION.BytesRead = 0; - switch (OidRequest->DATA.SET_INFORMATION.Oid) { - case OID_GEN_CURRENT_PACKET_FILTER: - case OID_GEN_CURRENT_LOOKAHEAD: - if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength != 4) { - OidRequest->DATA.SET_INFORMATION.BytesNeeded = 4; - return NDIS_STATUS_INVALID_LENGTH; - } - OidRequest->DATA.SET_INFORMATION.BytesRead = 4; - return NDIS_STATUS_SUCCESS; + switch (OidRequest->DATA.SET_INFORMATION.Oid) + { + case OID_GEN_CURRENT_PACKET_FILTER: + case OID_GEN_CURRENT_LOOKAHEAD: + if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength != 4) + { + OidRequest->DATA.SET_INFORMATION.BytesNeeded = 4; + return NDIS_STATUS_INVALID_LENGTH; + } + OidRequest->DATA.SET_INFORMATION.BytesRead = 4; + return NDIS_STATUS_SUCCESS; - case OID_GEN_LINK_PARAMETERS: - OidRequest->DATA.SET_INFORMATION.BytesRead = OidRequest->DATA.SET_INFORMATION.InformationBufferLength; - return NDIS_STATUS_SUCCESS; + case OID_GEN_LINK_PARAMETERS: + OidRequest->DATA.SET_INFORMATION.BytesRead = OidRequest->DATA.SET_INFORMATION.InformationBufferLength; + return NDIS_STATUS_SUCCESS; - case OID_GEN_INTERRUPT_MODERATION: - return NDIS_STATUS_INVALID_DATA; + case OID_GEN_INTERRUPT_MODERATION: + return NDIS_STATUS_INVALID_DATA; - case OID_PNP_SET_POWER: - if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength != sizeof(NDIS_DEVICE_POWER_STATE)) { - OidRequest->DATA.SET_INFORMATION.BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE); - return NDIS_STATUS_INVALID_LENGTH; - } - OidRequest->DATA.SET_INFORMATION.BytesRead = sizeof(NDIS_DEVICE_POWER_STATE); - return NDIS_STATUS_SUCCESS; - } + case OID_PNP_SET_POWER: + if (OidRequest->DATA.SET_INFORMATION.InformationBufferLength != sizeof(NDIS_DEVICE_POWER_STATE)) + { + OidRequest->DATA.SET_INFORMATION.BytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE); + return NDIS_STATUS_INVALID_LENGTH; + } + OidRequest->DATA.SET_INFORMATION.BytesRead = sizeof(NDIS_DEVICE_POWER_STATE); + return NDIS_STATUS_SUCCESS; + } - return NDIS_STATUS_NOT_SUPPORTED; + return NDIS_STATUS_NOT_SUPPORTED; } static MINIPORT_OID_REQUEST TunOidRequest; _Use_decl_annotations_ -static NDIS_STATUS TunOidRequest(NDIS_HANDLE MiniportAdapterContext, PNDIS_OID_REQUEST OidRequest) +static NDIS_STATUS +TunOidRequest(NDIS_HANDLE MiniportAdapterContext, PNDIS_OID_REQUEST OidRequest) { - switch (OidRequest->RequestType) { - case NdisRequestQueryInformation: - case NdisRequestQueryStatistics: - return TunOidQuery(MiniportAdapterContext, OidRequest); + switch (OidRequest->RequestType) + { + case NdisRequestQueryInformation: + case NdisRequestQueryStatistics: + return TunOidQuery(MiniportAdapterContext, OidRequest); - case NdisRequestSetInformation: - return TunOidSet(MiniportAdapterContext, OidRequest); + case NdisRequestSetInformation: + return TunOidSet(MiniportAdapterContext, OidRequest); - default: - return NDIS_STATUS_INVALID_OID; - } + default: + return NDIS_STATUS_INVALID_OID; + } } static MINIPORT_CANCEL_OID_REQUEST TunCancelOidRequest; _Use_decl_annotations_ -static void TunCancelOidRequest(NDIS_HANDLE MiniportAdapterContext, PVOID RequestId) +static void +TunCancelOidRequest(NDIS_HANDLE MiniportAdapterContext, PVOID RequestId) { } static MINIPORT_DIRECT_OID_REQUEST TunDirectOidRequest; _Use_decl_annotations_ -static NDIS_STATUS TunDirectOidRequest(NDIS_HANDLE MiniportAdapterContext, PNDIS_OID_REQUEST OidRequest) +static NDIS_STATUS +TunDirectOidRequest(NDIS_HANDLE MiniportAdapterContext, PNDIS_OID_REQUEST OidRequest) { - switch (OidRequest->RequestType) { - case NdisRequestQueryInformation: - case NdisRequestQueryStatistics: - case NdisRequestSetInformation: - return NDIS_STATUS_NOT_SUPPORTED; + switch (OidRequest->RequestType) + { + case NdisRequestQueryInformation: + case NdisRequestQueryStatistics: + case NdisRequestSetInformation: + return NDIS_STATUS_NOT_SUPPORTED; - default: - return NDIS_STATUS_INVALID_OID; - } + default: + return NDIS_STATUS_INVALID_OID; + } } static MINIPORT_CANCEL_DIRECT_OID_REQUEST TunCancelDirectOidRequest; _Use_decl_annotations_ -static void TunCancelDirectOidRequest(NDIS_HANDLE MiniportAdapterContext, PVOID RequestId) +static void +TunCancelDirectOidRequest(NDIS_HANDLE MiniportAdapterContext, PVOID RequestId) { } static MINIPORT_SYNCHRONOUS_OID_REQUEST TunSynchronousOidRequest; _Use_decl_annotations_ -static NDIS_STATUS TunSynchronousOidRequest(NDIS_HANDLE MiniportAdapterContext, PNDIS_OID_REQUEST OidRequest) +static NDIS_STATUS +TunSynchronousOidRequest(NDIS_HANDLE MiniportAdapterContext, PNDIS_OID_REQUEST OidRequest) { - switch (OidRequest->RequestType) { - case NdisRequestQueryInformation: - case NdisRequestQueryStatistics: - case NdisRequestSetInformation: - return NDIS_STATUS_NOT_SUPPORTED; + switch (OidRequest->RequestType) + { + case NdisRequestQueryInformation: + case NdisRequestQueryStatistics: + case NdisRequestSetInformation: + return NDIS_STATUS_NOT_SUPPORTED; - default: - return NDIS_STATUS_INVALID_OID; - } + default: + return NDIS_STATUS_INVALID_OID; + } } static MINIPORT_UNLOAD TunUnload; _Use_decl_annotations_ -static VOID TunUnload(PDRIVER_OBJECT DriverObject) +static VOID +TunUnload(PDRIVER_OBJECT DriverObject) { - NdisMDeregisterMiniportDriver(NdisMiniportDriverHandle); + NdisMDeregisterMiniportDriver(NdisMiniportDriverHandle); } DRIVER_INITIALIZE DriverEntry; _Use_decl_annotations_ -NTSTATUS DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath) +NTSTATUS +DriverEntry(DRIVER_OBJECT *DriverObject, UNICODE_STRING *RegistryPath) { - NTSTATUS status; + NTSTATUS status; - NdisVersion = NdisGetVersion(); - if (NdisVersion < NDIS_MINIPORT_VERSION_MIN) - return NDIS_STATUS_UNSUPPORTED_REVISION; - if (NdisVersion > NDIS_MINIPORT_VERSION_MAX) - NdisVersion = NDIS_MINIPORT_VERSION_MAX; + NdisVersion = NdisGetVersion(); + if (NdisVersion < NDIS_MINIPORT_VERSION_MIN) + return NDIS_STATUS_UNSUPPORTED_REVISION; + if (NdisVersion > NDIS_MINIPORT_VERSION_MAX) + NdisVersion = NDIS_MINIPORT_VERSION_MAX; - NDIS_MINIPORT_DRIVER_CHARACTERISTICS miniport = { - .Header = { - .Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS, - .Revision = NdisVersion < NDIS_RUNTIME_VERSION_680 ? NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2 : NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_3, - .Size = NdisVersion < NDIS_RUNTIME_VERSION_680 ? NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2 : NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_3 - }, + NDIS_MINIPORT_DRIVER_CHARACTERISTICS miniport = { + .Header = {.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS, + .Revision = NdisVersion < NDIS_RUNTIME_VERSION_680 ? NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2 + : NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_3, + .Size = NdisVersion < NDIS_RUNTIME_VERSION_680 + ? NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2 + : NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_3}, - .MajorNdisVersion = (UCHAR)((NdisVersion & 0x00ff0000) >> 16), - .MinorNdisVersion = (UCHAR) (NdisVersion & 0x000000ff), + .MajorNdisVersion = (UCHAR)((NdisVersion & 0x00ff0000) >> 16), + .MinorNdisVersion = (UCHAR)(NdisVersion & 0x000000ff), - .MajorDriverVersion = WINTUN_VERSION_MAJ, - .MinorDriverVersion = WINTUN_VERSION_MIN, + .MajorDriverVersion = WINTUN_VERSION_MAJ, + .MinorDriverVersion = WINTUN_VERSION_MIN, - .InitializeHandlerEx = TunInitializeEx, - .HaltHandlerEx = TunHaltEx, - .UnloadHandler = TunUnload, - .PauseHandler = TunPause, - .RestartHandler = TunRestart, - .OidRequestHandler = TunOidRequest, - .SendNetBufferListsHandler = TunSendNetBufferLists, - .ReturnNetBufferListsHandler = TunReturnNetBufferLists, - .CancelSendHandler = TunCancelSend, - .DevicePnPEventNotifyHandler = TunDevicePnPEventNotify, - .ShutdownHandlerEx = TunShutdownEx, - .CancelOidRequestHandler = TunCancelOidRequest, - .DirectOidRequestHandler = TunDirectOidRequest, - .CancelDirectOidRequestHandler = TunCancelDirectOidRequest, - .SynchronousOidRequestHandler = TunSynchronousOidRequest - }; - if (!NT_SUCCESS(status = NdisMRegisterMiniportDriver(DriverObject, RegistryPath, NULL, &miniport, &NdisMiniportDriverHandle))) - return status; + .InitializeHandlerEx = TunInitializeEx, + .HaltHandlerEx = TunHaltEx, + .UnloadHandler = TunUnload, + .PauseHandler = TunPause, + .RestartHandler = TunRestart, + .OidRequestHandler = TunOidRequest, + .SendNetBufferListsHandler = TunSendNetBufferLists, + .ReturnNetBufferListsHandler = TunReturnNetBufferLists, + .CancelSendHandler = TunCancelSend, + .DevicePnPEventNotifyHandler = TunDevicePnPEventNotify, + .ShutdownHandlerEx = TunShutdownEx, + .CancelOidRequestHandler = TunCancelOidRequest, + .DirectOidRequestHandler = TunDirectOidRequest, + .CancelDirectOidRequestHandler = TunCancelDirectOidRequest, + .SynchronousOidRequestHandler = TunSynchronousOidRequest}; + if (!NT_SUCCESS( + status = + NdisMRegisterMiniportDriver(DriverObject, RegistryPath, NULL, &miniport, &NdisMiniportDriverHandle))) + return status; - NdisDispatchPnP = DriverObject->MajorFunction[IRP_MJ_PNP]; - DriverObject->MajorFunction[IRP_MJ_PNP] = TunDispatchPnP; + NdisDispatchPnP = DriverObject->MajorFunction[IRP_MJ_PNP]; + DriverObject->MajorFunction[IRP_MJ_PNP] = TunDispatchPnP; - return STATUS_SUCCESS; + return STATUS_SUCCESS; }