Revert "Implement NDIS 6.30's NDIS_MINIPORT_ATTRIBUTES_NO_PAUSE_ON_SUSPEND"

This reverts commit 683cf83befbc8d95de3b13994851087306b19963.

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2019-04-03 05:46:50 +02:00
parent 1b9fee728b
commit 480000f429

206
wintun.c
View File

@ -52,23 +52,15 @@ typedef enum _TUN_STATE {
TUN_STATE_PAUSING, // In the Pausing state, a miniport driver completes any operations that are required to stop send and receive operations for an adapter. TUN_STATE_PAUSING, // In the Pausing state, a miniport driver completes any operations that are required to stop send and receive operations for an adapter.
} TUN_STATE; } TUN_STATE;
typedef enum _TUN_POWER {
TUN_POWER_RUNNING = 0, // D0
TUN_POWER_SUSPENDED, // D1-D3
TUN_POWER_RESUMING, // D1-D3 -> D0
TUN_POWER_SUSPENDING, // D0 -> D1-D3
} TUN_POWER;
typedef struct _TUN_CTX { typedef struct _TUN_CTX {
volatile TUN_STATE State; volatile TUN_STATE State;
volatile TUN_POWER Power;
volatile NDIS_DEVICE_POWER_STATE PowerState;
NDIS_HANDLE MiniportAdapterHandle; NDIS_HANDLE MiniportAdapterHandle;
NDIS_STATISTICS_INFO Statistics; NDIS_STATISTICS_INFO Statistics;
volatile LONG64 RunningTransactionCount; // Number of active transactions that require running adapter (active NBLs + active IRPs) volatile LONG64 ActiveTransactionCount;
volatile LONG64 PoweredTransactionCount; // Number of active transactions that require powered up adapter (active NBLs)
NDIS_OID_REQUEST *PendingPowerOIDReq;
struct { struct {
NDIS_HANDLE Handle; NDIS_HANDLE Handle;
@ -174,71 +166,32 @@ static void TunCompleteRequest(_Inout_ IRP *Irp, _In_ ULONG_PTR Information, _In
IoCompleteRequest(Irp, IO_NO_INCREMENT); IoCompleteRequest(Irp, IO_NO_INCREMENT);
} }
_IRQL_requires_same_
static void TunTransactionIncrement(_Inout_ TUN_CTX *ctx, _In_ LONG64 increment_nbl, _In_ LONG64 increment_irp)
{
ASSERT(InterlockedGet64(&ctx->RunningTransactionCount) <= MAXLONG64 - increment_nbl - increment_irp);
InterlockedAdd64(&ctx->RunningTransactionCount, increment_nbl + increment_irp);
ASSERT(InterlockedGet64(&ctx->PoweredTransactionCount) <= MAXLONG64 - increment_nbl);
InterlockedAdd64(&ctx->PoweredTransactionCount, increment_nbl);
}
_IRQL_requires_same_ _IRQL_requires_same_
_Must_inspect_result_ _Must_inspect_result_
static NTSTATUS TunTransactionStart(_Inout_ TUN_CTX *ctx, _In_ LONG64 increment_nbl, _In_ LONG64 increment_irp) static NTSTATUS TunCheckForPause(_Inout_ TUN_CTX *ctx, _In_ LONG64 increment)
{ {
TunTransactionIncrement(ctx, increment_nbl, increment_irp); ASSERT(InterlockedGet64(&ctx->ActiveTransactionCount) <= MAXLONG64 - increment);
InterlockedAdd64(&ctx->ActiveTransactionCount, increment);
return return
(increment_nbl || increment_irp) && InterlockedGet((LONG *)&ctx->State) != TUN_STATE_RUNNING ? STATUS_NDIS_PAUSED : InterlockedGet((LONG *)&ctx->State) != TUN_STATE_RUNNING ? STATUS_NDIS_PAUSED :
(increment_nbl ) && InterlockedGet((LONG *)&ctx->Power) != TUN_POWER_RUNNING ? STATUS_NDIS_LOW_POWER_STATE : ctx->PowerState >= NdisDeviceStateD1 ? STATUS_NDIS_LOW_POWER_STATE :
STATUS_SUCCESS; STATUS_SUCCESS;
} }
_IRQL_requires_same_
static void TunTransactionDecrement(_Inout_ TUN_CTX *ctx, _In_ LONG64 decrement_nbl, _In_ LONG64 decrement_irp, _Out_opt_ LONG64 *running_count, _Out_opt_ LONG64 *powered_count)
{
LONG64 result;
ASSERT(decrement_nbl + decrement_irp <= InterlockedGet64(&ctx->RunningTransactionCount));
result = InterlockedSubtract64(&ctx->RunningTransactionCount, decrement_nbl + decrement_irp);
if (running_count)
*running_count = result;
ASSERT(decrement_nbl <= InterlockedGet64(&ctx->PoweredTransactionCount));
result = InterlockedSubtract64(&ctx->PoweredTransactionCount, decrement_nbl);
if (powered_count)
*powered_count = result;
}
_IRQL_requires_max_(DISPATCH_LEVEL) _IRQL_requires_max_(DISPATCH_LEVEL)
static void TunTransactionEnd(_Inout_ TUN_CTX *ctx, _In_ LONG64 decrement_nbl, _In_ LONG64 decrement_irp, _Out_opt_ NDIS_STATUS *status_state, _Out_opt_ NDIS_STATUS *status_power) static NDIS_STATUS TunCompletePause(_Inout_ TUN_CTX *ctx, _In_ LONG64 decrement, _In_ BOOLEAN async_completion)
{ {
LONG64 running_count, powered_count; ASSERT(decrement <= InterlockedGet64(&ctx->ActiveTransactionCount));
TunTransactionDecrement(ctx, decrement_nbl, decrement_irp, &running_count, &powered_count); if (!InterlockedSubtract64(&ctx->ActiveTransactionCount, decrement) &&
InterlockedCompareExchange((LONG *)&ctx->State, TUN_STATE_PAUSED, TUN_STATE_PAUSING) == TUN_STATE_PAUSING) {
if (status_state)
*status_state = NDIS_STATUS_PENDING;
if (status_power)
*status_power = NDIS_STATUS_PENDING;
if (!running_count && InterlockedCompareExchange((LONG *)&ctx->State, TUN_STATE_PAUSED, TUN_STATE_PAUSING) == TUN_STATE_PAUSING) {
InterlockedExchange64(&ctx->Device.RefCount, 0); InterlockedExchange64(&ctx->Device.RefCount, 0);
TunIndicateStatus(ctx); TunIndicateStatus(ctx);
if (status_state) if (async_completion)
*status_state = NDIS_STATUS_SUCCESS;
else
NdisMPauseComplete(ctx->MiniportAdapterHandle); NdisMPauseComplete(ctx->MiniportAdapterHandle);
return NDIS_STATUS_SUCCESS;
} }
if (!powered_count && InterlockedCompareExchange((LONG *)&ctx->Power, TUN_POWER_SUSPENDED, TUN_POWER_SUSPENDING) == TUN_POWER_SUSPENDING) { return NDIS_STATUS_PENDING;
NDIS_OID_REQUEST *oid_req = InterlockedExchangePointer(&ctx->PendingPowerOIDReq, NULL);
if (status_power)
*status_power = NDIS_STATUS_SUCCESS;
else if (oid_req)
NdisMOidRequestComplete(ctx->MiniportAdapterHandle, oid_req, NDIS_STATUS_SUCCESS);
}
} }
static IO_CSQ_INSERT_IRP_EX TunCsqInsertIrpEx; static IO_CSQ_INSERT_IRP_EX TunCsqInsertIrpEx;
@ -307,7 +260,7 @@ static VOID TunCsqCompleteCanceledIrp(IO_CSQ *Csq, IRP *Irp)
{ {
TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq); TUN_CTX *ctx = CONTAINING_RECORD(Csq, TUN_CTX, Device.ReadQueue.Csq);
TunCompleteRequest(Irp, 0, STATUS_CANCELLED); TunCompleteRequest(Irp, 0, STATUS_CANCELLED);
TunTransactionEnd(ctx, 0, 1, NULL, NULL); TunCompletePause(ctx, 1, TRUE);
} }
_IRQL_requires_same_ _IRQL_requires_same_
@ -382,7 +335,7 @@ retry:
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
irp->IoStatus.Status = status; irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NETWORK_INCREMENT); IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
TunTransactionEnd(ctx, 0, 1, NULL, NULL); TunCompletePause(ctx, 1, TRUE);
goto retry; goto retry;
} }
@ -426,10 +379,8 @@ static NTSTATUS TunWriteIntoIrp(_Inout_ TUN_CTX *ctx, _Inout_ IRP *Irp, _Inout_
_IRQL_requires_same_ _IRQL_requires_same_
static void TunNBLRefInit(_Inout_ TUN_CTX *ctx, _Inout_ NET_BUFFER_LIST *nbl) static void TunNBLRefInit(_Inout_ TUN_CTX *ctx, _Inout_ NET_BUFFER_LIST *nbl)
{ {
TunTransactionIncrement(ctx, 1, 0); InterlockedAdd64(&ctx->ActiveTransactionCount, 1);
InterlockedAdd(&ctx->PacketQueue.NumNbl, 1);
ASSERT(InterlockedGet(&ctx->PacketQueue.NumNbl) < MAXLONG);
InterlockedIncrement(&ctx->PacketQueue.NumNbl);
InterlockedExchange64(NET_BUFFER_LIST_MINIPORT_RESERVED_REFCOUNT(nbl), 1); InterlockedExchange64(NET_BUFFER_LIST_MINIPORT_RESERVED_REFCOUNT(nbl), 1);
} }
@ -437,8 +388,7 @@ _IRQL_requires_same_
static void TunNBLRefInc(_Inout_ NET_BUFFER_LIST *nbl) static void TunNBLRefInc(_Inout_ NET_BUFFER_LIST *nbl)
{ {
ASSERT(InterlockedGet64(NET_BUFFER_LIST_MINIPORT_RESERVED_REFCOUNT(nbl))); ASSERT(InterlockedGet64(NET_BUFFER_LIST_MINIPORT_RESERVED_REFCOUNT(nbl)));
ASSERT(InterlockedGet64(NET_BUFFER_LIST_MINIPORT_RESERVED_REFCOUNT(nbl)) < MAXLONG); InterlockedAdd64(NET_BUFFER_LIST_MINIPORT_RESERVED_REFCOUNT(nbl), 1);
InterlockedIncrement64(NET_BUFFER_LIST_MINIPORT_RESERVED_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))
@ -446,12 +396,11 @@ _When_(!(SendCompleteFlags & NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL), _IRQL_req
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_MINIPORT_RESERVED_REFCOUNT(nbl))); ASSERT(InterlockedGet64(NET_BUFFER_LIST_MINIPORT_RESERVED_REFCOUNT(nbl)));
if (!InterlockedDecrement64(NET_BUFFER_LIST_MINIPORT_RESERVED_REFCOUNT(nbl))) { if (!InterlockedSubtract64(NET_BUFFER_LIST_MINIPORT_RESERVED_REFCOUNT(nbl), 1)) {
NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL; NET_BUFFER_LIST_NEXT_NBL(nbl) = NULL;
NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, SendCompleteFlags); NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, nbl, SendCompleteFlags);
ASSERT(InterlockedGet(&ctx->PacketQueue.NumNbl)); InterlockedSubtract(&ctx->PacketQueue.NumNbl, 1);
InterlockedDecrement(&ctx->PacketQueue.NumNbl); TunCompletePause(ctx, 1, TRUE);
TunTransactionEnd(ctx, 1, 0, NULL, NULL);
return TRUE; return TRUE;
} }
return FALSE; return FALSE;
@ -626,7 +575,7 @@ static void TunQueueProcess(_Inout_ TUN_CTX *ctx)
} else { } else {
irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(irp, IO_NETWORK_INCREMENT); IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
TunTransactionEnd(ctx, 0, 1, NULL, NULL); TunCompletePause(ctx, 1, TRUE);
irp = NULL; irp = NULL;
} }
@ -647,15 +596,15 @@ static NTSTATUS TunDispatchCreate(DEVICE_OBJECT *DeviceObject, IRP *Irp)
goto cleanup_complete_req; goto cleanup_complete_req;
} }
if (!NT_SUCCESS(status = TunTransactionStart(ctx, 0, 1))) if (!NT_SUCCESS(status = TunCheckForPause(ctx, 1)))
goto cleanup_TunTransactionEnd; goto cleanup_TunCompletePause;
ASSERT(InterlockedGet64(&ctx->Device.RefCount) < MAXLONG64); ASSERT(InterlockedGet64(&ctx->Device.RefCount) < MAXLONG64);
InterlockedIncrement64(&ctx->Device.RefCount); InterlockedIncrement64(&ctx->Device.RefCount);
TunIndicateStatus(ctx); TunIndicateStatus(ctx);
cleanup_TunTransactionEnd: cleanup_TunCompletePause:
TunTransactionEnd(ctx, 0, 1, NULL, NULL); TunCompletePause(ctx, 1, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, 0, status); TunCompleteRequest(Irp, 0, status);
return status; return status;
@ -673,15 +622,15 @@ static NTSTATUS TunDispatchClose(DEVICE_OBJECT *DeviceObject, IRP *Irp)
goto cleanup_complete_req; goto cleanup_complete_req;
} }
if (!NT_SUCCESS(status = TunTransactionStart(ctx, 0, 1))) if (!NT_SUCCESS(status = TunCheckForPause(ctx, 1)))
goto cleanup_TunTransactionEnd; goto cleanup_TunCompletePause;
ASSERT(InterlockedGet64(&ctx->Device.RefCount) > 0); ASSERT(InterlockedGet64(&ctx->Device.RefCount) > 0);
InterlockedDecrement64(&ctx->Device.RefCount); InterlockedDecrement64(&ctx->Device.RefCount);
TunIndicateStatus(ctx); TunIndicateStatus(ctx);
cleanup_TunTransactionEnd: cleanup_TunCompletePause:
TunTransactionEnd(ctx, 0, 1, NULL, NULL); TunCompletePause(ctx, 1, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, 0, status); TunCompleteRequest(Irp, 0, status);
return status; return status;
@ -699,24 +648,24 @@ static NTSTATUS TunDispatchRead(DEVICE_OBJECT *DeviceObject, IRP *Irp)
goto cleanup_complete_req; goto cleanup_complete_req;
} }
if (!NT_SUCCESS(status = TunTransactionStart(ctx, 0, 1))) if (!NT_SUCCESS(status = TunCheckForPause(ctx, 1)))
goto cleanup_TunTransactionEnd; goto cleanup_TunCompletePause;
Irp->IoStatus.Information = 0; Irp->IoStatus.Information = 0;
TunTransactionIncrement(ctx, 0, 1); InterlockedIncrement64(&ctx->ActiveTransactionCount);
status = IoCsqInsertIrpEx(&ctx->Device.ReadQueue.Csq, Irp, NULL, TUN_CSQ_INSERT_TAIL); status = IoCsqInsertIrpEx(&ctx->Device.ReadQueue.Csq, Irp, NULL, TUN_CSQ_INSERT_TAIL);
if (!NT_SUCCESS(status)) { if (!NT_SUCCESS(status)) {
TunTransactionDecrement(ctx, 0, 1, NULL, NULL); InterlockedDecrement64(&ctx->ActiveTransactionCount);
goto cleanup_TunTransactionEnd; goto cleanup_TunCompletePause;
} }
TunQueueProcess(ctx); TunQueueProcess(ctx);
TunTransactionEnd(ctx, 0, 1, NULL, NULL); TunCompletePause(ctx, 1, TRUE);
return STATUS_PENDING; return STATUS_PENDING;
cleanup_TunTransactionEnd: cleanup_TunCompletePause:
TunTransactionEnd(ctx, 0, 1, NULL, NULL); TunCompletePause(ctx, 1, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, 0, status); TunCompleteRequest(Irp, 0, status);
return status; return status;
@ -735,14 +684,14 @@ static NTSTATUS TunDispatchWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp)
goto cleanup_complete_req; goto cleanup_complete_req;
} }
if (!NT_SUCCESS(status = TunTransactionStart(ctx, 1, 1))) if (!NT_SUCCESS(status = TunCheckForPause(ctx, 1)))
goto cleanup_TunTransactionEnd; goto cleanup_TunCompletePause;
UCHAR *buffer; UCHAR *buffer;
ULONG size; ULONG size;
status = TunGetIrpBuffer(Irp, &buffer, &size); status = TunGetIrpBuffer(Irp, &buffer, &size);
if (!NT_SUCCESS(status)) if (!NT_SUCCESS(status))
goto cleanup_TunTransactionEnd; goto cleanup_TunCompletePause;
const UCHAR *b = buffer, *b_end = buffer + size; const UCHAR *b = buffer, *b_end = buffer + size;
ULONG nbl_count = 0; ULONG nbl_count = 0;
@ -846,8 +795,8 @@ static NTSTATUS TunDispatchWrite(DEVICE_OBJECT *DeviceObject, IRP *Irp)
information = b - buffer; information = b - buffer;
cleanup_TunTransactionEnd: cleanup_TunCompletePause:
TunTransactionEnd(ctx, 1, 1, NULL, NULL); TunCompletePause(ctx, 1, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, information, status); TunCompleteRequest(Irp, information, status);
return status; return status;
@ -865,19 +814,19 @@ static NTSTATUS TunDispatchCleanup(DEVICE_OBJECT *DeviceObject, IRP *Irp)
goto cleanup_complete_req; goto cleanup_complete_req;
} }
LONG64 count_irp = 1; LONG64 count = 1;
if (!NT_SUCCESS(status = TunTransactionStart(ctx, 0, count_irp))) if (!NT_SUCCESS(status = TunCheckForPause(ctx, count)))
goto cleanup_TunTransactionEnd; goto cleanup_TunCompletePause;
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp); IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(Irp);
IRP *pending_irp; IRP *pending_irp;
while ((pending_irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, stack->FileObject)) != NULL) { while ((pending_irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, stack->FileObject)) != NULL) {
count_irp++; count++;
TunCompleteRequest(pending_irp, 0, STATUS_CANCELLED); TunCompleteRequest(pending_irp, 0, STATUS_CANCELLED);
} }
cleanup_TunTransactionEnd: cleanup_TunCompletePause:
TunTransactionEnd(ctx, 0, count_irp, NULL, NULL); TunCompletePause(ctx, count, TRUE);
cleanup_complete_req: cleanup_complete_req:
TunCompleteRequest(Irp, 0, status); TunCompleteRequest(Irp, 0, status);
return status; return status;
@ -897,10 +846,11 @@ static NDIS_STATUS TunPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_P
{ {
TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext;
LONG64 count_irp = 1; LONG64 count = 1;
TunTransactionIncrement(ctx, 1, count_irp); InterlockedAdd64(&ctx->ActiveTransactionCount, count);
if (InterlockedCompareExchange((LONG *)&ctx->State, TUN_STATE_PAUSING, TUN_STATE_RUNNING) != TUN_STATE_RUNNING) { if (InterlockedCompareExchange((LONG *)&ctx->State, TUN_STATE_PAUSING, TUN_STATE_RUNNING) != TUN_STATE_RUNNING) {
TunTransactionDecrement(ctx, 1, count_irp, NULL, NULL); InterlockedDecrement64(&ctx->ActiveTransactionCount);
return NDIS_STATUS_FAILURE; return NDIS_STATUS_FAILURE;
} }
@ -909,13 +859,11 @@ static NDIS_STATUS TunPause(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT_P
/* Cancel pending IRPs to unblock waiting clients. */ /* Cancel pending IRPs to unblock waiting clients. */
IRP *pending_irp; IRP *pending_irp;
while ((pending_irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, NULL)) != NULL) { while ((pending_irp = IoCsqRemoveNextIrp(&ctx->Device.ReadQueue.Csq, NULL)) != NULL) {
count_irp++; count++;
TunCompleteRequest(pending_irp, 0, STATUS_CANCELLED); TunCompleteRequest(pending_irp, 0, STATUS_CANCELLED);
} }
NDIS_STATUS status; return TunCompletePause(ctx, count, FALSE);
TunTransactionEnd(ctx, 1, count_irp, &status, NULL);
return status;
} }
static MINIPORT_RESTART TunRestart; static MINIPORT_RESTART TunRestart;
@ -926,10 +874,7 @@ static NDIS_STATUS TunRestart(NDIS_HANDLE MiniportAdapterContext, PNDIS_MINIPORT
if (InterlockedCompareExchange((LONG *)&ctx->State, TUN_STATE_RESTARTING, TUN_STATE_PAUSED) != TUN_STATE_PAUSED) if (InterlockedCompareExchange((LONG *)&ctx->State, TUN_STATE_RESTARTING, TUN_STATE_PAUSED) != TUN_STATE_PAUSED)
return NDIS_STATUS_FAILURE; return NDIS_STATUS_FAILURE;
ASSERT(!InterlockedGet64(&ctx->RunningTransactionCount));
ASSERT(!InterlockedGet64(&ctx->PoweredTransactionCount));
ASSERT(!InterlockedGet64(&ctx->Device.RefCount)); ASSERT(!InterlockedGet64(&ctx->Device.RefCount));
TunIndicateStatus(ctx); TunIndicateStatus(ctx);
InterlockedExchange((LONG *)&ctx->State, TUN_STATE_RUNNING); InterlockedExchange((LONG *)&ctx->State, TUN_STATE_RUNNING);
@ -1014,7 +959,7 @@ static NDIS_STATUS TunInitializeEx(NDIS_HANDLE MiniportAdapterHandle, NDIS_HANDL
NdisZeroMemory(ctx, sizeof(*ctx)); NdisZeroMemory(ctx, sizeof(*ctx));
ctx->State = TUN_STATE_INITIALIZING; ctx->State = TUN_STATE_INITIALIZING;
ctx->Power = TUN_POWER_RUNNING; ctx->PowerState = NdisDeviceStateD0;
ctx->MiniportAdapterHandle = MiniportAdapterHandle; ctx->MiniportAdapterHandle = MiniportAdapterHandle;
ctx->Statistics.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; ctx->Statistics.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
@ -1046,7 +991,7 @@ static NDIS_STATUS TunInitializeEx(NDIS_HANDLE MiniportAdapterHandle, NDIS_HANDL
.Revision = NdisVersion < NDIS_RUNTIME_VERSION_630 ? NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1 : NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_2, .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 .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 | (NdisVersion >= NDIS_RUNTIME_VERSION_630 ? NDIS_MINIPORT_ATTRIBUTES_NO_PAUSE_ON_SUSPEND : 0), .AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND,
.InterfaceType = NdisInterfaceInternal, .InterfaceType = NdisInterfaceInternal,
.MiniportAdapterContext = ctx .MiniportAdapterContext = ctx
}; };
@ -1250,8 +1195,7 @@ static void TunHaltEx(NDIS_HANDLE MiniportAdapterContext, NDIS_HALT_ACTION HaltA
if (InterlockedGet((LONG *)&ctx->State) != TUN_STATE_PAUSED) if (InterlockedGet((LONG *)&ctx->State) != TUN_STATE_PAUSED)
return; return;
ASSERT(!InterlockedGet64(&ctx->RunningTransactionCount)); ASSERT(!InterlockedGet64(&ctx->ActiveTransactionCount));
ASSERT(!InterlockedGet64(&ctx->PoweredTransactionCount));
ASSERT(!InterlockedGet64(&ctx->Device.RefCount)); ASSERT(!InterlockedGet64(&ctx->Device.RefCount));
/* Reset adapter context in device object, as Windows keeps calling dispatch handlers even after NdisDeregisterDeviceEx(). */ /* Reset adapter context in device object, as Windows keeps calling dispatch handlers even after NdisDeregisterDeviceEx(). */
@ -1296,27 +1240,7 @@ static NDIS_STATUS TunOidSet(_Inout_ TUN_CTX *ctx, _Inout_ NDIS_OID_REQUEST *Oid
return NDIS_STATUS_INVALID_LENGTH; return NDIS_STATUS_INVALID_LENGTH;
} }
OidRequest->DATA.SET_INFORMATION.BytesRead = sizeof(NDIS_DEVICE_POWER_STATE); OidRequest->DATA.SET_INFORMATION.BytesRead = sizeof(NDIS_DEVICE_POWER_STATE);
if (*((NDIS_DEVICE_POWER_STATE *)OidRequest->DATA.SET_INFORMATION.InformationBuffer) >= NdisDeviceStateD1) { ctx->PowerState = *((NDIS_DEVICE_POWER_STATE *)OidRequest->DATA.SET_INFORMATION.InformationBuffer);
TunTransactionIncrement(ctx, 1, 0);
if (InterlockedCompareExchange((LONG *)&ctx->Power, TUN_POWER_SUSPENDING, TUN_POWER_RUNNING) != TUN_POWER_RUNNING) {
TunTransactionDecrement(ctx, 1, 0, NULL, NULL);
return NDIS_STATUS_FAILURE;
}
TunQueueClear(ctx);
InterlockedExchangePointer(&ctx->PendingPowerOIDReq, OidRequest);
NDIS_STATUS status;
TunTransactionEnd(ctx, 1, 0, NULL, &status);
return status;
} else {
if (InterlockedCompareExchange((LONG *)&ctx->Power, TUN_POWER_RESUMING, TUN_POWER_SUSPENDED) != TUN_POWER_SUSPENDED)
return NDIS_STATUS_FAILURE;
ASSERT(!InterlockedGet64(&ctx->PoweredTransactionCount));
InterlockedExchange((LONG *)&ctx->Power, TUN_POWER_RUNNING);
}
return NDIS_STATUS_SUCCESS; return NDIS_STATUS_SUCCESS;
} }
@ -1451,17 +1375,17 @@ static void TunSendNetBufferLists(NDIS_HANDLE MiniportAdapterContext, NET_BUFFER
TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext; TUN_CTX *ctx = (TUN_CTX *)MiniportAdapterContext;
NDIS_STATUS status; NDIS_STATUS status;
if (!NT_SUCCESS(status = TunTransactionStart(ctx, 1, 0))) { if (!NT_SUCCESS(status = TunCheckForPause(ctx, 1))) {
TunSetNBLStatus(NetBufferLists, status); TunSetNBLStatus(NetBufferLists, status);
NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, NetBufferLists, SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0); NdisMSendNetBufferListsComplete(ctx->MiniportAdapterHandle, NetBufferLists, SendFlags & NDIS_SEND_FLAGS_DISPATCH_LEVEL ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0);
goto cleanup_TunTransactionEnd; goto cleanup_TunCompletePause;
} }
TunQueueAppend(ctx, NetBufferLists, TUN_QUEUE_MAX_NBLS); TunQueueAppend(ctx, NetBufferLists, TUN_QUEUE_MAX_NBLS);
TunQueueProcess(ctx); TunQueueProcess(ctx);
cleanup_TunTransactionEnd: cleanup_TunCompletePause:
TunTransactionEnd(ctx, 1, 0, NULL, NULL); TunCompletePause(ctx, 1, TRUE);
} }
DRIVER_INITIALIZE DriverEntry; DRIVER_INITIALIZE DriverEntry;