我在这里有一个示例 WFP标注驱动程序。它可以通过使用" net start lbtest"来启动和停止。和" net start lbtest"。但是当我将StartType从 3(SERVICE_DEMAND_START)更改为 1(SERVICE_SYSTEM_START)时。我可以正常启动这个驱动程序。但是当系统重新启动时,驱动程序不会启动,如果我运行" net start lbtest",我将得到"系统错误2" 如下:
J:\nmap\mswin32\Debug>net start lbtest
System error 2 has occurred.
我的测试平台是Win8.1 x64。我认为这是世界粮食计划署的一个错误?或者在系统重新启动时使WFP标注驱动程序自动启动的正确方法是什么?
我的INF文件就像:
;
; lbtest.inf
;
[Version]
Signature = "$WINDOWS NT$"
Class = WFPCALLOUTS
ClassGuid = {57465043-616C-6C6F-7574-5F636C617373}
Provider = %LBTest%
CatalogFile = LBTest.cat
[DestinationDirs]
DefaultDestDir = 12
LBTest.DriverFiles = 12
[SourceDisksNames]
1 = %DiskName%,,,""
[SourceDisksFiles]
lbtest.sys = 1,,
[DefaultInstall]
OptionDesc = %LBTestServiceDesc%
CopyFiles = LBTest.DriverFiles
[DefaultInstall.Services]
AddService = %LBTestServiceName%,,LBTest.Service
[DefaultUninstall]
DelFiles = LBTest.DriverFiles
[DefaultUninstall.Services]
DelService = %LBTestServiceName%,0x200 ; SPSVCINST_STOPSERVICE
DelReg = LBTest.DelRegistry
[LBTest.DriverFiles]
lbtest.sys,,,0x00000040 ; COPYFLG_OVERWRITE_OLDER_ONLY
[LBTest.Service]
DisplayName = %LBTestServiceName%
Description = %LBTestServiceDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 1 ; SERVICE_SYSTEM_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\lbtest.sys ; %WinDir%\System32\Drivers\lbtest.sys
AddReg = LBTest.AddRegistry
[LBTest.AddRegistry]
HKR,"Parameters","BlockTraffic",0x00010001,"0" ; FLG_ADDREG_TYPE_DWORD
HKR,"Parameters","RemoteAddressToInspect",0x00000000,"192.168.1.2" ; FLG_ADDREG_TYPE_SZ
[LBTest.DelRegistry]
HKR,"Parameters",,,
[Strings]
LBTest = "LBTest Ltd."
LBTestServiceDesc = "NPcap Loopback Callout Driver"
LBTestServiceName = "LBTest"
DiskName="LBTest Source Disk"
lbtest.c
#include "stdafx.h"
#include <ntddk.h>
#include "Loopback.h"
#include "lbtest.h"
#include "debug.h"
extern HANDLE gWFPEngineHandle;
#ifdef ALLOC_PRAGMA
#pragma NDIS_INIT_FUNCTION(DriverEntry)
#endif // ALLOC_PRAGMA
#if DBG
// Declare the global debug flag for this driver.
ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
#endif
//
// Configurable parameters (addresses and ports are in host order)
//
WCHAR g_NPF_PrefixBuffer[512] = L"NPCAP" L"_";
WCHAR* bindT = NULL;
NDIS_STRING g_NPF_Prefix;
NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
/*!
\brief Port device extension.
Structure containing some data relative to every adapter on which NPF is bound.
*/
typedef struct _DEVICE_EXTENSION
{
NDIS_STRING AdapterName; ///< Name of the adapter.
PWSTR ExportString; ///< Name of the exported device, i.e. name that the applications will use
///< to open this adapter through WinPcap.
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
BOOLEAN
NPF_CreateDevice(
IN OUT PDRIVER_OBJECT adriverObjectP,
IN PUNICODE_STRING amacNameP
)
{
NTSTATUS status;
PDEVICE_OBJECT devObjP;
UNICODE_STRING deviceName;
UNICODE_STRING deviceSymLink;
TRACE_ENTER();
IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer, devicePrefix.Length) < devicePrefix.Length)
{
TRACE_EXIT();
return FALSE;
}
deviceName.Length = 0;
deviceName.MaximumLength = (USHORT)(amacNameP->Length + g_NPF_Prefix.Length + sizeof(UNICODE_NULL));
deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');
if (deviceName.Buffer == NULL)
{
TRACE_EXIT();
return FALSE;
}
deviceSymLink.Length = 0;
deviceSymLink.MaximumLength = (USHORT)(amacNameP->Length - devicePrefix.Length + symbolicLinkPrefix.Length + g_NPF_Prefix.Length + sizeof(UNICODE_NULL));
deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, '3PWA');
if (deviceSymLink.Buffer == NULL)
{
ExFreePool(deviceName.Buffer);
TRACE_EXIT();
return FALSE;
}
RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
RtlAppendUnicodeStringToString(&deviceName, &g_NPF_Prefix);
RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer + devicePrefix.Length / sizeof(WCHAR));
RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
RtlAppendUnicodeStringToString(&deviceSymLink, &g_NPF_Prefix);
RtlAppendUnicodeToString(&deviceSymLink, amacNameP->Buffer + devicePrefix.Length / sizeof(WCHAR));
IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName.Buffer);)
status = IoCreateDevice(adriverObjectP, sizeof(DEVICE_EXTENSION), &deviceName, FILE_DEVICE_TRANSPORT,
FILE_DEVICE_SECURE_OPEN, FALSE, &devObjP);
// UNICODE_STRING sddl = RTL_CONSTANT_STRING(L"D:P(A;;GA;;;SY)(A;;GA;;;BA)");
// const GUID guidClassNPF = { 0x26e0d1e0L, 0x8189, 0x12e0, { 0x99, 0x14, 0x08, 0x00, 0x22, 0x30, 0x19, 0x04 } };
// status = IoCreateDeviceSecure(adriverObjectP, sizeof(DEVICE_EXTENSION), &deviceName, FILE_DEVICE_TRANSPORT,
// FILE_DEVICE_SECURE_OPEN, FALSE, &sddl, (LPCGUID)&guidClassNPF, &devObjP);
if (NT_SUCCESS(status))
{
PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
IF_LOUD(DbgPrint("Device created successfully\n"););
devObjP->Flags |= DO_DIRECT_IO;
RtlInitUnicodeString(&devExtP->AdapterName, amacNameP->Buffer);
IF_LOUD(DbgPrint("Trying to create SymLink %ws\n", deviceSymLink.Buffer););
if (IoCreateSymbolicLink(&deviceSymLink, &deviceName) != STATUS_SUCCESS)
{
IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink.Buffer););
ExFreePool(deviceName.Buffer);
ExFreePool(deviceSymLink.Buffer);
devExtP->ExportString = NULL;
TRACE_EXIT();
return FALSE;
}
IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
devExtP->ExportString = deviceSymLink.Buffer;
ExFreePool(deviceName.Buffer);
TRACE_EXIT();
return TRUE;
}
else
{
IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
ExFreePool(deviceName.Buffer);
ExFreePool(deviceSymLink.Buffer);
TRACE_EXIT();
return FALSE;
}
}
_Use_decl_annotations_
VOID
NPF_Unload(
IN PDRIVER_OBJECT DriverObject
)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT OldDeviceObject;
PDEVICE_EXTENSION DeviceExtension;
NDIS_STRING SymLink;
TRACE_ENTER();
DeviceObject = DriverObject->DeviceObject;
while (DeviceObject != NULL)
{
OldDeviceObject = DeviceObject;
DeviceObject = DeviceObject->NextDevice;
DeviceExtension = OldDeviceObject->DeviceExtension;
TRACE_MESSAGE3(PACKET_DEBUG_LOUD, "Deleting Adapter %ws, Protocol Handle=xxx, Device Obj=%p (%p)", DeviceExtension->AdapterName.Buffer, DeviceObject, OldDeviceObject);
if (DeviceExtension->ExportString)
{
RtlInitUnicodeString(&SymLink, DeviceExtension->ExportString);
TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Deleting SymLink at %p", SymLink.Buffer);
IoDeleteSymbolicLink(&SymLink);
ExFreePool(DeviceExtension->ExportString);
}
IF_LOUD(DbgPrint("Device successfully deleted.\n\n"););
IoDeleteDevice(OldDeviceObject);
}
NPF_UnregisterCallouts();
// Free the adapters names
ExFreePool(bindT);
TRACE_EXIT();
}
_Use_decl_annotations_
NTSTATUS
DriverEntry(
DRIVER_OBJECT* DriverObject,
UNICODE_STRING* RegistryPath
)
{
NTSTATUS Status = STATUS_SUCCESS;
UNICODE_STRING macName;
UNREFERENCED_PARAMETER(RegistryPath);
TRACE_ENTER();
IF_LOUD(DbgPrint("\n\nThis is version [2]!!!.\n");)
bindT = (PWCHAR)ExAllocatePoolWithTag(PagedPool, 4096, 'NPCA');
//RtlCopyUnicodeString(bindT, L"\\Device\\{A22932C9-82CB-4080-993B-D5E82CAD06A7}"); //0006, Microsoft KM-TEST Loopback Adapter;
wcscpy(bindT, L"\\Device\\{A22932C9-82CB-4080-993B-D5E82CAD06A7}");
RtlInitUnicodeString(&macName, bindT);
NdisInitUnicodeString(&g_NPF_Prefix, g_NPF_PrefixBuffer);
DriverObject->DriverUnload = NPF_Unload;
//
// Standard device driver entry points stuff.
//
// DriverObject->MajorFunction[IRP_MJ_CREATE] = NULL;
// DriverObject->MajorFunction[IRP_MJ_CLOSE] = NULL;
// DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NULL;
// DriverObject->MajorFunction[IRP_MJ_READ] = NULL;
// DriverObject->MajorFunction[IRP_MJ_WRITE] = NULL;
// DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NULL;
Status = NPF_CreateDevice(DriverObject, &macName) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
if (Status != STATUS_SUCCESS)
{
IF_LOUD(DbgPrint("Failed to create WFP device.\n");)
TRACE_EXIT();
return STATUS_SUCCESS;
}
if (DriverObject->DeviceObject)
{
Status = NPF_RegisterCallouts(DriverObject->DeviceObject);
if (!NT_SUCCESS(Status))
{
if (gWFPEngineHandle != NULL)
{
NPF_UnregisterCallouts();
}
TRACE_EXIT();
return Status;
}
}
TRACE_EXIT();
return STATUS_SUCCESS;
};
loopback.c
#include "stdafx.h"
#include "Loopback.h"
#include "debug.h"
#define NPCAP_CALLOUT_DRIVER_TAG (UINT32) 'NPCA'
//
// Callout and sublayer GUIDs
//
// 2D605B3E-C244-4364-86E8-BD81E6C91B6D
DEFINE_GUID(
NPF_OUTBOUND_IPPACKET_CALLOUT_V4,
0x2d605b3e,
0xc244,
0x4364,
0x86, 0xe8, 0xbd, 0x81, 0xe6, 0xc9, 0x1b, 0x6d
);
// F935E4CD-9499-4934-824D-8E3726BA4A93
DEFINE_GUID(
NPF_OUTBOUND_IPPACKET_CALLOUT_V6,
0xf935e4cd,
0x9499,
0x4934,
0x82, 0x4d, 0x8e, 0x37, 0x26, 0xba, 0x4a, 0x93
);
// ED7E5EB2-6B09-4783-961C-5495EAAD361E
DEFINE_GUID(
NPF_INBOUND_IPPACKET_CALLOUT_V4,
0xed7e5eb2,
0x6b09,
0x4783,
0x96, 0x1c, 0x54, 0x95, 0xea, 0xad, 0x36, 0x1e
);
// 21022F40-9578-4C39-98A5-C97B8D834E27
DEFINE_GUID(
NPF_INBOUND_IPPACKET_CALLOUT_V6,
0x21022f40,
0x9578,
0x4c39,
0x98, 0xa5, 0xc9, 0x7b, 0x8d, 0x83, 0x4e, 0x27
);
// 2F32C254-A054-469B-B99B-3E8810275A71
DEFINE_GUID(
NPF_SUBLAYER,
0x2f32c254,
0xa054,
0x469b,
0xb9, 0x9b, 0x3e, 0x88, 0x10, 0x27, 0x5a, 0x71
);
//
// Callout driver global variables
//
HANDLE gWFPEngineHandle;
UINT32 gOutboundIPPacketV4 = 0;
UINT32 gOutboundIPPacketV6 = 0;
UINT32 gInboundIPPacketV4 = 0;
UINT32 gInboundIPPacketV6 = 0;
typedef struct CLASSIFY_DATA_
{
const FWPS_INCOMING_VALUES* pClassifyValues;
const FWPS_INCOMING_METADATA_VALUES* pMetadataValues;
VOID* pPacket; /// NET_BUFFER_LIST | FWPS_STREAM_CALLOUT_IO_PACKET
const VOID* pClassifyContext;
const FWPS_FILTER* pFilter;
UINT64 flowContext;
FWPS_CLASSIFY_OUT* pClassifyOut;
UINT64 classifyContextHandle;
BOOLEAN chainedNBL;
UINT32 numChainedNBLs;
}CLASSIFY_DATA, *PCLASSIFY_DATA;
/* ++
This is the classifyFn function for the Transport (v4 and v6) callout.
packets (inbound or outbound) are ueued to the packet queue to be processed
by the worker thread.
-- */
void
NPF_NetworkClassify(
_In_ const FWPS_INCOMING_VALUES* inFixedValues,
_In_ const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
_Inout_opt_ void* layerData,
_In_opt_ const void* classifyContext,
_In_ const FWPS_FILTER* filter,
_In_ UINT64 flowContext,
_Inout_ FWPS_CLASSIFY_OUT* classifyOut
)
#else
void
NPF_NetworkClassify(
_In_ const FWPS_INCOMING_VALUES* inFixedValues,
_In_ const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
_Inout_opt_ void* layerData,
_In_ const FWPS_FILTER* filter,
_In_ UINT64 flowContext,
_Inout_ FWPS_CLASSIFY_OUT* classifyOut
)
#endif
{
UNREFERENCED_PARAMETER(classifyContext);
UNREFERENCED_PARAMETER(filter);
UNREFERENCED_PARAMETER(flowContext);
// filter out fragment packets and reassembled packets.
if (inMetaValues->currentMetadataValues & FWPS_METADATA_FIELD_FRAGMENT_DATA)
{
return;
}
if (inMetaValues->currentMetadataValues & FWP_CONDITION_FLAG_IS_REASSEMBLED)
{
return;
}
TRACE_ENTER();
// make the default action.
if (classifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
classifyOut->actionType = FWP_ACTION_CONTINUE;
inMetaValues->frameLength;
layerData;
// print "protocol, direction, fragment, reassembled" info for the current packet.
int iProtocol = -1;
if (inFixedValues->layerId == FWPS_LAYER_OUTBOUND_IPPACKET_V4 || inFixedValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V4)
{
iProtocol = 0;
}
else if (inFixedValues->layerId == FWPS_LAYER_OUTBOUND_IPPACKET_V6 || inFixedValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V6)
{
iProtocol = 1;
}
int iDrection = -1;
if (inFixedValues->layerId == FWPS_LAYER_OUTBOUND_IPPACKET_V4 || inFixedValues->layerId == FWPS_LAYER_OUTBOUND_IPPACKET_V6)
{
iDrection = 0;
}
else if (inFixedValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V4 || inFixedValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V6)
{
iDrection = 1;
}
int iFragment = -1;
if (inMetaValues->currentMetadataValues & FWPS_METADATA_FIELD_FRAGMENT_DATA)
{
iFragment = 1;
}
else
{
iFragment = 0;
}
int iReassembled = -1;
if (inMetaValues->currentMetadataValues & FWP_CONDITION_FLAG_IS_REASSEMBLED)
{
iReassembled = 1;
}
else
{
iReassembled = 0;
}
IF_LOUD(DbgPrint("\n\nNPF_NetworkClassify: Loopback packet found !!! protocol=[%d] (ipv4=0, ipv6=1), direction=[%d] (out=0, in=1), fragment=[%d], reassembled=[%d]\n", iProtocol, iDrection, iFragment, iReassembled);)
TRACE_EXIT();
return;
}
NTSTATUS
NPF_NetworkNotify(
_In_ FWPS_CALLOUT_NOTIFY_TYPE notifyType,
_In_ const GUID* filterKey,
_Inout_ const FWPS_FILTER* filter
)
{
UNREFERENCED_PARAMETER(notifyType);
UNREFERENCED_PARAMETER(filterKey);
UNREFERENCED_PARAMETER(filter);
TRACE_ENTER();
TRACE_EXIT();
return STATUS_SUCCESS;
}
//
// Callout driver implementation
//
NTSTATUS
NPF_AddFilter(
_In_ const GUID* layerKey,
_In_ const GUID* calloutKey,
_In_ const int iFlag
)
{
TRACE_ENTER();
NTSTATUS status = STATUS_SUCCESS;
FWPM_FILTER filter = { 0 };
FWPM_FILTER_CONDITION filterConditions[1] = { 0 };
UINT conditionIndex;
filter.layerKey = *layerKey;
filter.displayData.name = L"Network NPcap Filter (Outbound)";
filter.displayData.description = L"NPcap inbound/outbound network traffic";
filter.action.calloutKey = *calloutKey;
filter.filterCondition = filterConditions;
filter.subLayerKey = NPF_SUBLAYER;
filter.rawContext = 0;
conditionIndex = 0;
if (iFlag == 0)
{
filter.action.type = FWP_ACTION_PERMIT;
filter.weight.type = FWP_UINT8;
filter.weight.uint8 = 0x5;
filterConditions[conditionIndex].fieldKey = FWPM_CONDITION_FLAGS;
filterConditions[conditionIndex].matchType = FWP_MATCH_FLAGS_NONE_SET;
filterConditions[conditionIndex].conditionValue.type = FWP_UINT32;
filterConditions[conditionIndex].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_LOOPBACK;
conditionIndex++;
}
else if (iFlag == 1)
{
filter.action.type = FWP_ACTION_PERMIT;
filter.weight.type = FWP_UINT8;
filter.weight.uint8 = 0x4;
filterConditions[conditionIndex].fieldKey = FWPM_CONDITION_FLAGS;
filterConditions[conditionIndex].matchType = FWP_MATCH_FLAGS_ALL_SET;
filterConditions[conditionIndex].conditionValue.type = FWP_UINT32;
filterConditions[conditionIndex].conditionValue.uint32 = FWPS_METADATA_FIELD_FRAGMENT_DATA;
conditionIndex++;
}
else if (iFlag == 2)
{
filter.action.type = FWP_ACTION_PERMIT;
filter.weight.type = FWP_UINT8;
filter.weight.uint8 = 0x3;
filterConditions[conditionIndex].fieldKey = FWPM_CONDITION_FLAGS;
filterConditions[conditionIndex].matchType = FWP_MATCH_FLAGS_ALL_SET;
filterConditions[conditionIndex].conditionValue.type = FWP_UINT32;
filterConditions[conditionIndex].conditionValue.uint32 = FWP_CONDITION_FLAG_IS_REASSEMBLED;
conditionIndex++;
}
else if (iFlag == 3)
{
filter.action.type = FWP_ACTION_CALLOUT_INSPECTION;
filter.weight.type = FWP_UINT8;
filter.weight.uint8 = 0x2;
filter.filterCondition = NULL;
}
// else if (iFlag == 1)
// {
// filter.action.type = FWP_ACTION_CALLOUT_INSPECTION;
// filter.weight.type = FWP_UINT8;
// filter.weight.uint8 = 0x4;
// filterConditions[conditionIndex].fieldKey = FWPM_CONDITION_FLAGS;
// filterConditions[conditionIndex].matchType = FWP_MATCH_FLAGS_NONE_SET;
// filterConditions[conditionIndex].conditionValue.type = FWP_UINT32;
// filterConditions[conditionIndex].conditionValue.uint32 = FWPS_METADATA_FIELD_FRAGMENT_DATA | FWP_CONDITION_FLAG_IS_REASSEMBLED;
// conditionIndex++;
// }
filter.numFilterConditions = conditionIndex;
status = FwpmFilterAdd(
gWFPEngineHandle,
&filter,
NULL,
NULL);
TRACE_EXIT();
return status;
}
NTSTATUS
NPF_RegisterCallout(
_In_ const GUID* layerKey,
_In_ const GUID* calloutKey,
_Inout_ void* deviceObject,
_Out_ UINT32* calloutId
)
/* ++
This function registers callouts and filters that intercept transport
traffic at the following layers --
FWPM_LAYER_INBOUND_IPPACKET_V4
FWPM_LAYER_INBOUND_IPPACKET_V6
FWPM_LAYER_OUTBOUND_IPPACKET_V4
FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD
-- */
{
TRACE_ENTER();
NTSTATUS status = STATUS_SUCCESS;
FWPS_CALLOUT sCallout = { 0 };
FWPM_CALLOUT mCallout = { 0 };
FWPM_DISPLAY_DATA displayData = { 0 };
BOOLEAN calloutRegistered = FALSE;
sCallout.calloutKey = *calloutKey;
sCallout.classifyFn = NPF_NetworkClassify;
sCallout.notifyFn = NPF_NetworkNotify;
status = FwpsCalloutRegister(
deviceObject,
&sCallout,
calloutId
);
if (!NT_SUCCESS(status))
{
goto Exit;
}
calloutRegistered = TRUE;
displayData.name = L"NPcap Network Callout";
displayData.description = L"NPcap inbound/outbound network traffic";
mCallout.calloutKey = *calloutKey;
mCallout.displayData = displayData;
mCallout.applicableLayer = *layerKey;
status = FwpmCalloutAdd(
gWFPEngineHandle,
&mCallout,
NULL,
NULL
);
if (!NT_SUCCESS(status))
{
goto Exit;
}
status = NPF_AddFilter(layerKey, calloutKey, 0);
if (!NT_SUCCESS(status))
{
goto Exit;
}
status = NPF_AddFilter(layerKey, calloutKey, 1);
if (!NT_SUCCESS(status))
{
goto Exit;
}
status = NPF_AddFilter(layerKey, calloutKey, 2);
if (!NT_SUCCESS(status))
{
goto Exit;
}
status = NPF_AddFilter(layerKey, calloutKey, 3);
if (!NT_SUCCESS(status))
{
goto Exit;
}
Exit:
if (!NT_SUCCESS(status))
{
IF_LOUD(DbgPrint("NPF_RegisterCallout: failed to register callout\n");)
if (calloutRegistered)
{
FwpsCalloutUnregisterById(*calloutId);
*calloutId = 0;
}
}
TRACE_EXIT();
return status;
}
NTSTATUS
NPF_RegisterCallouts(
_Inout_ void* deviceObject
)
/* ++
This function registers dynamic callouts and filters that intercept
transport traffic at ALE AUTH_CONNECT/AUTH_RECV_ACCEPT and
INBOUND/OUTBOUND transport layers.
Callouts and filters will be removed during DriverUnload.
-- */
{
TRACE_ENTER();
NTSTATUS status = STATUS_SUCCESS;
FWPM_SUBLAYER NPFSubLayer;
BOOLEAN engineOpened = FALSE;
BOOLEAN inTransaction = FALSE;
FWPM_SESSION session = { 0 };
session.flags = FWPM_SESSION_FLAG_DYNAMIC;
status = FwpmEngineOpen(
NULL,
RPC_C_AUTHN_WINNT,
NULL,
&session,
&gWFPEngineHandle
);
if (!NT_SUCCESS(status))
{
goto Exit;
}
engineOpened = TRUE;
status = FwpmTransactionBegin(gWFPEngineHandle, 0);
if (!NT_SUCCESS(status))
{
goto Exit;
}
inTransaction = TRUE;
RtlZeroMemory(&NPFSubLayer, sizeof(FWPM_SUBLAYER));
NPFSubLayer.subLayerKey = NPF_SUBLAYER;
NPFSubLayer.displayData.name = L"NPcap Loopback Sub-Layer";
NPFSubLayer.displayData.description = L"Sub-Layer for use by NPcap Loopback callouts";
NPFSubLayer.flags = 0;
NPFSubLayer.weight = 0; // must be less than the weight of
// FWPM_SUBLAYER_UNIVERSAL to be
// compatible with Vista's IpSec
// implementation.
status = FwpmSubLayerAdd(gWFPEngineHandle, &NPFSubLayer, NULL);
if (!NT_SUCCESS(status))
{
goto Exit;
}
//if (isV4)
{
status = NPF_RegisterCallout(
&FWPM_LAYER_OUTBOUND_IPPACKET_V4,
&NPF_OUTBOUND_IPPACKET_CALLOUT_V4,
deviceObject,
&gOutboundIPPacketV4
);
if (!NT_SUCCESS(status))
{
goto Exit;
}
status = NPF_RegisterCallout(
&FWPM_LAYER_INBOUND_IPPACKET_V4,
&NPF_INBOUND_IPPACKET_CALLOUT_V4,
deviceObject,
&gInboundIPPacketV4
);
if (!NT_SUCCESS(status))
{
goto Exit;
}
}
//else
{
status = NPF_RegisterCallout(
&FWPM_LAYER_OUTBOUND_IPPACKET_V6,
&NPF_OUTBOUND_IPPACKET_CALLOUT_V6,
deviceObject,
&gOutboundIPPacketV6
);
if (!NT_SUCCESS(status))
{
goto Exit;
}
status = NPF_RegisterCallout(
&FWPM_LAYER_INBOUND_IPPACKET_V6,
&NPF_INBOUND_IPPACKET_CALLOUT_V6,
deviceObject,
&gInboundIPPacketV6
);
if (!NT_SUCCESS(status))
{
goto Exit;
}
}
status = FwpmTransactionCommit(gWFPEngineHandle);
if (!NT_SUCCESS(status))
{
goto Exit;
}
inTransaction = FALSE;
Exit:
if (!NT_SUCCESS(status))
{
IF_LOUD(DbgPrint("NPF_RegisterCallouts: failed to register callouts\n");)
if (inTransaction)
{
FwpmTransactionAbort(gWFPEngineHandle);
_Analysis_assume_lock_not_held_(gWFPEngineHandle); // Potential leak if "FwpmTransactionAbort" fails
}
if (engineOpened)
{
FwpmEngineClose(gWFPEngineHandle);
gWFPEngineHandle = NULL;
}
}
TRACE_EXIT();
return status;
}
void
NPF_UnregisterCallouts(
)
{
TRACE_ENTER();
if (gWFPEngineHandle)
{
FwpmEngineClose(gWFPEngineHandle);
gWFPEngineHandle = NULL;
}
if (gOutboundIPPacketV4)
{
FwpsCalloutUnregisterById(gOutboundIPPacketV4);
}
if (gOutboundIPPacketV6)
{
FwpsCalloutUnregisterById(gOutboundIPPacketV6);
}
if (gInboundIPPacketV4)
{
FwpsCalloutUnregisterById(gInboundIPPacketV4);
}
if (gInboundIPPacketV6)
{
FwpsCalloutUnregisterById(gInboundIPPacketV6);
}
TRACE_EXIT();
}