@@ -339,6 +339,8 @@ extern VOID windivert_create(IN WDFDEVICE device, IN WDFREQUEST request,
339
339
static NTSTATUS windivert_install_sublayer (layer_t layer );
340
340
static NTSTATUS windivert_install_callouts (context_t context , UINT8 layer ,
341
341
UINT64 flags );
342
+ static NTSTATUS windivert_install_callout (context_t context , UINT idx ,
343
+ layer_t layer , UINT32 * callout_id_ptr );
342
344
static void windivert_uninstall_callouts (context_t context ,
343
345
context_state_t state );
344
346
extern VOID windivert_cleanup (IN WDFFILEOBJECT object );
@@ -1224,6 +1226,7 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
1224
1226
if (!NT_SUCCESS (status ))
1225
1227
{
1226
1228
DEBUG_ERROR ("failed to begin WFP transaction" , status );
1229
+ FwpmTransactionAbort0 (engine_handle );
1227
1230
goto driver_entry_exit ;
1228
1231
}
1229
1232
status = windivert_install_sublayer (
@@ -1347,6 +1350,7 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
1347
1350
if (!NT_SUCCESS (status ))
1348
1351
{
1349
1352
DEBUG_ERROR ("failed to commit WFP transaction" , status );
1353
+ FwpmTransactionAbort0 (engine_handle );
1350
1354
goto driver_entry_exit ;
1351
1355
}
1352
1356
@@ -1482,6 +1486,7 @@ static void windivert_driver_unload(void)
1482
1486
if (!NT_SUCCESS (status ))
1483
1487
{
1484
1488
DEBUG_ERROR ("failed to commit WFP transaction" , status );
1489
+ FwpmTransactionAbort0 (engine_handle );
1485
1490
}
1486
1491
FwpmEngineClose0 (engine_handle );
1487
1492
}
@@ -1653,17 +1658,10 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
1653
1658
KLOCK_QUEUE_HANDLE lock_handle ;
1654
1659
UINT8 i , j ;
1655
1660
layer_t layers [WINDIVERT_CONTEXT_MAXLAYERS ];
1656
- UINT32 callout_ids [WINDIVERT_CONTEXT_MAXLAYERS ] = {0 };
1661
+ UINT32 * callout_ids [WINDIVERT_CONTEXT_MAXLAYERS ] = {NULL };
1657
1662
BOOL inbound , outbound , ipv4 , ipv6 , bind , connect , listen ,
1658
1663
accept , close ;
1659
1664
HANDLE engine = NULL ;
1660
- FWPS_CALLOUT0 scallout ;
1661
- FWPM_CALLOUT0 mcallout ;
1662
- FWPM_FILTER0 filter ;
1663
- UINT64 weight ;
1664
- UINT32 priority ;
1665
- GUID callout_guid , filter_guid ;
1666
- WDFDEVICE device ;
1667
1665
NTSTATUS status = STATUS_SUCCESS ;
1668
1666
1669
1667
inbound = ((flags & WINDIVERT_FILTER_FLAG_INBOUND ) != 0 );
@@ -1723,10 +1721,12 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
1723
1721
case WINDIVERT_LAYER_FLOW :
1724
1722
if (ipv4 )
1725
1723
{
1724
+ callout_ids [i ] = & context -> flow_v4_callout_id ;
1726
1725
layers [i ++ ] = WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV4 ;
1727
1726
}
1728
1727
if (ipv6 )
1729
1728
{
1729
+ callout_ids [i ] = & context -> flow_v6_callout_id ;
1730
1730
layers [i ++ ] = WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV6 ;
1731
1731
}
1732
1732
break ;
@@ -1769,7 +1769,6 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
1769
1769
{
1770
1770
layers [i ++ ] = WINDIVERT_LAYER_AUTH_RECV_ACCEPT_IPV6 ;
1771
1771
}
1772
-
1773
1772
if (ipv6 && close )
1774
1773
{
1775
1774
layers [i ++ ] = WINDIVERT_LAYER_RESOURCE_RELEASE_IPV6 ;
@@ -1778,64 +1777,23 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
1778
1777
break ;
1779
1778
1780
1779
case WINDIVERT_LAYER_REFLECT :
1781
- return STATUS_SUCCESS ;
1780
+ break ;
1782
1781
1783
1782
default :
1784
1783
return STATUS_INVALID_PARAMETER ;
1785
1784
}
1786
1785
1787
1786
if (i == 0 )
1788
1787
{
1789
- // Nothing to do...
1790
1788
return STATUS_SUCCESS ;
1791
1789
}
1792
1790
1793
- // Register the callouts:
1794
1791
KeAcquireInStackQueuedSpinLock (& context -> lock , & lock_handle );
1795
- for (j = 0 ; j < i ; j ++ )
1796
- {
1797
- if (context -> state != WINDIVERT_CONTEXT_STATE_OPEN )
1798
- {
1799
- KeReleaseInStackQueuedSpinLock (& lock_handle );
1800
- status = STATUS_INVALID_DEVICE_STATE ;
1801
- goto windivert_install_callouts_error ;
1802
- }
1803
- device = context -> device ;
1804
- RtlCopyMemory (& callout_guid , & context -> callout_guid [j ],
1805
- sizeof (callout_guid ));
1806
- KeReleaseInStackQueuedSpinLock (& lock_handle );
1807
-
1808
- RtlZeroMemory (& scallout , sizeof (scallout ));
1809
- scallout .calloutKey = callout_guid ;
1810
- scallout .classifyFn = layers [j ]-> classify ;
1811
- scallout .notifyFn = windivert_notify ;
1812
- scallout .flowDeleteFn = layers [j ]-> flow_delete ;
1813
-
1814
- status = FwpsCalloutRegister0 (WdfDeviceWdmGetDeviceObject (device ),
1815
- & scallout , callout_ids + j );
1816
- if (!NT_SUCCESS (status ))
1817
- {
1818
- goto windivert_install_callouts_error ;
1819
- }
1820
-
1821
- DEBUG ("REGISTER: callout %ls" , layers [j ]-> callout_name );
1822
-
1823
- KeAcquireInStackQueuedSpinLock (& context -> lock , & lock_handle );
1824
- context -> installed [j ] = TRUE;
1825
- if (layers [j ] == WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV4 )
1826
- {
1827
- context -> flow_v4_callout_id = callout_ids [j ];
1828
- }
1829
- else if (layers [j ] == WINDIVERT_LAYER_FLOW_ESTABLISHED_IPV6 )
1830
- {
1831
- context -> flow_v6_callout_id = callout_ids [j ];
1832
- }
1833
- }
1834
1792
if (context -> state != WINDIVERT_CONTEXT_STATE_OPEN )
1835
1793
{
1836
1794
KeReleaseInStackQueuedSpinLock (& lock_handle );
1837
1795
status = STATUS_INVALID_DEVICE_STATE ;
1838
- goto windivert_install_callouts_error ;
1796
+ return status ;
1839
1797
}
1840
1798
engine = context -> engine_handle ;
1841
1799
KeReleaseInStackQueuedSpinLock (& lock_handle );
@@ -1849,82 +1807,136 @@ static NTSTATUS windivert_install_callouts(context_t context, UINT8 layer,
1849
1807
if (!NT_SUCCESS (status ))
1850
1808
{
1851
1809
DEBUG_ERROR ("failed to begin WFP transaction" , status );
1852
- goto windivert_install_callouts_error ;
1810
+ engine = NULL ;
1811
+ goto windivert_install_callouts_exit ;
1853
1812
}
1854
1813
for (j = 0 ; j < i ; j ++ )
1855
1814
{
1856
- KeAcquireInStackQueuedSpinLock (& context -> lock , & lock_handle );
1857
- if (context -> state != WINDIVERT_CONTEXT_STATE_OPEN )
1858
- {
1859
- KeReleaseInStackQueuedSpinLock (& lock_handle );
1860
- status = STATUS_INVALID_DEVICE_STATE ;
1861
- goto windivert_install_callouts_error ;
1862
- }
1863
- priority = context -> priority ;
1864
- RtlCopyMemory (& callout_guid , & context -> callout_guid [j ],
1865
- sizeof (callout_guid ));
1866
- RtlCopyMemory (& filter_guid , & context -> filter_guid [j ],
1867
- sizeof (filter_guid ));
1868
- KeReleaseInStackQueuedSpinLock (& lock_handle );
1869
-
1870
- weight = (UINT64 )priority ;
1871
-
1872
- RtlZeroMemory (& mcallout , sizeof (mcallout ));
1873
- mcallout .calloutKey = callout_guid ;
1874
- mcallout .displayData .name = layers [j ]-> callout_name ;
1875
- mcallout .displayData .description = layers [j ]-> callout_desc ;
1876
- mcallout .applicableLayer = * (layers [j ]-> layer_guid );
1877
- RtlZeroMemory (& filter , sizeof (filter ));
1878
- filter .filterKey = filter_guid ;
1879
- filter .layerKey = * (layers [j ]-> layer_guid );
1880
- filter .displayData .name = layers [j ]-> filter_name ;
1881
- filter .displayData .description = layers [j ]-> filter_desc ;
1882
- filter .action .type = FWP_ACTION_CALLOUT_UNKNOWN ;
1883
- filter .action .calloutKey = callout_guid ;
1884
- filter .subLayerKey = * (layers [j ]-> sublayer_guid );
1885
- filter .weight .type = FWP_UINT64 ;
1886
- filter .weight .uint64 = & weight ;
1887
- filter .rawContext = (UINT64 )context ;
1888
-
1889
- status = FwpmCalloutAdd0 (engine , & mcallout , NULL , NULL );
1815
+ status = windivert_install_callout (context , j , layers [j ],
1816
+ callout_ids [j ]);
1890
1817
if (!NT_SUCCESS (status ))
1891
1818
{
1892
- DEBUG_ERROR ("failed to add WFP callout" , status );
1893
- goto windivert_install_callouts_error ;
1819
+ goto windivert_install_callouts_exit ;
1894
1820
}
1895
- status = FwpmFilterAdd0 (engine , & filter , NULL , NULL );
1896
- if (!NT_SUCCESS (status ))
1897
- {
1898
- DEBUG_ERROR ("failed to add WFP filter" , status );
1899
- goto windivert_install_callouts_error ;
1900
- }
1901
-
1902
- DEBUG ("INSTALL: callout %ls" , layers [j ]-> callout_name );
1903
1821
}
1904
1822
status = FwpmTransactionCommit0 (engine );
1905
1823
if (!NT_SUCCESS (status ))
1906
1824
{
1907
1825
DEBUG_ERROR ("failed to commit WFP transaction" , status );
1908
- goto windivert_install_callouts_error ;
1826
+ goto windivert_install_callouts_exit ;
1909
1827
}
1828
+ engine = NULL ;
1910
1829
1911
- return status ;
1912
-
1913
- windivert_install_callouts_error :
1830
+ windivert_install_callouts_exit :
1914
1831
1915
1832
if (engine != NULL )
1916
1833
{
1917
1834
FwpmTransactionAbort0 (engine );
1918
1835
}
1919
- for ( j = 0 ; j < i ; j ++ )
1836
+ if (! NT_SUCCESS ( status ) )
1920
1837
{
1921
- if (callout_ids [j ] == 0 )
1922
- {
1923
- continue ;
1924
- }
1925
- FwpsCalloutUnregisterById0 (callout_ids [j ]);
1838
+ windivert_uninstall_callouts (context , WINDIVERT_CONTEXT_STATE_OPEN );
1839
+ }
1840
+
1841
+ return status ;
1842
+ }
1843
+
1844
+ /*
1845
+ * Register a WFP callout.
1846
+ */
1847
+ static NTSTATUS windivert_install_callout (context_t context , UINT idx ,
1848
+ layer_t layer , UINT32 * callout_id_ptr )
1849
+ {
1850
+ KLOCK_QUEUE_HANDLE lock_handle ;
1851
+ FWPS_CALLOUT0 scallout ;
1852
+ FWPM_CALLOUT0 mcallout ;
1853
+ FWPM_FILTER0 filter ;
1854
+ UINT64 weight ;
1855
+ UINT32 priority ;
1856
+ GUID callout_guid , filter_guid ;
1857
+ UINT32 callout_id ;
1858
+ WDFDEVICE device ;
1859
+ HANDLE engine ;
1860
+ NTSTATUS status ;
1861
+
1862
+ KeAcquireInStackQueuedSpinLock (& context -> lock , & lock_handle );
1863
+ if (context -> state != WINDIVERT_CONTEXT_STATE_OPEN )
1864
+ {
1865
+ KeReleaseInStackQueuedSpinLock (& lock_handle );
1866
+ status = STATUS_INVALID_DEVICE_STATE ;
1867
+ return status ;
1868
+ }
1869
+ priority = context -> priority ;
1870
+ callout_guid = context -> callout_guid [idx ];
1871
+ filter_guid = context -> filter_guid [idx ];
1872
+ device = context -> device ;
1873
+ engine = context -> engine_handle ;
1874
+ KeReleaseInStackQueuedSpinLock (& lock_handle );
1875
+
1876
+ weight = (UINT64 )priority ;
1877
+
1878
+ RtlZeroMemory (& scallout , sizeof (scallout ));
1879
+ scallout .calloutKey = callout_guid ;
1880
+ scallout .classifyFn = layer -> classify ;
1881
+ scallout .notifyFn = windivert_notify ;
1882
+ scallout .flowDeleteFn = layer -> flow_delete ;
1883
+ RtlZeroMemory (& mcallout , sizeof (mcallout ));
1884
+ mcallout .calloutKey = callout_guid ;
1885
+ mcallout .displayData .name = layer -> callout_name ;
1886
+ mcallout .displayData .description = layer -> callout_desc ;
1887
+ mcallout .applicableLayer = * (layer -> layer_guid );
1888
+ RtlZeroMemory (& filter , sizeof (filter ));
1889
+ filter .filterKey = filter_guid ;
1890
+ filter .layerKey = * (layer -> layer_guid );
1891
+ filter .displayData .name = layer -> filter_name ;
1892
+ filter .displayData .description = layer -> filter_desc ;
1893
+ filter .action .type = FWP_ACTION_CALLOUT_UNKNOWN ;
1894
+ filter .action .calloutKey = callout_guid ;
1895
+ filter .subLayerKey = * (layer -> sublayer_guid );
1896
+ filter .weight .type = FWP_UINT64 ;
1897
+ filter .weight .uint64 = & weight ;
1898
+ filter .rawContext = (UINT64 )context ;
1899
+ status = FwpsCalloutRegister0 (WdfDeviceWdmGetDeviceObject (device ),
1900
+ & scallout , & callout_id );
1901
+ if (!NT_SUCCESS (status ))
1902
+ {
1903
+ DEBUG_ERROR ("failed to install WFP callout" , status );
1904
+ return status ;
1905
+ }
1906
+ if (callout_id_ptr != NULL )
1907
+ {
1908
+ KeAcquireInStackQueuedSpinLock (& context -> lock , & lock_handle );
1909
+ * callout_id_ptr = callout_id ;
1910
+ KeReleaseInStackQueuedSpinLock (& lock_handle );
1911
+ }
1912
+ status = FwpmCalloutAdd0 (engine , & mcallout , NULL , NULL );
1913
+ if (!NT_SUCCESS (status ))
1914
+ {
1915
+ DEBUG_ERROR ("failed to add WFP callout" , status );
1916
+ goto windivert_install_callout_error ;
1917
+ }
1918
+ status = FwpmFilterAdd0 (engine , & filter , NULL , NULL );
1919
+ if (!NT_SUCCESS (status ))
1920
+ {
1921
+ DEBUG_ERROR ("failed to add WFP filter" , status );
1922
+ goto windivert_install_callout_error ;
1926
1923
}
1927
1924
1925
+ KeAcquireInStackQueuedSpinLock (& context -> lock , & lock_handle );
1926
+ if (context -> state != WINDIVERT_CONTEXT_STATE_OPEN )
1927
+ {
1928
+ KeReleaseInStackQueuedSpinLock (& lock_handle );
1929
+ FwpsCalloutUnregisterByKey0 (& callout_guid );
1930
+ status = STATUS_INVALID_DEVICE_STATE ;
1931
+ return status ;
1932
+ }
1933
+ context -> installed [idx ] = TRUE;
1934
+ KeReleaseInStackQueuedSpinLock (& lock_handle );
1935
+
1936
+ return STATUS_SUCCESS ;
1937
+
1938
+ windivert_install_callout_error :
1939
+ FwpsCalloutUnregisterByKey0 (& callout_guid );
1928
1940
return status ;
1929
1941
}
1930
1942
@@ -2939,7 +2951,7 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
2939
2951
{
2940
2952
case WINDIVERT_LAYER_ETHERNET :
2941
2953
2942
- // Ethernet inject requires the WFP filters to remain valid.
2954
+ // Ethernet inject requires the WFP filters to be valid.
2943
2955
// Thus, we increment the ref count for the context object
2944
2956
// until the inject is completed. This prevents the filter
2945
2957
// from being removed until the injection has completed.
@@ -2969,6 +2981,7 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
2969
2981
addr [i ].Ethernet .IfIdx , addr [i ].Ethernet .SubIfIdx ,
2970
2982
buffers , windivert_inject_complete , object );
2971
2983
}
2984
+
2972
2985
if (!NT_SUCCESS (status ))
2973
2986
{
2974
2987
WdfObjectDereference (object );
0 commit comments