CONTAINING_RECORD() fail to work

Anyone can tell me why CONTAINING_RECORD cann’t work.
typedef struct _ReadIRPEntry
{
//LIST_ENTRY listEntry;
PIRP Irp;
LARGE_INTEGER readIRPTimeout;
BOOLEAN bCanceled;//if this IRP is canceled, then it is true;
} ReadIRPEntry, *PReadIRPEntry;

I keep an queue for every read IRP with an entry of the above structure ReadIRPEntry.
And I set a cancel routine for every enqueued read Irp.

VOID ReadCancelRoutine(IN PDEVICE_OBJECT pFdo,
IN PIRP Irp)
{
PDEVICE_EXTENSION pdx= (PDEVICE_EXTENSION)pFdo->DeviceExtension;
NTSTATUS status=STATUS_UNSUCCESSFUL;
KIRQL OldIrql;
PReadIRPEntry pReadIrpEntry =NULL;
LIST_ENTRY listEntry;
PKLIST_NODE pListNode;
BOOLEAN bDelete;
pReadIrpEntry=CONTAINING_RECORD(&Irp,ReadIRPEntry,Irp);
bDelete = pReadIrpEntry->bCanceled;
if (bDelete)
{
ExFreePool(pReadIrpEntry);
}
else
{
pListNode=CONTAINING_RECORD(&pReadIrpEntry,KLIST_NODE,m_pvData);
RemoveNode(&pdx->ReadIRPQueue, pListNode, TRUE);

}
IoReleaseCancelSpinLock(Irp->CancelIrql);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest( Irp, IO_NO_INCREMENT);
lPendingIRPCountDecrement(pdx);
return;
}

in IRP_MJ_DEVICE_CONTROL dispatch routine, I called IoCancelIrp as the following.
pReadIrpEntry = RemoveHead(&pdx->ReadIRPQueue, FALSE);
if (pReadIrpEntry!=NULL && pReadIrpEntry->Irp!=NULL)
{
pReadIrpEntry->bCanceled = TRUE;
IoCancelIrp(pReadIrpEntry->Irp);
}

The error is pReadIrpEntry’s address in IRP_MJ_DEVICE_CONTROL dispatch routine is different to pReadIrpEntry’s in Cancel IRP routine(or to pReadIrpEntry=CONTAINING_RECORD(&Irp,ReadIRPEntry,Irp);).

Why?

thank you very much!

The CONTAINING_RECORD macro allows you to find the base of a structure if
you know the address of one of its fields. It looks like you are trying to
use this for a completely different purpose, like searching the right record
for you in a list,or trying to obtain the base of a record by value and not
by address all of which is not going to work.

/Daniel

wrote in message news:xxxxx@ntdev…
> Anyone can tell me why CONTAINING_RECORD cann’t work.
> typedef struct _ReadIRPEntry
> {
> //LIST_ENTRY listEntry;
> PIRP Irp;
> LARGE_INTEGER readIRPTimeout;
> BOOLEAN bCanceled;//if this IRP is canceled, then it is true;
> } ReadIRPEntry, *PReadIRPEntry;
>
> I keep an queue for every read IRP with an entry of the above structure
> ReadIRPEntry.
> And I set a cancel routine for every enqueued read Irp.
>
> VOID ReadCancelRoutine(IN PDEVICE_OBJECT pFdo,
> IN PIRP Irp)
> {
> PDEVICE_EXTENSION pdx= (PDEVICE_EXTENSION)pFdo->DeviceExtension;
> NTSTATUS status=STATUS_UNSUCCESSFUL;
> KIRQL OldIrql;
> PReadIRPEntry pReadIrpEntry =NULL;
> LIST_ENTRY listEntry;
> PKLIST_NODE pListNode;
> BOOLEAN bDelete;
> pReadIrpEntry=CONTAINING_RECORD(&Irp,ReadIRPEntry,Irp);
> bDelete = pReadIrpEntry->bCanceled;
> if (bDelete)
> {
> ExFreePool(pReadIrpEntry);
> }
> else
> {
> pListNode=CONTAINING_RECORD(&pReadIrpEntry,KLIST_NODE,m_pvData);
> RemoveNode(&pdx->ReadIRPQueue, pListNode, TRUE);
>
> }
> IoReleaseCancelSpinLock(Irp->CancelIrql);
> Irp->IoStatus.Information = 0;
> Irp->IoStatus.Status = STATUS_CANCELLED;
> IoCompleteRequest( Irp, IO_NO_INCREMENT);
> lPendingIRPCountDecrement(pdx);
> return;
> }
>
> in IRP_MJ_DEVICE_CONTROL dispatch routine, I called IoCancelIrp as the
> following.
> pReadIrpEntry = RemoveHead(&pdx->ReadIRPQueue, FALSE);
> if (pReadIrpEntry!=NULL && pReadIrpEntry->Irp!=NULL)
> {
> pReadIrpEntry->bCanceled = TRUE;
> IoCancelIrp(pReadIrpEntry->Irp);
> }
>
> The error is pReadIrpEntry’s address in IRP_MJ_DEVICE_CONTROL dispatch
> routine is different to pReadIrpEntry’s in Cancel IRP routine(or to
> pReadIrpEntry=CONTAINING_RECORD(&Irp,ReadIRPEntry,Irp);).
>
> Why?
>
> thank you very much!
>
>
>

Either I’m missing something, or it looks like you are attempting to
rely the layout of objects in memory across a system call. That is,
because you declared a ReadIRPEntry in one routine, and passed the
address of a member (PIRP), which is itself a pointer that you borrowed
from the system, you’re expecting the be able to deencapsulate you’re
way back to your structure. If that is what you are trying to do, you
need to stop, because there’s no reason why that should work.
Speaking in generic terms, if you had the actual IRP (v. PIRP), this
would still be a terrible idea, but might work. That PIRP member is
probably referenced in several places, only one of which is your code.
For what you are trying to do to have any shot of working, you would
have to pass & ReadpIRPEntry->Irp, which would never work with cancel
IRP.

If this is just wrong, my apologies, because I feel like I have to be
missing something, because what you are trying to do appears to me to be
so strange.

What are trying to accomplish with ReadIRPEntry?

mm

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Monday, July 02, 2007 04:36
To: Windows System Software Devs Interest List
Subject: [ntdev] CONTAINING_RECORD() fail to work

Anyone can tell me why CONTAINING_RECORD cann’t work.
typedef struct _ReadIRPEntry
{
//LIST_ENTRY listEntry;
PIRP Irp;
LARGE_INTEGER readIRPTimeout;
BOOLEAN bCanceled;//if this IRP is canceled,
then it is true;
} ReadIRPEntry, *PReadIRPEntry;

I keep an queue for every read IRP with an entry of the above structure
ReadIRPEntry.
And I set a cancel routine for every enqueued read Irp.

VOID ReadCancelRoutine(IN PDEVICE_OBJECT pFdo,
IN PIRP Irp)
{
PDEVICE_EXTENSION pdx= (PDEVICE_EXTENSION)pFdo->DeviceExtension;
NTSTATUS status=STATUS_UNSUCCESSFUL;
KIRQL OldIrql;
PReadIRPEntry pReadIrpEntry =NULL;
LIST_ENTRY listEntry;
PKLIST_NODE pListNode;
BOOLEAN bDelete;
pReadIrpEntry=CONTAINING_RECORD(&Irp,ReadIRPEntry,Irp);
bDelete = pReadIrpEntry->bCanceled;
if (bDelete)
{
ExFreePool(pReadIrpEntry);
}
else
{

pListNode=CONTAINING_RECORD(&pReadIrpEntry,KLIST_NODE,m_pvData);
RemoveNode(&pdx->ReadIRPQueue, pListNode, TRUE);

}
IoReleaseCancelSpinLock(Irp->CancelIrql);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest( Irp, IO_NO_INCREMENT);
lPendingIRPCountDecrement(pdx);
return;
}

in IRP_MJ_DEVICE_CONTROL dispatch routine, I called IoCancelIrp as the
following.
pReadIrpEntry = RemoveHead(&pdx->ReadIRPQueue, FALSE);
if (pReadIrpEntry!=NULL && pReadIrpEntry->Irp!=NULL)
{
pReadIrpEntry->bCanceled = TRUE;
IoCancelIrp(pReadIrpEntry->Irp);
}

The error is pReadIrpEntry’s address in IRP_MJ_DEVICE_CONTROL dispatch
routine is different to pReadIrpEntry’s in Cancel IRP routine(or to
pReadIrpEntry=CONTAINING_RECORD(&Irp,ReadIRPEntry,Irp);).

Why?

thank you very much!


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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

Hi MM thank you very much.
Because when I can’t process a read IRP, I will allocate an ReadIRPEntry for this IRP, and put it into the read queue.
So I need to free the ReadIRPEntry memory when I cancel this IRP. But I only know the address of Irp in cancel routine, So I need use CONTAINNING_RECORD to get the ReadIRPEntry’s base address.
Then free it.

You can’t use the IRP itself, you must allocate your ReadIrpEntry and
then store the pointer to the allocation within the irp, using one of
the 4 DriverContext fields. Better yet, use an IoCSQ and it does this
for you.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Monday, July 02, 2007 6:26 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] CONTAINING_RECORD() fail to work

Hi MM thank you very much.
Because when I can’t process a read IRP, I will allocate an ReadIRPEntry
for this IRP, and put it into the read queue.
So I need to free the ReadIRPEntry memory when I cancel this IRP. But I
only know the address of Irp in cancel routine, So I need use
CONTAINNING_RECORD to get the ReadIRPEntry’s base address.
Then free it.


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

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

Hi Doron Holan
Thank you for your answer. I will use the following way you taught me.

You can’t use the IRP itself, you must allocate your ReadIrpEntry and
then store the pointer to the allocation within the irp, using one of
the 4 DriverContext fields. Better yet, use an IoCSQ and it does this
for you.

Denny