Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to disable a device in the windows environment

Tags:

c++

windows

By coming back home this WE I went to a problem concerning a steam video game : I got regular lags, and by searching the web I found that this came from some control devices, as my WE keyboard.

The solution is to deactivate some HID devices in the device manager (human interface devices section) with the standard right-click => disable operation. So I started to code a small utility to disable these devices while launching the game, and re-enable them after exiting.

Using SetupDI API functions, I managed to isolate the devices I wanted to disable, but when I disable them by applying the DICS_DISABLE operation, instead of acting as if I disabled them with the right mouse button method, the devices become "unkown devices" in the device manager. I have to update the devices's drivers to get them back in the device manager. I also tried the DICS_STOP operation, but with this one the devices simply disappear from the DM...

Is there something I am missing in this operation ?

Here is my prototype code : (console application, x64) => the system is x64, and if my application is 32 bits, all device operations simply fail.

#include <stdio.h>
#include <Windows.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>

#pragma comment (lib, "Newdev.lib")
#pragma comment (lib, "Setupapi.lib")

int main(int argc, void * argv[])
{
    HDEVINFO hDevInfo;
    SP_DEVINFO_DATA DeviceInfoData;
    DWORD i;
    SP_PROPCHANGE_PARAMS params; // params to set in order to enable/disable the device

    // Create a HDEVINFO with all present devices.
    hDevInfo = SetupDiGetClassDevs(NULL,
        0, // Enumerator
        0,
        DIGCF_PRESENT | DIGCF_ALLCLASSES );

    if (hDevInfo == INVALID_HANDLE_VALUE)
    {
        // Insert error handling here.
        return 1;
    }

    // Enumerate through all devices in Set.

    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
    for (i=0;SetupDiEnumDeviceInfo(hDevInfo,i,
        &DeviceInfoData);i++)
    {
        DWORD DataT;
        LPTSTR buffer = NULL;
        LPTSTR servBuffer = NULL;
        DWORD buffersize = 0;
        DWORD servBufferSize = 0;

        //
        // Call function with null to begin with,
        // then use the returned buffer size (doubled)
        // to Alloc the buffer. Keep calling until
        // success or an unknown failure.
        //
        //  Double the returned buffersize to correct
        //  for underlying legacy CM functions that
        //  return an incorrect buffersize value on
        //  DBCS/MBCS systems.
        //
        while (!SetupDiGetDeviceRegistryProperty(
            hDevInfo,
            &DeviceInfoData,
            SPDRP_DEVICEDESC,
            &DataT,
            (PBYTE)buffer,
            buffersize,
            &buffersize))
        {
            if (GetLastError() ==
                ERROR_INSUFFICIENT_BUFFER)
            {
                // Change the buffer size.
                if (buffer) LocalFree(buffer);
                // Double the size to avoid problems on
                // W2k MBCS systems per KB 888609.
                buffer = (LPTSTR)LocalAlloc(LPTR,buffersize * 2);
            }
            else
            {
                // Insert error handling here.
                break;
            }
        }

        while (!SetupDiGetDeviceRegistryProperty(
            hDevInfo,
            &DeviceInfoData,
            SPDRP_SERVICE,
            &DataT,
            (PBYTE)servBuffer,
            servBufferSize,
            &servBufferSize))
        {
            if (GetLastError() ==
                ERROR_INSUFFICIENT_BUFFER)
            {
                // Change the buffer size.
                if (servBuffer) LocalFree(servBuffer);
                // Double the size to avoid problems on
                // W2k MBCS systems per KB 888609.
                servBuffer = (LPTSTR)LocalAlloc(LPTR,servBufferSize * 2);
            }
            else
            {
                // Insert error handling here.
                break;
            }
        }

        if (strstr((char *)buffer, "(HID)") && NULL == servBuffer)
        {
            printf("New device found : %s\n", buffer);
            printf("disabling...\n");
            // init the structure
            params.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
            params.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
            params.HwProfile = 0;
            params.Scope = DICS_FLAG_CONFIGSPECIFIC;
            params.StateChange = DICS_DISABLE;
            // prepare operation
            if (!SetupDiSetClassInstallParams(hDevInfo, &DeviceInfoData, &params.ClassInstallHeader, sizeof(params)))
            {
                printf("Error while preparing params !\n");
                break;
            }
            // launch op
            if (!SetupDiCallClassInstaller(DICS_DISABLE, hDevInfo, &DeviceInfoData))
            {
                printf("Error while calling OP ! Return code is %x\n", GetLastError());
                continue;
            }
            printf("done.\n\n");
        }

        if (buffer) LocalFree(buffer);
    }


    if ( GetLastError()!=NO_ERROR &&
        GetLastError()!=ERROR_NO_MORE_ITEMS )
    {
        // Insert error handling here.
        return 1;
    }

    //  Cleanup
    SetupDiDestroyDeviceInfoList(hDevInfo);

    return 0;
}
like image 592
axiagame Avatar asked Jun 24 '12 16:06

axiagame


People also ask

How do I disable a device on Windows?

Open Start on Windows 10. Search for Device Manager and click the top result to open the app. Expand the branch with the driver you want to disable. Right-click the device and select the Disable device option.

How can I disable a device using CMD?

Type the desired command - /disable to disable a device , /enable to enable a device , /disable_enable to disable and the enable again the specified device , and /uninstall to uninstall a device.

What does disabling a device do in Device Manager?

Windows enables all devices it recognizes. Once disabled, Windows will no longer assign system resources to the device and no software on your computer will be able to use it.


1 Answers

You have the parameter wrong, you need

SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &DeviceInfoData)

with a filled SP_PROPCHANGE_PARAMS in DeviceInfoData.

See this for example. (it's in Chinese, just read the code is enough)

like image 84
J-16 SDiZ Avatar answered Nov 14 '22 22:11

J-16 SDiZ