Eliminating empty handlers

Don’t come back empty-handlered

NDIS drivers have several opportunities to supply advanced functionality through optional handlers. But if you don’t want the advanced functionality, you don’t need to bother implementing an empty handler.

Why does it matter to you? It matters because it makes your code (slightly) more difficult to maintain. “Dummy” code is more lines of worthless boilerplate code that distracts you from your “real” code. There’s also a tiny performance cost, as NDIS has to set up the function call and jump into your code.

Let’s look at an example. Filter drivers are a good model, because the majority of their handlers are optional. From MSDN, we see that the FilterSendNetBufferLists/ FilterSendNetBufferListsComplete handlers are optional.

Suppose your filter looks like this:

 
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
    )
{
    NDIS_FILTER_DRIVER_CHARACTERISTICS FChars;
    // ...
    FChars.SendNetBufferListsHandler = FilterSendNetBufferLists;
    FChars.SendNetBufferListsCompleteHandler = FilterSendNetBufferListsComplete;
    // ...

    Status = NdisFRegisterFilterDriver(
        DriverObject,
        (NDIS_HANDLE)FilterDriverObject,
        &FChars,
        &FilterDriverHandle);
    // ...
}

VOID
FilterSendNetBufferLists(
    IN NDIS_HANDLE FilterModuleContext,
    IN PNET_BUFFER_LIST NetBufferLists,
    IN NDIS_PORT_NUMBER PortNumber,
    IN ULONG SendFlags
)
{
    // Dummy function; just pass the NBLs through
    NdisFSendNetBufferLists(
        pFilter->FilterHandle,
        NetBufferLists,
        PortNumber,
        SendFlags);
}

VOID
FilterSendNetBufferListsComplete(
    IN NDIS_HANDLE FilterModuleContext,
    IN PNET_BUFFER_LIST NetBufferLists,
    IN ULONG SendCompleteFlags
)
{
    // Dummy function; just pass the NBLs through
    NdisFSendNetBufferListsComplete(
        pFilter->FilterHandle,
        PrevNbl,
        SendCompleteFlags);
}

As you can see, the FilterSendNetBufferLists and FilterSendNetBufferListsComplete functions don’t do anything useful. How could we improve the code? Simple: just delete the dummy functions and register NULL for the function handlers.

 
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
)
{
    NDIS_FILTER_DRIVER_CHARACTERISTICS FChars;
    // ...
    FChars.SendNetBufferListsHandler = NULL;
    FChars.SendNetBufferListsCompleteHandler = NULL;
    // ...

    Status = NdisFRegisterFilterDriver(
        DriverObject,
        (NDIS_HANDLE)FilterDriverObject,
        &FChars,
        &FilterDriverHandle);
    // ...
}

Much better!