I am writing a driver (WFP) to filter IP packets. The driver is stable (ish) in that I have managed to send packet information back to a C app using an IRP.
I am now porting this code to C#, and when I pass in the output buffer to DeviceIOControl I get a blue screen (IRQ_NOT_LESS_OR_EQUAL)
The minidump shows the driver tries to write to corrupt memory. So in fairness the memory I am passing in from user mode is not right.
In C I use malloc and zero memory and it works like a charm.
From C# I use
where fm is the structure that is being populated by the driver.
This is the structure in C
And this is my C# representation of it
Including my declaration of LIST_ENTRY
I have other more simple IOCTLS that pass in a structure like this
with the following C# implementation of it as
As I say this happens when calling DeviceIOControl and my api declaration looks like this
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool DeviceIoControl(
Microsoft.Win32.SafeHandles.SafeFileHandle hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
uint nInBufferSize,
[Out] IntPtr lpOutBuffer,
uint nOutBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped);
but this still causes a blue screen.
The call to the api looks like this
As I say I am totally baffled so if anyone on here has written drivers and accessed them from a high level interpreted language such as C# your insight would be appreciated.
As I say, works perfectly from C.
I am now porting this code to C#, and when I pass in the output buffer to DeviceIOControl I get a blue screen (IRQ_NOT_LESS_OR_EQUAL)
The minidump shows the driver tries to write to corrupt memory. So in fairness the memory I am passing in from user mode is not right.
In C I use malloc and zero memory and it works like a charm.
From C# I use
Code:
ptrOutput = Marshal.AllocHGlobal(Marshal.SizeOf(fm));
This is the structure in C
Code:
typedef struct FIREWALL_MESSAGE_
{
LIST_ENTRY listEntry;
int srcport;
int destport;
char sourceIp[16];
char destIp[16];
int protocol;
long packetRef;
FWP_DIRECTION direction; //FWP_DIRECTION Defined in Inspect.h
int type;
} FIREWALL_MESSAGE;
Code:
public struct LIST_ENTRY
{
/// _LIST_ENTRY*
public System.IntPtr Flink;
/// _LIST_ENTRY*
public System.IntPtr Blink;
}
public struct FIREWALL_MESSAGE
{
public LIST_ENTRY listEntry;
public uint srcport;
public uint destport;
public char[] sourceIp;
public char[] destIp;
public uint protocol;
public uint packetRef;
public EFWPDIRECTION direction; //FWP_DIRECTION Defined in Inspect.h
public uint type;
}
I have other more simple IOCTLS that pass in a structure like this
Code:
typedef struct FIREWALL_STATUS_
{
int upTime; //Length of time the firewall has been running in time_t format
int packetsProcessed;
int packetsDropped;
int connectionAttemptsProcessed;
int connectionAttemptsRefused;
} FIREWALL_STATUS, *PFIREWALL_STATUS;
with the following C# implementation of it as
Code:
public struct FIREWALL_STATUS
{
uint upTime;
uint packetsProcessed;
uint packetsDropped;
uint connectionAttemptsProcessed;
uint connectionAttemptsRefused;
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool DeviceIoControl(
Microsoft.Win32.SafeHandles.SafeFileHandle hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
uint nInBufferSize,
[Out] IntPtr lpOutBuffer,
uint nOutBufferSize,
ref uint lpBytesReturned,
IntPtr lpOverlapped);
but this still causes a blue screen.
The call to the api looks like this
Code:
private bool sendIOControl(uint ioctlCode, object inputBuffer, ref FIREWALL_STATUS fs)
{
uint bytesReturned = 0;
uint inputBufferSize = 0;
uint outputBufferSize = 0;
IntPtr ptrOutput = IntPtr.Zero;
IntPtr ptrInput = IntPtr.Zero;
bool retVal = false;
ptrOutput = Marshal.AllocHGlobal(Marshal.SizeOf(fs));
if (inputBuffer != null)
{
inputBufferSize = (uint)Marshal.SizeOf(inputBuffer);
}
outputBufferSize = (uint)Marshal.SizeOf(fs);
retVal = DeviceIoControl(hDriver, ioctlCode, ptrInput, inputBufferSize, ptrOutput, outputBufferSize, ref bytesReturned, IntPtr.Zero);
return retVal;
}
As I say, works perfectly from C.




Comment