Hang on uninstall of NDIS IM driver

I was wondering if anyone could point me at some reasons why an NDIS IM
driver could hang when I go to manually uninstall it from the Local Area
Connection Properties (where it was manually installed in the first place)?

I am using the “James” version of the NDIS IM example from here:
http://www.wd-3.com/archive/ExtendingPassthru2.htm

I had seen failure-to-unload behavior like this in the past, and the
*apparent* cause was that I was subtly corrupting the stack with some inline
asm where I put a dword onto the stack and didn’t remove it before I
returned from a function (still not really sure how it worked since you’d
think the saved EIP would be completely out of whack). But I fixed that and
didn’t see this behavior again until recently.

Nowadays I have isolated this problem to the following: If I set
the decision = true in the *FilterPacket* function (thus telling the
function who called FilterPacket() not to indicate the packet up, thus
dropping it, it won’t unload. If I don’t try to drop the packets, it will
unload. To make it a little more complicated, I can load it up and unload it
right away, but if I load it up, send a packet to be filtered, and then try
to unload, that’s when it will fail.

Here is the output from WinDbg on a successful unload:
*******************************************
INFO:–> ::SysNotifyBindingPath, dwChangeFlag 0x00000002
INFO:–> ::SysNotifyBindingPath path enable
INFO:PathToken
<ms_passthru->PCI\VEN_14E4&DEV_4312&SUBSYS_00071028&REV_01\4&360A6DE&0&00E1>
INFO:–> ::SysNotifyBindingPath, dwChangeFlag 0x00000002
INFO:–> ::SysNotifyBindingPath path enable
INFO:PathToken
<ms_passthru->PCI\VEN_14E4&DEV_1600&SUBSYS_01CC1028&REV_02\4&378EDFA4&0&00E2>
INFO:–> ::SysNotifyBindingPath, dwChangeFlag 0x00000002
INFO:–> ::SysNotifyBindingPath path enable
INFO:PathToken <ms_passthru->ROOT\NET\0000>
INFO:–> ::SysNotifyComponent dwChangeFlag 0x00080002
INFO:–> ::ApplyRegistryChanges
INFO:–> ::ApplyRegistryChanges default 4
INFO:–> ::ApplyRegistryChanges exit
PtPnPHandler: Adapt 862ACCB8, Event 2
==> PtUnbindAdapter: Adapt 862ACCB8
==>MiniportHalt: Adapt 862ACCB8
CloseAdapterComplete: Adapt 862ACCB8, Status 0
<== MiniportHalt: pAdapt 862ACCB8
<== PtUnbindAdapter: Adapt 862ACCB8
PtPnPHandler: Adapt 861D8518, Event 2
==> PtUnbindAdapter: Adapt 861D8518
==>MiniportHalt: Adapt 861D8518
CloseAdapterComplete: Adapt 861D8518, Status 0
<== MiniportHalt: pAdapt 861D8518
<== PtUnbindAdapter: Adapt 861D8518
PtUnloadProtocol: done!
PtUnload: entered
PtUnloadProtocol: done!
PtUnload: done!
INFO:–> ::ApplyPnpChanges
INFO:DNE is in filter class
INFO: is not set
INFO:Adding other IMs…
INFO:NetTransport: Ndisuio
INFO:NetTransport: RasPppoe
INFO:NetTransport: Tcpip
INFO:NetTransport: NdisWan
INFO:NetTransport: NetBT
INFO:0000 is a node
INFO:No RootDevice: 0000
INFO:0001 is a node
INFO:–keep settings to 0001
INFO: UpperBind: {Tcpip}
INFO: RootDevice {60E9DBFB-CAA9-469D-9C5E-6D7E8D693D56} NIC1394
INFO:0002 is a node
INFO:–keep settings to 0002
INFO: UpperBind: {NdisWan}
INFO: RootDevice {F7600427-A36D-4167-82BE-87D42CCD52E9} AsyncMac
INFO:0003 is a node
INFO:–keep settings to 0003
INFO: UpperBind: {NdisWan}
INFO: RootDevice {67F8C768-D35F-4EBF-B6D4-A141AE50BDA9} Rasl2tp
INFO:0004 is a node
INFO:–keep settings to 0004
INFO: UpperBind: {NdisWan}
INFO: RootDevice {30D710C5-884A-4DDC-AD0F-4946FF3F055F} PptpMiniport
INFO:0005 is a node
INFO:–keep settings to 0005
INFO: UpperBind: {NdisWan}
INFO: RootDevice {19FD3F2E-0ED8-4611-B5ED-E86EF078E59A} RasPppoe
INFO:0006 is a node
INFO:–keep settings to 0006
INFO: UpperBind: {NdisWan}
INFO: RootDevice {8537FD13-6F99-4691-AA42-96727D0070E5} Raspti
INFO:0007 is a leaf
INFO:0008 is a node
INFO:–keep settings to 0008
INFO: UpperBind: {Tcpip}
INFO: RootDevice {9CCB311B-3326-46F7-BFE0-0CD1B8C7FFF5} PSched
INFO: RootDevice {01437611-D309-47CD-A9B7-7BA0F3D5F8FC} DNE
INFO: RootDevice NdisWanIp
INFO:0009 is a leaf
INFO:0010 is a node
INFO:–keep settings to 0010
INFO: UpperBind: {VMnetBridge,RasPppoe,Ndisuio,Tcpip}
INFO: RootDevice {88C444BC-E250-4CA7-851D-8B7CC6113540} PSched
INFO: RootDevice {5EFE6A26-71DE-4251-98D5-6AF1E528D794} DNE
INFO: RootDevice {1EE4A082-73D6-4C68-B295-86BAA298ACBF} BCM43XX
INFO:0011 is a leaf
INFO:0012 is a node
INFO:–keep settings to 0012
INFO: UpperBind: {VMnetBridge,RasPppoe,Ndisuio,Tcpip}
INFO: RootDevice {912B93A3-4599-41CE-AEDD-0BEC593244FE} PSched
INFO: RootDevice {9FC3E02C-C1C7-49D7-9C8E-DE1914DBDE02} DNE
INFO: RootDevice {FF736D39-8192-4676-ADA4-936B6AD72837} b57w2k
INFO:0013 is a leaf
INFO:0014 is a node
INFO:–keep settings to 0014
INFO: UpperBind: {VMnetBridge,RasPppoe,Ndisuio,Tcpip}
INFO: RootDevice {53AAB423-53EE-4BC9-B61B-30ECEFCCCE80} PSched
INFO: RootDevice {38B89128-1DAA-4652-917C-604D6A181AB0} DNE
INFO: RootDevice {FD5933BC-B80D-4FA8-996D-E34E611CDA67} CVirtA
INFO:0015 is a leaf
INFO:0016 is a leaf
INFO:0017 is a leaf
INFO:0018 is a leaf
INFO:0022 is a node
INFO:–keep settings to 0022
INFO: UpperBind: {RasPppoe,Ndisuio,Tcpip}
INFO: RootDevice {AC3109C9-1051-43B5-A02F-1BBD540D13D0} VMnetAdapter
INFO:0023 is a node
INFO:–keep settings to 0023
INFO: UpperBind: {RasPppoe,Ndisuio,Tcpip}
INFO: RootDevice {A6C53BFF-3872-4C05-84FC-DF7071F22757} VMnetAdapter
INFO:0024 is a node
INFO:–keep settings to 0024
INFO: UpperBind: {Tcpip}
INFO: RootDevice {82B97891-11FD-4A49-B3BE-CAA48A73F3CF} NIC1394
INFO:OrderIM: success changed=0
INFO:–> ::ApplyPnpChanges exit
INFO:DllCanUnloadNow hr=1

Here is the output from WinDbg on an unsuccessful unload:

Non-IP abort
INFO:–> ::SysNotifyBindingPath, dwChangeFlag 0x00000002
INFO:–> ::SysNotifyBindingPath path enable
INFO:PathToken

<ms_passthru->PCI\VEN_14E4&DEV_4312&SUBSYS_00071028&REV_01\4&360A6DE&0&00E1>
INFO:–> ::SysNotifyBindingPath, dwChangeFlag 0x00000002
INFO:–> ::SysNotifyBindingPath path enable
INFO:PathToken

<ms_passthru->PCI\VEN_14E4&DEV_1600&SUBSYS_01CC1028&REV_02\4&378EDFA4&0&00E2>
INFO:–> ::SysNotifyBindingPath, dwChangeFlag 0x00000002
INFO:–> ::SysNotifyBindingPath path enable
INFO:PathToken <ms_passthru->ROOT\NET\0000>
INFO:–> ::SysNotifyComponent dwChangeFlag 0x00080002
INFO:–> ::ApplyRegistryChanges
INFO:–> ::ApplyRegistryChanges default 4
INFO:–> ::ApplyRegistryChanges exit
PtPnPHandler: Adapt 85E13178, Event 2
==> PtUnbindAdapter: Adapt 85E13178
==>MiniportHalt: Adapt 85E13178
CloseAdapterComplete: Adapt 85E13178, Status 0
<== MiniportHalt: pAdapt 85E13178
<== PtUnbindAdapter: Adapt 85E13178
PtPnPHandler: Adapt 86424AF8, Event 2
==> PtUnbindAdapter: Adapt 86424AF8
==>MiniportHalt: Adapt 86424AF8
CloseAdapterComplete: Adapt 86424AF8, Status 0
<== MiniportHalt: pAdapt 86424AF8
<== PtUnbindAdapter: Adapt 86424AF8
PtUnloadProtocol: done!
PtUnload: entered
PtUnloadProtocol: done!
PtUnload: done!
*******************************************
Note, it doesn’t hang the entire system, it just hangs the interface to the
Local Area Connection Properties window, which eventually then makes the
system take a long time to shutdown (but it will eventually shut down of
its own volition)

Any help for what would cause something to not unload would be super
appreciated.

Billy Volta Esq.</ms_passthru-></ms_passthru-></ms_passthru-></ms_passthru-></ms_passthru-></ms_passthru->

That sounds pretty convincingly like a reference counting error or a failure
to return the dropped packet to the owner (or pool).

If you can break into the system with WinDbg and dump the kernel mode stacks

!stacks 2 ndis!

You may well find that a thread is waiting in your IM driver for some event
for resources to be returned and make it safe to stop/unload/etc.

This could be NDIS waiting for transfers (packets) that have traversed the
‘binding’ (open) and not been returned or it could be some reference count
in your driver, or some other related driver.

In any event, since the situation is triggered by the ‘drop’ processing path
in your driver, it is quite likely how you are ‘dropping’ the packet that is
causing a leak of some resource.

Good Luck,
Dave Cattley

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Billy Volta
Sent: Wednesday, January 27, 2010 1:09 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Hang on uninstall of NDIS IM driver

I was wondering if anyone could point me at some reasons why an NDIS IM
driver could hang when I go to manually uninstall it from the Local Area
Connection Properties (where it was manually installed in the first place)?

I am using the “James” version of the NDIS IM example from
here:?http://www.wd-3.com/archive/ExtendingPassthru2.htm

I had seen failure-to-unload behavior like this in the past, and the
*apparent* cause was that I was subtly corrupting the stack with some inline
asm where I put a dword onto the stack and didn’t remove it before I
returned from a function (still not really sure how it worked since you’d
think the saved EIP would be completely out of whack). But I fixed that and
didn’t see this behavior again until recently.

Nowadays I have isolated this problem to the following: If I set
the?decision?= true in the?FilterPacket?function (thus telling the function
who called FilterPacket() not to indicate the packet up, thus dropping it,
it won’t unload. If I don’t try to drop the packets, it will unload. To make
it a little more complicated, I can load it up and unload it right away, but
if I load it up, send a packet to be filtered, and then try to unload,
that’s when it will fail.

Thank you David for the suggested command to try, since I had never used
that before. I get the following result, which I think is indicative that
whatever the problem is, it isn’t due to a stack with ndis anywhere in any
function names…

0: kd> !stacks 2 ndis!
Proc.Thread .Thread Ticks ThreadState Blocker

Max cache size is : 1048576 bytes (0x400 KB)
Total memory in cache : 0 bytes (0 KB)
Number of regions cached: 0
0 full reads broken into 0 partial reads
counts: 0 cached/0 uncached, 0.00% cached
bytes : 0 cached/0 uncached, 0.00% cached
** Prototype PTEs are implicitly decoded
[867c49c8 System]

[86315da0 smss.exe]

[85f1a020 csrss.exe]

[865f9b58 winlogon.exe]

[862e8c88 services.exe]

[8626ec68 lsass.exe]

[85f08860 svchost.exe]

[862d3da0 svchost.exe]

[85f08be0 svchost.exe]

[866775a0 svchost.exe]

[86203a20 svchost.exe]

[865dc810 svchost.exe]

[861f26a0 svchost.exe]

[861b7990 WLTRYSVC.EXE]

[8664eda0 BCMWLTRY.EXE]

[865cbb28 spoolsv.exe]

[861f8be0 scardsvr.exe]

[861bc500 svchost.exe]

[861f6860 cvpnd.exe]

[86650da0 nvsvc32.exe]

[85de87a8 vmware-ufad.exe]

[85de7968 vmware-authd.ex]

[85dbc020 vmount2.exe]

[85d38268 explorer.exe]

[866ebda0 vmnat.exe]

[85d32c10 vmnetdhcp.exe]

[85cf7da0 WLTRAY.EXE]

[86489bf8 rundll32.exe]

[86484be8 stsystra.exe]

[85cf6468 ctfmon.exe]

[861d1440 Dbgview.exe]

[8642cda0 vmserverdWin32.]

[85ccdda0 alg.exe]

[866ec6b0 wscntfy.exe]

[85cdf020 cmd.exe]

[8630bb80 bash.exe]

[8647cda0 cmd.exe]

[8632ada0 bash.exe]

[85cfc810 msiexec.exe]

[85cd04f8 wmiprvse.exe]

Threads Processed: 384

Max cache size is : 1048576 bytes (0x400 KB)
Total memory in cache : 0 bytes (0 KB)
Number of regions cached: 0
0 full reads broken into 0 partial reads
counts: 0 cached/0 uncached, 0.00% cached
bytes : 0 cached/0 uncached, 0.00% cached
** Transition PTEs are implicitly decoded
** Prototype PTEs are implicitly decoded

And while I don’t think I changed anything in the example code outside of
the FilterPacket() function, I was looking a little closer at the logic for
where the function was used. Do you think the following abridged stuff could
be the problem?

in PtReceive() the logic is like
PtReceive(){

do{

Status = FilterPacket( // See if packet to be
dropped.
pAdapt,
Packet,
NULL,
FALSE, // Receive
action.
&bDecision
);

if (
NDIS_STATUS_SUCCESS==Status //
Everything OK?
&&
TRUE==bDecision // Packet
to be dropped?
)
{
break; // Leave
‘do’ group.
}

}while(false);

return Status;
}

It seems to essentially be jumping to the end, and returning without doing
any cleanup. Is that bad in general? Is it bad if it
calls NdisGetReceivedPacket() before the first FilterPacket()? If it’s bad,
what should I be doing to cleanup? (remember I’m using example code because
it’s not all clear in my head :-))

Billy Volta Esq.

On Wed, Jan 27, 2010 at 1:16 PM, David R. Cattley wrote:

> That sounds pretty convincingly like a reference counting error or a
> failure
> to return the dropped packet to the owner (or pool).
>
> If you can break into the system with WinDbg and dump the kernel mode
> stacks
>
> !stacks 2 ndis!
>
> You may well find that a thread is waiting in your IM driver for some event
> for resources to be returned and make it safe to stop/unload/etc.
>
> This could be NDIS waiting for transfers (packets) that have traversed the
> ‘binding’ (open) and not been returned or it could be some reference count
> in your driver, or some other related driver.
>
> In any event, since the situation is triggered by the ‘drop’ processing
> path
> in your driver, it is quite likely how you are ‘dropping’ the packet that
> is
> causing a leak of some resource.
>
> Good Luck,
> Dave Cattley
>
>
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Billy Volta
> Sent: Wednesday, January 27, 2010 1:09 PM
> To: Windows System Software Devs Interest List
> Subject: [ntdev] Hang on uninstall of NDIS IM driver
>
> I was wondering if anyone could point me at some reasons why an NDIS IM
> driver could hang when I go to manually uninstall it from the Local Area
> Connection Properties (where it was manually installed in the first place)?
>
> I am using the “James” version of the NDIS IM example from
> here: http://www.wd-3.com/archive/ExtendingPassthru2.htm
>
> I had seen failure-to-unload behavior like this in the past, and the
> apparent cause was that I was subtly corrupting the stack with some
> inline
> asm where I put a dword onto the stack and didn’t remove it before I
> returned from a function (still not really sure how it worked since you’d
> think the saved EIP would be completely out of whack). But I fixed that and
> didn’t see this behavior again until recently.
>
> Nowadays I have isolated this problem to the following: If I set
> the decision = true in the FilterPacket function (thus telling the function
> who called FilterPacket() not to indicate the packet up, thus dropping it,
> it won’t unload. If I don’t try to drop the packets, it will unload. To
> make
> it a little more complicated, I can load it up and unload it right away,
> but
> if I load it up, send a packet to be filtered, and then try to unload,
> that’s when it will fail.
>
>
> —
> 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
>

You might want to go ?the full monty? and use the command

!process 0 7

and look at every stack in the system to find out what component might be
waiting on something that could influence unbinding your IM.

As for your question about the code: Tough to tell since you supply only a
very small bit of it. You say that PtReceive() is not doing any cleanup
but the code does not show what needs to be cleaned up. So if the routine
is allocating resources it should free them or the system should ensure they
get freed eventually.

Good Luck,

Dave Cattley