Win7 Miniport driver: Halt handler getting called but Unload handler not called

I have a miniport driver for which the unload handler is not getting called after the halt handler has done its job, this is on Windowos7. All my OIDS are completed successfully and all the handlers called by NDIS have returned success. I do not have sends and recieves active as I have not connected to any AP(this is a WIFI network driver). I am cancelling all my timers, freeing spinlocks, I have not called any Ndis specific functions in my initialization to call their opposites during Halt. One thing I havent checked is for memory leaks as I am under the assumption that memory leaks is not such a serious problem to not cause a driver unload.

Since the unload handler is not getting called, the second time I try to enable the adapter it does not call MiniportInitialize(because the previous disable did not complete properly).

Any ideas as to how I can approach this?

Thanks in advance

Debugging stuff I have done:


0: kd> !miniports
NDIS Driver verifier level: 0
NDIS Failed allocations : 0
Miniport Driver Block: 87b762c8, Version 0.2
Miniport: 87d0a0e0, NetLuidIndex: 4, IfIndex: 15, My Wireless LAN Adapter
Miniport Driver Block: 8487acc8, Version 0.0
Miniport: 85c690e0, NetLuidIndex: 0, IfIndex: 2, WAN Miniport (SSTP)
Miniport Driver Block: 85547570, Version 0.0
Miniport: 85c670e0, NetLuidIndex: 3, IfIndex: 5, WAN Miniport (PPTP)
Miniport Driver Block: 85c51950, Version 0.0
Miniport: 85c650e0, NetLuidIndex: 0, IfIndex: 6, WAN Miniport (PPPOE)
Miniport Driver Block: 85bb7590, Version 0.0
Miniport: 85c630e0, NetLuidIndex: 0, IfIndex: 7, WAN Miniport (IPv6)
Miniport: 85c4e0e0, NetLuidIndex: 4, IfIndex: 9, WAN Miniport (IP)
Miniport: 85bbc0e0, NetLuidIndex: 1, IfIndex: 8, WAN Miniport (Network Monitor)
Miniport Driver Block: 85bcece0, Version 0.0
Miniport: 8489b0e0, NetLuidIndex: 2, IfIndex: 4, WAN Miniport (L2TP)
Miniport Driver Block: 85bd07f8, Version 1.0
Miniport: 848790e0, NetLuidIndex: 1, IfIndex: 3, WAN Miniport (IKEv2)
Miniport Driver Block: 85bd6df0, Version 1.0
Miniport: 85b930e0, NetLuidIndex: 6, IfIndex: 12, Broadcom NetXtreme 57xx Gigabit Controller
Miniport Driver Block: 85be7010, Version 1.4
Miniport: 855460e0, NetLuidIndex: 0, IfIndex: 11, Intel(R) Wireless WiFi Link 4965AGN
Miniport Driver Block: 85b69800, Version 1.0
Miniport: 85ad00e0, NetLuidIndex: 5, IfIndex: 14, Microsoft ISATAP Adapter #2
Miniport: 85ad70e0, NetLuidIndex: 4, IfIndex: 13, Microsoft ISATAP Adapter
0: kd> !miniport 87d0a0e0

Miniport 87d0a0e0 : My Wireless LAN Adapter, v6.0

AdapterContext : 00000000
Flags : 2c452000
IGNORE_TOKEN_RING_ERRORS, DESERIALIZED, RESOURCES_AVAILABLE
SUPPORTS_MEDIA_SENSE, DOES_NOT_DO_LOOPBACK, MEDIA_CONNECTED
NOT_BUS_MASTER,
PnPFlags : 20620031
PM_SUPPORTED, REMOVE_IN_PROGRESS, DEVICE_POWER_ENABLED
REJECT_REQUESTS, HARDWARE_DEVICE, NDIS_WDM_DRIVER
MiniportState : STATE_HALTED
IfIndex : 15
Ndis5MiniportInNdis6Mode : 0
InternalResetCount : 0000
MiniportResetCount : 0000
References : 2
UserModeOpenReferences: 0
PnPDeviceState : PNP_DEVICE_REMOVED
CurrentDevicePowerState : PowerDeviceD0
Bus PM capabilities
DeviceD1: 0
DeviceD2: 0
WakeFromD0: 0
WakeFromD1: 0
WakeFromD2: 0
WakeFromD3: 0

SystemState DeviceState
PowerSystemUnspecified PowerDeviceUnspecified
S0 D0
S1 D3
S2 D3
S3 D3
S4 D3
S5 D3
SystemWake: S0
DeviceWake: D0

WakeupMethods Enabled 0:

WakeUpCapabilities:
MinMagicPacketWakeUp: 0
MinPatternWakeUp: 0
MinLinkChangeWakeUp: 0
Current PnP and PM Settings: : 00000010
DISABLE_WAKE_UP,
No Resources Allocated
MediaType : 802.11
DeviceObject : 87d0a028, PhysDO : 87bbb998 Next DO: 87bbb998
MapRegisters : 00000000
FirstPendingPkt: 00000000
DriverVerifyFlags : 00000000
Miniport Interrupt : 00000000
Miniport version 6.0
Miniport Filter List:
Miniport Open Block Queue:
0: kd> !mopen 87b762c8
Miniport Open Block 87b762c8
Protocol 00000006 = , ProtocolContext 00000000, Miniport 87d0a0e0 = My Wireless LAN Adapter, v6.0

MiniportAdapterContext: 87b76464
Flags : 95c359a0
PACKET_RECEIVED, STATUS_RECEIVED, OPEN_UNBINDING
OPEN_CALL_MANAGER, OPEN_USE_MULTICAST_LIST, OPEN_WRAPPED_TO_NDIS6
References : -1782354352
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
[848398c0 System]
4.000030 848bf798 00005fe Blocked nt!KiSwapContext+0x26
nt!KiSwapThread+0x266
nt!KiCommitThreadWait+0x1df
nt!KeWaitForSingleObject+0x393
ndis!ndisPnPRemoveDeviceEx+0xe3
ndis!ndisPnPDispatch+0x3cf
nt!IofCallDriver+0x63
nt!IopSynchronousCall+0xc2
nt!IopRemoveDevice+0xd4
nt!PnpRemoveLockedDeviceNode+0x16c
nt!PnpDeleteLockedDeviceNode+0x2d
nt!PnpDeleteLockedDeviceNodes+0x4c
nt!PnpProcessQueryRemoveAndEject+0x946
nt!PnpProcessTargetDeviceEvent+0x38
nt!PnpDeviceEventWorker+0x216
nt!ExpWorkerThread+0x10d
nt!PspSystemThreadStartup+0x9e
nt!KiThreadStartup+0x19
4.0000b8 855eed48 0002a1b Blocked nt!KiSwapContext+0x26
nt!KiSwapThread+0x266
nt!KiCommitThreadWait+0x1df
nt!KeWaitForSingleObject+0x393
ndis!ndisThreadPoolTimerHandler+0xd9
nt!PspSystemThreadStartup+0x9e
nt!KiThreadStartup+0x19
4.0000bc 855eea70 0000c8f Blocked nt!KiSwapContext+0x26
nt!KiSwapThread+0x266
nt!KiCommitThreadWait+0x1df
nt!KeRemoveQueueEx+0x4f8
nt!KeRemoveQueue+0x1b
ndis!ndisWorkerThread+0x22
nt!PspSystemThreadStartup+0x9e
nt!KiThreadStartup+0x19
4.0000c0 855f2b98 00004a1 Blocked nt!KiSwapContext+0x26
nt!KiSwapThread+0x266
nt!KiCommitThreadWait+0x1df
nt!KeWaitForSingleObject+0x393
ndis!ndisCmWaitThread+0x5b
nt!PspSystemThreadStartup+0x9e
nt!KiThreadStartup+0x19

[85b6fb68 smss.exe]

[86d812c8 csrss.exe]

[86dfb130 wininit.exe]

[848b4030 csrss.exe]

[87599030 services.exe]

[8759f030 winlogon.exe]

[86d75738 lsass.exe]

[875a3030 lsm.exe]

Based on the miniport PnPFlags having REMOVE_IN_PROGRESS asserted and the
MiniportState as STATE_HALTED I would have to assume that eventhough you
are convinced that you shutdown everything in your miniport in response to
MiniportHalt() that you have not actually done so.

The other disturbing thing is the associated open block. How did you
arrive at its address? The list of opens in the !miniport dump is empty
which should mean there are not any opens. So I am wondering if we can
actually trust the information dumped by !mopen.

The references count in the open is suspect (-1782354352) and makes me
question if you have simply asked ndiskd to ‘dump’ the memory that was once
an open block but is no longer actually valid.

The way I would go about debugging this is to make careful note of the state
of the miniport (using ndiskd.miniport) on entry to MiniportInitialize and
after every initialization step your driver takes that allocates resources,
and finally after it returns from Init. Then do the same on entry to Halt
and after every step where you ‘undo’ what you did in Init and see that the
undo is actually taking effect.

Also, if you don’t already, add simple interlocked counters to track the
count of netbuffers and requests in & out of or allocated & freed by your
miniport so you can detect any possible imbalance at halt time.

Good Luck,
Dave Cattley

Dave,

Thanks for your advice, I actually fixed it the day after I sent out this post using the Checked version of Ndis.sys of Windows 7. Like you said it was because of couple of work items not being freed. The code was in place but because they are inside a wrong if condition they never got executed :slight_smile: and that was the reason behind this unload not happening correctly.

Well apart from this, I would also wanna tell you that using checked version of ndis.sys of windows7 is not as straight forward as it was on xp maybe. Replacing the checked version of ndis.sys doesnt straight away give you prints. I assume this is basically because of use of KdPrintEx inside it replacing the much straight forward KdPrint. I had to tinker with the debug filter mask to get to see the prints. The msdn has not documented this!! else it would have saved us few frustrating moments. I can share this to people who are finding it difficult to see the Ndis prints on the debugger.

Well, now to the debugging I had done, I found out that whenever we take a ndis resource we see the reference count incremented with the print “<==ndisReferenceMiniport:xxxxx Ref=value”. Calling the Ndis APIs also sometimes increments the reference count because of some resource allocation that is done internally in those Ndis APIs. So I kept track of the reference count(resource allocation) by single stepping my miniport initialize function(where I saw before in the log the reference counter got incremented twice- if u remember !miniports debug command output in my previous post also referred to these two resources- workitems) and found out that the reference count incremented twice is because of the two work items that I allocated using NdisAllocateIoWorkItem.I then searched in my code for freeing of them and found that they were put in a wrong conditional block and so were never freed!!

Thanks for your response
Srinivas