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

svn path=/trunk/; revision=17344
This commit is contained in:
Hervé Poussineau 2005-08-12 19:03:35 +00:00
parent 905e145f73
commit e5b47d0df9
2 changed files with 431 additions and 11 deletions

View file

@ -79,9 +79,33 @@ static const WCHAR EnumKeyName[] = {'S','y','s','t','e','m','\\',
/* 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,21 +2782,303 @@ BOOL WINAPI SetupDiSetClassInstallParamsA(
* 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 @@ SetupDiSetSelectedDriverW(
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;
}

View file

@ -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)