Question on RemoveEntryList usage!

According to DDK documentation;

“RemoveEntryList removes the entry by setting the Flink member of the entry before Entry to point to the entry after Entry, and the Blink member of the entry after Entry to point to the entry before Entry.”

In some of the samples in DDK, I see the following usages;

Usage 1:

ExAcquireFastMutex (&DeviceData->Mutex);

listHead = &DeviceData->ListOfPDOs;

for(entry = listHead->Flink,nextEntry = entry->Flink;
entry != listHead;
entry = nextEntry,nextEntry = entry->Flink) {

pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
RemoveEntryList (&pdoData->Link);
InitializeListHead (&pdoData->Link);
pdoData->ParentFdo = NULL;
pdoData->ReportedMissing = TRUE;
}

ExReleaseFastMutex (&DeviceData->Mutex);

Here the RemoveEntryList() call is followed by a call to InitializeListHead().

Usage 2:

Here RemoveEntryList() is not followed by InitializeListHead()

for (entry = FailGroup->FOG_DeviceList.Flink;
entry != &FailGroup->FOG_DeviceList;
entry = entry->Flink) {

fogDeviceListEntry = CONTAINING_RECORD(entry,
DSM_FOG_DEVICELIST_ENTRY,
ListEntry);

if (fogDeviceListEntry->DeviceInfo == DeviceInfo) {

DeviceInfo->FailGroup = NULL;
RemoveEntryList(entry);
DsmpFreePool(fogDeviceListEntry);

InterlockedDecrement((LONG volatile*)&FailGroup->Count);
}
}

Can anyone please explain under which conditions we can just delete an item from the List, and then reinitialize the List, compared to just delete a list entry?

TIA!

> According to DDK documentation;

“RemoveEntryList removes the entry by setting the Flink member of the
entry before Entry to point to the entry after Entry, and the Blink member
of the entry after Entry to point to the entry before Entry.”

In some of the samples in DDK, I see the following usages;

Usage 1:

ExAcquireFastMutex (&DeviceData->Mutex);

listHead = &DeviceData->ListOfPDOs;

for(entry = listHead->Flink,nextEntry = entry->Flink;
entry != listHead;
entry = nextEntry,nextEntry = entry->Flink) {

pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
RemoveEntryList (&pdoData->Link);
InitializeListHead (&pdoData->Link);

It looks to me like, for safety, the LIST_ENTRY field of the removed node
is being reset so that it no longer has stale pointers to its previous
Flink and Blink nodes; in other worlds, this might be done by setting both
Flink and Blink to NULL for the removed node, but in the case shown here,
the programmer has chosen to make the LIST_ENTRY be “safe” for access (the
node points to itself along either path), which means that a “recursive”
loop on the object will discover it has no other nodes referenced.

So if we have A<->B<->C<->D<->A and we remove C, we have

A<->B<->D<->A
and
C<->C

pdoData->ParentFdo = NULL;
pdoData->ReportedMissing = TRUE;
}

ExReleaseFastMutex (&DeviceData->Mutex);

Here the RemoveEntryList() call is followed by a call to
InitializeListHead().

Usage 2:

Here RemoveEntryList() is not followed by InitializeListHead()

for (entry = FailGroup->FOG_DeviceList.Flink;
entry != &FailGroup->FOG_DeviceList;
entry = entry->Flink) {

fogDeviceListEntry = CONTAINING_RECORD(entry,
DSM_FOG_DEVICELIST_ENTRY,
ListEntry);

if (fogDeviceListEntry->DeviceInfo == DeviceInfo) {

DeviceInfo->FailGroup = NULL;
RemoveEntryList(entry);

In this case, the programmer has been less careful, so the removed node
has Flink and Blink still pointing into cells in the list. So if we have
A<->B<->C<->D<->A, and remove C, we find we are now left with

A<->B<->D<->A
and
C->D<->A<->B<->D<->A
and
A<->B<->D<->A<->B<-C

so if we try to follow the links from C, they are still valid addresses,
but they end up giving us a totally erroneous result if we follow them.
So I would say the Case 1 programmer was slighly more conservative than
the Case 2 programmer when it comes to data structure integrity. I do
not believe there is any “formal” rule involved.
joe

DsmpFreePool(fogDeviceListEntry);

InterlockedDecrement((LONG volatile*)&FailGroup->Count);
}
}

Can anyone please explain under which conditions we can just delete an
item from the List, and then reinitialize the List, compared to just
delete a list entry?

TIA!


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

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

It is for safety. Typically this is followed with an ASSERT(IsListEmpty(ple)) when you cleanup the struct before freeing it to make sure you are not removing an active list entry from the list, thus corrupting it

d

Bent from my phone


From: xxxxx@flounder.commailto:xxxxx
Sent: ?11/?13/?2013 2:31 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: Re: [ntdev] Question on RemoveEntryList usage!

> According to DDK documentation;
>
> “RemoveEntryList removes the entry by setting the Flink member of the
> entry before Entry to point to the entry after Entry, and the Blink member
> of the entry after Entry to point to the entry before Entry.”
>
> In some of the samples in DDK, I see the following usages;
>
> Usage 1:
>
> ExAcquireFastMutex (&DeviceData->Mutex);
>
> listHead = &DeviceData->ListOfPDOs;
>
> for(entry = listHead->Flink,nextEntry = entry->Flink;
> entry != listHead;
> entry = nextEntry,nextEntry = entry->Flink) {
>
> pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
> RemoveEntryList (&pdoData->Link);
> InitializeListHead (&pdoData->Link);

It looks to me like, for safety, the LIST_ENTRY field of the removed node
is being reset so that it no longer has stale pointers to its previous
Flink and Blink nodes; in other worlds, this might be done by setting both
Flink and Blink to NULL for the removed node, but in the case shown here,
the programmer has chosen to make the LIST_ENTRY be “safe” for access (the
node points to itself along either path), which means that a “recursive”
loop on the object will discover it has no other nodes referenced.

So if we have A<->B<->C<->D<->A and we remove C, we have

A<->B<->D<->A
and
C<->C

> pdoData->ParentFdo = NULL;
> pdoData->ReportedMissing = TRUE;
> }
>
> ExReleaseFastMutex (&DeviceData->Mutex);
>
> Here the RemoveEntryList() call is followed by a call to
> InitializeListHead().
>
> Usage 2:
>
> Here RemoveEntryList() is not followed by InitializeListHead()
>
> for (entry = FailGroup->FOG_DeviceList.Flink;
> entry != &FailGroup->FOG_DeviceList;
> entry = entry->Flink) {
>
> fogDeviceListEntry = CONTAINING_RECORD(entry,
> DSM_FOG_DEVICELIST_ENTRY,
> ListEntry);
>
> if (fogDeviceListEntry->DeviceInfo == DeviceInfo) {
>
> DeviceInfo->FailGroup = NULL;
> RemoveEntryList(entry);

In this case, the programmer has been less careful, so the removed node
has Flink and Blink still pointing into cells in the list. So if we have
A<->B<->C<->D<->A, and remove C, we find we are now left with

A<->B<->D<->A
and
C->D<->A<->B<->D<->A
and
A<->B<->D<->A<->B<-C

so if we try to follow the links from C, they are still valid addresses,
but they end up giving us a totally erroneous result if we follow them.
So I would say the Case 1 programmer was slighly more conservative than
the Case 2 programmer when it comes to data structure integrity. I do
not believe there is any “formal” rule involved.
joe

> DsmpFreePool(fogDeviceListEntry);
>
> InterlockedDecrement((LONG volatile*)&FailGroup->Count);
> }
> }
>
> Can anyone please explain under which conditions we can just delete an
> item from the List, and then reinitialize the List, compared to just
> delete a list entry?
>
> TIA!
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> OSR is HIRING!! See http://www.osr.com/careers
>
> 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
>


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

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</mailto:xxxxx></mailto:xxxxx>

xxxxx@yahoo.com wrote:

Usage 1:

ExAcquireFastMutex (&DeviceData->Mutex);

listHead = &DeviceData->ListOfPDOs;

for(entry = listHead->Flink,nextEntry = entry->Flink;
entry != listHead;
entry = nextEntry,nextEntry = entry->Flink) {

pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link);
RemoveEntryList (&pdoData->Link);
InitializeListHead (&pdoData->Link);
pdoData->ParentFdo = NULL;
pdoData->ReportedMissing = TRUE;
}

ExReleaseFastMutex (&DeviceData->Mutex);

Here the RemoveEntryList() call is followed by a call to InitializeListHead().

Can anyone please explain under which conditions we can just delete an item from the List, and then reinitialize the List, compared to just delete a list entry?

Take another look at that code. It’s not re-initializing the list.
It’s initializing the list pointers within the object that was just
removed. That’s strictly a debugging measure, just to make sure you
don’t accidentally keep around stale pointers. I will sometimes store
zeros there, just so any stale pointer dereference causes an immediate
blue screen.

One of the strange attributes of the RemoveEntryList function is that it
is not given the head of the list. It removes the item from whatever
list it happens to be in.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.