[PATCH 1/3] setupapi: Implement SetupDiGetSelectedDriver().

Zhiyi Zhang zzhang at codeweavers.com
Sat Mar 7 20:04:53 CST 2020



On 3/8/20 9:50 AM, Zebediah Figura wrote:
> From: Zebediah Figura <z.figura12 at gmail.com>
>
> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48639
> Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
> ---
>  dlls/setupapi/devinst.c       | 90 +++++++++++++++++++++++++----------
>  dlls/setupapi/setupapi.spec   |  4 +-
>  dlls/setupapi/tests/devinst.c | 14 ++++++
>  3 files changed, 82 insertions(+), 26 deletions(-)
>
> diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c
> index 268965f0fed..69b339e49b3 100644
> --- a/dlls/setupapi/devinst.c
> +++ b/dlls/setupapi/devinst.c
> @@ -4645,16 +4645,42 @@ BOOL WINAPI SetupDiBuildDriverInfoList(HDEVINFO devinfo, SP_DEVINFO_DATA *device
>      return TRUE;
>  }
>  
> +static BOOL copy_driver_data(SP_DRVINFO_DATA_W *data, const struct driver *driver)
> +{
> +    INFCONTEXT ctx;
> +    HINF hinf;
> +
> +    if ((hinf = SetupOpenInfFileW(driver->inf_path, NULL, INF_STYLE_WIN4, NULL)) == INVALID_HANDLE_VALUE)
> +        return FALSE;
> +
> +    data->ProviderName[0] = 0;
> +    if (SetupFindFirstLineW(hinf, L"Version", L"Provider", &ctx))
> +        SetupGetStringFieldW(&ctx, 1, data->ProviderName, ARRAY_SIZE(data->ProviderName), NULL);
> +    wcscpy(data->Description, driver->description);
> +    wcscpy(data->MfgName, driver->manufacturer);
> +    data->DriverType = SPDIT_COMPATDRIVER;
> +
> +    SetupCloseInfFile(hinf);
> +
> +    return TRUE;
> +}
> +
> +static void driver_data_wtoa(SP_DRVINFO_DATA_A *a, const SP_DRVINFO_DATA_W *w)
> +{
> +    a->DriverType = w->DriverType;
> +    a->Reserved = w->Reserved;
> +    WideCharToMultiByte(CP_ACP, 0, w->Description, -1, a->Description, sizeof(a->Description), NULL, NULL);
> +    WideCharToMultiByte(CP_ACP, 0, w->MfgName, -1, a->MfgName, sizeof(a->MfgName), NULL, NULL);
> +    WideCharToMultiByte(CP_ACP, 0, w->ProviderName, -1, a->ProviderName, sizeof(a->ProviderName), NULL, NULL);
> +}
> +
>  /***********************************************************************
>   *              SetupDiEnumDriverInfoW (SETUPAPI.@)
>   */
>  BOOL WINAPI SetupDiEnumDriverInfoW(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data,
>          DWORD type, DWORD index, SP_DRVINFO_DATA_W *driver_data)
>  {
> -    static const WCHAR providerW[] = {'P','r','o','v','i','d','e','r',0};
>      struct device *device;
> -    INFCONTEXT ctx;
> -    HINF hinf;
>  
>      TRACE("devinfo %p, device_data %p, type %#x, index %u, driver_data %p.\n",
>              devinfo, device_data, type, index, driver_data);
> @@ -4675,19 +4701,7 @@ BOOL WINAPI SetupDiEnumDriverInfoW(HDEVINFO devinfo, SP_DEVINFO_DATA *device_dat
>          return FALSE;
>      }
>  
> -    if ((hinf = SetupOpenInfFileW(device->drivers[index].inf_path, NULL, INF_STYLE_WIN4, NULL)) == INVALID_HANDLE_VALUE)
> -        return FALSE;
> -
> -    driver_data->ProviderName[0] = 0;
> -    if (SetupFindFirstLineW(hinf, Version, providerW, &ctx))
> -        SetupGetStringFieldW(&ctx, 1, driver_data->ProviderName, ARRAY_SIZE(driver_data->ProviderName), NULL);
> -    lstrcpyW(driver_data->Description, device->drivers[index].description);
> -    lstrcpyW(driver_data->MfgName, device->drivers[index].manufacturer);
> -    driver_data->DriverType = SPDIT_COMPATDRIVER;
> -
> -    SetupCloseInfFile(hinf);
> -
> -    return TRUE;
> +    return copy_driver_data(driver_data, &device->drivers[index]);
>  }
>  
>  /***********************************************************************
> @@ -4701,14 +4715,7 @@ BOOL WINAPI SetupDiEnumDriverInfoA(HDEVINFO devinfo, SP_DEVINFO_DATA *device_dat
>  
>      driver_dataW.cbSize = sizeof(driver_dataW);
>      ret = SetupDiEnumDriverInfoW(devinfo, device_data, type, index, &driver_dataW);
> -    driver_data->DriverType = driver_dataW.DriverType;
> -    driver_data->Reserved = driver_dataW.Reserved;
> -    WideCharToMultiByte(CP_ACP, 0, driver_dataW.Description, -1, driver_data->Description,
> -            sizeof(driver_data->Description), NULL, NULL);
> -    WideCharToMultiByte(CP_ACP, 0, driver_dataW.MfgName, -1, driver_data->MfgName,
> -            sizeof(driver_data->MfgName), NULL, NULL);
> -    WideCharToMultiByte(CP_ACP, 0, driver_dataW.ProviderName, -1, driver_data->ProviderName,
> -            sizeof(driver_data->ProviderName), NULL, NULL);
> +    driver_data_wtoa(driver_data, &driver_dataW);
>      return ret;
>  }
>  
> @@ -4738,6 +4745,41 @@ BOOL WINAPI SetupDiSelectBestCompatDrv(HDEVINFO devinfo, SP_DEVINFO_DATA *device
>      return TRUE;
>  }
>  
> +/***********************************************************************
> + *              SetupDiGetSelectedDriverW (SETUPAPI.@)
> + */
> +BOOL WINAPI SetupDiGetSelectedDriverW(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data, SP_DRVINFO_DATA_W *driver_data)
> +{
> +    struct device *device;
> +
> +    TRACE("devinfo %p, device_data %p, driver_data %p.\n", devinfo, device_data, driver_data);
> +
> +    if (!(device = get_device(devinfo, device_data)))
> +        return FALSE;
> +
> +    if (!device->selected_driver)
> +    {
> +        SetLastError(ERROR_NO_DRIVER_SELECTED);
> +        return FALSE;
> +    }
> +
> +    return copy_driver_data(driver_data, device->selected_driver);
> +}
> +
> +/***********************************************************************
> + *              SetupDiGetSelectedDriverA (SETUPAPI.@)
> + */
> +BOOL WINAPI SetupDiGetSelectedDriverA(HDEVINFO devinfo, SP_DEVINFO_DATA *device_data, SP_DRVINFO_DATA_A *driver_data)
> +{
> +    SP_DRVINFO_DATA_W driver_dataW;
> +    BOOL ret;
> +
> +    driver_dataW.cbSize = sizeof(driver_dataW);
> +    ret = SetupDiGetSelectedDriverW(devinfo, device_data, &driver_dataW);
> +    driver_data_wtoa(driver_data, &driver_dataW);
This need to return early upon failure. Otherwise with driver_dataW
containing uninitialized string fields, WideCharToMultiByte() in driver_data_wtoa()
could read pass those fields.
> +    return ret;
> +}
> +
>  /***********************************************************************
>   *              SetupDiInstallDriverFiles (SETUPAPI.@)
>   */
> diff --git a/dlls/setupapi/setupapi.spec b/dlls/setupapi/setupapi.spec
> index 33ccc480974..233a02e550c 100644
> --- a/dlls/setupapi/setupapi.spec
> +++ b/dlls/setupapi/setupapi.spec
> @@ -361,8 +361,8 @@
>  @ stdcall SetupDiGetINFClassA(str ptr ptr long ptr)
>  @ stdcall SetupDiGetINFClassW(wstr ptr ptr long ptr)
>  @ stub SetupDiGetSelectedDevice
> -@ stub SetupDiGetSelectedDriverA
> -@ stub SetupDiGetSelectedDriverW
> +@ stdcall SetupDiGetSelectedDriverA(ptr ptr ptr)
> +@ stdcall SetupDiGetSelectedDriverW(ptr ptr ptr)
>  @ stub SetupDiGetWizardPage
>  @ stdcall SetupDiInstallClassA(long str long ptr)
>  @ stub SetupDiInstallClassExA
> diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c
> index a9ac0d849f6..9eed8e73d87 100644
> --- a/dlls/setupapi/tests/devinst.c
> +++ b/dlls/setupapi/tests/devinst.c
> @@ -2434,6 +2434,20 @@ static void test_driver_list(void)
>      ok(!ret, "Expected failure.\n");
>      ok(GetLastError() == ERROR_NO_MORE_ITEMS, "Got unexpected error %#x.\n", GetLastError());
>  
> +    ret = SetupDiGetSelectedDriverA(set, &device, &driver);
> +    ok(!ret, "Expected failure.\n");
> +    ok(GetLastError() == ERROR_NO_DRIVER_SELECTED, "Got unexpected error %#x.\n", GetLastError());
> +
> +    ret = SetupDiSelectBestCompatDrv(set, &device);
> +    ok(ret, "Failed to select driver, error %#x.\n", GetLastError());
> +
> +    ret = SetupDiGetSelectedDriverA(set, &device, &driver);
> +    ok(ret, "Failed to get selected driver, error %#x.\n", GetLastError());
> +    ok(driver.DriverType == SPDIT_COMPATDRIVER, "Got wrong type %#x.\n", driver.DriverType);
> +    ok(!strcmp(driver.Description, "desc1"), "Got wrong description '%s'.\n", driver.Description);
> +    ok(!strcmp(driver.MfgName, wow64 ? "mfg1_wow" : "mfg1"), "Got wrong manufacturer '%s'.\n", driver.MfgName);
> +    ok(!strcmp(driver.ProviderName, ""), "Got wrong provider '%s'.\n", driver.ProviderName);
> +
>      SetupDiDestroyDeviceInfoList(set);
>      ret = DeleteFileA(inf_path);
>      ok(ret, "Failed to delete %s, error %u.\n", inf_path, GetLastError());




More information about the wine-devel mailing list