Enumerating list of PCI devices

Hello,

I am a beginner to windows driver development. I have a KMDF driver in which I would like to go through list of PCI devices.
Linux has an API to get a pci device pointer to a specific vendor ID using pci_get_device()
https://elixir.bootlin.com/linux/latest/source/drivers/pci/search.c#L328
I am looking for something similar for Windows.

I have written a function to do it which get a list of interfaces. But from symbolic name, I cannot get PDO of the device.
Am I doing something fundamentally wrong? Here is the code:

void check_dev_id(void)    
{
PFILE_OBJECT pFileObject;
PDEVICE_OBJECT pDeviceObject;
NTSTATUS status;
PZZWSTR symbolicLinkList;
PWSTR SymbolicLinkListPtr;
const GUID guid = {0x5b45201d, 0xf2f2, 0x4f3b, 0x85, 0xbb, 0x30,
   0xff,       0x1f,   0x95,   0x35, 0x99};

status = IoGetDeviceInterfaces(&guid, NULL, 0, &symbolicLinkList);
if (!NT_SUCCESS(status))
return;
for (SymbolicLinkListPtr = symbolicLinkList;
    SymbolicLinkListPtr[0] != 0 && SymbolicLinkListPtr[1] != 0;
    SymbolicLinkListPtr += wcslen(SymbolicLinkListPtr) + 1) {

UNICODE_STRING SymbolicLink;
WCHAR deviceID[512];
ULONG dataLen;

SymbolicLink.Buffer = SymbolicLinkListPtr;
SymbolicLink.Length = SymbolicLink.MaximumLength = (USHORT)wcslen(SymbolicLinkListPtr);

status = IoGetDeviceObjectPointer(&SymbolicLink, FILE_READ_DATA, &pFileObject, &pDeviceObject);
if (!NT_SUCCESS(status)) {
// Fails here to get the PDO
continue;
}

// Now we have a DeviceObject. Get device ID
status = IoGetDeviceProperty(pDeviceObject, DevicePropertyHardwareID, sizeof(deviceID), deviceID, &dataLen);
if (!NT_SUCCESS(status))
continue;
// Otherwise Device ID found
}

ExFreePool(symbolicLinkList);
}

Why do you want to do this? Windows roughly 20 years ago replaced the model of enumerating devices in your driver with Plug and Play where the driver called when a device that it supports if found.

Because I want to check an existence of a display adapter from another driver.

For what it’s worth, this line is wrong:
SymbolicLinkListPtr[0] != 0 && SymbolicLinkListPtr[1] != 0;
The list is terminated by one null character, not two.

If you need to get notified when a new display device is connected to the computer, and you wish to get its device object, register your driver as an lower/upper filter for the Display device setup class.

Symbolic links returned by IoGetDeviceInterfaces can also be used. In some cases however, you need to remove certain suffixes to get the real symbolic link (I experienced this with some Bluetooth devices). Also, calling IoGetDeviceObjectPointer generates an IRP_MJ_CREATE request to the target device which you might find undesirable.

There is also a VERY hacky way of enumerating PCI devices: use of an undocumented ObReferenceObjectByName API to obtain driver object for \Driver\pci and enumerate its device objects via a (documented) IoEnumerateDeviceObjectList function.

Because I want to check an existence of a display adapter from another driver.

ANY old display adapter, or a SPECIFIC display adapter? One that YOU OWN or one that somebody else writes the driver for??

I’ll amplify slightly on what Mr. Dráb said: If you just want to know about the existence/arrival of a display adapter, you can register for Device Interface Change Notification for GUID_DEVINTERFACE_DISPLAY_ADAPTER or GUID_DISPLAY_DEVICE_ARRIVAL. This is typically how we solve the problem “I need to know when a device that I do not want to filter arrives/departs from the system, including if the device arrives before my driver (or my app, for that matter) starts running.”

Will that work??

Peter

The older pci register access is still working, try 0xcf8 stuff

That never worked properly. You can mess up a system. I was involved with a company that successfully sued out of existence a firm that did that crap and messed up our servers.