• Want to receive the latest contracting news and advice straight to your inbox? Sign up to the ContractorUK newsletter here. Every sign up will also be entered into a draw to WIN £100 Amazon vouchers!

IRP problem

suityou01

Potty-trained
Thanks received
222
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

Code:
ptrOutput = Marshal.AllocHGlobal(Marshal.SizeOf(fm));

where fm is the structure that is being populated by the driver.

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;

And this is my C# representation of it

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;
        }

Including my declaration of LIST_ENTRY

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;
        }

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

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 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. :confused:
 
Don't you need to specify the size of the char arrays in the c# struct?

Sure, how?

I tried char[16] blah;

and it would not compile

so I try char[] blah = new char[16];

and it would not compile.

At the moment the size of the buffer is 40 bytes which is woefully short of where it should be.

I create an instance of the struct then set the char arrays to char[16] like this

FIREWALL_MESSAGE fm = new FIREWALL_MESSAGE();
fm.sourceIp = new char[16];
fm.destIp = new char[16];

still it only sizeof's to 40 bytes. :frown

perhaps I need to use Marshal.AllocHGlobal for the char arrays as well . . .

ponders

:throw:

Edit : Nope that gives me a compile error Error 1

Cannot implicitly convert type 'System.IntPtr' to 'char[]' C:\transfer\c# fork\src\PortKnox\DriverInterface\DriverInterface\Driver.cs 302 27 DriverInterface
 
Well, that I don't know, it just seemed that the call would be expecting a bigger structure than you pass in. Perhaps allocate the right amount of memory (based on working it out) and then use Marshal.copy to shuffle data back and forth?

The call with the FIREWALL_STATUS looks OK size wise though, does that fail as well?
 
Well, that I don't know, it just seemed that the call would be expecting a bigger structure than you pass in. Perhaps allocate the right amount of memory (based on working it out) and then use Marshal.copy to shuffle data back and forth?

The call with the FIREWALL_STATUS looks OK size wise though, does that fail as well?

Thanks for the reply dood.

The FIREWALL_STATUS call works but the returned values look a bit iffy. I'll fathom that out later. The IRP processing in my driver must also be more defensively coded I think. It should check the size of the buffer provided and return an error rather than BSOD.

I am convinced the problem is with the structure declaration. And also to do with those char[16] declarations I cannot port to c#.

Edit : May try this

Code:
[MarshalAs (UnmanagedType.ByValArray, SizeConst = 16)]
byte[] sourceIP;
[MarshalAs (UnmanagedType.ByValArray, SizeConst = 16)]
byte[] destIP;
 
Last edited: 20:21
Thanks for the reply dood.

The FIREWALL_STATUS call works but the returned values look a bit iffy. I'll fathom that out later. The IRP processing in my driver must also be more defensively coded I think. It should check the size of the buffer provided and return an error rather than BSOD.

I am convinced the problem is with the structure declaration. And also to do with those char[16] declarations I cannot port to c#.

Edit : May try this

Code:
[MarshalAs (UnmanagedType.ByValArray, SizeConst = 16)]
byte[] sourceIP;
[MarshalAs (UnmanagedType.ByValArray, SizeConst = 16)]
byte[] destIP;

Yip, that did it. Now getting data back (lawd knows what) and no bsods. Just need to marshal the buffer back to my struct. :yay::yay:
 

Advertisers

Back
Top