mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 18:33:10 +00:00

Seems I'll need to do some work on the SCM before this'll be running for me. svn path=/trunk/; revision=3883
1388 lines
39 KiB
C
1388 lines
39 KiB
C
/*
|
|
* Copyright (c) 1999, 2000
|
|
* Politecnico di Torino. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that: (1) source code distributions
|
|
* retain the above copyright notice and this paragraph in its entirety, (2)
|
|
* distributions including binary code include the above copyright notice and
|
|
* this paragraph in its entirety in the documentation or other materials
|
|
* provided with the distribution, and (3) all advertising materials mentioning
|
|
* features or use of this software display the following acknowledgement:
|
|
* ``This product includes software developed by the Politecnico
|
|
* di Torino, and its contributors.'' Neither the name of
|
|
* the University 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
*/
|
|
|
|
#ifdef _MSC_VER
|
|
#include "stdarg.h"
|
|
#include "ntddk.h"
|
|
#include "ntiologc.h"
|
|
#include "ndis.h"
|
|
#else
|
|
#include <ddk/ntddk.h>
|
|
#include <net/ndis.h>
|
|
#endif
|
|
|
|
#include "ntddpack.h"
|
|
|
|
#include "debug.h"
|
|
#include "packet.h"
|
|
#include "win_bpf.h"
|
|
#include "win_bpf_filter_init.h"
|
|
|
|
#include "tme.h"
|
|
|
|
#if DBG
|
|
// Declare the global debug flag for this driver.
|
|
//ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
|
|
ULONG PacketDebugFlag = PACKET_DEBUG_LOUD + PACKET_DEBUG_VERY_LOUD + PACKET_DEBUG_INIT;
|
|
|
|
#endif
|
|
|
|
PDEVICE_EXTENSION GlobalDeviceExtension;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
#define ROBERTS_PATCH
|
|
#ifdef ROBERTS_PATCH
|
|
|
|
#define NDIS_STRING_CONST(x) {sizeof(L##x)-2, sizeof(L##x), L##x}
|
|
|
|
//void __moddi3(void) {}
|
|
//void __divdi3(void) {}
|
|
|
|
#endif // ROBERTS_PATCH
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Global strings
|
|
//
|
|
NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("NPF_");
|
|
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;
|
|
|
|
//
|
|
// Packet Driver's entry routine.
|
|
//
|
|
NTSTATUS
|
|
#ifdef __GNUC__
|
|
STDCALL
|
|
#endif
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
{
|
|
|
|
NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
|
|
UNICODE_STRING MacDriverName;
|
|
UNICODE_STRING UnicodeDeviceName;
|
|
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;
|
|
PWSTR BindString;
|
|
PWSTR ExportString;
|
|
PWSTR BindStringSave;
|
|
PWSTR ExportStringSave;
|
|
NDIS_HANDLE NdisProtocolHandle;
|
|
WCHAR* bindT;
|
|
PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
|
|
UNICODE_STRING macName;
|
|
|
|
// This driver at the moment works only on single processor machines
|
|
if(NdisSystemProcessorCount() != 1){
|
|
return STATUS_IMAGE_MP_UP_MISMATCH;
|
|
}
|
|
|
|
IF_LOUD(DbgPrint("Packet: DriverEntry\n");)
|
|
|
|
RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
|
|
|
|
#ifdef NDIS50
|
|
ProtocolChar.MajorNdisVersion = 5;
|
|
#else
|
|
ProtocolChar.MajorNdisVersion = 3;
|
|
#endif
|
|
ProtocolChar.MinorNdisVersion = 0;
|
|
#ifndef __GNUC__
|
|
ProtocolChar.Reserved = 0;
|
|
#else
|
|
ProtocolChar.u1.Reserved = 0;
|
|
#endif
|
|
ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete;
|
|
ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
|
|
#ifndef __GNUC__
|
|
ProtocolChar.SendCompleteHandler = NPF_SendComplete;
|
|
ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
|
|
#else
|
|
ProtocolChar.u2.SendCompleteHandler = NPF_SendComplete;
|
|
ProtocolChar.u3.TransferDataCompleteHandler = NPF_TransferDataComplete;
|
|
#endif
|
|
ProtocolChar.ResetCompleteHandler = NPF_ResetComplete;
|
|
ProtocolChar.RequestCompleteHandler = NPF_RequestComplete;
|
|
#ifndef __GNUC__
|
|
ProtocolChar.ReceiveHandler = NPF_tap;
|
|
#else
|
|
ProtocolChar.u4.ReceiveHandler = NPF_tap;
|
|
#endif
|
|
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;
|
|
|
|
/*
|
|
// Get the name of the Packet driver and the name of the NIC driver
|
|
// to bind to from the registry
|
|
Status=NPF_ReadRegistry(
|
|
&BindString,
|
|
&ExportString,
|
|
RegistryPath
|
|
);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
|
|
IF_LOUD(DbgPrint("Trying dynamic binding\n");)
|
|
*/
|
|
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;
|
|
/*
|
|
}
|
|
BindStringSave = BindString;
|
|
ExportStringSave = ExportString;
|
|
//
|
|
// create a device object for each entry
|
|
//
|
|
while (*BindString!= UNICODE_NULL && *ExportString!= UNICODE_NULL) {
|
|
//
|
|
// Create a counted unicode string for both null terminated strings
|
|
//
|
|
RtlInitUnicodeString(
|
|
&MacDriverName,
|
|
BindString);
|
|
RtlInitUnicodeString(
|
|
&UnicodeDeviceName,
|
|
ExportString);
|
|
//
|
|
// Advance to the next string of the MULTI_SZ string
|
|
//
|
|
BindString += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
|
|
ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
|
|
IF_LOUD(DbgPrint("NPF: DeviceName=%ws MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);)
|
|
//
|
|
// Create the device object
|
|
//
|
|
Status = IoCreateDevice(
|
|
DriverObject,
|
|
sizeof(DEVICE_EXTENSION),
|
|
&UnicodeDeviceName,
|
|
FILE_DEVICE_PROTOCOL,
|
|
0,
|
|
FALSE,
|
|
&DeviceObject);
|
|
if (Status != STATUS_SUCCESS) {
|
|
IF_LOUD(DbgPrint("NPF: IoCreateDevice() failed:\n");)
|
|
break;
|
|
}
|
|
DevicesCreated++;
|
|
DeviceObject->Flags |= DO_DIRECT_IO;
|
|
DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
|
|
DeviceExtension->DeviceObject = DeviceObject;
|
|
//
|
|
// Save the the name of the MAC driver to open in the Device Extension
|
|
//
|
|
DeviceExtension->AdapterName=MacDriverName;
|
|
if (DevicesCreated == 1) {
|
|
DeviceExtension->BindString = NULL;
|
|
DeviceExtension->ExportString = NULL;
|
|
}
|
|
DeviceExtension->NdisProtocolHandle=NdisProtocolHandle;
|
|
}
|
|
if (DevicesCreated > 0) {
|
|
//
|
|
// Managed to create at least one device.
|
|
//
|
|
IF_LOUD(DbgPrint("NPF: Managed to create at least one device.\n");)
|
|
return STATUS_SUCCESS;
|
|
}
|
|
ExFreePool(BindStringSave);
|
|
ExFreePool(ExportStringSave);
|
|
*/
|
|
|
|
RegistryError:
|
|
IF_LOUD(DbgPrint("NPF: RegistryError: calling NdisDeregisterProtocol()\n");)
|
|
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;
|
|
|
|
#define NPF_TAG_DEVICENAME TAG('0', 'P', 'W', 'A')
|
|
PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, 4096, NPF_TAG_DEVICENAME);
|
|
|
|
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("Status of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
|
|
IF_LOUD(DbgPrint("Status of %x opening %ws\n", status, AdapterListKey.Buffer);)
|
|
|
|
} else { //OK
|
|
ULONG resultLength;
|
|
KEY_VALUE_PARTIAL_INFORMATION valueInfo;
|
|
CHAR AdapInfo[1024];
|
|
UINT i=0;
|
|
|
|
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;
|
|
KEY_VALUE_PARTIAL_INFORMATION valueInfo;
|
|
ULONG resultLength;
|
|
|
|
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)) {
|
|
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]);
|
|
#define NPF_TAG_KEYVALUE TAG('1', 'P', 'W', 'A')
|
|
PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, NPF_TAG_KEYVALUE);
|
|
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);)
|
|
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]);
|
|
#define NPF_TAG_KEYVALUE2 TAG('2', 'P', 'W', 'A')
|
|
PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
|
|
(PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, NPF_TAG_KEYVALUE2);
|
|
|
|
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));
|
|
#define NPF_TAG_DEVICENAMEBUF TAG('3', 'P', 'W', 'A')
|
|
deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, NPF_TAG_DEVICENAMEBUF);
|
|
|
|
if (deviceName.Buffer == NULL)
|
|
return FALSE;
|
|
|
|
deviceSymLink.Length = 0;
|
|
deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length
|
|
+ symbolicLinkPrefix.Length
|
|
+ NPF_Prefix.Length
|
|
+ sizeof(UNICODE_NULL));
|
|
|
|
#define NPF_TAG_SYMLINKBUF TAG('3', 'P', 'W', 'A')
|
|
deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, NPF_TAG_SYMLINKBUF);
|
|
|
|
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(PDEVICE_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;
|
|
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 );
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
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;
|
|
PLIST_ENTRY PacketListEntry;
|
|
UINT i;
|
|
PUCHAR tpointer;
|
|
ULONG dim,timeout;
|
|
PUCHAR prog;
|
|
PPACKET_OID_DATA OidData;
|
|
int *StatsBuf;
|
|
PNDIS_PACKET pPacket;
|
|
ULONG mode;
|
|
PWSTR DumpNameBuff;
|
|
PUCHAR TmpBPFProgram;
|
|
INT WriteRes;
|
|
BOOLEAN SyncWrite = FALSE;
|
|
struct bpf_insn *initprogram;
|
|
ULONG insns;
|
|
ULONG cnt;
|
|
BOOLEAN IsExtendedFilter=FALSE;
|
|
|
|
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(INT)){
|
|
EXIT_FAILURE(0);
|
|
}
|
|
|
|
*(((PUINT)Irp->UserBuffer)+3) = Open->Accepted;
|
|
*(((PUINT)Irp->UserBuffer)) = Open->Received;
|
|
*(((PUINT)Irp->UserBuffer)+1) = Open->Dropped;
|
|
*(((PUINT)Irp->UserBuffer)+2) = 0; // Not yet supported
|
|
|
|
EXIT_SUCCESS(4*sizeof(INT));
|
|
|
|
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);
|
|
}
|
|
|
|
RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
|
|
|
|
EXIT_SUCCESS(26);
|
|
|
|
break;
|
|
|
|
case BIOCSENDPACKETSSYNC:
|
|
|
|
SyncWrite = TRUE;
|
|
|
|
case BIOCSENDPACKETSNOSYNC:
|
|
|
|
WriteRes = NPF_BufferedWrite(Irp,
|
|
(PUCHAR)Irp->AssociatedIrp.SystemBuffer,
|
|
IrpSp->Parameters.DeviceIoControl.InputBufferLength,
|
|
SyncWrite);
|
|
|
|
if( WriteRes != -1)
|
|
{
|
|
EXIT_SUCCESS(WriteRes);
|
|
}
|
|
|
|
EXIT_FAILURE(WriteRes);
|
|
|
|
break;
|
|
|
|
case BIOCSETF:
|
|
|
|
// Free the previous buffer if it was present
|
|
if(Open->bpfprogram!=NULL){
|
|
TmpBPFProgram=Open->bpfprogram;
|
|
Open->bpfprogram = NULL;
|
|
ExFreePool(TmpBPFProgram);
|
|
}
|
|
|
|
if (Open->Filter!=NULL)
|
|
{
|
|
JIT_BPF_Filter *OldFilter=Open->Filter;
|
|
Open->Filter=NULL;
|
|
BPF_Destroy_JIT_Filter(OldFilter);
|
|
}
|
|
|
|
// Get the pointer to the new program
|
|
prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if(prog==NULL){
|
|
IF_LOUD(DbgPrint("0001");)
|
|
|
|
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);)
|
|
|
|
if (((struct bpf_insn*)prog)[cnt].code==BPF_SEPARATION && (insns-cnt-1)!=0)
|
|
{
|
|
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");)
|
|
|
|
EXIT_FAILURE(0);
|
|
}
|
|
}
|
|
|
|
//the NPF processor has been initialized, we have to validate the operative instructions
|
|
insns=cnt;
|
|
|
|
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
|
|
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()
|
|
#define NPF_TAG_BPFPROG TAG('4', 'P', 'W', 'A')
|
|
TmpBPFProgram=(PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), NPF_TAG_BPFPROG);
|
|
if (TmpBPFProgram==NULL){
|
|
IF_LOUD(DbgPrint("Error - No memory for filter");)
|
|
// no memory
|
|
EXIT_FAILURE(0);
|
|
}
|
|
|
|
//copy the program in the new buffer
|
|
RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
|
|
Open->bpfprogram=TmpBPFProgram;
|
|
|
|
// 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");)
|
|
EXIT_FAILURE(0);
|
|
}
|
|
|
|
//return
|
|
Open->Bhead = 0;
|
|
Open->Btail = 0;
|
|
(INT)Open->BLastByte = -1;
|
|
Open->Received = 0;
|
|
Open->Dropped = 0;
|
|
Open->Accepted = 0;
|
|
|
|
EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
|
|
|
|
break;
|
|
|
|
case BIOCSMODE: //set the capture mode
|
|
|
|
mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
|
|
|
|
if(mode == MODE_CAPT){
|
|
Open->mode=MODE_CAPT;
|
|
|
|
EXIT_SUCCESS(0);
|
|
}
|
|
else if (mode==MODE_MON){
|
|
Open->mode=MODE_MON;
|
|
|
|
EXIT_SUCCESS(0);
|
|
}
|
|
else{
|
|
if(mode & MODE_STAT){
|
|
Open->mode = MODE_STAT;
|
|
Open->Nbytes.QuadPart=0;
|
|
Open->Npackets.QuadPart=0;
|
|
|
|
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:
|
|
|
|
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
|
|
#define NPF_TAG_DUMPNAMEBUF TAG('5', 'P', 'W', 'A')
|
|
DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, NPF_TAG_DUMPNAMEBUF);
|
|
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
|
|
((SHORT*)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;
|
|
|
|
case BIOCSETDUMPLIMITS:
|
|
|
|
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;
|
|
|
|
case BIOCISDUMPENDED:
|
|
if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4){
|
|
EXIT_FAILURE(0);
|
|
}
|
|
|
|
*((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
|
|
|
|
EXIT_SUCCESS(4);
|
|
|
|
break;
|
|
|
|
case BIOCSETBUFFERSIZE:
|
|
|
|
// Get the number of bytes to allocate
|
|
dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
|
|
|
|
// Free the old buffer
|
|
tpointer = Open->Buffer;
|
|
if(tpointer != NULL){
|
|
Open->BufSize = 0;
|
|
Open->Buffer = NULL;
|
|
ExFreePool(tpointer);
|
|
}
|
|
// Allocate the new buffer
|
|
if(dim!=0){
|
|
#define NPF_TAG_TPOINTER TAG('6', 'P', 'W', 'A')
|
|
tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, NPF_TAG_TPOINTER);
|
|
if (tpointer==NULL) {
|
|
// no memory
|
|
Open->BufSize = 0;
|
|
Open->Buffer = NULL;
|
|
EXIT_FAILURE(0);
|
|
}
|
|
}
|
|
else
|
|
tpointer = NULL;
|
|
|
|
Open->Buffer = tpointer;
|
|
Open->Bhead = 0;
|
|
Open->Btail = 0;
|
|
(INT)Open->BLastByte = -1;
|
|
|
|
Open->BufSize = (UINT)dim;
|
|
EXIT_SUCCESS(dim);
|
|
|
|
break;
|
|
|
|
case BIOCSRTIMEOUT: //set the timeout on the read calls
|
|
|
|
timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
|
|
if((int)timeout==-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
|
|
|
|
Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
|
|
|
|
EXIT_SUCCESS(Open->Nwrites);
|
|
|
|
break;
|
|
|
|
case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
|
|
|
|
Open->MinToCopy = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
|
|
|
|
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;
|
|
|
|
|
|
default:
|
|
|
|
EXIT_FAILURE(0);
|
|
}
|
|
|
|
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 = 1514; // 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;
|
|
|
|
#define NPF_TAG_PATH TAG('7', 'P', 'W', 'A')
|
|
Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), NPF_TAG_PATH);
|
|
|
|
if (Path == NULL) {
|
|
IF_LOUD(DbgPrint("\nPacketReadRegistry: returing STATUS_INSUFFICIENT_RESOURCES\n");)
|
|
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].QueryRoutine = NPF_QueryRegistryRoutine;
|
|
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
|
|
);
|
|
|
|
if (Status != STATUS_SUCCESS) {
|
|
// insert hard coded parameters here while registry on ROS is not working...
|
|
IF_LOUD(DbgPrint("PacketReadRegistry() RtlQueryRegistryValues failed - returing fixed parameters\n");)
|
|
|
|
*MacDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
|
|
//memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR));
|
|
memcpy(*MacDriverName, L"\\Device\\ne2000", 15 * sizeof(WCHAR));
|
|
|
|
*PacketDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
|
|
memcpy(*PacketDriverName, L"\\Device\\NPF_ne2000", 19 * sizeof(WCHAR));
|
|
Status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
#define NPF_TAG_REGBUF TAG('8', 'P', 'W', 'A')
|
|
Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, NPF_TAG_REGBUF);
|
|
|
|
if (Buffer==NULL) {
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
Buffer,
|
|
ValueData,
|
|
ValueLength
|
|
);
|
|
|
|
*((PUCHAR *)EntryContext)=Buffer;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|