Customizing a Windows Packet Filter driver usually starts with a small change: give it your own name. The details matter because Windows, the installer and your application all need to agree on which driver they are using. A renamed binary with an old service name or filter GUID can leave you debugging the wrong part of the installation.
This guide covers that identity change, the build workflow and the older projects that remain useful when maintaining legacy systems. The examples use a source package whose LWF version resource reports 3.6.1.1. Follow the build notes supplied with your own delivery when its project files differ.
For Windows 10/11 and current Windows Server work, start with the NDIS 6.x lightweight filter (LWF) project. Keep the source version, target OS, processor architecture and toolchain together as one build configuration. An old project label is not a compatibility test.
Source layout and package versions
This licensed source package contains a kernel directory alongside ndisapi. The following layout describes that package and the older projects documented in this article; it is not a list of currently supported operating systems. Paths in this list are relative to kernel/; ../ndisapi/ is its sibling:
bin/: Holds build outputs for the configurations supplied in the package.common/: Contains source code shared across all supported Windows versions. This folder should be your primary target for adding new code when constructing a kernel-mode solution based on Windows Packet Filter.IM/: Includes files pertinent to the NDIS 5.1 Intermediate driver build, which is employed on Windows XP and Windows Server 2003. Keep this as a legacy build path. Microsoft no longer supports filtering intermediate drivers on Windows 8 and later; use the NDIS 6.x filter interface for those systems.LWF/: Incorporates files specific to NDIS 6.x Lightweight Filter driver builds used from Windows Vista (NDIS 6.0) on later Windows versions. Windows 10 originally introduced NDIS 6.50; the NDIS version and the minimum OS target of a particular binary are separate concerns.ndisrdlwf Package/: Provides the NDIS 6.x Lightweight Filter driver companion Visual Studio 2012 project, primarily for building installation packages.SYS/: Includes files relating to Windows NT 4.0 and Windows 2000 NDIS-hooking drivers, which can also be used for 32-bit Windows XP/2003, and belong to the historical 32-bit path. They are not an alternative to the supported LWF model on current x64 systems.VxD/: Contains files specific to Windows 95, Windows 98, and Windows Millennium.../ndisapi: Carries the source code for the NDISAPI.DLL, which provides C/C++ interfaces to Windows Packet Filter drivers.INF/: Holds INF files needed for building installation packages for NDIS 5.1 Intermediate driver and NDIS 6.x Lightweight Filter driver.
Choose the target and toolchain first
In this source package, kernel/LWF/ndisrdlwf.2017.vcxproj uses WindowsKernelModeDriver10.0 and pins WindowsTargetPlatformVersion to 10.0.19041.0. Its name does not mean that every Visual Studio version or installed WDK will work with it. Start by reproducing an unmodified build with the package’s matching tools, then make the identity changes.
Microsoft’s WDK installation guidance and supported WDK list distinguish current development from older targets. As of October 2026:
| Work to do | Toolchain guidance |
|---|---|
| Current driver development | Visual Studio 2026 with WDK 28000.2526; use an SDK with the same kit build number. |
| Continue with Visual Studio 2022 | Microsoft lists WDK 26100.6584 for this route, again with a matching SDK build. |
| Maintain Windows 7/8/8.1 targets | Microsoft lists the 19041 kit family with Visual Studio 2019 for these legacy targets. This project selects build 19041. |
These are Microsoft toolchain choices, not a claim that this older WinpkFilter project has been ported to each kit. Retargeting needs its own build and test pass. The kit build number must match between SDK and WDK; their servicing revision numbers do not generally have to match. For 32-bit driver work, consult the architecture-specific entries in the supported WDK list rather than assuming the newest kit covers every old configuration.
Choose a real target combination. This project declares Win10 Release|x64, Win10 Release|ARM64 and Win10 Release|Win32, but it also contains legacy-labelled ARM64 configurations. Those labels do not establish Windows 7 or Windows 8 support on ARM64. Validate the actual OS, NDIS target and architecture together.
Set up the matching Visual Studio 2019 toolchain
To reproduce this source package with its selected 19041 kit, install Visual Studio 2019 with the C++ desktop tools and the v142 x86/x64 Spectre-mitigated libraries, then install the Windows SDK and WDK from the 19041 family. The kit headers live under 10.0.19041.0 even when the installed servicing revision is newer.
Check the WDK integration as well as the installed kit. In our clean setup, the kit installer completed successfully but the first build still failed with MSB8020 because WindowsKernelModeDriver10.0 was unavailable. Installing the supplied C:\Program Files (x86)\Windows Kits\10\Vsix\VS2019\WDK.vsix into Visual Studio 2019 registered the missing toolset. If that toolset is missing, complete the extension installation before retargeting or changing the project.
Building Windows Packet Filter drivers
Part I. Common changes
Start with the shared header. In this source package it is ndisapi/include/Common.h; the kernel precompiled header includes that same file. It has a USER_NAMES switch that includes user_settings.h, so you can keep the derived identity together instead of editing each generated name separately.
For a header with that switch, add user_settings.h to its include search path and enable USER_NAMES in the driver’s preprocessor definitions. For example:
#pragma once
#define NDISRD_NAME_A "MYFILTER"
#define NDISRD_NAME_U L"MYFILTER"
#define NDISRD_NAME_LOWER_A "myfilter"
#define NDISRD_NAME_LOWER_U L"myfilter"
#define FILTER_FRIENDLY_NAME L"My Product Packet Filter"
#define FILTER_UNIQUE_NAME L"{22A20A3B-5E78-407E-BF8B-A56D879A1DB6}"
The GUID above is illustrative. Generate a GUID for your own filter and use that same value in the INF. The header derives DRIVER_NAME_A/U, DEVICE_NAME, SYMLINK_NAME, the registry paths and FILTER_SERVICE_NAME from these definitions. A custom SDK build can use the same settings. An application using an existing SDK can instead pass the custom driver name explicitly when opening it.
Passing a name selects the device to open. Registry configuration helpers in this SDK still use the compiled WINNT_REG_PARAM path: for example, MTU-decrement, adapter-startup-mode and pool-size settings. If your application uses those helpers, build the SDK with the matching custom identity or handle your custom service’s registry settings explicitly; opening the custom device does not redirect those helpers automatically.
Earlier headers: the original identity definitions
Older packages may expose the strings directly rather than through USER_NAMES. The fragment below illustrates that layout; apply the method that matches your actual shared header.
// Common strings set
#define DRIVER_NAME_A "NDISRD"
#define DRIVER_NAME_U L"NDISRD"
#define DEVICE_NAME L"\\Device\\NDISRD"
#define SYMLINK_NAME L"\\DosDevices\\NDISRD"
#define WIN9X_REG_PARAM "System\\CurrentControlSet\\Services\\VxD\\ndisrd\\Parameters"
#define WINNT_REG_PARAM TEXT("SYSTEM\\CurrentControlSet\\Services\\ndisrd\\Parameters")
#define FILTER_FRIENDLY_NAME L"WinpkFilter NDIS LightWeight Filter"
#define FILTER_UNIQUE_NAME L"{CD75C963-E19F-4139-BC3B-14019EF72F19}" //unique name, quid name
#define FILTER_SERVICE_NAME L"NDISRD"Give the filter a descriptive FILTER_FRIENDLY_NAME. Keep its unique filter GUID separate from the standard INF ClassGUID: the latter identifies the Windows NetService class and should not be replaced with your product GUID.
Next, update the INF and packaging files for the driver model you actually ship. This LWF project uses kernel/INF/ndisrd_lwf.inf; ndisrd.inf and ndisrd_m.inf belong to the older IM package. Rename the intended binary, INF and catalog consistently, then inspect the references rather than applying an unchecked global replacement.
In [Install], set NetCfgInstanceId to the GUID used by FILTER_UNIQUE_NAME. The driver passes this value as its NDIS filter unique name. In this package, also check the nt_ndisrd component ID in the manufacturer/model sections, AddService, Ndi\Service, Ndi\CoServices, ServiceBinary, copy-file entries and CatalogFile. Update display strings, version resources, installer install/uninstall logic and the application’s open-driver name. Microsoft’s modifying-filter INF guidance explains these fields; the service and binary names are related references, not a requirement that every INF identifier be identical.
Part II. Building NDIS 6.x Lightweight Filter drivers
Open the LWF project supplied for your target. In this source package, kernel/LWF/ndisrdlwf.2017.vcxproj is the Windows 10 WDK project; ndisrdlwf.vcxproj is the older Windows 8 WDK project. Update TargetName, the INF input and catalog-name settings in each configuration you use. Its version resource is ndisrd.rc. Confirm the evaluated output paths as well as the filenames.
With the use of the Visual Studio resource editor, you can further customize the project version resource. You can add your company name, product name, and copyright information to this section for additional personalization.
The Visual Studio 2012 and 2017/2019 instructions in this section are retained as historical project recipes. Their signing settings describe local build/package generation; use the separate signing and release workflow for current distribution.
For this project, an unsigned x64 build can be requested from the matching developer command prompt, starting at the package root:
msbuild kernel\LWF\ndisrdlwf.2017.vcxproj /m /t:Build ^
/p:Configuration="Win10 Release" /p:Platform=x64 /p:SignMode=Off
This selects a configuration present in the source snapshot; it does not install or production-sign the driver. The project still requires its selected SDK/WDK. Use Win32, not x86, for this project’s 32-bit platform name. Rebuild only the configurations appropriate to the OS and architecture you intend to test.
This 3.6.1.1 source was built in a Windows 11 x64 VM with Visual Studio Professional 2019 16.11.60, Windows SDK 19041.5609 and WDK 19041.5738. The stock Win10 Release|x64 project, a clean rebuild and a separate MYFILTER customization using the settings above completed with zero warnings and errors. Both generated INFs passed the kit’s default InfVerif checks; Inf2Cat generated unsigned catalogs for 10_x64 without warnings. These checks cover compilation and package generation. Driver installation, runtime behavior, other target configurations and Microsoft production signing require separate validation.
After the final code and INF changes, validate the INF with InfVerif and generate the catalog for the intended targets with Inf2Cat. A catalog covers package-file hashes: changing the INF or binary afterward requires catalog regeneration and signing again. Test installation, upgrade, removal and application access on isolated target systems, including the security configuration you plan to support.
Building, test signing and production release are separate steps
A successful Release build is a compiler result. Its configuration name does not establish trust on a customer’s machine. During development, use a test certificate and a test machine configured for that signing route; see Microsoft’s test-signing guidance. Secure Boot and Memory Integrity/HVCI affect testing, so validate with the settings required by your target environment.
For Partner Center submissions, Microsoft requires an organization account with a valid associated EV certificate. Its certificate requirements also allow submissions signed with an appropriate registered Authenticode certificate; an EV signature on a locally built file is not itself Microsoft production signing.
For production distribution, plan the applicable HLK/WHCP submission and test requirements. Microsoft documents attestation as a testing route for Windows 10 Desktop and later, with no retail Windows Update distribution; Windows Server 2016 and later does not accept attestation-signed device/filter driver submissions. Follow the signing options for your actual targets rather than treating attestation as a universal replacement for certification.
There is an additional policy boundary in 2026. On systems where the Windows Driver Policy applies and is enforcing, loading is limited to WHCP-signed drivers and its allow-listed legacy cross-signed drivers. Audit mode records violations instead of blocking them. A historical cross-signature or an earlier successful install does not establish acceptance under that policy.
Historical: Visual Studio 2012 / Windows 8 WDK (Vista/2008)
- Load both
ndisrdlwf.vcxprojandndisrdlwf Package.vcxprojprojects into one workspace in Visual Studio 2012. - Configure your code signing certificates within the properties of both the
ndisrdlwfandndisrdlwf Packageprojects (navigate through: Configuration Properties → Driver Signing). Choose test signing for a development package. A Release configuration can also be test-signed; production acceptance follows the separate submission requirements above. - Proceed to rebuild all projects. During the rebuild process, Visual Studio 2012 will handle the building and signing of the driver binaries for
ndisrdlwf. For thendisrdlwf Package, it will generate and sign CAT (Catalog) files.
Historical: Visual Studio 2017/2019 / Windows 10 WDK
- Open
ndisrdlwf.2017.vcxproj. Unlike the older Visual Studio 2012 workflow, this recipe does not use the separatendisrdlwf Packagecompanion project. - Configure your code signing certificates in
ndisrdlwfproject properties (Configuration Properties ⇾ Driver Signing). Choose the signing route independently of Debug/Release; local certificate settings do not replace the production submission workflow. - Rebuild the project’s configurations. Visual Studio will build and sign driver binaries and generate and sign CAT files as well.
Historical toolchains for legacy systems
The remaining legacy recipes record the tools used with those older projects. Keep them with the matching source delivery and legacy test OS; availability of a tool or project file does not establish current product support:
- For Windows 95, 98, and ME: Visual Studio 6.0 and VToolsD.
- For Windows NT 4.0 and Windows 2000: Microsoft Windows 2000 Driver Developer Kit.
- For Windows XP and Windows Server 2003: Driver Development Kits like Microsoft Windows Server 2003 Driver Developer Kit, Windows Vista WDK, or Windows 7 WDK.
Part III. Historical NDIS 5.1 intermediate driver
This is the historical Windows XP/Server 2003 filtering-IM path. Windows 8 and later removed support for this model. It can be compiled using various toolsets, including the Microsoft Windows Server 2003 Driver Developer Kit, Windows Vista WDK, or the Windows 7 WDK.
- Go to
WinpkFilter/Kernel/IM - Edit
ndisrd.rcto include any company, product or copyright information into the version resource. - Open a file named
sourcesand in the first stringTARGETNAME=ndisrdreplacendisrdwith the driver/device name you have chosen. - Start
Windows Server 2003 x64 Free Build Environmentand WindowsServer 2003 x86 Free Build Environment. Each will open a new command line window. - In each command line window opened in previous step, change directory to
WinpkFilter/Kernel/IMand rundbuild.batscript.
Part IV. Historical Windows NT 4.0 / Windows 2000 hooking driver
This driver type is designed for Windows NT 4.0 and Windows 2000, and it can also be deployed on a 32-bit Windows XP system. The original build uses the Windows 2000 Driver Development Kit. It relies on historical hooking techniques; Microsoft’s x64 kernel restrictions prohibit modifying protected kernel code or undocumented structures. Retain this recipe for the old source and systems it describes.
- Go to
WinpkFilter/Kernel/SYSfolder. - Edit
ndisrd.rcto include any company, product or copyright information into the version resource. - Open a file named
sourcesand in the first stringTARGETNAME=ndisrdreplacendisrdwith the driver/device name you have chosen. - Start Windows 2000 Free Build Environment to open a new command line window.
- In command line window opened in previous step, change directory to
WinpkFilter/Kernel/SYSand rundbuild.batscript.
Part V. Historical Windows 95/98/ME VxD driver
This specific driver type is compatible with Windows 95, Windows 98, and Windows Millennium Edition. Building this driver will necessitate the use of certain legacy tools:
- Microsoft Visual Studio 6.0
- Compuware/Numega VToolsD (the latest release was included in Compuware Driver Studio 2.0)
To customize the driver name and resources please perform the steps below:
- Navigate to
WinpkFilter/Kernel/VxD - Open
NDISRDr.makin text editor. Find the stringDEVICENAME = NDISRDand changeNDISRDto the driver/device name you have chosen. - Repeat the step above for
NDISRD.mak. - Rename
NDISRD.VRCtoYOU_DRIVER_NAME.VRCand edit this version resource to include any company, product or copyright information. - Open
w9xndisrd.dspin Microsoft Visual Studio 6.0 and rebuild the project.
Part VI. Bring the pieces together
The identity change is complete when the shared header, INF, project outputs, installer and application all refer to the intended driver. Build with the tools that match your source delivery, regenerate the package after the final edits, and validate the signed result on each target you plan to support. The legacy recipes remain here for maintaining those older systems; they do not extend the support matrix of a current build.