struct InfFileDetails
{
HINF hInf;
- ULONG References;
+ LONG References;
};
struct DriverInfoElement /* Element of DeviceInfoSet.DriverListHead and DeviceInfoElement.DriverListHead */
*RequiredSize = BufferSize;
switch(rc) {
case ERROR_SUCCESS:
- ret = TRUE;
+ if (PropertyBuffer != NULL || BufferSize == 0)
+ ret = TRUE;
+ else
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
break;
case ERROR_MORE_DATA:
SetLastError(ERROR_INSUFFICIENT_BUFFER);
goto cleanup;
}
- /* W->A conversion for function name */
- FunctionNameA = UnicodeToMultiByte(Comma + 1, CP_ACP);
- if (!FunctionNameA)
- {
- rc = GetLastError();
- goto cleanup;
- }
-
/* Load library */
*Comma = '\0';
hModule = LoadLibraryW(InstallerName);
goto cleanup;
}
+ /* Skip comma spaces */
+ while (*Comma == ',' || isspaceW(*Comma))
+ Comma++;
+
+ /* W->A conversion for function name */
+ FunctionNameA = UnicodeToMultiByte(Comma, CP_ACP);
+ if (!FunctionNameA)
+ {
+ rc = GetLastError();
+ goto cleanup;
+ }
+
/* Search function */
*FunctionPointer = GetProcAddress(hModule, FunctionNameA);
if (!*FunctionPointer)
if (CanHandle & DEVICE_COINSTALLER)
{
- FIXME("Doesn't use Device co-installers at the moment\n");
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
+ if (hKey != INVALID_HANDLE_VALUE)
+ {
+ rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, &dwRegType, NULL, &dwLength);
+ if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
+ {
+ LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
+ if (KeyBuffer != NULL)
+ {
+ rc = RegQueryValueExW(hKey, L"CoInstallers32", NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
+ if (rc == ERROR_SUCCESS)
+ {
+ LPWSTR ptr;
+ for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
+ {
+ /* Add coinstaller to DeviceCoInstallersListHead list */
+ struct CoInstallerElement *coinstaller;
+ TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
+ coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
+ if (!coinstaller)
+ continue;
+ memset(coinstaller, 0, sizeof(struct CoInstallerElement));
+ if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
+ InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
+ else
+ HeapFree(GetProcessHeap(), 0, coinstaller);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, KeyBuffer);
+ }
+ }
+ RegCloseKey(hKey);
+ }
}
if (CanHandle & CLASS_COINSTALLER)
{
if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
{
rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
- if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
+ if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
{
LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
if (KeyBuffer != NULL)
rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
if (rc == ERROR_SUCCESS)
{
- LPCWSTR ptr;
+ LPWSTR ptr;
for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
{
/* Add coinstaller to ClassCoInstallersListHead list */
- FIXME("Class coinstaller is '%S'. UNIMPLEMENTED!\n", ptr);
+ struct CoInstallerElement *coinstaller;
+ TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
+ coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
+ if (!coinstaller)
+ continue;
+ memset(coinstaller, 0, sizeof(struct CoInstallerElement));
+ if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
+ InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
+ else
+ HeapFree(GetProcessHeap(), 0, coinstaller);
}
}
HeapFree(GetProcessHeap(), 0, KeyBuffer);
if (rc == ERROR_SUCCESS)
{
/* Get ClassInstaller function pointer */
+ TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
{
InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
Buffer, RequiredSize,
&RequiredSize);
}
+ if (!Result && GetLastError() == ERROR_FILE_NOT_FOUND)
+ {
+ /* No .inf file in specified directory. So, we should
+ * success as we created an empty driver info list.
+ */
+ ret = TRUE;
+ goto done;
+ }
if (Result)
{
LPCWSTR filename;
if (!DeviceInfoData)
/* Fall back to destroying class driver list */
DriverType = SPDIT_CLASSDRIVER;
- if (DriverType == SPDIT_CLASSDRIVER)
- {
- if (!(InstallParams.Flags & DI_DIDCLASS))
- /* The list was not created */
- goto done;
- }
- else if (DriverType == SPDIT_COMPATDRIVER)
- {
- if (!(InstallParams.Flags & DI_DIDCOMPAT))
- /* The list was not created */
- goto done;
- }
if (DriverType == SPDIT_CLASSDRIVER)
{
return ret;
}
+
+/***********************************************************************
+ * SetupDiSetSelectedDriverA (SETUPAPI.@)
+ */
+BOOL WINAPI
+SetupDiSetSelectedDriverA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL)
+{
+ SP_DRVINFO_DATA_V1_W DriverInfoDataW;
+ PSP_DRVINFO_DATA_W pDriverInfoDataW = NULL;
+ BOOL ret = FALSE;
+
+ if (DriverInfoData != NULL)
+ {
+ if (DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V2_A) &&
+ DriverInfoData->cbSize != sizeof(SP_DRVINFO_DATA_V1_A));
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ DriverInfoDataW.cbSize = sizeof(SP_DRVINFO_DATA_V1_W);
+ DriverInfoDataW.Reserved = DriverInfoData->Reserved;
+
+ if (DriverInfoDataW.Reserved == 0)
+ {
+ DriverInfoDataW.DriverType = DriverInfoData->DriverType;
+
+ /* convert the strings to unicode */
+ if (!MultiByteToWideChar(CP_ACP,
+ 0,
+ DriverInfoData->Description,
+ LINE_LEN,
+ DriverInfoDataW.Description,
+ LINE_LEN) ||
+ !MultiByteToWideChar(CP_ACP,
+ 0,
+ DriverInfoData->ProviderName,
+ LINE_LEN,
+ DriverInfoDataW.ProviderName,
+ LINE_LEN))
+ {
+ return FALSE;
+ }
+ }
+
+ pDriverInfoDataW = (PSP_DRVINFO_DATA_W)&DriverInfoDataW;
+ }
+
+ ret = SetupDiSetSelectedDriverW(DeviceInfoSet,
+ DeviceInfoData,
+ pDriverInfoDataW);
+
+ if (ret && pDriverInfoDataW != NULL)
+ {
+ DriverInfoData->Reserved = DriverInfoDataW.Reserved;
+ }
+
+ return ret;
+}
+
+
/***********************************************************************
* SetupDiSetSelectedDriverW (SETUPAPI.@)
*/
InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
if (!ret)
- goto cleanup;
+ goto done;
SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
if (!SelectedDriver)
{
SetLastError(ERROR_NO_DRIVER_SELECTED);
- goto cleanup;
+ goto done;
}
ret = SetupDiGetActualSectionToInstallW(
SelectedDriver->Details.SectionName,
SectionName, MAX_PATH, &SectionNameLength, NULL);
if (!ret)
- goto cleanup;
+ goto done;
- if (InstallParams.InstallMsgHandler)
- {
- ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
- SelectedDriver->InfFileDetails->hInf, SectionName,
- SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
- InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
- DeviceInfoSet, DeviceInfoData);
- }
- else
- {
- PVOID callback_context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
- ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
- SelectedDriver->InfFileDetails->hInf, SectionName,
- SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
- SetupDefaultQueueCallbackW, callback_context,
- DeviceInfoSet, DeviceInfoData);
- SetupTermDefaultQueueCallback(callback_context);
- }
-cleanup:
- if (ret)
+ if (!InstallParams.InstallMsgHandler)
{
- InstallParams.Flags |= DI_NOFILECOPY;
- ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
+ InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
}
+ ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
+ InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
+ DeviceInfoSet, DeviceInfoData);
}
+done:
TRACE("Returning %d\n", ret);
return ret;
}
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData)
{
+ BOOL ret = FALSE; /* Return value */
+
TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
- FIXME("SetupDiRegisterCoDeviceInstallers not implemented. Doing nothing\n");
- //SetLastError(ERROR_GEN_FAILURE);
- //return FALSE;
- return TRUE;
+ 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 (!DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ struct DriverInfoElement *SelectedDriver;
+ BOOL Result;
+ DWORD DoAction;
+ WCHAR SectionName[MAX_PATH];
+ DWORD SectionNameLength = 0;
+ HKEY hKey = INVALID_HANDLE_VALUE;;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
+ Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!Result)
+ goto cleanup;
+
+ SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
+ if (SelectedDriver == NULL)
+ {
+ SetLastError(ERROR_NO_DRIVER_SELECTED);
+ goto cleanup;
+ }
+
+ /* Get .CoInstallers section name */
+ Result = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
+ SectionName, MAX_PATH, &SectionNameLength, NULL);
+ if (!Result || SectionNameLength > MAX_PATH - wcslen(L".CoInstallers") - 1)
+ goto cleanup;
+ wcscat(SectionName, L".CoInstallers");
+
+ /* Open/Create driver key information */
+#if _WIN32_WINNT >= 0x502
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
+#else
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
+#endif
+ if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
+ hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ /* Install .CoInstallers section */
+ DoAction = SPINST_REGISTRY;
+ if (!(InstallParams.Flags & DI_NOFILECOPY))
+ {
+ DoAction |= SPINST_FILES;
+ if (!InstallParams.InstallMsgHandler)
+ {
+ InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
+ InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ }
+ }
+ Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
+ DoAction, hKey, NULL, SP_COPY_NEWER,
+ InstallParams.InstallMsgHandler, InstallParams.InstallMsgHandlerContext,
+ DeviceInfoSet, DeviceInfoData);
+ if (!Result)
+ goto cleanup;
+
+ ret = TRUE;
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
}
/***********************************************************************
/* Install main section */
DoAction = SPINST_REGISTRY;
if (!(InstallParams.Flags & DI_NOFILECOPY))
+ {
DoAction |= SPINST_FILES;
- /* Files have already been copied in SetupDiInstallDriverFiles.
- * Process only registry entries. */
+ if (!InstallParams.InstallMsgHandler)
+ {
+ InstallParams.InstallMsgHandler = SetupDefaultQueueCallbackW;
+ InstallParams.InstallMsgHandlerContext = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
+ SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ }
+ }
*pSectionName = '\0';
Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
SelectedDriver->InfFileDetails->hInf, SectionName,
goto cleanup;
if (!(InstallParams.Flags & DI_NOFILECOPY) && !(InstallParams.Flags & DI_NOVCP))
{
- Result = SetupCommitFileQueueW(InstallParams.hwndParent,
- InstallParams.FileQueue,
- InstallParams.InstallMsgHandler,
- InstallParams.InstallMsgHandlerContext);
+ if (Result && InstallParams.InstallMsgHandler == SetupDefaultQueueCallbackW)
+ {
+ /* Delete resources allocated by SetupInitDefaultQueueCallback */
+ SetupTermDefaultQueueCallback(InstallParams.InstallMsgHandlerContext);
+ }
}
InstallParams.Flags |= DI_NOFILECOPY;
SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);