KMDF PCI Bus Filter Driver

I want to write a PCI bus filter driver. To read PCI config space and manipulate some registers. I've seen many post prior on this topi here. now I am little confuse, I want to know is it possible to write a PCI bus filter driver KMDF way??
because I have written a filter driver to PCI but unable to install it for *PNP0a03, may be I've not written the INF correctly.
can some one please help.
"
[Version]
Signature=“$WINDOWS NT$”
Class=System
ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318}
Provider=%TEST%
CatalogFile=PCIFltr.cat
DriverVer = 07/14/2025,1.0.0.1
PnpLockdown=1

;*************************
; Source file information
;*************************

[SourceDisksNames]
1 = %DiskName%,“”

[SourceDisksFiles]
PCIFltr.sys = 1,

[DestinationDirs]
DefaultDestDir = 12 ;system32/drivers

[ControlFlags]
ExcludeFromSelect=*

;*****************************************
; filter Install Section
;*****************************************

[Manufacturer]
%TEST%=Standard,NTamd64

[Standard.NTamd64]
%filter.DeviceDesc%=FilterInstall, *PNP0a03

[FilterInstall]
Include=machine.inf
Needs=PCI_DRV
CopyFiles=FilterInstall.Copy

[FilterInstall.Copy]
PCIFltr.sys

[FilterInstall.HW]
Include=machine.inf
Needs=PCI_DRV.HW
AddReg=FilterInstall.HW.AddReg

[FilterInstall.HW.AddReg]
HKR,“UpperFilters”,0x00010008,“PCIFltr”

[FilterInstall.Services]
;Do not specify SPSVCINST_ASSOCSERVICE on filter drivers.
Include=machine.inf
Needs=PCI_DRV.Services
AddService=PCIFltr,ufilter_Service_Inst

[ufilter_Service_Inst]
DisplayName = %ufilter.SvcName%
Description = %ufilter.SvcDesc%
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
StartType = 3 ; SERVICE_DEMAND_START
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
ServiceBinary = %12%\PCIFltr.sys
LoadOrderGroup = “PnP Filter”

[Strings]
TEST=“Storage Systems Inc.”
DiskName = “Filter Installation Disk”
filter.DeviceDesc = “PCI Upstream Port”
ufilter.SvcName = “PCI Upper Filter”
ufilter.SvcDesc = “PCI Upper Filter Service”

It has been a very long time since I've run my pci bus filter, but at the time it was PCI_DRV_ROOT, not PCI_DRV that you needed to include.

1 Like

“Thanks for clarifying that, Mark. I was wondering the same thing about PCI_DRV vs PCI_DRV_ROOT. So to confirm, the INF should use PCI_DRV_ROOT in the Include and Needs entries instead of PCI_DRV for a PCI bus filter?”

1 Like

Yes replace all the PCI_DRV entries.

1 Like

Thank you Mark for pointing out the mistake.
After fix, the driver is installing successfully.
In my AddDevice Routine I am trying to fetch the capabilityPtr from
DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT)
UCHAR buffer[sizeof(PCI_COMMON_CONFIG)];
PPCI_COMMON_CONFIG pPciConfig = (PPCI_COMMON_CONFIG)buffer;
NTSTATUS Status = STATUS_SUCCESS;

RtlZeroMemory(buffer, sizeof(buffer));

// 1) Read the first pointer at 0x34
bytesRead = DeviceContext->PciBusInterface.GetBusData(  DeviceContext->PciBusInterface.Context,
                                                        PCI_WHICHSPACE_CONFIG,
                                                        &buffer,
                                                        FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.CapabilitiesPtr),
                                                        0xe2);
if (bytesRead != sizeof(PCI_COMMON_CONFIG)) {
    KdPrint(("Failed to read capability list pointer: %u bytes\n", bytesRead));
    return STATUS_INVALID_DEVICE_REQUEST;
}

but the call always returned with 0, bytes why?
is it not possible in KMDF ? if yes then why if not shall I write a WDM for this?
the similar thing I can see works perfectly fine in MSDN PCI sample for NIC.

Thank you for the help.

You're asking to read 0xE2 bytes. The capabilities pointer is at offset 0x34. 0x34 + 0xE2 is 0x116, which is beyond the size of the configuration data.

I suspect you only wanted 4 bytes here.

1 Like

Thanks again for catching the length mistake. I am now reading exactly 4 bytes from the dynamically retrieved CapabilitiesPtr, but still getting zero bytes back. A few follow-ups:
Duplicate filter instances
With my current INF the driver shows up twice in Device Manager—one installs successfully. the other has a yellow exclamation (Error 31). Could that mean I've broken PCI.sys? If so, how can I restore its normal loading? If not, what else might produce a phantom, warning-marked instance?

Silent GetBusData failures
Assuming I've correctly queried the bus interface on the PDO and I'm calling at PASSIVE_LEVEL(in prepareHW), are there any other reasons GetBusData might quietly return zero?

PCI driver load impact
Since I see two instances of my driver, is it possible that the underlying PCI driver failed to load, leaving me with zero bytes on every read?

Any ideas on these points would be much appreciated!

Thank you very much.

That almost always means you made the mistake of using devcon install to install it. Never, ever use devcon install to install a PnP INF. What that does is create a FAKE device, and then mounts your driver to handle it.

Instead, use pnputil /add-driver /install. That places your INF into the driver store, then does a scan to see if your driver is a better match for existing hardware.

1 Like

Hi Tim,

Thank you again for the guidance on using "pnputil" instead of devcon. I ran your suggested command:
Here's the console output I observed:

pnputil /add-driver filter.inf /install
Adding driver package: filter.inf
Driver package added successfully.
Published Name: oem7.inf
Driver package is up-to-date on device: ACPI\PNP0A03\2&daba3ff&0

Total driver packages: 1
Added driver packages: 0

I've verified that both "filter.inf" and "filter.sys" are present under %SystemRoot%\System32\DriverStore\FileRepository\oem7.inf_*. However, my filter still doesn't actually attach to the PCI device no new service appears, and I don't see the driver in Device Manager (nor is my "DriverEntry" invoked).

Could you help me understand what might be preventing the driver from binding? In particular:

  1. INF Publication vs. Service Registration
    Does the output "Added driver packages: 0" indicate that Windows considered the published INF already up-to-date—and therefore skipped installing the service??
  2. Hardware Matching
    Is there any further step or flag required in the INF to force a scan-and-bind to existing hardware??
    3.Driver Store vs. Binding
    Once an INF is published, what triggers Windows to enumerate real devices against it? Should I explicitly rescan or issue another command?
    4.Troubleshooting Tips
    Are there specific registry keys or event-log entries I should inspect to see why the filter isn't loading?

Below is the relevant portion of my "filter.inf" for your reference:

;filter driver inf

[Version]
Signature="$WINDOWS NT$"
Class=System
ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318}
Provider=%WINDDK%
DriverVer=07/14/2025,1.00.0000.1
CatalogFile=filter.cat
PnpLockdown=1

[DestinationDirs]
DefaultDestDir = 12

;;;;; files ;;;;;
[SourceDisksNames.amd64]
1 = %DISK_NAME%,,,""

[SourceDisksFiles]
Filter.sys = 1,,

[ControlFlags]
ExcludeFromSelect=*

[Manufacturer]
%WINDDK%=WINDDK_FILTER,NTAMD64

[WINDDK_FILTER.NTAMD64]
; ACPI\PNP0A03\2&DABA3FF&0

%pcifilter.DeviceDesc%=pcifilter_Device, *pnp0a03

[pcifilter_Device]
Include = machine.inf ; The function driver
Needs = PCI_DRV_ROOT ; Install section for the function driver

CopyFiles=Drivers_Dir

[Drivers_Dir]
filter.sys,,,2

[pcifilter_Device.HW]
AddReg = WINDDK_Filter_Reg
Include = machine.inf ; The function driver
Needs = PCI_DRV_ROOT.HW ; Install section for the function driver

[WINDDK_Filter_Reg]
HKR,,"UpperFilters", 0x00010008, "filter"

[pcifilter_Device.Services]
AddService = filter,,WINDDK_Filter_ServiceInstallSection
Include = machine.inf ; The function driver
Needs = PCI_DRV_ROOT.Services ; Install section for the function driver

[WINDDK_Filter_ServiceInstallSection]
DisplayName = %pcifilter_svcdesc%
ServiceType = %SERVICE_KERNEL_DRIVER%
StartType = %SERVICE_DEMAND_START%
ErrorControl = %SERVICE_ERROR_NORMAL%
ServiceBinary = %12%\filter.sys
LoadOrderGroup = "Boot Bus Extender"

;;;;; string definition ;;;;;;;;
[Strings]
WINDDK = "WINDDK"
AMDPCIE.DeviceDesc = "Pci Bus"
SystemClassName = "System devices"
pcifilter_svcdesc = "PCI Filter Driver"
DISK_NAME = "PCI Filter Driver Install Disk"
SPSVCINST_ASSOCSERVICE = 0x00000002
SERVICE_KERNEL_DRIVER = 1
SERVICE_BOOT_START = 0
SERVICE_DEMAND_START = 3
SERVICE_ERROR_NORMAL = 1

Any insights on the PCI bus or pointers to additional diagnostics would be greatly appreciated.

Thank you for your help!!

On modern systems there are multiple PCI Express Root Complex devices, and they are all PNP0A08, not PNP0A03.

Also, you should probably include pci.inf directly instead of using the ancient machine.inf. The include sections would then all be PCI_ROOT instead of PCI_DRV_ROOT.

Also, examining "C:\Windows\INF\setupapi.dev.log" is frequently helpful.

And finally, a reboot is going to be required to install your filter.

1 Like