See, I told you so. It was all my fault.
After tons more code spelunking and debugging, it became obvious
that NDIS was simply failing to set up the miniport block for my driver correctly. It even lacked the special miniport block magic number (which is ‘NDMP’ in big-endian). I spent hours tracing through the internals and finally gave up and went to bed, hoping for inspiration the next day.
I found several samples that called NdisReadConfiguration() in the DDK, and noticed in particular that Elyias Yakub’s netvmini sample was passing a variable called ‘WrapperConfigurationContext’ to NdisOpenConfiguration. I’d read the docs about 100 times, but for some reason, that variable stuck out this time. So I went back to the NdisOpenConfiguration() docs to see what that parameter should be. The documentation reads: Specifies the handle input to MiniportInitialize
. So I looked at the MiniportInitialize documentation, and Lo And Behold, there are two handles input to MiniportInitialize(). Sure enough this code was passing the wrong one in.
It would have helped if I had named that variable precisely WrapperConfigurationContext the first time, instead of something slightly and confusingly different, because then I wouldn’t have had to make the tacit translation of variable names from the docs to my code, and the error would have been (more) obvious. Reason #143,532 to have coding standards.
So, back to testing. What a pain. I discovered several interesting NDIS-related bugs along the way, though, so it wasn’t a total loss. NdisInitializeString() is just weird, and to add to that, there are a couple of minor type bugs in NdisInitializeString() (again!) and NdisMEthIndicateReceive(), where things that are documented as taking VOID are actually prototyped as taking PUCHAR.