How to install a lower level filter driver on previously enumerated for test purposes

Hello,I’m tasked with installing a lower level filter driver on a USB device only for test purposes (i.e., to be able to issue USB transfers from/to the hardware). The USB device is a composite deviceI don’t need any help with the filter driver itself as that is straight forward with documentation and samples.

I did look at the article here: http://www.osronline.com/article.cfm?article=446, but when you look at the sample code for the install project, there is only a readme referring to the nonpnp WDK sample. For prototyping purposes, I’ve started with the OSR FX2 board (yes, I know, not a composite device) with the sample driver from the Windows 8.1 WDK. I figured it would be best to have a “simple”.Anyway, I tried the nonpnp sample, modifying it for my prototype, but then StartService fails (in install.c, StartDriver(…) with this error:
//
// MessageId: ERROR_SERVICE_DISABLED
//
// MessageText:
//
// The service cannot be started, either because it is disabled or because it has no enabled devices associated with it.
//
#define ERROR_SERVICE_DISABLED 1058L

I’d like to be very selective in which devices have this test lower level filter driver installed. And I cannot modify any .inf files nor add an interface for loading a custom driver to issue commands. So, I’m hoping that someone can steer me in the right direction for getting the PnP stack to disable a devstack and rebuild it with the lower level filter driver that I specify. This is of course on a test enabled machine.

On May 12, 2015, at 5:04 PM, xxxxx@gmail.com wrote:

I’d like to be very selective in which devices have this test lower level filter driver installed. And I cannot modify any .inf files nor add an interface for loading a custom driver to issue commands. So, I’m hoping that someone can steer me in the right direction for getting the PnP stack to disable a devstack and rebuild it with the lower level filter driver that I specify. This is of course on a test enabled machine.

There are four steps involved in getting a device filter up and running.

  1. Copy the SYS file into place.
  2. Create a service entry pointing to the SYS
  3. Add a LowerFilters entry to the Enum registry key for the device
  4. Restart the device

You can do #1 and #2 with many tools, including a batch file using the “sc” command. #3 is most easily done with SetupDiSetDeviceRegistryProperty. #4 can be done using the code in deacon. Removing the filter is then a matter of removing the service from the LowerFilters entry and restarting again.

It’s really not that hard. There’s a lot of typing, but once you get it, you’ll reuse the code over and over.

Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Tim,

Thanks for the response. I’m unclear with regards to step 2. When you say a service entry pointing to the driver, do you mean a service?

I did #1 manually (for now).

For #3 and 4, I wrote a little application (running elevated) that combines code from devcon and usbview to find a device with a specific vid/pid and then call a callback routine, which is as follows:

void
Callback(In HDEVINFO hDevInfo, In PSP_DEVINFO_DATA pSpDevInfoData, In PVOID Context)
{
PCMD_LINE_ARGS pArgs = (PCMD_LINE_ARGS)Context;
BOOL bResult;
DWORD propertyBufferSize = (DWORD)(wcslen(pArgs->DriverName) + 1) * sizeof(WCHAR);

printf(“In callback. %snstalling %ws as the lower level filter driver for VID/PID 0x%04x/0x%04x\n”,
pArgs->bInstall ? “I” : “Uni”,
pArgs->DriverName,
pArgs->VendorID,
pArgs->ProductID);

if (pArgs->bInstall)
{
SP_PROPCHANGE_PARAMS pcp;

bResult = SetupDiSetDeviceRegistryProperty(hDevInfo, pSpDevInfoData, SPDRP_LOWERFILTERS, (const BYTE *)pArgs->DriverName, propertyBufferSize);

printf(“SetupDiSetDeviceRegistryProperty %s with last error %dL\n”, bResult ? “passed” : “FAILED”, GetLastError());

pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
pcp.StateChange = DICS_PROPCHANGE;
pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
pcp.HwProfile = 0;

bResult = SetupDiSetClassInstallParams(hDevInfo, pSpDevInfoData, &pcp.ClassInstallHeader, sizeof(pcp));
printf(“SetupDiSetClassInstallParams %s with last error %dL\n”, bResult ? “passed” : “FAILED”, GetLastError());

if (bResult != FALSE)
{
bResult = SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, pSpDevInfoData);
printf(“SetupDiCallClassInstaller %s with last error %dL\n”, bResult ? “passed” : “FAILED”, GetLastError());
}

}
}

The output is as follows:

In callback. Installing TestLowerLevelFilter.sys as the lower level filter driver for VID/PID /
SetupDiSetDeviceRegistryProperty passed with last error 0L
SetupDiSetClassInstallParams passed with last error 0L
SetupDiCallClassInstaller passed with last error 0L

The problem that I’m having is that the device is banged out in device manager:

Windows cannot start this hardware device because its configuration information (in the registry) is incomplete or damaged. (Code 19)

I am finding a registry value, LowerFilters, of type REG_MULTI_SZ, with a value of “TestLowerLevelFilter.sys” for the device.

And it does exist in system32\driver:

Directory of c:\Windows\System32\drivers

05/11/2015 12:20 PM 19,648 TestLowerLevelFilter.sys

So I’m hoping that I’m close to where I need to be, with hopefully just one clue to finish. Any ideas? Thanks.

The LowerFilters value uses service names, not binaries. Try changing it to “TestLowerLevelFilter” (or whatever you named your service).

-scott
OSR
@OSRDrivers

Thanks Scott! That was exactly it. Moving onto the fun stuff now. Hopefully someone else will find the code snippet useful.