pbatard / libwdi

Windows Driver Installer library for USB devices
GNU General Public License v3.0
1.9k stars 468 forks source link

WinUSB Driver created by libwdi/ZaDig only works if I extract and then manually install the .INF #219

Closed OOPMan closed 3 years ago

OOPMan commented 3 years ago

Hi there, thanks for the very useful work you've done with libwdi.

I am trying to integrate libwdi into my application so that it can install the WinUSB driver for the devices I use directly rather in order to make usage simpler for my users.

I'm running into a rather odd issue though.

As the title says, if I install the WinUSB driver for my device either in my own application or in ZaDig via the Install Driver operation, for some reason my application seems to be unable to detect the device (even though device manager reports that it is using the WinUSB driver) via the WinUSB APIs. Just to be sure I tried restarting and nothing.

However, if I use ZaDig to simply extract driver installation files via a preset and then manually install the extracted driver using the .inf my application is able to see the device.

Do you have any idea why this might be?

mcuee commented 3 years ago

I do not quite understand what you are trying to say here. I guess you want to create an installer for the end user. You may want to look at the following two options. 1) use wdi-simple example: https://github.com/pbatard/libwdi/tree/master/examples 2) you can also try libusbk inf wizard which uses libwdi (a bit older version, with SHA256 support but not SHA512 support). It has an option to generate the installer. It has a bug that option "install only" does not work, but the installer created works fine. https://github.com/mcuee/libusbk/releases

pbatard commented 3 years ago

@OOPMan, you'll want to check your C:\Windows\INF\setupapi.dev.log to spot the difference between Zadig/Your_App and manual .inf install.

setupapi.dev.log gives very comprehensive information as to what exactly Windows is doing to install the drive, so if you find that one specific way of installing a driver works, whereas the other doesn't, the first thing to search for clues is that log.

The whole point of Zadig/libwdi is to automate what a user would do if they picked a .inf and proceeded to install the driver, and there really aren't any options we can control when it comes to the driver installation after we have generated the driver package. We're pretty much pointing Windows to the .inf and telling it "Please install that" by calling UpdateDriverForPlugAndPlayDevices(), which is the same call that Windows should use for a manual install, and the only special flag we're applying in INSTALLFLAG_FORCE, so I suppose, one possibility is that when you go through a manual install, and you don't have the FORCE flag, Windows may consider that it has a "better" driver already and discard the one you are trying to install manually, hence the difference.

But really, C:\Windows\INF\setupapi.dev.log should be able to tell you what's up.

mcuee commented 3 years ago

Now I understand the issue better. libusbk issue https://github.com/mcuee/libusbk/issues/22 is related to libwdi but I was thinking it is due to the use of older version of libwdi.

I am not so sure if this is related or not. Basically creating the driver installer and then installation work. Direct installation from libusbk-inf-wizard using "Install Only" will not work.

OOPMan commented 3 years ago

Thanks for the replies. It might be best for me to screen record and demonstrate what I mean. I'll post another comment later today after I've collected some more data.

I realize my original message was not the most useful thing.

OOPMan commented 3 years ago

Okay, I'm back for round two. I spent some time collect setupapi logs and recording video to demonstrate the issue I'm having. Let me also provide some context to what I'm doing.

Context

I develop an application called https://github.com/OOPMan/XBOFS.win/ which uses WinUSB to communicate with two particular XBox One arcade stick controllers (The Razer Atrox XBO and the Madcatz TE2 XBO). By default these controllers use the WICD driver provided by Microsoft which has the unfortunate characteristic of only exposing said devices via the Windows UWP APIs, rather than the XInput API used by most game software. As a result, if you using the default WICD driver these devices only work on PC in exactly one game (Killer Instinct Windows Store version). There is a solution involving install an old beta version of the WICD driver from Microsoft but it has certain issues and as a result I decided to develop my application.

My application uses WinUSB to communicate with the controllers I mentioned and then passes along with input data to a virtual XBox 360 controller created using VigEmBus, a very nice little project that allows you to create and manage virtual XB360 and DS4 controllers. In order to use my application the end-user currently needs to use ZaDig to extract a driver installation package which is then used to install the WinUSB driver in place of the default WICD driver. I want to make things simple for my users (who sometimes have issues following the instructions in the guide I created the details the process using ZaDig) and integrate WinUSB driver installation directly into my application.

So, that's the context.

Problem

The issue I'm having is that I've found that my application is only able to retrieve and connect to the controllers it supports if the WinUSB driver was installed using the Extract-and-Manual-Install approach.

If the WinUSB driver is installed for the controller directly by ZaDig for some reason my application is unable to list and connect to the controller.

I discovered this while working on a new branch to integrate the libwdi driver preparation and installation directly into my application.

So, now for the video recordings.

First, here is an example of the current process that works by manually installing an INF generated by ZaDig: https://youtu.be/4zvKV9AEnTM

Second, here is an example of the non-working process via ZaDig direct install: https://youtu.be/OsSs9r1Mwyo

Finally, here is an example using the new code I've added in to XBOFS.win: https://youtu.be/G2BCMeOsuV8

The last video reveals an additional issue which is that the UAC elevation for wdi_install_driver does not seem to work and the driver will only install correctly if I run my application as an Administrator. This is not a huge issue for me though.

As an additional note, I recorded this using a VM for convenience but it is also an issue with real hardware.

Finally, I also collected setupapi logs from each of the three scenarios:

OOPMan commented 3 years ago

@mcuee I suspect this issue might be related and does not seem to be restricted to older versions of libwdi. My application is using the latest code from the master branch in the libwdi repository.

OOPMan commented 3 years ago

I forgot to mention, here is a link to the way my application itself uses WinUSB to list the devices:

https://github.com/OOPMan/XBOFS.win/blob/406f93a02d2d59cd481309dafccb76579dbdec8f/XBOFS.win/src/WinUsbDeviceManager.cpp#L96

And here is a link to the code used to connect:

https://github.com/OOPMan/XBOFS.win/blob/406f93a02d2d59cd481309dafccb76579dbdec8f/XBOFS.win/src/WinUsbDevice.cpp#L169

@pbatard I had a though looking at the first section of code I linked above. Could this be related to the fact that my code which lists WinUSB devices makes use of a specific Device Interface GUID? I'm guessing that when ZaDig installs the driver directly it uses a random different Device Interface GUID? My own code using libwdi to install does not, at present specify a Device Interface GUID, I should probably test specifying one...

OOPMan commented 3 years ago

@pbatard I can confirm that my suspicion was correct. The issue was me not specifying the device interface GUID when calling wdi_prepare_driver. I just tested a version that specifies this and it worked correctly!

mcuee commented 3 years ago

Glad that you sort out the issue. libusbk issue https://github.com/mcuee/libusbk/issues/22 is probably different.

mcuee commented 3 years ago

BTW, there was an interesting issue here in libusbk: https://github.com/mcuee/libusbk/issues/4 libusbK.dll has been changed to accommodate both DeviceInterfaceGUID and DeviceInterfaceGUIDs.