Installing legacy driver in Windows 10

Hi all,

I have problems in installing a CAN device driver in Windows 10. The driver is written in KMDF.
The CAN device is reported as ?Motherboard resources? with the Hardware Id ?ACPI\PNP0C02? and its resources (I/O Range and IRQ). The problem is that the Hardware Id is not unique; three additional devices are reported with the same id. So I need an opportunity to install the driver only on one of these four devices.
In Windows 7 and Windows 8.1 I installed the driver with the Setup API functions:

  • Get all system devices with SetupDiGetClassDevs
  • Check the interrupt number of the device (Interrupt is unique).
  • Set the hardware id of the device to ROOT\CAN with SetupDiSetDeviceRegistryProperty ? SPDRP_HARDWAREID
  • Build driver list with SetupDiBuildDriverInfoList
  • Select the driver with SetupDiSetSelectedDriver
  • Install the Driver with InstallSelectedDriver of newdev.dll

This solution doesn?t work any longer in Windows 10. It is not possible to set the Hardware Id with SetupDiSetDeviceRegistryProperty - SPDRP_HARDWAREID. The function fails with error code ERROR_INVALID_REG_PROPERTY.

Is there another way to install this driver? It is necessary to install the driver on the reported CAN device, because the interrupt is needed and the function HalGetInterruptVector is not implemented in 64 bit systems.

Thanks,
Manuel

And the doc page for SetupDiSetDeviceRegistryProperty says:

The following values are reserved for use by the operating system and cannot be used in the Property parameter:

SPDRP_HARDWAREID

It was apparently a bug that it worked before, and they fixed it in Win 10.

So how does your device not have a unique id?

Jan

On 7/29/15, 5:19 AM, “xxxxx@lists.osr.com on behalf of manuel.parfant@br-automation.com” wrote:

>This solution doesn?t work any longer in Windows 10. It is not possible to set the Hardware Id with SetupDiSetDeviceRegistryProperty - SPDRP_HARDWAREID. The function fails with error code ERROR_INVALID_REG_PROPERTY.

Hello Jan,
thank you for your answer.

You are right, the MSDN says, that this parameter can not be set. But otherwise MSDN says:

Source: https://msdn.microsoft.com/en-us/library/windows/hardware/ff543686
If an installer detects a non-PnP device, the installer should select a driver for the device as follows: create a device information element
(SetupDiCreateDeviceInfo), set the SPDRP_HARDWAREID property by calling SetupDiSetDeviceRegistryProperty, call SetupDiBuildDriverInfoList, and then
call SetupDiCallClassInstaller to send a DIF_SELECTBESTCOMPATDRV request.

It is by design, that the device doesn’t have a unique id. In the meantime, I have the same problem with a second driver. It is a KMDF touch screen driver for the serial port. It is developed as a upper level filter driver and has also to be installed on a specific com port. COM ports are also reported by ACPI with non unique id. In the past, the drive was also installed by setting a new hardware id with the SetupDiSetDeviceRegistryProperty function.

Manuel

So I looked at the link you gave us, and it says:

"This DIF code is reserved for system use. Vendor-supplied installers must not handle this request unless the vendor provides non-PnP devices that must be detected by the installer.

A DIF_FIRSTTIMESETUP request directs an installer to perform any class-specific installation tasks that have to be completed during the initial installation of the operating system.”

Are you doing an initial install of the operating system? It offhand looks like this refers to the pre-Vista days when OS install had an initial text based setup phase and then when the OS could be bootstrapped, a more advanced GUI phase. From Vista and later, the setup boots a copy of WinPE, and there never is a text mode phase.

Is there a reason you don’t have unique PnP ID’s?

There is/was a defined protocol to detect devices on a serial port. Is the issue with your other driver that your hardware doesn’t support this serial port device enumeration protocol, so can’t figure out it’s your device attached to a standard serial port?

Jan

On 8/2/15, 10:44 PM, “xxxxx@lists.osr.com on behalf of manuel.parfant@br-automation.com” wrote:

>Hello Jan,
>thank you for your answer.
>
>You are right, the MSDN says, that this parameter can not be set. But otherwise MSDN says:
>
>Source: https://msdn.microsoft.com/en-us/library/windows/hardware/ff543686
>If an installer detects a non-PnP device, the installer should select a driver for the device as follows: create a device information element
>(SetupDiCreateDeviceInfo), set the SPDRP_HARDWAREID property by calling SetupDiSetDeviceRegistryProperty, call SetupDiBuildDriverInfoList, and then
>call SetupDiCallClassInstaller to send a DIF_SELECTBESTCOMPATDRV request.
>
>It is by design, that the device doesn’t have a unique id. In the meantime, I have the same problem with a second driver. It is a KMDF touch screen driver for the serial port. It is developed as a upper level filter driver and has also to be installed on a specific com port. COM ports are also reported by ACPI with non unique id. In the past, the drive was also installed by setting a new hardware id with the SetupDiSetDeviceRegistryProperty function.
>
>Manuel
>
>—
>NTDEV is sponsored by OSR
>
>Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
>OSR is HIRING!! See http://www.osr.com/careers
>
>For our schedule of WDF, WDM, debugging and other seminars visit:
>http://www.osr.com/seminars
>
>To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Thank you for your additional information.

The reason for not having a unique PnP ID is that the device interface is very old and should not be changed for compatibility reasons with other operating systems.

Thank you for the idea with the device enumeration protocol. This protocol is unfortunately not supported by the touch controller.

In the meantime I have found a solution to solve these problems. I added the ControlFlag ExcludeFromSelect=* to the inf file and install the driver with the setup API functions without changing the hardware id. If you are interested in details, I can post the source code.

Manuel

I have another problem with this driver. The driver can only be opened once.

The following code is used:
hDrv = CreateFile(
_T(“\\.\InaCanDevice0”),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hDrv == INVALID_HANDLE_VALUE)
_tprintf(_T(“Can’t open driver. Error: %d\n”), GetLastError());

The second open returns error number 5 - ERROR_ACCESS_DENIED. The event handler of EVT_WDF_DEVICE_FILE_CREATE is only called for the first open. It seems that the CreateFile request is blocked from outside the driver.

The device is not marked as exclusive device. Mark the device as not exclusive with WdfDeviceInitSetExclusive(DeviceInit, FALSE) doesn’t fix this issue. The driver uses the System device class.

Are there any restrictions when using a legacy driver or device that is reported by ACPI?

Isn’t this about SDDL string for the ACL?

<manuel.parfant> wrote in message news:xxxxx@ntdev…
>I have another problem with this driver. The driver can only be opened once.
>
> The following code is used:
> hDrv = CreateFile(
> _T(“\\.\InaCanDevice0”),
> GENERIC_READ | GENERIC_WRITE,
> FILE_SHARE_READ | FILE_SHARE_WRITE,
> NULL, OPEN_EXISTING,
> FILE_ATTRIBUTE_NORMAL, NULL);
> if (hDrv == INVALID_HANDLE_VALUE)
> _tprintf(_T(“Can’t open driver. Error: %d\n”), GetLastError());
>
> The second open returns error number 5 - ERROR_ACCESS_DENIED. The event handler of EVT_WDF_DEVICE_FILE_CREATE is only called for the first open. It seems that the CreateFile request is blocked from outside the driver.
>
> The device is not marked as exclusive device. Mark the device as not exclusive with WdfDeviceInitSetExclusive(DeviceInit, FALSE) doesn’t fix this issue. The driver uses the System device class.
>
> Are there any restrictions when using a legacy driver or device that is reported by ACPI?
></manuel.parfant>

Yes, that was the problem.
I added the SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RW_RES_R with WdfDeviceInitAssignSDDLString() and now it works.

Thank you for the tip!