Implement SetupDiCallClassInstaller (still doesn't support custom class installers/co-installers) Implement SetupDiGetDeviceInstallParamsA by calling SetupDiGetDeviceInstallParamsW. Add stub for SetupDiGetDeviceInstallParamsW Basic implementation of SetupDiSelectBestCompatDrv (selects first driver of the list) Add stubs for SetupDiInstallDriverFiles, SetupDiRegisterCoDeviceInstallers, SetupDiInstallDeviceInterfaces, SetupDiInstallDevice Modified: trunk/reactos/lib/setupapi/devinst.c Modified: trunk/reactos/lib/setupapi/setupapi.spec _____
Modified: trunk/reactos/lib/setupapi/devinst.c --- trunk/reactos/lib/setupapi/devinst.c 2005-08-12 19:00:04 UTC (rev 17343) +++ trunk/reactos/lib/setupapi/devinst.c 2005-08-12 19:03:35 UTC (rev 17344) @@ -79,9 +79,33 @@
/* FIXME: header mess */ DEFINE_GUID(GUID_NULL, 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +typedef DWORD +(CALLBACK* CLASS_INSTALL_PROC) ( + IN DI_FUNCTION InstallFunction, + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL); +typedef BOOL +(WINAPI* DEFAULT_CLASS_INSTALL_PROC) ( + IN HDEVINFO DeviceInfoSet, + IN OUT PSP_DEVINFO_DATA DeviceInfoData); +typedef DWORD +(CALLBACK* COINSTALLER_PROC) ( + IN DI_FUNCTION InstallFunction, + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL, + IN OUT PCOINSTALLER_CONTEXT_DATA Context);
#define SETUP_DEV_INFO_SET_MAGIC 0xd00ff057
+struct CoInstallerElement +{ + LIST_ENTRY ListEntry; + + COINSTALLER_PROC Function; + BOOL DoPostProcessing; + PVOID PrivateData; +}; + struct DeviceInterface /* Element of DeviceInfoElement.InterfaceListHead */ { LIST_ENTRY ListEntry; @@ -2758,22 +2782,304 @@ * SetupDiCallClassInstaller (SETUPAPI.@) */ BOOL WINAPI SetupDiCallClassInstaller( - DI_FUNCTION InstallFunction, - HDEVINFO DeviceInfoSet, - PSP_DEVINFO_DATA DeviceInfoData) + IN DI_FUNCTION InstallFunction, + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) { - FIXME("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData); - return FALSE; + BOOL ret = FALSE; + + TRACE("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData); + + if (!DeviceInfoSet) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) + SetLastError(ERROR_INVALID_HANDLE); + else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC) + SetLastError(ERROR_INVALID_HANDLE); + else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE) + SetLastError(ERROR_INVALID_HANDLE); + else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else + { +#define CLASS_COINSTALLER 0x1 +#define DEVICE_COINSTALLER 0x2 +#define CLASS_INSTALLER 0x4 + UCHAR CanHandle = 0; + DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL; + + switch (InstallFunction) + { + case DIF_ALLOW_INSTALL: + CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; + break; + case DIF_DESTROYPRIVATEDATA: + CanHandle = CLASS_INSTALLER; + break; + case DIF_INSTALLDEVICE: + CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; + DefaultHandler = SetupDiInstallDevice; + break; + case DIF_INSTALLDEVICEFILES: + CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; + DefaultHandler = SetupDiInstallDriverFiles; + break; + case DIF_INSTALLINTERFACES: + CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; + DefaultHandler = SetupDiInstallDeviceInterfaces; + break; + case DIF_NEWDEVICEWIZARD_FINISHINSTALL: + CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER; + break; + case DIF_NEWDEVICEWIZARD_POSTANALYZE: + CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; + break; + case DIF_NEWDEVICEWIZARD_PREANALYZE: + CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; + break; + case DIF_REGISTER_COINSTALLERS: + CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; + DefaultHandler = SetupDiRegisterCoDeviceInstallers; + break; + case DIF_SELECTBESTCOMPATDRV: + CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER; + DefaultHandler = SetupDiSelectBestCompatDrv; + break; + default: + FIXME("Install function %ld not implemented\n", InstallFunction); + SetLastError(ERROR_INVALID_PARAMETER); + } + + if (CanHandle != 0) + { + LIST_ENTRY ClassCoInstallersListHead; + LIST_ENTRY DeviceCoInstallersListHead; + CLASS_INSTALL_PROC ClassInstaller = NULL; + COINSTALLER_CONTEXT_DATA Context; + PLIST_ENTRY ListEntry; + HKEY hKey; + DWORD dwRegType, dwLength; + DWORD rc = NO_ERROR; + + InitializeListHead(&ClassCoInstallersListHead); + InitializeListHead(&DeviceCoInstallersListHead); + + if (CanHandle & CLASS_COINSTALLER) + { + FIXME("Doesn't use Class co-installers at the moment\n"); + } + if (CanHandle & DEVICE_COINSTALLER) + { + rc = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + L"SYSTEM\CurrentControlSet\Control\CoDeviceInstallers", + 0, /* Options */ + KEY_QUERY_VALUE, + &hKey); + if (rc == ERROR_SUCCESS) + { + LPWSTR lpGuidString; + if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK) + { + rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength); + if (rc == ERROR_SUCCESS && dwRegType == REG_SZ) + { + LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); + if (KeyBuffer != NULL) + { + rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); + if (rc == ERROR_SUCCESS) + { + LPCWSTR ptr; + for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1) + { + /* Add coinstaller to DeviceCoInstallersListHead list */ + FIXME("Device coinstaller is '%S'\n", ptr); + } + } + HeapFree(GetProcessHeap(), 0, KeyBuffer); + } + } + RpcStringFreeW(&lpGuidString); + } + RegCloseKey(hKey); + } + } + if (CanHandle & CLASS_INSTALLER) + { + hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE); + if (hKey != INVALID_HANDLE_VALUE) + { + rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength); + if (rc == ERROR_SUCCESS && dwRegType == REG_SZ) + { + LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength); + if (KeyBuffer != NULL) + { + rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); + if (rc == ERROR_SUCCESS) + { + /* Set ClassInstaller function pointer */ + FIXME("Installer is '%S'\n", KeyBuffer); + } + HeapFree(GetProcessHeap(), 0, KeyBuffer); + } + } + RegCloseKey(hKey); + } + } + + /* Call Class co-installers */ + Context.PostProcessing = FALSE; + rc = NO_ERROR; + ListEntry = ClassCoInstallersListHead.Flink; + while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead) + { + struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry; + rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); + coinstaller->PrivateData = Context.PrivateData; + if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) + { + coinstaller->DoPostProcessing = TRUE; + rc = NO_ERROR; + } + ListEntry = ListEntry->Flink; + } + + /* Call Device co-installers */ + ListEntry = DeviceCoInstallersListHead.Flink; + while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead) + { + struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry; + rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); + coinstaller->PrivateData = Context.PrivateData; + if (rc == ERROR_DI_POSTPROCESSING_REQUIRED) + { + coinstaller->DoPostProcessing = TRUE; + rc = NO_ERROR; + } + ListEntry = ListEntry->Flink; + } + + /* Call Class installer */ + if (ClassInstaller) + rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData); + else + rc = ERROR_DI_DO_DEFAULT; + + /* Call default handler */ + if (rc == ERROR_DI_DO_DEFAULT) + { + if (DefaultHandler /*FIXME && DI_NODI_DEFAULTACTION not set */) + { + if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData)) + rc = NO_ERROR; + else + rc = GetLastError(); + } + else + rc = NO_ERROR; + } + + /* Call Class co-installers that required postprocessing */ + Context.PostProcessing = TRUE; + ListEntry = ClassCoInstallersListHead.Flink; + while (ListEntry != &ClassCoInstallersListHead) + { + struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry; + if (coinstaller->DoPostProcessing) + { + Context.InstallResult = rc; + Context.PrivateData = coinstaller->PrivateData; + rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); + } + ListEntry = ListEntry->Flink; + } + + /* Call Device co-installers that required postprocessing */ + ListEntry = DeviceCoInstallersListHead.Flink; + while (ListEntry != &DeviceCoInstallersListHead) + { + struct CoInstallerElement *coinstaller = (struct CoInstallerElement *)ListEntry; + if (coinstaller->DoPostProcessing) + { + Context.InstallResult = rc; + Context.PrivateData = coinstaller->PrivateData; + rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context); + } + ListEntry = ListEntry->Flink; + } + + /* Free allocated memory */ + while (!IsListEmpty(&ClassCoInstallersListHead)) + { + ListEntry = RemoveHeadList(&ClassCoInstallersListHead); + HeapFree(GetProcessHeap(), 0, ListEntry); + } + while (!IsListEmpty(&DeviceCoInstallersListHead)) + { + ListEntry = RemoveHeadList(&DeviceCoInstallersListHead); + HeapFree(GetProcessHeap(), 0, ListEntry); + } + + ret = (rc == NO_ERROR); + } + } + + TRACE("Returning %d\n", ret); + return ret; }
/*********************************************************************** * SetupDiGetDeviceInstallParamsA (SETUPAPI.@) */ BOOL WINAPI SetupDiGetDeviceInstallParamsA( - HDEVINFO DeviceInfoSet, - PSP_DEVINFO_DATA DeviceInfoData, - PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData, + OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) { + SP_DEVINSTALL_PARAMS_W deviceInstallParamsW; + BOOL ret = FALSE; + + TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); + + if (DeviceInstallParams == NULL) + SetLastError(ERROR_INVALID_PARAMETER); + else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A)) + SetLastError(ERROR_INVALID_USER_BUFFER); + else + { + deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); + ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW); + + if (ret) + { + /* Do W->A conversion */ + memcpy( + DeviceInstallParams, + &deviceInstallParamsW, + FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath)); + if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1, + DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0) + { + DeviceInstallParams->DriverPath[0] = '\0'; + ret = FALSE; + } + } + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/********************************************************************** * + * SetupDiGetDeviceInstallParamsW (SETUPAPI.@) + */ +BOOL WINAPI SetupDiGetDeviceInstallParamsW( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData, + OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams) +{ FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); return FALSE; } @@ -3864,3 +4170,114 @@ TRACE("Returning %d\n", ret); return ret; } + +/********************************************************************** * + * SetupDiSelectBestCompatDrv (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiSelectBestCompatDrv( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData) +{ + SP_DRVINFO_DATA_W drvInfoData; + BOOL ret; + + TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); + + FIXME("SetupDiSelectBestCompatDrv() is selecting the 1st driver...\n"); + + drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA_W); + ret = SetupDiEnumDriverInfoW( + DeviceInfoSet, + DeviceInfoData, + SPDIT_COMPATDRIVER, + 0, /* Member index */ + &drvInfoData); + + if (ret) + { + ret = SetupDiSetSelectedDriverW( + DeviceInfoSet, + DeviceInfoData, + &drvInfoData); + } + + TRACE("Returning %d\n", ret); + return ret; +} + +/********************************************************************** * + * SetupDiInstallDriverFiles (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiInstallDriverFiles( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL) +{ + TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); + + FIXME("SetupDiInstallDriverFiles not implemented. Doing nothing\n"); + //SetLastError(ERROR_GEN_FAILURE); + //return FALSE; + return TRUE; +} + +/********************************************************************** * + * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiRegisterCoDeviceInstallers( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData) +{ + TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); + + FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n"); + //SetLastError(ERROR_GEN_FAILURE); + //return FALSE; + return TRUE; +} + +/********************************************************************** * + * SetupDiInstallDeviceInterfaces (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiInstallDeviceInterfaces( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData) +{ + TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); + + FIXME("SetupDiInstallDeviceInterfaces not implemented. Doing nothing\n"); + //SetLastError(ERROR_GEN_FAILURE); + //return FALSE; + return TRUE; +} + +/********************************************************************** * + * SetupDiInstallDevice (SETUPAPI.@) + */ +BOOL WINAPI +SetupDiInstallDevice( + IN HDEVINFO DeviceInfoSet, + IN PSP_DEVINFO_DATA DeviceInfoData) +{ + TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData); + + /* Steps to follow: + * 0. If DI_FLAGSEX_SETFAILEDINSTALL is set, set FAILEDINSTALL flag in ConfigFlags registry and exit + * 1. Create driver key and write InfPath and ProviderName + * 2a Process inf sections: {DDInstall}, {DDInstall}.HW [SetupDiOpenDevRegKey] + * b Process {DDInstall}.LogConfigOverride if present [SetupDiOpenDevRegKey] + * c Process {DDInstall}.Services [SetupDiOpenDevRegKey] + * 3. Copy inf file to Inf\ directory [SetupCopyOEMInf] + * 4. Install other waiting files + * 5. Load the driver/Call AddDevice + * 6. Send IRP_MN_START_DEVICE if DI_NEEDRESTART, DI_NEEDREBOOT and DI_DONOTCALLCONFIGMG are not set + */ + + FIXME("SetupDiInstallDevice not implemented. Doing nothing\n"); + //SetLastError(ERROR_GEN_FAILURE); + //return FALSE; + return TRUE; +} _____
Modified: trunk/reactos/lib/setupapi/setupapi.spec --- trunk/reactos/lib/setupapi/setupapi.spec 2005-08-12 19:00:04 UTC (rev 17343) +++ trunk/reactos/lib/setupapi/setupapi.spec 2005-08-12 19:03:35 UTC (rev 17344) @@ -321,7 +321,7 @@
@ stdcall SetupDiGetDeviceInfoListDetailA(ptr ptr) @ stdcall SetupDiGetDeviceInfoListDetailW(ptr ptr) @ stdcall SetupDiGetDeviceInstallParamsA(ptr ptr ptr) -@ stub SetupDiGetDeviceInstallParamsW +@ stdcall SetupDiGetDeviceInstallParamsW(ptr ptr ptr) @ stub SetupDiGetDeviceInstanceIdA @ stub SetupDiGetDeviceInstanceIdW @ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr) @@ -350,8 +350,9 @@ @ stub SetupDiInstallClassExA @ stub SetupDiInstallClassExW @ stdcall SetupDiInstallClassW(long wstr long ptr) -@ stub SetupDiInstallDevice -@ stub SetupDiInstallDriverFiles +@ stdcall SetupDiInstallDevice(ptr ptr) +@ stdcall SetupDiInstallDeviceInterfaces(ptr ptr) +@ stdcall SetupDiInstallDriverFiles(ptr ptr) @ stub SetupDiLoadClassIcon @ stub SetupDiMoveDuplicateDevice @ stdcall SetupDiOpenClassRegKey(ptr long) @@ -363,9 +364,11 @@ @ stdcall SetupDiOpenDeviceInterfaceA(ptr str long ptr) @ stub SetupDiOpenDeviceInterfaceRegKey @ stdcall SetupDiOpenDeviceInterfaceW(ptr wstr long ptr) +@ stdcall SetupDiRegisterCoDeviceInstallers(ptr ptr) @ stub SetupDiRegisterDeviceInfo @ stub SetupDiRemoveDevice @ stub SetupDiRemoveDeviceInterface +@ stdcall SetupDiSelectBestCompatDrv(ptr ptr) @ stub SetupDiSelectDevice @ stub SetupDiSelectOEMDrv @ stdcall SetupDiSetClassInstallParamsA(ptr ptr ptr long)