Irp->AssociatedIrp.SystemBuffer

I post this hoping to get some help, and not criticised for either not researching this enough first, or for not posting code. I have done both now so hope to get some constructive help.

My problem is this. I want to receive some data from the driver - a filter driver.

In the driver I am trying to populate a structure, and return it via the Irp->AssociatedIrp.SystemBuffer.

The structure within the driver looks like

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;

and I have all of my device ios firing correctly.

The one I am having trouble with is the firewall status query,

the code for this is as below

int getFirewallStatus(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp)
{
FIREWALL_STATUS fwallStatus;
NTSTATUS ntStatus;
PIO_STACK_LOCATION irpSp;// Pointer to current stack location

ntStatus = STATUS_SUCCESS;

irpSp = IoGetCurrentIrpStackLocation( Irp );

ntStatus = STATUS_SUCCESS;

DbgPrint(“Get firewall status message received”);

fwallStatus.upTime=999999;
fwallStatus.packetsProcessed=888888;
fwallStatus.packetsDropped=777777;
fwallStatus.connectionAttemptsProcessed=666666;
fwallStatus.connectionAttemptsRefused=555555;

Irp->AssociatedIrp.SystemBuffer = &fwallStatus;
irpSp->Parameters.DeviceIoControl.OutputBufferLength = sizeof(fwallStatus);
Irp->IoStatus.Information = sizeof(fwallStatus);

Irp->IoStatus.Status = ntStatus;
IoCompleteRequest( Irp, IO_NO_INCREMENT );

return 0;
}

Note, this is called from with the main deviceio function that is registered with the io manager. The function is called ok, but the result is a BSOD. As far as the MSDN tells me, using buffered IO the system buffer is for both input and output io, and you must pass a pointer to the output buffer to the system buffer, and also set the output buffer length. In some articles I have found they even say to set the IoStatus.Information to the size out the output buffer as well.

For completeness, the client side code I have calling this is as follows :

void getFirewallStatus(){
FIREWALL_STATUS outputBuffer;
BOOL bRc;
ULONG bytesReturned;
int errNum;

if (!hDevice){
hDevice = CreateFile(“\\.\SimpleSys”,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);

}
if (hDevice == INVALID_HANDLE_VALUE){
printf(“Invalid handle value returned from CreateFile \n”);
errNum = GetLastError();
printf(“CreateFile failed! ERROR CODE = %d\n”, errNum);
return;
}
else{
bRc = DeviceIoControl ( hDevice,
IOCTL_GET_FIREWALL_STATUS,
gFirewallRules,
sizeof(TL_PORT_RULE) * gFirewallRulesCount,
&outputBuffer,
sizeof( outputBuffer),
&bytesReturned,
NULL
);

printf(“Uptime %d”,outputBuffer.upTime);
}
}

Cast the Irp->AssociatedIrp.SystemBuffer to your fw_status.i.e.:
pfwallStatus = Irp->AssociatedIrp.SystemBuffer;
pfwallStatus->upTime=999999;

With buffered i/o, the os creates a buffer for both input and output. that is Irp->AssociatedIrp.SystemBuffer. you don’t need your own for output, just use it.

Calvin

— On Sun, 9/28/08, xxxxx@yahoo.co.uk wrote:

> From: xxxxx@yahoo.co.uk
> Subject: [ntdev] Irp->AssociatedIrp.SystemBuffer
> To: “Windows System Software Devs Interest List”
> Received: Sunday, September 28, 2008, 10:06 AM
> I post this hoping to get some help, and not criticised for
> either not researching this enough first, or for not posting
> code. I have done both now so hope to get some constructive
> help.
>
> My problem is this. I want to receive some data from the
> driver - a filter driver.
>
> In the driver I am trying to populate a structure, and
> return it via the Irp->AssociatedIrp.SystemBuffer.
>
> The structure within the driver looks like
>
> 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;
>
> and I have all of my device ios firing correctly.
>
> The one I am having trouble with is the firewall status
> query,
>
> the code for this is as below
>
> int getFirewallStatus(
> in PDEVICE_OBJECT DeviceObject,
>
in PIRP Irp)
> {
> FIREWALL_STATUS fwallStatus;
> NTSTATUS ntStatus;
> PIO_STACK_LOCATION irpSp;// Pointer to current stack
> location
>
> ntStatus = STATUS_SUCCESS;
>
> irpSp = IoGetCurrentIrpStackLocation( Irp );
>
> ntStatus = STATUS_SUCCESS;
>
> DbgPrint(“Get firewall status message
> received”);
>
> fwallStatus.upTime=999999;
> fwallStatus.packetsProcessed=888888;
> fwallStatus.packetsDropped=777777;
> fwallStatus.connectionAttemptsProcessed=666666;
> fwallStatus.connectionAttemptsRefused=555555;
>
> Irp->AssociatedIrp.SystemBuffer = &fwallStatus;
> irpSp->Parameters.DeviceIoControl.OutputBufferLength =
> sizeof(fwallStatus);
> Irp->IoStatus.Information = sizeof(fwallStatus);
>
> Irp->IoStatus.Status = ntStatus;
> IoCompleteRequest( Irp, IO_NO_INCREMENT );
>
> return 0;
> }
>
> Note, this is called from with the main deviceio function
> that is registered with the io manager. The function is
> called ok, but the result is a BSOD. As far as the MSDN
> tells me, using buffered IO the system buffer is for both
> input and output io, and you must pass a pointer to the
> output buffer to the system buffer, and also set the output
> buffer length. In some articles I have found they even say
> to set the IoStatus.Information to the size out the output
> buffer as well.
>
> For completeness, the client side code I have calling this
> is as follows :
>
> void getFirewallStatus(){
> FIREWALL_STATUS outputBuffer;
> BOOL bRc;
> ULONG bytesReturned;
> int errNum;
>
> if (!hDevice){
> hDevice =
> CreateFile(“\\.\SimpleSys”,
> GENERIC_READ | GENERIC_WRITE,
> 0,
> NULL,
> OPEN_EXISTING,
> 0,
> NULL);
>
> }
> if (hDevice == INVALID_HANDLE_VALUE){
> printf(“Invalid handle value returned from
> CreateFile \n”);
> errNum = GetLastError();
> printf(“CreateFile failed! ERROR CODE =
> %d\n”, errNum);
> return;
> }
> else{
> bRc = DeviceIoControl ( hDevice,
> IOCTL_GET_FIREWALL_STATUS,
> gFirewallRules,
> sizeof(TL_PORT_RULE) *
> gFirewallRulesCount,
> &outputBuffer,
> sizeof( outputBuffer),
> &bytesReturned,
> NULL
> );
>
> printf(“Uptime
> %d”,outputBuffer.upTime);
> }
> }
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars
> visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online
> at http://www.osronline.com/page.cfm?name=ListServer

__________________________________________________________________
Be smarter than spam. See how smart SpamGuard is at giving junk email the boot with the All-new Yahoo! Mail. Click on Options in Mail and switch to New Mail today or register for free at http://mail.yahoo.ca

when I try

fwallStatus = Irp->AssociatedIrp.SystemBuffer;

I get a compile time error

c:\simplesysbuild\firewall.c(23) : error C2440: ‘=’ : cannot convert from 'PVOID
’ to ‘FIREWALL_STATUS’

of course you will need to define fwallStatus as pointer:

FIREWALL_STATUS *fwallStatus;

Calvin

— On Sun, 9/28/08, xxxxx@yahoo.co.uk wrote:

> From: xxxxx@yahoo.co.uk
> Subject: RE:[ntdev] Irp->AssociatedIrp.SystemBuffer
> To: “Windows System Software Devs Interest List”
> Received: Sunday, September 28, 2008, 10:31 AM
> when I try
>
> fwallStatus = Irp->AssociatedIrp.SystemBuffer;
>
> I get a compile time error
>
> c:\simplesysbuild\firewall.c(23) : error C2440:
> ‘=’ : cannot convert from 'PVOID
> ’ to ‘FIREWALL_STATUS’
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars
> visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online
> at http://www.osronline.com/page.cfm?name=ListServer

__________________________________________________________________
Instant Messaging, free SMS, sharing photos and more… Try the new Yahoo! Canada Messenger at http://ca.beta.messenger.yahoo.com/

Wow, no blue screen now thanks!
When in user mode I get to the line

printf(“Uptime %d”,&outputBuffer.upTime);

I don’t get the expected 99999 value. I tried both &outputBuffer and outputBuffer. I get what looks like a pointer reference (huge unexpected number) in both cases.

Thanks for your help and Im sure I can debug from here, but if you have another flash of inspiration I would be most grateful. Thanks once again for your timely response, on a weekend!

Glad to be able to help.

Double check that you set the Irp->IoStatus.Information correctly to the size of FIREWALL_STATUS, not the size of the pointer to it.

Good luck,
Calvin

— On Sun, 9/28/08, xxxxx@yahoo.co.uk wrote:

> From: xxxxx@yahoo.co.uk
> Subject: RE:[ntdev] Irp->AssociatedIrp.SystemBuffer
> To: “Windows System Software Devs Interest List”
> Received: Sunday, September 28, 2008, 10:55 AM
> Wow, no blue screen now thanks!
> When in user mode I get to the line
>
> printf(“Uptime %d”,&outputBuffer.upTime);
>
> I don’t get the expected 99999 value. I tried both
> &outputBuffer and outputBuffer. I get what looks like a
> pointer reference (huge unexpected number) in both cases.
>
> Thanks for your help and Im sure I can debug from here, but
> if you have another flash of inspiration I would be most
> grateful. Thanks once again for your timely response, on a
> weekend!
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars
> visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online
> at http://www.osronline.com/page.cfm?name=ListServer

__________________________________________________________________
Instant Messaging, free SMS, sharing photos and more… Try the new Yahoo! Canada Messenger at http://ca.beta.messenger.yahoo.com/

Good steer. I believe I am. The driver function that now works looks like

int getFirewallStatus(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp)
{
FIREWALL_STATUS * fwallStatus;
NTSTATUS ntStatus;
PIO_STACK_LOCATION irpSp;// Pointer to current stack location

ntStatus = STATUS_SUCCESS;

irpSp = IoGetCurrentIrpStackLocation( Irp );

ntStatus = STATUS_SUCCESS;

DbgPrint(“Get firewall status message received”);

fwallStatus = Irp->AssociatedIrp.SystemBuffer;

fwallStatus->upTime=999999;
fwallStatus->packetsProcessed=888888;
fwallStatus->packetsDropped=777777;
fwallStatus->connectionAttemptsProcessed=666666;
fwallStatus->connectionAttemptsRefused=555555;

irpSp->Parameters.DeviceIoControl.OutputBufferLength = sizeof(fwallStatus);
Irp->IoStatus.Information = sizeof(fwallStatus);

Irp->IoStatus.Status = ntStatus;
IoCompleteRequest( Irp, IO_NO_INCREMENT );

return 0;
}

The line in contention is this one
Irp->IoStatus.Information = sizeof(fwallStatus);
whereas clearly fwallStatus is just the pointer, so I changed it to
Irp->IoStatus.Information = sizeof(FIREWALL_STATUS);

Frustratingly I still can’t get anything intelligable out of the structure in user mode.

I also tried

irpSp->Parameters.DeviceIoControl.OutputBufferLength = sizeof(fwallStatus);

to

irpSp->Parameters.DeviceIoControl.OutputBufferLength = sizeof(FIREWALL_STATUS);

I don’t want this to turn into a hand holding session, but I really have run out of ideas. Still not getting the blue screen is a big leap forward for me. Thanks for all your help.

I got there, and boy was that a boost for my confidence!

In user mode, I needed to make sure I was passing in the sizeof(FIREWALL_STATUS) in the output buffer size. The code that works is :

void getFirewallStatus(){
FIREWALL_STATUS outputBuffer;
BOOL bRc;
ULONG bytesReturned;
int errNum;
int outputbufferlen;

if (!hDevice){
hDevice = CreateFile(“\\.\SimpleSys”,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);

}
if (hDevice == INVALID_HANDLE_VALUE){
printf(“Invalid handle value returned from CreateFile \n”);
errNum = GetLastError();
printf(“CreateFile failed! ERROR CODE = %d\n”, errNum);
return;
}
else{
bRc = DeviceIoControl ( hDevice,
IOCTL_GET_FIREWALL_STATUS,
gFirewallRules,
sizeof(TL_PORT_RULE) * gFirewallRulesCount,
&outputBuffer,
sizeof(FIREWALL_STATUS),
&bytesReturned,
NULL
);

printf(“Uptime %d”,outputBuffer.upTime);
}
}

Thanks for all your help. I was indeed using the sizeof(pointer) rather than sizeof(structure) in the kernel mode code, and when I applied this thought process throughout the code I got there. Thanks once again.

Charlie

Assigning to irpSp->Parameters.DeviceIoControl.OutputBufferLength is not correct, it is an input parameter. What you are NOT doing is checking irpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(FIREWALL_STATUS) before dereferencing the buffer. That means if the UM app sends too small a buffer down, you corrupt memory.

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.co.uk
Sent: Sunday, September 28, 2008 11:28 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Irp->AssociatedIrp.SystemBuffer

Good steer. I believe I am. The driver function that now works looks like

int getFirewallStatus(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp)
{
FIREWALL_STATUS * fwallStatus;
NTSTATUS ntStatus;
PIO_STACK_LOCATION irpSp;// Pointer to current stack location

ntStatus = STATUS_SUCCESS;

irpSp = IoGetCurrentIrpStackLocation( Irp );

ntStatus = STATUS_SUCCESS;

DbgPrint(“Get firewall status message received”);

fwallStatus = Irp->AssociatedIrp.SystemBuffer;

fwallStatus->upTime=999999;
fwallStatus->packetsProcessed=888888;
fwallStatus->packetsDropped=777777;
fwallStatus->connectionAttemptsProcessed=666666;
fwallStatus->connectionAttemptsRefused=555555;

irpSp->Parameters.DeviceIoControl.OutputBufferLength = sizeof(fwallStatus);
Irp->IoStatus.Information = sizeof(fwallStatus);

Irp->IoStatus.Status = ntStatus;
IoCompleteRequest( Irp, IO_NO_INCREMENT );

return 0;
}

The line in contention is this one
Irp->IoStatus.Information = sizeof(fwallStatus);
whereas clearly fwallStatus is just the pointer, so I changed it to
Irp->IoStatus.Information = sizeof(FIREWALL_STATUS);

Frustratingly I still can’t get anything intelligable out of the structure in user mode.

I also tried

irpSp->Parameters.DeviceIoControl.OutputBufferLength = sizeof(fwallStatus);

to

irpSp->Parameters.DeviceIoControl.OutputBufferLength = sizeof(FIREWALL_STATUS);

I don’t want this to turn into a hand holding session, but I really have run out of ideas. Still not getting the blue screen is a big leap forward for me. Thanks for all your help.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

> I post this hoping to get some help, and not criticised for either not researching this enough first

Well, what else are we supposed to say when we see the lines like

FIREWALL_STATUS fwallStatus;

Irp->AssociatedIrp.SystemBuffer = &fwallStatus;
irpSp->Parameters.DeviceIoControl.OutputBufferLength = sizeof(fwallStatus);

Look - first of all, you change Irp->AssociatedIrp.SystemBuffer, i.e. replace a pointer to the system-allocated buffer into which you are supposed to copy data (and which the system is going to free afterwards, once it believes that it has allocated it). In addition to that, you replace it with the address of a local variable, effectively making a local pointer outlive its scope (which does not really matter in this context - the system will crash anyway when it tries to free it). If it is still not enough, you replace the input parameter that specifies the buffer length…

The summary - 3 bugs in 10 lines of code. What else are we supposed to say, apart from telling you to go and do you homework??

Anton Bassov