Search code examples
cwdkndiswdm

Unable to use NDIS related functions from a Visual Studio's Empty WDM Driver template


I was looking at try writing an NDIS miniport driver and created a new project in my VS2019 installation, choosing the "Empty WDM Driver" as my starting template. I can include ndis.h, but many functions appear not be available including important things like NDIS_MINIPORT_DRIVER_CHARACTERISTICS and NdisMRegisterMiniportDriver cannot be used. Quickly searching for these in the actual ndis.h file shows that they are greyed out under the preprocessor directive #if NDIS_SUPPORT_NDIS6

I have the driver samples repository cloned, and the miniport driver sample works fine, with nothing and uses the same WDK installation. Looking at the configuration between my project and the samples, the options under the "Driver Settings" section are completely different. I'm still rather new to all this, so I'm assuming this is some misconfiguration on my part. Is there anything else I have to edit in my project configuration? The only change I've mad so far in making sure the linker links with the NDIS library. Perhaps the WDM driver template is not what I want for this type of driver, though in that case I'm not sure how to properly set up my project. VS only has one NDIS template and it's for filter drivers.


Solution

  • To make all those APIs show up, you need to set the NDIS version that you're targeting. For example, if you're targeting Windows 7 and later, that would be NDIS 6.20, so you'd put this somewhere before including ndis.h:

    #define NDIS620_MINIPORT 1
    

    That's all you have to define; ndis.h will automatically fill out the other versioning macros on your behalf.

    To see a list of all NDIS versions, look at the top of ndis.h.

    In general, you can bang on the "WDM template" or even a completely empty .C file until it becomes an NDIS driver. If you're starting from scratch, you should ensure that you:

    • define an NDIS version macro, like /DNDIS620_MINIPORT=1 above
    • compile with the /kernel flag
    • compile with the recommended set of security flags (which currently includes /GS /guard:cf /Qspectre, but seems to change often, so consider this answer to already be out of date)
    • link against ndis.lib
    • add a DriverEntry that doesn't touch the DRIVER_OBJECT directly; let NdisMRegisterMiniportDriver do that instead

    If you're using a generic WDM template, note that you'll have to replace any DriverUnload (NDIS has its own flavor of that) and delete any AddDevice (NDIS handles that on your behalf). You'll probably want to delete anything that mentions IRPs. While NDIS allows you to handle IRP_MJ_DEVICE_CONTROL with a control device object (CDO) created via NdisRegisterDeviceEx, it's not strictly necessary and many real-world miniports don't use IRPs at all.

    Once you fill out all the callbacks that NdisMRegisterMiniportDriver demands, you'll have a skeleton of an NDIS miniport driver. This is a valuable educational exercise, and I do recommend building a driver from scratch, so you'll see how all the pieces fall together. But you don't have to do this yourself, if you're in a hurry. We have a sample miniport here.