Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/newdev/Makefile.in | 1 + dlls/newdev/main.c | 97 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/dlls/newdev/Makefile.in b/dlls/newdev/Makefile.in index 728dea3218f..c447a388614 100644 --- a/dlls/newdev/Makefile.in +++ b/dlls/newdev/Makefile.in @@ -1,4 +1,5 @@ MODULE = newdev.dll IMPORTLIB = newdev +IMPORTS = setupapi
C_SRCS = main.c diff --git a/dlls/newdev/main.c b/dlls/newdev/main.c index b1a5ccf0909..108aec042ec 100644 --- a/dlls/newdev/main.c +++ b/dlls/newdev/main.c @@ -1,5 +1,5 @@ /* - * NewDev + * New Device installation API * * Copyright 2003 Ulrich Czekalla * @@ -25,12 +25,14 @@ #include "winbase.h" #include "winuser.h" #include "winreg.h" +#include "cfgmgr32.h" #include "newdev.h"
-#include "wine/unicode.h" #include "wine/debug.h" +#include "wine/heap.h" +#include "wine/unicode.h"
-WINE_DEFAULT_DEBUG_CHANNEL(newdev); +WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
/*********************************************************************** * InstallNewDevice (NEWDEV.@) @@ -53,21 +55,96 @@ BOOL WINAPI InstallSelectedDriver(HWND parent, HDEVINFO info, const WCHAR *reser /*********************************************************************** * UpdateDriverForPlugAndPlayDevicesA (NEWDEV.@) */ -BOOL WINAPI UpdateDriverForPlugAndPlayDevicesA(HWND hwndParent, LPCSTR HardwareId, - LPCSTR FullInfPath, DWORD InstallFlags, PBOOL bRebootRequired OPTIONAL) +BOOL WINAPI UpdateDriverForPlugAndPlayDevicesA(HWND parent, const char *hardware_id, + const char *inf_path, DWORD flags, BOOL *reboot) { - FIXME("Stub! %s %s 0x%08x\n", HardwareId, FullInfPath, InstallFlags); - return TRUE; + WCHAR hardware_idW[MAX_DEVICE_ID_LEN]; + WCHAR inf_pathW[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, hardware_id, -1, hardware_idW, ARRAY_SIZE(hardware_idW)); + MultiByteToWideChar(CP_ACP, 0, inf_path, -1, inf_pathW, ARRAY_SIZE(inf_pathW)); + + return UpdateDriverForPlugAndPlayDevicesW(parent, hardware_idW, inf_pathW, flags, reboot); }
+static BOOL hardware_id_matches(const WCHAR *id, const WCHAR *device_ids) +{ + while (*device_ids) + { + if (!strcmpW(id, device_ids)) + return TRUE; + device_ids += strlenW(device_ids) + 1; + } + return FALSE; +}
/*********************************************************************** * UpdateDriverForPlugAndPlayDevicesW (NEWDEV.@) */ -BOOL WINAPI UpdateDriverForPlugAndPlayDevicesW(HWND hwndParent, LPCWSTR HardwareId, - LPCWSTR FullInfPath, DWORD InstallFlags, PBOOL bRebootRequired OPTIONAL) +BOOL WINAPI UpdateDriverForPlugAndPlayDevicesW(HWND parent, const WCHAR *hardware_id, + const WCHAR *inf_path, DWORD flags, BOOL *reboot) { - FIXME("Stub! %s %s 0x%08x\n", debugstr_w(HardwareId), debugstr_w(FullInfPath), InstallFlags); + SP_DEVINSTALL_PARAMS_W params = {sizeof(params)}; + SP_DEVINFO_DATA device = {sizeof(device)}; + WCHAR *device_ids = NULL; + DWORD size = 0, i, j; + HDEVINFO set; + + static const DWORD dif_list[] = + { + DIF_SELECTBESTCOMPATDRV, + DIF_ALLOW_INSTALL, + DIF_INSTALLDEVICEFILES, + DIF_REGISTER_COINSTALLERS, + DIF_INSTALLINTERFACES, + DIF_INSTALLDEVICE, + DIF_NEWDEVICEWIZARD_FINISHINSTALL, + }; + + TRACE("parent %p, hardware_id %s, inf_path %s, flags %#x, reboot %p.\n", + parent, debugstr_w(hardware_id), debugstr_w(inf_path), flags, reboot); + + if (flags) + FIXME("Unhandled flags %#x.\n", flags); + + if (reboot) *reboot = FALSE; + + if ((set = SetupDiGetClassDevsW(NULL, NULL, 0, DIGCF_ALLCLASSES)) == INVALID_HANDLE_VALUE) + return FALSE; + + for (i = 0; SetupDiEnumDeviceInfo(set, i, &device); ++i) + { + if (!SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_HARDWAREID, NULL, (BYTE *)device_ids, size, &size)) + { + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + continue; + device_ids = heap_realloc(device_ids, size); + SetupDiGetDeviceRegistryPropertyW(set, &device, SPDRP_HARDWAREID, NULL, (BYTE *)device_ids, size, NULL); + } + + if (!hardware_id_matches(hardware_id, device_ids)) + continue; + + if (!SetupDiGetDeviceInstallParamsW(set, &device, ¶ms)) + continue; + + strcpyW(params.DriverPath, inf_path); + params.Flags |= DI_ENUMSINGLEINF; + if (!SetupDiSetDeviceInstallParamsW(set, &device, ¶ms)) + continue; + + if (!SetupDiBuildDriverInfoList(set, &device, SPDIT_COMPATDRIVER)) + continue; + + for (j = 0; j < ARRAY_SIZE(dif_list); ++j) + { + if (!SetupDiCallClassInstaller(dif_list[j], set, &device) && GetLastError() != ERROR_DI_DO_DEFAULT) + break; + } + } + + SetupDiDestroyDeviceInfoList(set); + heap_free(device_ids); return TRUE; }