@@ -273,8 +273,6 @@ struct flow_s
273
273
UINT64 flow_id ; // WFP flow ID.
274
274
UINT32 callout_id ; // WFP callout ID.
275
275
UINT16 layer_id ; // WFP layout ID.
276
- BOOL inserted :1 ; // Flow inserted into context?
277
- BOOL deleted :1 ; // Flow deleted from context?
278
276
BOOL outbound :1 ; // Flow is outound?
279
277
BOOL loopback :1 ; // Flow is loopback?
280
278
BOOL ipv6 :1 ; // Flow is ipv6?
@@ -1981,17 +1979,20 @@ extern VOID windivert_cleanup(IN WDFFILEOBJECT object)
1981
1979
context -> state = WINDIVERT_CONTEXT_STATE_CLOSING ;
1982
1980
sniff_mode = ((context -> flags & WINDIVERT_FLAG_SNIFF ) != 0 );
1983
1981
forward = (context -> layer == WINDIVERT_LAYER_NETWORK_FORWARD );
1984
- while (!IsListEmpty (& context -> flow_set ))
1982
+ entry = context -> flow_set .Flink ;
1983
+ if (entry != & context -> flow_set )
1985
1984
{
1986
- entry = RemoveHeadList (& context -> flow_set );
1987
- flow = CONTAINING_RECORD (entry , struct flow_s , entry );
1988
- flow -> deleted = TRUE;
1989
1985
KeReleaseInStackQueuedSpinLock (& lock_handle );
1990
- status = FwpsFlowRemoveContext0 (flow -> flow_id , flow -> layer_id ,
1991
- flow -> callout_id );
1992
- if (!NT_SUCCESS (status ))
1986
+ for (; entry != & context -> flow_set ; entry = entry -> Flink )
1993
1987
{
1994
- windivert_free (flow );
1988
+ flow = CONTAINING_RECORD (entry , struct flow_s , entry );
1989
+ status = FwpsFlowRemoveContext0 (flow -> flow_id , flow -> layer_id ,
1990
+ flow -> callout_id );
1991
+ if (!NT_SUCCESS (status ) && status != STATUS_UNSUCCESSFUL )
1992
+ {
1993
+ // For STATUS_UNSUCCESSFUL, flow_delete() is still called.
1994
+ WdfObjectDereference ((WDFOBJECT )object );
1995
+ }
1995
1996
}
1996
1997
KeAcquireInStackQueuedSpinLock (& context -> lock , & lock_handle );
1997
1998
}
@@ -2086,6 +2087,8 @@ extern VOID windivert_destroy(IN WDFOBJECT object)
2086
2087
KLOCK_QUEUE_HANDLE lock_handle ;
2087
2088
context_t context = windivert_context_get ((WDFFILEOBJECT )object );
2088
2089
const WINDIVERT_FILTER * filter ;
2090
+ PLIST_ENTRY entry ;
2091
+ flow_t flow ;
2089
2092
NTSTATUS status ;
2090
2093
2091
2094
DEBUG ("DESTROY: destroying WinDivert context (context=%p)" , context );
@@ -2106,6 +2109,12 @@ extern VOID windivert_destroy(IN WDFOBJECT object)
2106
2109
FwpmEngineClose0 (context -> engine_handle );
2107
2110
}
2108
2111
windivert_free ((PVOID )filter );
2112
+ while (!IsListEmpty (& context -> flow_set ))
2113
+ {
2114
+ entry = RemoveHeadList (& context -> flow_set );
2115
+ flow = CONTAINING_RECORD (entry , struct flow_s , entry );
2116
+ windivert_free (flow );
2117
+ }
2109
2118
if (context -> process != NULL )
2110
2119
{
2111
2120
ObDereferenceObject (context -> process );
@@ -4179,22 +4188,11 @@ static void windivert_flow_established_classify(context_t context,
4179
4188
flow -> flow_id = flow_id ;
4180
4189
flow -> callout_id = callout_id ;
4181
4190
flow -> layer_id = layer_id ;
4182
- flow -> inserted = FALSE;
4183
- flow -> deleted = FALSE;
4184
4191
flow -> outbound = outbound ;
4185
4192
flow -> loopback = loopback ;
4186
4193
flow -> ipv6 = !ipv4 ;
4187
4194
RtlCopyMemory (& flow -> data , flow_data , sizeof (flow -> data ));
4188
4195
4189
- status = FwpsFlowAssociateContext0 (flow_id , layer_id , callout_id ,
4190
- (UINT64 )flow );
4191
- if (!NT_SUCCESS (status ))
4192
- {
4193
- windivert_free (flow );
4194
- WdfObjectDereference (object );
4195
- return ;
4196
- }
4197
-
4198
4196
KeAcquireInStackQueuedSpinLock (& context -> lock , & lock_handle );
4199
4197
if (context -> state != WINDIVERT_CONTEXT_STATE_OPEN ||
4200
4198
context -> shutdown_recv )
@@ -4204,19 +4202,16 @@ static void windivert_flow_established_classify(context_t context,
4204
4202
WdfObjectDereference (object );
4205
4203
return ;
4206
4204
}
4207
- if (!flow -> deleted )
4208
- {
4209
- InsertTailList (& context -> flow_set , & flow -> entry );
4210
- flow -> inserted = TRUE;
4211
- }
4212
- else
4205
+ status = FwpsFlowAssociateContext0 (flow_id , layer_id , callout_id ,
4206
+ (UINT64 )flow );
4207
+ if (!NT_SUCCESS (status ))
4213
4208
{
4214
- // Flow was deleted before insertion; we are responsible for cleanup.
4215
4209
KeReleaseInStackQueuedSpinLock (& lock_handle );
4216
4210
windivert_free (flow );
4217
4211
WdfObjectDereference (object );
4218
4212
return ;
4219
4213
}
4214
+ InsertTailList (& context -> flow_set , & flow -> entry );
4220
4215
KeReleaseInStackQueuedSpinLock (& lock_handle );
4221
4216
}
4222
4217
@@ -4243,18 +4238,16 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
4243
4238
{
4244
4239
return ;
4245
4240
}
4246
-
4247
4241
timestamp = KeQueryPerformanceCounter (NULL ).QuadPart ;
4248
4242
context = flow -> context ;
4249
4243
4250
4244
KeAcquireInStackQueuedSpinLock (& context -> lock , & lock_handle );
4251
4245
object = (WDFOBJECT )context -> object ; // referenced in flow_established.
4252
- if (flow -> inserted && !flow -> deleted )
4246
+ cleanup = (context -> state == WINDIVERT_CONTEXT_STATE_OPEN );
4247
+ if (cleanup )
4253
4248
{
4254
4249
RemoveEntryList (& flow -> entry );
4255
4250
}
4256
- flow -> deleted = TRUE;
4257
- cleanup = flow -> inserted ;
4258
4251
if (context -> state != WINDIVERT_CONTEXT_STATE_OPEN ||
4259
4252
context -> shutdown_recv )
4260
4253
{
@@ -4279,12 +4272,12 @@ static void windivert_flow_delete_notify(UINT16 layer_id, UINT32 callout_id,
4279
4272
}
4280
4273
4281
4274
windivert_flow_delete_notify_exit :
4282
-
4283
4275
if (cleanup )
4284
4276
{
4277
+ // If context->state != OPEN, then destroy() will free the flow.
4285
4278
windivert_free (flow );
4286
- WdfObjectDereference (object );
4287
4279
}
4280
+ WdfObjectDereference (object );
4288
4281
}
4289
4282
4290
4283
/*
0 commit comments