Decoding the error codes

“I compiled my NDIS filter driver, but NdisFRegisterFilterDriver fails in my DriverEntry function.  Now what?”

Here’s a table listing common problems and fixes.  Rows are grouped by symptom.

Problem Resolution
NDIS_STATUS_BAD_CHARACTERISTICS (0xc0010005)
The Characteristics block has the wrong Header for the NDIS driver version. If you are writing an NDIS 6.0 filter driver, set NDIS_FILTER_DRIVER_CHARACTERISTICS::Header::Revision to NDIS_FILTER_CHARACTERISTICS_REVISION_1.  Otherwise, for any version NDIS 6.1 or later, use NDIS_FILTER_CHARACTERISTICS_REVISION_2.
The Characteristics block has an incorrect Size or Type.

Make sure that NDIS_FILTER_DRIVER_CHARACTERISTICS::Header.Size is set to sizeof(NDIS_FILTER_DRIVER_CHARACTERISTICS).

Make sure that NDIS_FILTER_DRIVER_CHARACTERISTICS::Header.Type is set to NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS.

Your filter is missing the 4 mandatory handlers. Make sure you provide FilterPause, FilterRestart, FilterAttach, and FilterDetach handlers in your characteristics block.
Your filter has inconsistent OID handlers.

If you provide FilterOidRequest, you must provide FilterOidRequestComplete.  Likewise, if you provide FilterOidRequestComplete, you must provide FilterOidRequest.

Likewise, do not provide a FilterCancelOidRequest handler if you do not have a FilterOidRequest handler.  However, the inverse is not true: if you provide FilterOidRequest, you may optionally provide FilterCancelOidRequest.  I only recommend you provide it if you queue OIDs for some nontrivial amount of time.

Both rules above also apply to Direct OID handlers.

Your filter has inconsistent NBL handlers. If you do not provide a FilterSendNetBufferLists handler, then you must not provide a FilterCanceSendNetBufferLists handler either.
NDIS_STATUS_FAILURE (0xc0000001)
The filter doesn’t match the INF. Check that NDIS_FILTER_DRIVER_CHARACTERISTICS::UniqueName:
  1. is a GUID,
  2. has curly braces, and
  3. precisely matches what’s in your INF’s NetcfgInstanceId directive.
The filter was not correctly installed. Verify that this key exists:

HKLM\SYSTEM\CurrentControlSet\Control\Network\{4d36e974-e325-11ce-bfc1-08002be10318}\{your filter’s GUID}\Ndi

If the key doesn’t exist, check whether your installer actually ran, and whether its call to INetCfgClassSetup::Install succeeded.

NDIS_STATUS_BAD_VERSION (0xc0010004)
The current implementation of NDIS doesn’t support the NDIS contract version that your filter driver is asking for.

Check the list of NDIS versions by OS version against the NDIS_FILTER_DRIVER_CHARACTERISTICS::MajorNdisVersion and ::MinorNdisVersion that your driver is requesting.  Make sure that you’re getting the right version.

In particular, note that there is no such thing as “NDIS 6.2”.  If you’re setting MajorNdisVersion=6 and MinorNdisVersion=2, you’ll get this error code.  Use MinorNdisVersion=20 instead.

Some other error code
Your filter driver’s FilterSetOptions handler was called and returned a failure code.

NDIS calls into your FilterSetOptions handler within the context of your filter’s call to NdisFRegisterFilterDriver.  If your FilterSetOptions handler returns an error code, then NdisFRegisterFilterDriver will fail with the same error code.

Set a breakpoint on your filter’s FilterSetOptions handler and verify that it succeeds.

A hang, crash, or other strange behavior
Your filter driver is using a duplicate UniqueName. Make sure that no other filter uses the same UniqueName as your filter.  In particular, ensure that you are not using the same UniqueName as the WDK sample filter: {5cbf81bd-5055-47cd-9055-a76b2b4e3697}
Another network driver hangs when trying to attach your filter.

Use a kernel debugger to run:

!stacks 2 ndis!

Check whether there are any tall callstacks in NDIS that appear to be pausing or unbinding any drivers.  It’s likely that some driver has hung.  This hang may not be caused directly by your filter driver; it may only be exposed while NDIS tried to attach your filter driver.

When all else fails, you can often get more detail by looking at NDIS trace messages.  If you spend a lot of time working on NDIS drivers, I encourage you to get comfortable with reading these traces, since that ability will save you time in the long run.  In this case, NdisFRegisterFilterDriver will often trace a message saying exactly what has gone wrong.