none
Joystick driver prevents installation of another driver even when uninstalled RRS feed

  • Question

  • I have written a KMDF virtual joystick driver about 2 years ago. It is functional and is used by many as it is free and signed. Lately, a user has complained that he cannot install another (much older) virtual joystick driver when my driver is installed. Worse, the older driver cannot be installed even after my driver was removed.

    My first inclination was to search for differences between the registry setup before installation and after uninstalling my driver. However, this yielded thousands of differences. Even when I found registry entries that I suspect as problematic  I was unable to remove them.

    Can someone suggest a more useful approach to debugging inter-driver installation problems. Perhaps the problem has nothing to do with the registry? Thank you!

    Sunday, January 26, 2014 4:37 PM

All replies

  • First thing to do is enable the SetupAPI log http://msdn.microsoft.com/en-us/library/windows/hardware/ff550887(v=vs.85).aspx then try the installation and see what is failing, and hopefully the error message.  Assuming you have the source from both, if you can find what step in the process is failing from the logs, you can then debug the second install fairly easily.

    A quick question, was the newer driver derived from the older one?  If so check that there is not a name conflict on the device objects.


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Sunday, January 26, 2014 4:47 PM
  • Thank you Don,

    First thing to do is enable the SetupAPI log

    SetupApi.dev was on my mind when I suspected the registry. Here is where it reports the failure of the old driver:

         dvi:                {Install DEVICE exit (0x00000000)}
         dvi:                Writing common driver property settings.
         dvi:                     DriverDescription=Parallel Port Joystick device 2
         dvi:                     DeviceDisplayName=Parallel Port Joystick device 2
         dvi:                Install Device: Restarting device. 12:24:34.467
         dvi:                Install Device: Restarting device completed. 12:24:36.248
    !!!  dvi:                Device not started: Device has problem: 0x32: CM_PROB_SETPROPERTIES_FAILED.
         dvi:           Default installer: Exit
     

     Assuming you have the source from both

    Well, getting the source of the old driver might be possible. However, compiling a ten years old code will be my last resort.

     was the newer driver derived from the older one?

    This was a wise question (Seriously). No it is not. The VID and the PID are different. The IOCTRL targets are supposed to be different but even if not - why would my driver interfere once uninstalled?


     
    Sunday, January 26, 2014 6:53 PM
  • At this point I would use RegMon to monitor the install of the older driver.  CM_PROB_SETPROPERTIES_FAILED can be a lot of things, but a common one is failure in setting up the registry.


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Sunday, January 26, 2014 7:07 PM
  • Don,

    RegMon was replaced by "Process Monitor" but this is beside the point.

    I ran the tool on both successful and unsuccessful installations of the 'old' driver. Since I got just under quarter of a million events I tried to filter those that are suspicious. There where 48 cases of "Access Denied" (to the registry)but I confirmed that they were for good reason.

    I tried to sync the events with the setupapi.dev messages but they cannot be synced.

    I looked into my code but found only some uninteresting accesses to the registry that are unlikely to cause the problem.

    Is it possible that CM_PROB_SETPROPERTIES_FAILED is not a result of inability to write to the registry? Is it possible that my driver (or installer) changes registry permissions without my explicit request? I'm out of ideas, do you have some?

    • Proposed as answer by IgHR Monday, January 27, 2014 12:11 PM
    • Unproposed as answer by IgHR Monday, January 27, 2014 12:11 PM
    Monday, January 27, 2014 11:37 AM
  • At this point, you need to step through the DriverEntry and AddDevice routines of the failing driver.  The good news here is that you don't need the source to help localize the problem.  You can use assembler and see what call is failing and look at the EAX register immediately after the call for the result of the function which should present you the error code.

    This is a pain, but this is probably the best way to proceed at this point.  Debug DriverEntry, and at the end of DriverEntry look at the DEVICE_OBJECT and its extension to get the AddDevice routine address.  Put a breakpoint at AddDevice if DriverEntry did not fail and step through it.


    Don Burn Windows Filesystem and Driver Consulting Website: http://www.windrvr.com Blog: http://msmvps.com/blogs/WinDrvr

    Monday, January 27, 2014 12:25 PM
  • Hi, Sorry for entering on this discussion. I may have travelled some of this steps before and I may contribute with some additional information.

    When using the process monitor and filtering quarter a million entries, I found useful a filter to see only "Operation" "is" "Process Create" and then, explore the process ID parent and Process ID to check who launched the process and what the process did.

    While reading the documentation of the systems calls, and exploring the source code, I found the following sequence of calls is used:

    1. SetupDiGetINFClass is used to obtain the class HIDCLASS that is the root of all HID devices installed
    2. SetupDiCreateDeviceInfoList is used on the class returned from previous call
    3. SetupDiCreateDeviceInfo is used (I suspect for the entire list returned from previous call)
    4. SetupDiSetDeviceRegistryProperty (Is used after the previous call)
    5. SetupDiCallClassInstaller Is called and lauches DrvInst.exe once per Joystick registered on the system. I think the parameters used for this "second registration" are not the same used during the "first registration" and the joystick installation becomes corrupted.

    There is a chance. (I'm not sure) the sequence of calls used above is, in fact, trying to register (or re-register) all existing joysticks under the HIDCLASS and the parameters to the calls may not be the same used when the joystick was registered first time, so, the "corruption" is because DrvInst.exe is called with wrong parameters.

    Note none of the previous calls raise an error during the driver installation phase.


    • Edited by IgHR Monday, January 27, 2014 1:06 PM
    Monday, January 27, 2014 12:43 PM
  • Hmm, this is a tough one. Tried bu PPortJoy64!DriverEntry and indeed got a break. 
    However, I could not see the registers.

    So I tried to play with my code:

    First of all I let the DriverEntry conclude, then I caught vJoyEvtDeviceAdd as it was called and returned immediately. The outcome was installation of the driver without a device - this seems to be harmless to the old driver!
    I conclude that something happens while loading the device (and an additional raw device).

    This leads me to the more general questions:

    • How do I know for sure that my driver was totally uninstalled?
    • What an uninstalled driver leave behind? I can think of the following:
      - It removed vital registry entries
      - It changed registry protection
      - It stopped some system services

    BTW, there's a ling to the old driver sources, written 12 years ago. So if anyone is interested, here it is - https://github.com/elitak/PPJoy

    Any additional ideas will be great!

    Tuesday, January 28, 2014 10:47 AM
  • Pavel,

    I have one GUID in the code that is unique: DEFINE_GUID(GUID_DEVINTERFACE_VJOY, 0x781EF630, 0x72B2, 0x11d2, 0xB8, 0x52, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x01);

    In the INF file I have: ClassGuid={745a17a0-74d3-11d0-b6fe-00a0c90f57da} // HIDClass

    That was a good idea though. Thanks.



    Tuesday, January 28, 2014 7:23 PM
  • Pavel,

    We are testing on Vista & Windows7 x64 platforms.

    Wednesday, January 29, 2014 6:30 AM
  • We have some interesting input.

    Apparently, my driver changes the old driver's PDO Hardware IDs. Worse, if you access the data through the device manager you see that the PDO's HwID changed from:

    HID\VID_DEAD&PID_BEF0 HID_DEVICE_SYSTEM_GAME HID_DEVICE_UP:0001_U:0004 HID_DEVICE

    to:

    PPJOYBUS\VID_DEAD&PID_BEF0

    If you take a look at the registry entry (HKLM\SYSTEM\CurrentControlSet\Enum\HID\VID_DEAD&PID_BEF0\2&19b2707a&0&0000\HardwareID) then nothing has changed. 

    It seems that the system now takes the data from a different (wrong) location.

    BTW, my installer is nothing much more than a slightly customized DEVCON. As such, I use

    SetupDiSetDeviceRegistryProperty(DeviceInfoSet,        
    &DeviceInfoData,       
    SPDRP_HARDWAREID,       
    (LPBYTE)hwIdList,       
    (lstrlen(hwIdList)+1+1)*sizeof(TCHAR))
    MS warns not to use SPDRP_HARDWAREID. Could this be the problem?

    Wednesday, January 29, 2014 8:11 PM
  • Hi,

    The CM_PROB_SETPROPERTIES_FAILED problem indicates a problem applying some properties to the device stack during the AddDevice phase.  I think the most likely cause is that some of these properties that were configured for the device are invalid.  These properties include things like the "Security", "DeviceType", "DeviceCharacteristics", and "Exclusive".  Take a special look at "Security", as it must also be a valid Security Descriptor (in self-relative format).

    These properties can be set by the INF (in an AddReg section) or programmatically (SetupDiSetDeviceRegistryProperty).  They can also be set either for the device instance, or for every device in the class (again, INF or SetupDiSetDeviceRegistryProperty).

    My guess is that your INF, your installer or some other component set invalid data for one of these properties, either for the device or the entire class, and it is failing when that data is validated when the device is started.  These settings persist even when you uninstall your own driver, so if these were not restored to good values, they will continue to affect the device (or all in the class) even when another driver is installed.

    Does uninstalling the device (or its parent) using Device Manager's "right-click, Uninstall", then re-scan, and re-install allow the other driver to work?  If so, the problem may have been with the device.  If not, it may be with the class and you would need to programmatically restore the properties to good values (match them with a "clean" machine).

    RE: "MS warns not to use SPDRP_HARDWAREID. Could this be the problem?"

    The docs are correct, this is not supported.  A device's Hardware IDs are re-queried when the PDO is re-enumerated from the bus, so any manual changes will not be preserved.  When the IDs change back, the device will no longer match your driver.  If the device is uninstalled or changes location, your driver will also not be selected.  Your installer must not change the IDs of the device, instead the INF should match one of the bus-reported IDs the device already has.

    In current version of Windows, it is no longer possible to manually change the Hardware/Compatible IDs of a device like this.

    Hope this helps,
    Jim.


    This posting is provided "AS IS" with no warranties, and confers no rights.

    Thursday, January 30, 2014 3:03 AM
  • Thank you Jim for your important post. I went through my code and here's what I found:

    INF file:

    Nothing interesting, just installation of the usual things. The token "security" does not appear:

    [vjoy.Inst.NT.HW]
    AddReg = vjoy.AddReg [vjoy.AddReg]
    HKR,,"UpperFilters",0x00010000,"hidkmdf"[vjoy_Win7_Parameters.AddReg]
    HKR,,"UpperFilters",0x00010000,"mshidkmdf"[vjoy_EventLog_Inst]
    AddReg                      =vJoyEventLogAddReg
    [vJoyEventLogAddReg]
    HKR,,EventMessageFile,0x00020000,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\vjoy.sys"
    HKR,,TypesSupported,0x00010001,7[vjoy.Inst.NT.CoInstallers]
    AddReg=vjoy.Inst_CoInstaller_AddReg
    CopyFiles=vjoy.Inst_CoInstaller_CopyFiles
    [vjoy.Inst_CoInstaller_AddReg]
    HKR,,CoInstallers32,0x00010000, "WdfCoInstaller01005.dll,WdfCoInstaller"

    Installer:
    There are two instances of SetupDiSetDeviceRegistryProperty(), both with SPDRP_HARDWAREID.
    I cannot answer at the moment what they do (I copied this from DevCon code).
    Can they have class-wide effect?

    Driver code:
    I was looking for cases where the driver directly writes to the registry. I found the following cases where the driver accesses the registry in my code:

    1. WdfRegistryOpenKey()  All of mine are with GENERIC_READ.
      Is it possible that failing to close a key prevents another driver from loading?
    2. WdfFdoInitOpenRegistryKey() with GENERIC_READ
    3. WdfDriverOpenParametersRegistryKey() with WRITE_DAC.
      It is suspicious though I use it for reading only. To be tested with KEY_READ
    4. Many WdfRegistryQueryValue() and WdfRegistryClose()

    Uninstalling my driver and then rebooting will not release the system. Is there any tool to inspect (changes in) registry permission or to better understand the reason for CM_PROB_SETPROPERTIES_FAILED?


    • Edited by shaul_ei Thursday, January 30, 2014 11:17 AM
    Thursday, January 30, 2014 11:16 AM