1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-23 01:49:53 +03:00
SoftEtherVPN/src/See/Packet.c

1644 lines
44 KiB
C

/*
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
* Copyright (c) 2005 CACE Technologies, Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Politecnico di Torino, CACE Technologies
* nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <GlobalConst.h>
#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#include "ntddpack.h"
#include "debug.h"
#include "packet.h"
#include "win_bpf.h"
#include "win_bpf_filter_init.h"
#if DBG
// Declare the global debug flag for this driver.
ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
#endif
PDEVICE_EXTENSION GlobalDeviceExtension;
//
// Global strings
//
NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("SEE_");
NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
/// Global variable that points to the names of the bound adapters
WCHAR* bindP = NULL;
extern struct time_conv G_Start_Time; // from openclos.c
extern NDIS_SPIN_LOCK Opened_Instances_Lock;
ULONG NCpu = 1;
ULONG TimestampMode;
UINT g_SendPacketFlags = 0;
// Crush now
void Crush(UINT a, UINT b, UINT c, UINT d)
{
KeBugCheckEx(0x3f000000 + a, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
}
//
// Packet Driver's entry routine.
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
PDEVICE_OBJECT DeviceObject = NULL;
PDEVICE_EXTENSION DeviceExtension = NULL;
NTSTATUS Status = STATUS_SUCCESS;
NTSTATUS ErrorCode = STATUS_SUCCESS;
NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
ULONG DevicesCreated=0;
NDIS_HANDLE NdisProtocolHandle;
WCHAR* bindT;
PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
UNICODE_STRING macName;
ULONG OsMajorVersion, OsMinorVersion;
PsGetVersion(&OsMajorVersion, &OsMinorVersion, NULL, NULL);
//
// Define the correct flag to skip the loopback packets, according to the OS
//
if((OsMajorVersion == 5) && (OsMinorVersion == 0))
{
// Windows 2000 wants both NDIS_FLAGS_DONT_LOOPBACK and NDIS_FLAGS_SKIP_LOOPBACK
g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK | NDIS_FLAGS_SKIP_LOOPBACK_W2K;
}
else
{
// Windows XP, 2003 and following want only NDIS_FLAGS_DONT_LOOPBACK
g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK;
}
if (((OsMajorVersion == 6) && (OsMinorVersion >= 1)) || (OsMajorVersion >= 7))
{
// Use KeQueryActiveProcessors to get the number of CPUs in Windows 7 or later
KAFFINITY cpus = KeQueryActiveProcessors();
NCpu = 0;
while (cpus)
{
if (cpus % 2)
{
NCpu++;
}
cpus = cpus / 2;
}
}
else
{
// Use NdisSystemProcessorCount in Windows Vista or earlier
NCpu = NdisSystemProcessorCount();
}
ReadTimeStampModeFromRegistry(RegistryPath);
IF_LOUD(DbgPrint("%ws",RegistryPath->Buffer);)
IF_LOUD(DbgPrint("\n\nPacket: DriverEntry\n");)
RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
#ifdef NDIS50
ProtocolChar.MajorNdisVersion = 5;
#else
ProtocolChar.MajorNdisVersion = 3;
#endif
ProtocolChar.MinorNdisVersion = 0;
ProtocolChar.Reserved = 0;
ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete;
ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
ProtocolChar.SendCompleteHandler = NPF_SendComplete;
ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
ProtocolChar.ResetCompleteHandler = NPF_ResetComplete;
ProtocolChar.RequestCompleteHandler = NPF_RequestComplete;
ProtocolChar.ReceiveHandler = NPF_tap;
ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete;
ProtocolChar.StatusHandler = NPF_Status;
ProtocolChar.StatusCompleteHandler = NPF_StatusComplete;
#ifdef NDIS50
ProtocolChar.BindAdapterHandler = NPF_BindAdapter;
ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter;
ProtocolChar.PnPEventHandler = NPF_PowerChange;
ProtocolChar.ReceivePacketHandler = NULL;
#endif
ProtocolChar.Name = ProtoName;
NdisRegisterProtocol(
&Status,
&NdisProtocolHandle,
&ProtocolChar,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
if (Status != NDIS_STATUS_SUCCESS) {
IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
return Status;
}
NdisAllocateSpinLock(&Opened_Instances_Lock);
// Set up the device driver entry points.
DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = NPF_Close;
DriverObject->MajorFunction[IRP_MJ_READ] = NPF_Read;
DriverObject->MajorFunction[IRP_MJ_WRITE] = NPF_Write;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NPF_IoControl;
DriverObject->DriverUnload = NPF_Unload;
bindP = getAdaptersList();
if (bindP == NULL)
{
IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
tcpBindingsP = getTcpBindings();
if (tcpBindingsP == NULL)
{
IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
goto RegistryError;
}
bindP = (WCHAR*)tcpBindingsP;
bindT = (WCHAR*)(tcpBindingsP->Data);
}
else
{
bindT = bindP;
}
for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR))
{
RtlInitUnicodeString(&macName, bindT);
createDevice(DriverObject, &macName, NdisProtocolHandle);
}
return STATUS_SUCCESS;
RegistryError:
NdisDeregisterProtocol(
&Status,
NdisProtocolHandle
);
Status=STATUS_UNSUCCESSFUL;
return(Status);
}
//-------------------------------------------------------------------
PWCHAR getAdaptersList(void)
{
PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
OBJECT_ATTRIBUTES objAttrs;
NTSTATUS status;
HANDLE keyHandle;
UINT BufPos=0;
UINT BufLen=4096;
PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen, '0PWA');
if (DeviceNames == NULL) {
IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
return NULL;
}
InitializeObjectAttributes(&objAttrs, &AdapterListKey,
OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
if (!NT_SUCCESS(status)) {
IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
}
else { //OK
ULONG resultLength;
CHAR AdapInfo[1024];
UINT i=0;
KEY_VALUE_PARTIAL_INFORMATION valueInfo;
IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%x\n",DeviceNames);)
// Scan the list of the devices
while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS)
{
WCHAR ExportKeyName [512];
PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
PWCHAR LinkageKeyPrefix = L"\\Linkage";
UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
UNICODE_STRING AdapterKeyName;
HANDLE ExportKeyHandle;
RtlCopyMemory(ExportKeyName,
ExportKeyPrefix,
ExportKeyPrefixSize);
RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
tInfo->Name,
tInfo->NameLength+2);
RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
LinkageKeyPrefix,
LinkageKeyPrefixSize);
IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
OBJ_CASE_INSENSITIVE, NULL, NULL);
status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
if (!NT_SUCCESS(status)) {
IF_LOUD(DbgPrint("OpenKey Failed, %d!\n",status);)
i++;
continue;
}
status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
KeyValuePartialInformation, &valueInfo,
sizeof(valueInfo), &resultLength);
if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
}
else { // We know how big it needs to be.
ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');
if (valueInfoP != NULL) {
status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
KeyValuePartialInformation,
valueInfoP,
valueInfoLength, &resultLength);
if (!NT_SUCCESS(status)) {
IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
}
else{
IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
if( BufPos + valueInfoP->DataLength > BufLen ) {
// double the buffer size
PWCHAR DeviceNames2 = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen
<< 1, '0PWA');
if( DeviceNames2 ) {
RtlCopyMemory((PCHAR)DeviceNames2, (PCHAR)DeviceNames, BufLen);
BufLen <<= 1;
ExFreePool(DeviceNames);
DeviceNames = DeviceNames2;
}
}
if( BufPos + valueInfoP->DataLength < BufLen ) {
RtlCopyMemory((PCHAR)DeviceNames+BufPos,
valueInfoP->Data,
valueInfoP->DataLength);
BufPos+=valueInfoP->DataLength-2;
}
}
ExFreePool(valueInfoP);
}
else {
IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
}
}
// terminate the buffer
DeviceNames[BufPos/2]=0;
DeviceNames[BufPos/2+1]=0;
ZwClose (ExportKeyHandle);
i++;
}
ZwClose (keyHandle);
}
if(BufPos==0){
ExFreePool(DeviceNames);
return NULL;
}
return DeviceNames;
}
//-------------------------------------------------------------------
PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
{
PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
OBJECT_ATTRIBUTES objAttrs;
NTSTATUS status;
HANDLE keyHandle;
InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
OBJ_CASE_INSENSITIVE, NULL, NULL);
status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
if (!NT_SUCCESS(status)) {
IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
}
else {
ULONG resultLength;
KEY_VALUE_PARTIAL_INFORMATION valueInfo;
IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
status = ZwQueryValueKey(keyHandle, &bindValueName,
KeyValuePartialInformation, &valueInfo,
sizeof(valueInfo), &resultLength);
if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
}
else { // We know how big it needs to be.
ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
(PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA');
if (valueInfoP != NULL) {
status = ZwQueryValueKey(keyHandle, &bindValueName,
KeyValuePartialInformation,
valueInfoP,
valueInfoLength, &resultLength);
if (!NT_SUCCESS(status)) {
IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
}
else if (valueInfoLength != resultLength) {
IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
"but previous len = %u\n",
resultLength, valueInfoLength);)
}
else if (valueInfoP->Type != REG_MULTI_SZ) {
IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
valueInfoP->Type);)
}
else { // It's OK
#if DBG
ULONG i;
WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
IF_LOUD(DbgPrint("\n\nBind value:\n");)
for (i = 0; *dataP != UNICODE_NULL; i++) {
UNICODE_STRING macName;
RtlInitUnicodeString(&macName, dataP);
IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
dataP +=
(macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
}
#endif // DBG
result = valueInfoP;
}
}
}
ZwClose(keyHandle);
}
return result;
}
//-------------------------------------------------------------------
BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
{
NTSTATUS status;
PDEVICE_OBJECT devObjP;
UNICODE_STRING deviceName;
UNICODE_STRING deviceSymLink;
IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
devicePrefix.Length) < devicePrefix.Length)
{
return FALSE;
}
deviceName.Length = 0;
deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');
if (deviceName.Buffer == NULL)
return FALSE;
deviceSymLink.Length = 0;
deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length
+ symbolicLinkPrefix.Length
+ NPF_Prefix.Length
+ sizeof(UNICODE_NULL));
deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, '3PWA');
if (deviceSymLink.Buffer == NULL)
{
ExFreePool(deviceName.Buffer);
return FALSE;
}
RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
devicePrefix.Length / sizeof(WCHAR));
RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
RtlAppendUnicodeStringToString(&deviceSymLink, &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,
0,
FALSE,
&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);
devExtP->NdisProtocolHandle=aProtoHandle;
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;
return FALSE;
}
IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
devExtP->ExportString = deviceSymLink.Buffer;
ExFreePool(deviceName.Buffer);
return TRUE;
}
else
{
IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
ExFreePool(deviceName.Buffer);
ExFreePool(deviceSymLink.Buffer);
return FALSE;
}
}
//-------------------------------------------------------------------
VOID NPF_Unload(IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT OldDeviceObject;
PDEVICE_EXTENSION DeviceExtension;
NDIS_HANDLE NdisProtocolHandle = NULL;
NDIS_STATUS Status;
NDIS_STRING SymLink;
IF_LOUD(DbgPrint("NPF: Unload\n"););
DeviceObject = DriverObject->DeviceObject;
while (DeviceObject != NULL) {
OldDeviceObject = DeviceObject;
DeviceObject = DeviceObject->NextDevice;
DeviceExtension = OldDeviceObject->DeviceExtension;
NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
DeviceExtension->AdapterName.Buffer,
NdisProtocolHandle,
DeviceObject,
OldDeviceObject););
if (DeviceExtension->ExportString)
{
RtlInitUnicodeString(&SymLink , DeviceExtension->ExportString);
IF_LOUD(DbgPrint("Deleting SymLink at %p\n", SymLink.Buffer););
IoDeleteSymbolicLink(&SymLink);
ExFreePool(DeviceExtension->ExportString);
}
IoDeleteDevice(OldDeviceObject);
}
NdisDeregisterProtocol(
&Status,
NdisProtocolHandle
);
// Free the adapters names
ExFreePool( bindP );
}
#define SET_FAILURE_BUFFER_SMALL() do{\
Information = 0; \
Status = STATUS_BUFFER_TOO_SMALL; \
} while(FALSE)
#define SET_RESULT_SUCCESS(__a__) do{\
Information = __a__; \
Status = STATUS_SUCCESS; \
} while(FALSE)
#define SET_FAILURE_INVALID_REQUEST() do{\
Information = 0; \
Status = STATUS_INVALID_DEVICE_REQUEST; \
} while(FALSE)
#define SET_FAILURE_UNSUCCESSFUL() do{\
Information = 0; \
Status = STATUS_UNSUCCESSFUL; \
} while(FALSE)
#define SET_FAILURE_NOMEM() do{\
Information = 0; \
Status = STATUS_INSUFFICIENT_RESOURCES; \
} while(FALSE)
//-------------------------------------------------------------------
NTSTATUS NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PLIST_ENTRY RequestListEntry;
PINTERNAL_REQUEST pRequest;
ULONG FunctionCode;
NDIS_STATUS Status;
UINT i;
PUCHAR tpointer;
ULONG dim,timeout;
PUCHAR prog;
PPACKET_OID_DATA OidData;
ULONG mode;
// PWSTR DumpNameBuff;
PUCHAR TmpBPFProgram;
INT WriteRes;
BOOLEAN SyncWrite = FALSE;
// struct bpf_insn *initprogram;
ULONG insns;
ULONG cnt;
BOOLEAN IsExtendedFilter=FALSE;
BOOLEAN Flag;
PUINT pStats;
ULONG Information = 0;
BOOLEAN check_ok;
IF_LOUD(DbgPrint("NPF: IoControl\n");)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
Open=IrpSp->FileObject->FsContext;
Irp->IoStatus.Status = STATUS_SUCCESS;
IF_LOUD(DbgPrint("NPF: Function code is %08lx buff size=%08lx %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
switch (FunctionCode){
case BIOCGSTATS: //function to get the capture stats
if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(UINT)){
EXIT_FAILURE(0);
}
check_ok = TRUE;
__try
{
ProbeForWrite(Irp->UserBuffer, IrpSp->Parameters.DeviceIoControl.OutputBufferLength, 1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
check_ok = FALSE;
}
if (check_ok == FALSE)
{
EXIT_FAILURE(0);
}
else
{
pStats = (PUINT)(Irp->UserBuffer);
pStats[3] = 0;
pStats[0] = 0;
pStats[1] = 0;
pStats[2] = 0; // Not yet supported
for(i = 0 ; i < NCpu ; i++)
{
pStats[3] += Open->CpuData[i].Accepted;
pStats[0] += Open->CpuData[i].Received;
pStats[1] += Open->CpuData[i].Dropped;
pStats[2] += 0; // Not yet supported
}
EXIT_SUCCESS(4*sizeof(UINT));
}
break;
case BIOCGEVNAME: //function to get the name of the event associated with the current instance
if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){
EXIT_FAILURE(0);
}
check_ok = TRUE;
__try
{
ProbeForWrite(Irp->UserBuffer, IrpSp->Parameters.DeviceIoControl.OutputBufferLength, 1);
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
check_ok = FALSE;
}
if (check_ok == FALSE)
{
EXIT_FAILURE(0);
}
else
{
RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
EXIT_SUCCESS(26);
}
break;
case BIOCSENDPACKETSSYNC:
SyncWrite = TRUE;
case BIOCSENDPACKETSNOSYNC:
NdisAcquireSpinLock(&Open->WriteLock);
if(Open->WriteInProgress)
{
// Another write operation is currently in progress
EXIT_FAILURE(0);
}
else
{
Open->WriteInProgress = TRUE;
}
NdisReleaseSpinLock(&Open->WriteLock);
WriteRes = NPF_BufferedWrite(Irp,
(PUCHAR)Irp->AssociatedIrp.SystemBuffer,
IrpSp->Parameters.DeviceIoControl.InputBufferLength,
SyncWrite);
NdisAcquireSpinLock(&Open->WriteLock);
Open->WriteInProgress = FALSE;
NdisReleaseSpinLock(&Open->WriteLock);
if( WriteRes != -1)
{
EXIT_SUCCESS(WriteRes);
}
EXIT_FAILURE(WriteRes);
break;
case BIOCSETF:
Open->SkipProcessing = 1;
do
{
Flag = FALSE;
for(i = 0; i < NCpu ; i++)
if (Open->CpuData[i].Processing == 1)
Flag = TRUE;
}
while(Flag); //BUSY FORM WAITING...
// Free the previous buffer if it was present
if(Open->bpfprogram != NULL){
TmpBPFProgram = Open->bpfprogram;
Open->bpfprogram = NULL;
ExFreePool(TmpBPFProgram);
}
//
// Jitted filters are supported on x86 (32bit) only
//
#ifdef __NPF_x86__
if (Open->Filter != NULL)
{
JIT_BPF_Filter *OldFilter=Open->Filter;
Open->Filter=NULL;
BPF_Destroy_JIT_Filter(OldFilter);
}
#endif // __NPF_x86__
// Get the pointer to the new program
prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
if(prog==NULL)
{
Open->SkipProcessing = 0;
EXIT_FAILURE(0);
}
insns = (IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
//count the number of operative instructions
for (cnt=0;(cnt<insns) &&(((struct bpf_insn*)prog)[cnt].code!=BPF_SEPARATION); cnt++);
IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt);)
#ifdef __NPF_x86__
if ( cnt != insns && insns != cnt+1 && ((struct bpf_insn*)prog)[cnt].code == BPF_SEPARATION )
{
IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns-cnt-1);)
IsExtendedFilter=TRUE;
initprogram=&((struct bpf_insn*)prog)[cnt+1];
if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
{
IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
Open->SkipProcessing = 0;
EXIT_FAILURE(0);
}
}
#else //x86-64 and IA64
if ( cnt != insns)
{
IF_LOUD(DbgPrint("Error installing the BPF filter. The filter contains TME extensions,"
" not supported on 64bit platforms.\n");)
Open->SkipProcessing = 0;
EXIT_FAILURE(0);
}
#endif
//the NPF processor has been initialized, we have to validate the operative instructions
insns = cnt;
//NOTE: the validation code checks for TME instructions, and fails if a TME instruction is
//encountered on 64 bit machines
if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0)
{
IF_LOUD(DbgPrint("Error validating program");)
//FIXME: the machine has been initialized(?), but the operative code is wrong.
//we have to reset the machine!
//something like: reallocate the mem_ex, and reset the tme_core
Open->SkipProcessing = 0;
EXIT_FAILURE(0);
}
// Allocate the memory to contain the new filter program
// We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
TmpBPFProgram = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), '4PWA');
if (TmpBPFProgram == NULL)
{
IF_LOUD(DbgPrint("Error - No memory for filter");)
// no memory
Open->SkipProcessing = 0;
EXIT_FAILURE(0);
}
//copy the program in the new buffer
RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
Open->bpfprogram=TmpBPFProgram;
//
// At the moment the JIT compiler works on x86 (32 bit) only
//
#ifdef __NPF_x86__
// Create the new JIT filter function
if(!IsExtendedFilter)
if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt)) == NULL)
{
IF_LOUD(DbgPrint("Error jittering filter");)
Open->SkipProcessing = 0;
EXIT_FAILURE(0);
}
#endif
//return
for (i = 0 ; i < NCpu ; i++)
{
Open->CpuData[i].C=0;
Open->CpuData[i].P=0;
Open->CpuData[i].Free = Open->Size;
Open->CpuData[i].Accepted=0;
Open->CpuData[i].Dropped=0;
Open->CpuData[i].Received = 0;
}
Open->ReaderSN=0;
Open->WriterSN=0;
Open->SkipProcessing = 0;
EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
break;
case BIOCSMODE: //set the capture mode
if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
{
EXIT_FAILURE(0);
}
mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
///////kernel dump does not work at the moment//////////////////////////////////////////
if (mode & MODE_DUMP)
{
EXIT_FAILURE(0);
}
///////kernel dump does not work at the moment//////////////////////////////////////////
if(mode == MODE_CAPT)
{
Open->mode = MODE_CAPT;
EXIT_SUCCESS(0);
}
else if (mode == MODE_MON)
{
//
// The MONITOR_MODE (aka TME extensions) is not supported on
// 64 bit architectures
//
#ifdef __NPF_x86__
Open->mode = MODE_MON;
EXIT_SUCCESS(0);
#else // _NPF_x86__
EXIT_FAILURE(0);
#endif // __NPF_x86__
}
else{
if(mode & MODE_STAT){
Open->mode = MODE_STAT;
NdisAcquireSpinLock(&Open->CountersLock);
Open->Nbytes.QuadPart = 0;
Open->Npackets.QuadPart = 0;
NdisReleaseSpinLock(&Open->CountersLock);
if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart = -10000000;
}
if(mode & MODE_DUMP){
Open->mode |= MODE_DUMP;
// Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
}
EXIT_SUCCESS(0);
}
EXIT_FAILURE(0);
break;
case BIOCSETDUMPFILENAME:
///////kernel dump does not work at the moment//////////////////////////////////////////
EXIT_FAILURE(0);
///////kernel dump does not work at the moment//////////////////////////////////////////
//
// Remove the following #if 0 to enable the kernel dump again
//
#if 0
if(Open->mode & MODE_DUMP)
{
// Close current dump file
if(Open->DumpFileHandle != NULL)
{
NPF_CloseDumpFile(Open);
Open->DumpFileHandle = NULL;
}
if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
EXIT_FAILURE(0);
}
// Allocate the buffer that will contain the string
DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, '5PWA');
if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
EXIT_FAILURE(0);
}
// Copy the buffer
RtlCopyBytes((PVOID)DumpNameBuff,
Irp->AssociatedIrp.SystemBuffer,
IrpSp->Parameters.DeviceIoControl.InputBufferLength);
// Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
((PSHORT)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
// Create the unicode string
RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
Open->DumpFileName.Buffer,
IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
// Try to create the file
if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
NT_SUCCESS( NPF_StartDump(Open)))
{
EXIT_SUCCESS(0);
}
}
EXIT_FAILURE(0);
break;
#endif // #if 0
case BIOCSETDUMPLIMITS:
///////kernel dump does not work at the moment//////////////////////////////////////////
EXIT_FAILURE(0);
///////kernel dump does not work at the moment//////////////////////////////////////////
//
// Remove the following #if 0 to enable the kernel dump again
//
#if 0
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 2*sizeof(ULONG))
{
EXIT_FAILURE(0);
}
Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
EXIT_SUCCESS(0);
break;
#endif // #if 0
case BIOCISDUMPENDED:
///////kernel dump does not work at the moment//////////////////////////////////////////
EXIT_FAILURE(0);
///////kernel dump does not work at the moment//////////////////////////////////////////
//
// Remove the following #if 0 to enable the kernel dump again
//
#if 0
if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT))
{
EXIT_FAILURE(0);
}
*((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
EXIT_SUCCESS(4);
break;
#endif // #if 0
case BIOCSETBUFFERSIZE:
if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
{
EXIT_FAILURE(0);
}
// Get the number of bytes to allocate
dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
Open->SkipProcessing = 1;
do
{
Flag = FALSE;
for(i=0;i<NCpu;i++)
if (Open->CpuData[i].Processing == 1)
Flag = TRUE;
}
while(Flag); //BUSY FORM WAITING...
if (dim / NCpu < sizeof(struct PacketHeader))
dim = 0;
else
{
tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');
if (tpointer==NULL)
{
// no memory
Open->SkipProcessing = 0;
EXIT_FAILURE(0);
}
}
if (Open->CpuData[0].Buffer != NULL)
ExFreePool(Open->CpuData[0].Buffer);
for (i = 0 ; i < NCpu ; i++)
{
if (dim > 0)
Open->CpuData[i].Buffer=(PUCHAR)tpointer + (dim/NCpu)*i;
else
Open->CpuData[i].Buffer = NULL;
Open->CpuData[i].Free = dim/NCpu;
Open->CpuData[i].P = 0;
Open->CpuData[i].C = 0;
Open->CpuData[i].Accepted = 0;
Open->CpuData[i].Dropped = 0;
Open->CpuData[i].Received = 0;
}
Open->ReaderSN=0;
Open->WriterSN=0;
Open->Size = dim/NCpu;
Open->SkipProcessing = 0;
EXIT_SUCCESS(dim);
break;
case BIOCSRTIMEOUT: //set the timeout on the read calls
if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
{
EXIT_FAILURE(0);
}
timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
if(timeout == (ULONG)-1)
Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
else
{
Open->TimeOut.QuadPart = (LONGLONG)timeout;
Open->TimeOut.QuadPart *= 10000;
Open->TimeOut.QuadPart = -Open->TimeOut.QuadPart;
}
IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
EXIT_SUCCESS(timeout);
break;
case BIOCSWRITEREP: //set the writes repetition number
if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
{
EXIT_FAILURE(0);
}
Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
EXIT_SUCCESS(Open->Nwrites);
break;
case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
{
EXIT_FAILURE(0);
}
Open->MinToCopy = (*((PULONG)Irp->AssociatedIrp.SystemBuffer))/NCpu; //An hack to make the NCPU-buffers behave like a larger one
EXIT_SUCCESS(Open->MinToCopy);
break;
case IOCTL_PROTOCOL_RESET:
IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);
NdisReset(&Status,Open->AdapterHandle);
if (Status != NDIS_STATUS_PENDING)
{
IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
NPF_ResetComplete(Open,Status);
}
break;
case BIOCSETOID:
case BIOCQUERYOID:
// Extract a request from the list of free ones
RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
if (RequestListEntry == NULL)
{
EXIT_FAILURE(0);
}
pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
pRequest->Irp = Irp;
pRequest->Internal = FALSE;
//
// See if it is an Ndis request
//
OidData=Irp->AssociatedIrp.SystemBuffer;
if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
&&
(IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
&&
(IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
&&
(IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);)
//
// The buffer is valid
//
if (FunctionCode == BIOCSETOID){
pRequest->Request.RequestType=NdisRequestSetInformation;
pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;
pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;
pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;
}
else{
pRequest->Request.RequestType=NdisRequestQueryInformation;
pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;
pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;
pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;
}
NdisResetEvent(&Open->IOEvent);
//
// submit the request
//
NdisRequest(
&Status,
Open->AdapterHandle,
&pRequest->Request
);
} else {
//
// buffer too small
//
Status=NDIS_STATUS_FAILURE;
pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
}
if (Status != NDIS_STATUS_PENDING) {
IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
NPF_RequestComplete(Open, &pRequest->Request, Status);
return Status;
}
NdisWaitEvent(&Open->IOEvent, 5000);
return(Open->IOStatus);
break;
case BIOCISETLOBBEH:
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(INT))
{
SET_FAILURE_BUFFER_SMALL();
break;
}
#ifdef __NPF_NT4__
// NT4 doesn't support loopback inhibition / activation
SET_FAILURE_INVALID_REQUEST();
break;
#else //not __NPF_NT4__
//
// win2000/xp/2003/vista
//
if(*(PINT)Irp->AssociatedIrp.SystemBuffer == 1)
{
Open->SkipSentPackets = TRUE;
//
// Reset the capture buffers, since they could contain loopbacked packets
//
// NPF_ResetBufferContents(Open);
SET_RESULT_SUCCESS(0);
break;
}
else
if(*(PINT)Irp->AssociatedIrp.SystemBuffer == 2)
{
Open->SkipSentPackets = FALSE;
SET_RESULT_SUCCESS(0);
break;
}
else
{
// Unknown operation
SET_FAILURE_INVALID_REQUEST();
break;
}
#endif // !__NPF_NT4__
break;
default:
EXIT_FAILURE(0);
}
if (FunctionCode == BIOCISETLOBBEH)
{
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
return Status;
}
//-------------------------------------------------------------------
VOID
NPF_RequestComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST NdisRequest,
IN NDIS_STATUS Status
)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PIRP Irp;
PINTERNAL_REQUEST pRequest;
UINT FunctionCode;
// KIRQL OldIrq;
PPACKET_OID_DATA OidData;
IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
Open= (POPEN_INSTANCE)ProtocolBindingContext;
pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
Irp=pRequest->Irp;
if(pRequest->Internal == TRUE){
// Put the request in the list of the free ones
ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
if(Status != NDIS_STATUS_SUCCESS)
Open->MaxFrameSize = 1600; // Assume Ethernet
// We always return success, because the adapter has been already opened
Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
OidData=Irp->AssociatedIrp.SystemBuffer;
if (FunctionCode == BIOCSETOID) {
OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
} else {
if (FunctionCode == BIOCQUERYOID) {
OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);)
}
}
Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
ExInterlockedInsertTailList(
&Open->RequestList,
&pRequest->ListElement,
&Open->RequestSpinLock);
Irp->IoStatus.Status = Status;
Open->IOStatus = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
// Unlock the caller
NdisSetEvent(&Open->IOEvent);
return;
}
//-------------------------------------------------------------------
VOID
NPF_Status(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
{
IF_LOUD(DbgPrint("NPF: Status Indication\n");)
return;
}
//-------------------------------------------------------------------
VOID
NPF_StatusComplete(
IN NDIS_HANDLE ProtocolBindingContext
)
{
IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
return;
}
//-------------------------------------------------------------------
NTSTATUS
NPF_ReadRegistry(
IN PWSTR *MacDriverName,
IN PWSTR *PacketDriverName,
IN PUNICODE_STRING RegistryPath
)
{
NTSTATUS Status;
RTL_QUERY_REGISTRY_TABLE ParamTable[4];
PWSTR Bind = L"Bind";
PWSTR Export = L"Export";
PWSTR Parameters = L"Parameters";
PWSTR Linkage = L"Linkage";
PWCHAR Path;
Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), '7PWA');
if (Path == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(
Path,
RegistryPath->Length+sizeof(WCHAR)
);
RtlCopyMemory(
Path,
RegistryPath->Buffer,
RegistryPath->Length
);
IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
RtlZeroMemory(
ParamTable,
sizeof(ParamTable)
);
//
// change to the linkage key
//
ParamTable[0].QueryRoutine = NULL;
ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
ParamTable[0].Name = Linkage;
//
// Get the name of the mac driver we should bind to
//
ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
RTL_QUERY_REGISTRY_NOEXPAND;
ParamTable[1].Name = Bind;
ParamTable[1].EntryContext = (PVOID)MacDriverName;
ParamTable[1].DefaultType = REG_MULTI_SZ;
//
// Get the name that we should use for the driver object
//
ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
RTL_QUERY_REGISTRY_NOEXPAND;
ParamTable[2].Name = Export;
ParamTable[2].EntryContext = (PVOID)PacketDriverName;
ParamTable[2].DefaultType = REG_MULTI_SZ;
Status=RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
Path,
ParamTable,
NULL,
NULL
);
ExFreePool(Path);
return Status;
}
//-------------------------------------------------------------------
NTSTATUS
NPF_QueryRegistryRoutine(
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext
)
{
PUCHAR Buffer;
IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
if (ValueType != REG_MULTI_SZ) {
return STATUS_OBJECT_NAME_NOT_FOUND;
}
Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, '8PWA');
if (Buffer==NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(
Buffer,
ValueData,
ValueLength
);
*((PUCHAR *)EntryContext)=Buffer;
return STATUS_SUCCESS;
}