static const WCHAR Class[] = {'C','l','a','s','s',0};
static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
+static const WCHAR InterfaceInstall32[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
static const WCHAR NoInstallClass[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0};
(WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
IN HDEVINFO DeviceInfoSet,
IN OUT PSP_DEVINFO_DATA DeviceInfoData);
-typedef DWORD
+typedef DWORD
(CALLBACK* COINSTALLER_PROC) (
IN DI_FUNCTION InstallFunction,
IN HDEVINFO DeviceInfoSet,
IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
IN OUT PCOINSTALLER_CONTEXT_DATA Context);
+typedef BOOL
+(WINAPI* PROPERTY_PAGE_PROVIDER) (
+ IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest,
+ IN LPFNADDPROPSHEETPAGE fAddFunc,
+ IN LPARAM lParam);
+typedef BOOL
+(*UPDATE_CLASS_PARAM_HANDLER) (
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize);
struct CoInstallerElement
{
PVOID PrivateData;
};
+static BOOL
+PropertyChangeHandler(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize);
+
+static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers[] = {
+ NULL, /* DIF_SELECTDEVICE */
+ NULL, /* DIF_INSTALLDEVICE */
+ NULL, /* DIF_ASSIGNRESOURCES */
+ NULL, /* DIF_PROPERTIES */
+ NULL, /* DIF_REMOVE */
+ NULL, /* DIF_FIRSTTIMESETUP */
+ NULL, /* DIF_FOUNDDEVICE */
+ NULL, /* DIF_SELECTCLASSDRIVERS */
+ NULL, /* DIF_VALIDATECLASSDRIVERS */
+ NULL, /* DIF_INSTALLCLASSDRIVERS */
+ NULL, /* DIF_CALCDISKSPACE */
+ NULL, /* DIF_DESTROYPRIVATEDATA */
+ NULL, /* DIF_VALIDATEDRIVER */
+ NULL, /* DIF_MOVEDEVICE */
+ NULL, /* DIF_DETECT */
+ NULL, /* DIF_INSTALLWIZARD */
+ NULL, /* DIF_DESTROYWIZARDDATA */
+ PropertyChangeHandler, /* DIF_PROPERTYCHANGE */
+ NULL, /* DIF_ENABLECLASS */
+ NULL, /* DIF_DETECTVERIFY */
+ NULL, /* DIF_INSTALLDEVICEFILES */
+ NULL, /* DIF_UNREMOVE */
+ NULL, /* DIF_SELECTBESTCOMPATDRV */
+ NULL, /* DIF_ALLOW_INSTALL */
+ NULL, /* DIF_REGISTERDEVICE */
+ NULL, /* DIF_NEWDEVICEWIZARD_PRESELECT */
+ NULL, /* DIF_NEWDEVICEWIZARD_SELECT */
+ NULL, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
+ NULL, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
+ NULL, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
+ NULL, /* DIF_UNUSED1 */
+ NULL, /* DIF_INSTALLINTERFACES */
+ NULL, /* DIF_DETECTCANCEL */
+ NULL, /* DIF_REGISTER_COINSTALLERS */
+ NULL, /* DIF_ADDPROPERTYPAGE_ADVANCED */
+ NULL, /* DIF_ADDPROPERTYPAGE_BASIC */
+ NULL, /* DIF_RESERVED1 */
+ NULL, /* DIF_TROUBLESHOOTER */
+ NULL, /* DIF_POWERMESSAGEWAKE */
+ NULL, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
+ NULL, /* DIF_UPDATEDRIVER_UI */
+ NULL /* DIF_RESERVED2 */
+};
+
/***********************************************************************
* SetupDiBuildClassInfoList (SETUPAPI.@)
*/
LONG lError;
DWORD dwGuidListIndex = 0;
- TRACE("\n");
+ TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
+ ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
if (RequiredSize != NULL)
*RequiredSize = 0;
hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
- KEY_ALL_ACCESS,
+ KEY_ENUMERATE_SUB_KEYS,
DIOCR_INSTALLER,
MachineName,
Reserved);
TRACE("RegEnumKeyExW() returns %ld\n", lError);
if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
{
- TRACE("Key name: %p\n", szKeyName);
+ TRACE("Key name: %s\n", debugstr_w(szKeyName));
if (RegOpenKeyExW(hClassesKey,
szKeyName,
0,
- KEY_ALL_ACCESS,
+ KEY_QUERY_VALUE,
&hClassKey))
{
RegCloseKey(hClassesKey);
RegCloseKey(hClassKey);
- TRACE("Guid: %p\n", szKeyName);
+ TRACE("Guid: %s\n", debugstr_w(szKeyName));
if (dwGuidListIndex < ClassGuidListSize)
{
if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
{
szKeyName[37] = 0;
}
- TRACE("Guid: %p\n", &szKeyName[1]);
+ TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
UuidFromStringW(&szKeyName[1],
&ClassGuidList[dwGuidListIndex]);
LONG lError;
DWORD dwGuidListIndex = 0;
+ TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
+ ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
if (RequiredSize != NULL)
*RequiredSize = 0;
TRACE("RegEnumKeyExW() returns %ld\n", lError);
if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
{
- TRACE("Key name: %p\n", szKeyName);
+ TRACE("Key name: %s\n", debugstr_w(szKeyName));
if (RegOpenKeyExW(hClassesKey,
szKeyName,
(LPBYTE)szClassName,
&dwLength))
{
- TRACE("Class name: %p\n", szClassName);
+ TRACE("Class name: %s\n", debugstr_w(szClassName));
if (strcmpiW(szClassName, ClassName) == 0)
{
TRACE("Found matching class name\n");
- TRACE("Guid: %p\n", szKeyName);
+ TRACE("Guid: %s\n", debugstr_w(szKeyName));
if (dwGuidListIndex < ClassGuidListSize)
{
if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
{
szKeyName[37] = 0;
}
- TRACE("Guid: %p\n", &szKeyName[1]);
+ TRACE("Guid: %s\n", debugstr_w(&szKeyName[1]));
UuidFromStringW(&szKeyName[1],
&ClassGuidList[dwGuidListIndex]);
DWORD dwLength;
LONG rc;
+ TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
+ ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
KEY_QUERY_VALUE,
DIOCR_INSTALLER,
LPWSTR MachineNameW = NULL;
HDEVINFO hDevInfo;
- TRACE("%p %p %s %p\n", ClassGuid, hwndParent, MachineName, Reserved);
+ TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
+ debugstr_a(MachineName), Reserved);
if (MachineName)
{
return hDevInfo;
}
+static DWORD
+GetErrorCodeFromCrCode(const IN CONFIGRET cr)
+{
+ switch (cr)
+ {
+ case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
+ case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
+ case CR_SUCCESS: return ERROR_SUCCESS;
+ default:
+ /* FIXME */
+ return ERROR_GEN_FAILURE;
+ }
+
+ /* Does not happen */
+}
+
/***********************************************************************
* SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
*/
PVOID Reserved)
{
struct DeviceInfoSet *list;
+ LPWSTR UNCServerName = NULL;
+ DWORD size;
DWORD rc;
+ //CONFIGRET cr;
+ HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;;
- TRACE("%p %p %S %p\n", ClassGuid, hwndParent, MachineName, Reserved);
+ TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
+ debugstr_w(MachineName), Reserved);
- list = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInfoSet));
+ size = FIELD_OFFSET(struct DeviceInfoSet, szData);
+ if (MachineName)
+ size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
+ list = HeapAlloc(GetProcessHeap(), 0, size);
if (!list)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return (HDEVINFO)INVALID_HANDLE_VALUE;
+ goto cleanup;
}
memset(list, 0, sizeof(struct DeviceInfoSet));
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
- HeapFree(GetProcessHeap(), 0, list);
- return (HDEVINFO)INVALID_HANDLE_VALUE;
+ goto cleanup;
+ }
+ UNCServerName = HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName) + 3) * sizeof(WCHAR));
+ if (!UNCServerName)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
}
+
+ strcpyW(UNCServerName + 2, MachineName);
+ list->szData[0] = list->szData[1] = '\\';
+ strcpyW(list->szData + 2, MachineName);
+ list->MachineName = list->szData;
}
else
{
+ DWORD Size = MAX_PATH;
list->HKLM = HKEY_LOCAL_MACHINE;
+ UNCServerName = HeapAlloc(GetProcessHeap(), 0, (MAX_PATH + 2) * sizeof(WCHAR));
+ if (!UNCServerName)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ if (!GetComputerNameW(UNCServerName + 2, &Size))
+ goto cleanup;
+ list->MachineName = NULL;
}
+#if 0
+ UNCServerName[0] = UNCServerName[1] = '\\';
+ cr = CM_Connect_MachineW(UNCServerName, &list->hMachine);
+ if (cr != CR_SUCCESS)
+ {
+ SetLastError(GetErrorCodeFromCrCode(cr));
+ goto cleanup;
+ }
+#endif
InitializeListHead(&list->DriverListHead);
InitializeListHead(&list->ListHead);
- return (HDEVINFO)list;
+
+ ret = (HDEVINFO)list;
+
+cleanup:
+ if (ret == INVALID_HANDLE_VALUE)
+ {
+ if (list && list->HKLM != 0 && list->HKLM != HKEY_LOCAL_MACHINE)
+ RegCloseKey(list->HKLM);
+ HeapFree(GetProcessHeap(), 0, list);
+ }
+ HeapFree(GetProcessHeap(), 0, UNCServerName);
+ return ret;
}
/***********************************************************************
else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
{
struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
-
+
if (list->magic != SETUP_DEV_INFO_SET_MAGIC)
SetLastError(ERROR_INVALID_HANDLE);
else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
memcpy(&DeviceInfoData->ClassGuid,
&DevInfo->ClassGuid,
sizeof(GUID));
- DeviceInfoData->DevInst = 0; /* FIXME */
- /* Note: this appears to be dangerous, passing a private
- * pointer a heap-allocated datum to the caller. However, the
- * expected lifetime of the device data is the same as the
- * HDEVINFO; once that is closed, the data are no longer valid.
- */
+ DeviceInfoData->DevInst = DevInfo->dnDevInst;
DeviceInfoData->Reserved = (ULONG_PTR)DevInfo;
ret = TRUE;
}
DWORD dwFullLength;
LONG lLineCount = -1;
+ TRACE("%p %s %p %lu %p %p\n", InfHandle, debugstr_w(InfSectionName),
+ InfSectionWithExt, InfSectionWithExtSize, RequiredSize, Extension);
+
lstrcpyW(szBuffer, InfSectionName);
dwLength = lstrlenW(szBuffer);
HKEY hKey;
DWORD dwLength;
+ TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
+ ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
+
hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
- KEY_ALL_ACCESS,
+ KEY_QUERY_VALUE,
DIOCR_INSTALLER,
MachineName,
Reserved);
static BOOL
CreateDeviceInfoElement(
+ IN struct DeviceInfoSet *list,
IN LPCWSTR InstancePath,
IN LPCGUID pClassGuid,
OUT struct DeviceInfoElement **pDeviceInfo)
{
DWORD size;
+ CONFIGRET cr;
struct DeviceInfoElement *deviceInfo;
*pDeviceInfo = NULL;
- size = sizeof(struct DeviceInfoElement) + (wcslen(InstancePath) + 1) * sizeof(WCHAR);
+ size = FIELD_OFFSET(struct DeviceInfoElement, Data) + (wcslen(InstancePath) + 1) * sizeof(WCHAR);
deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
if (!deviceInfo)
{
return FALSE;
}
memset(deviceInfo, 0, size);
+
+ cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
+ if (cr != CR_SUCCESS)
+ {
+ SetLastError(GetErrorCodeFromCrCode(cr));
+ return FALSE;
+ }
+
deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
wcscpy(deviceInfo->Data, InstancePath);
deviceInfo->DeviceName = deviceInfo->Data;
*pDeviceInterface = NULL;
- deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
+ deviceInterface = HeapAlloc(GetProcessHeap(), 0,
+ FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (wcslen(SymbolicLink) + 1) * sizeof(WCHAR));
if (!deviceInterface)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
DWORD i = 0, j;
DWORD dwLength, dwRegType;
DWORD rc;
-
+
/* Enumerate device IDs (subkeys of hEnumeratorKey) */
while (TRUE)
{
if (pClassGuid)
/* Skip this bad entry as we can't verify it */
continue;
+ /* Set a default GUID for this device */
+ memcpy(&KeyGuid, &GUID_NULL, sizeof(GUID));
}
else if (rc != ERROR_SUCCESS)
{
RegCloseKey(hDeviceIdKey);
return ERROR_GEN_FAILURE;
}
-
- KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
- if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
+ else
{
- RegCloseKey(hDeviceIdKey);
- return GetLastError();
+ KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */
+ if (UuidFromStringW(&KeyBuffer[1], &KeyGuid) != RPC_S_OK)
+ /* Bad GUID, skip the entry */
+ continue;
}
+
if (pClassGuid && !IsEqualIID(&KeyGuid, pClassGuid))
{
/* Skip this entry as it is not the right device class */
}
/* Add the entry to the list */
- if (!CreateDeviceInfoElement(InstancePath, &KeyGuid, &deviceInfo))
+ if (!CreateDeviceInfoElement(list, InstancePath, &KeyGuid, &deviceInfo))
{
RegCloseKey(hDeviceIdKey);
return GetLastError();
return rc;
/* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
- * Else, enumerate all enumerators all call SETUP_CreateDevListFromEnumerator
+ * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
* for each one.
*/
if (Enumerator)
struct DeviceInterface *interfaceInfo;
TRACE("Adding %s to list\n", debugstr_w(ptr));
/* Step 1. Create a device info element */
- if (!CreateDeviceInfoElement(ptr, &GUID_SERENUM_BUS_ENUMERATOR, &deviceInfo))
+ if (!CreateDeviceInfoElement(list, ptr, &GUID_SERENUM_BUS_ENUMERATOR, &deviceInfo))
{
if (devices != buf)
HeapFree(GetProcessHeap(), 0, devices);
RegCloseKey(hDeviceInstanceKey);
continue;
}
-
+
/* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
j = 0;
while (TRUE)
/* We have found a device */
/* Step 1. Create a device info element */
- if (!CreateDeviceInfoElement(InstancePath, &ClassGuid, &deviceInfo))
+ if (!CreateDeviceInfoElement(list, InstancePath, &ClassGuid, &deviceInfo))
{
RegCloseKey(hReferenceKey);
RegCloseKey(hDeviceInstanceKey);
}
}
+/***********************************************************************
+ * SetupDiGetClassImageIndex (SETUPAPI.@)
+ */
+
+static BOOL GetIconIndex(
+ IN HKEY hClassKey,
+ OUT PINT ImageIndex)
+{
+ LPWSTR Buffer = NULL;
+ DWORD dwRegType, dwLength;
+ LONG rc;
+ BOOL ret = FALSE;
+
+ /* Read "Icon" registry key */
+ rc = RegQueryValueExW(hClassKey, L"Icon", NULL, &dwRegType, NULL, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ } else if (dwRegType != REG_SZ)
+ {
+ SetLastError(ERROR_INVALID_INDEX);
+ goto cleanup;
+ }
+ Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+ if (!Buffer)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hClassKey, L"Icon", NULL, NULL, (LPBYTE)Buffer, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ /* make sure the returned buffer is NULL-terminated */
+ Buffer[dwLength / sizeof(WCHAR)] = 0;
+
+ /* Transform "Icon" value to a INT */
+ *ImageIndex = atoiW(Buffer);
+ ret = TRUE;
+
+cleanup:
+ MyFree(Buffer);
+ return ret;
+}
+
+BOOL WINAPI SetupDiGetClassImageIndex(
+ IN PSP_CLASSIMAGELIST_DATA ClassImageListData,
+ IN CONST GUID *ClassGuid,
+ OUT PINT ImageIndex)
+{
+ struct ClassImageList *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %s %p\n", ClassImageListData, debugstr_guid(ClassGuid), ImageIndex);
+
+ if (!ClassImageListData || !ClassGuid || !ImageIndex)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if ((list = (struct ClassImageList *)ClassImageListData->Reserved) == NULL)
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (list->magic != SETUP_CLASS_IMAGE_LIST_MAGIC)
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (!ImageIndex)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ INT iconIndex;
+
+ /* Read Icon registry entry into Buffer */
+ hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INTERFACE, list->MachineName, NULL);
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+ if (!GetIconIndex(hKey, &iconIndex))
+ goto cleanup;
+
+ if (iconIndex >= 0)
+ {
+ SetLastError(ERROR_INVALID_INDEX);
+ goto cleanup;
+ }
+
+ *ImageIndex = -iconIndex;
+ ret = TRUE;
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetClassImageList(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassImageList(
+ OUT PSP_CLASSIMAGELIST_DATA ClassImageListData)
+{
+ return SetupDiGetClassImageListExW(ClassImageListData, NULL, NULL);
+}
+
+/***********************************************************************
+ * SetupDiGetClassImageListExA(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassImageListExA(
+ OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
+ IN PCSTR MachineName OPTIONAL,
+ IN PVOID Reserved)
+{
+ PWSTR MachineNameW = NULL;
+ BOOL ret;
+
+ if (MachineName)
+ {
+ MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
+ if (MachineNameW == NULL)
+ return FALSE;
+ }
+
+ ret = SetupDiGetClassImageListExW(ClassImageListData, MachineNameW, Reserved);
+
+ if (MachineNameW)
+ MyFree(MachineNameW);
+
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetClassImageListExW(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassImageListExW(
+ OUT PSP_CLASSIMAGELIST_DATA ClassImageListData,
+ IN PCWSTR MachineName OPTIONAL,
+ IN PVOID Reserved)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p\n", ClassImageListData, debugstr_w(MachineName), Reserved);
+
+ if (!ClassImageListData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (ClassImageListData->cbSize != sizeof(SP_CLASSIMAGELIST_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (Reserved)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ struct ClassImageList *list = NULL;
+ DWORD size;
+
+ size = FIELD_OFFSET(struct ClassImageList, szData);
+ if (MachineName)
+ size += (wcslen(MachineName) + 3) * sizeof(WCHAR);
+ list = HeapAlloc(GetProcessHeap(), 0, size);
+ if (!list)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ list->magic = SETUP_CLASS_IMAGE_LIST_MAGIC;
+ if (MachineName)
+ {
+ list->szData[0] = list->szData[1] = '\\';
+ strcpyW(list->szData + 2, MachineName);
+ list->MachineName = list->szData;
+ }
+ else
+ {
+ list->MachineName = NULL;
+ }
+
+ ClassImageListData->Reserved = (DWORD)list; /* FIXME: 64 bit portability issue */
+ ret = TRUE;
+
+cleanup:
+ if (!ret)
+ MyFree(list);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiLoadClassIcon(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiLoadClassIcon(
+ IN CONST GUID *ClassGuid,
+ OUT HICON *LargeIcon OPTIONAL,
+ OUT PINT MiniIconIndex OPTIONAL)
+{
+ BOOL ret = FALSE;
+
+ if (!ClassGuid)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ LPWSTR Buffer = NULL;
+ LPCWSTR DllName;
+ INT iconIndex;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+
+ hKey = SetupDiOpenClassRegKey(ClassGuid, KEY_QUERY_VALUE);
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ if (!GetIconIndex(hKey, &iconIndex))
+ goto cleanup;
+
+ if (iconIndex > 0)
+ {
+ /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
+ PWCHAR Comma;
+ LONG rc;
+ DWORD dwRegType, dwLength;
+ rc = RegQueryValueExW(hKey, L"Installer32", NULL, &dwRegType, NULL, &dwLength);
+ if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
+ {
+ Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+ if (Buffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hKey, L"Installer32", NULL, NULL, (LPBYTE)Buffer, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ /* make sure the returned buffer is NULL-terminated */
+ Buffer[dwLength / sizeof(WCHAR)] = 0;
+ }
+ else if
+ (ERROR_SUCCESS == (rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, &dwRegType, NULL, &dwLength))
+ && dwRegType == REG_SZ)
+ {
+ Buffer = MyMalloc(dwLength + sizeof(WCHAR));
+ if (Buffer == NULL)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, NULL, (LPBYTE)Buffer, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ /* make sure the returned buffer is NULL-terminated */
+ Buffer[dwLength / sizeof(WCHAR)] = 0;
+ }
+ else
+ {
+ /* Unable to find where to load the icon */
+ SetLastError(ERROR_FILE_NOT_FOUND);
+ goto cleanup;
+ }
+ Comma = strchrW(Buffer, ',');
+ if (!Comma)
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ *Comma = '\0';
+ DllName = Buffer;
+ }
+ else
+ {
+ /* Look up icon in setupapi.dll */
+ DllName = L"setupapi.dll";
+ iconIndex = -iconIndex;
+ }
+
+ TRACE("Icon index %d, dll name %s\n", iconIndex, debugstr_w(DllName));
+ if (LargeIcon)
+ {
+ if (1 != ExtractIconEx(DllName, iconIndex, LargeIcon, NULL, 1))
+ {
+ SetLastError(ERROR_INVALID_INDEX);
+ goto cleanup;
+ }
+ }
+ if (MiniIconIndex)
+ *MiniIconIndex = iconIndex;
+ ret = TRUE;
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+ MyFree(Buffer);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
/***********************************************************************
* SetupDiEnumDeviceInterfaces (SETUPAPI.@)
*/
&DevItf->InterfaceClassGuid,
sizeof(GUID));
DeviceInterfaceData->Flags = 0; /* FIXME */
- /* Note: this appears to be dangerous, passing a private
- * pointer a heap-allocated datum to the caller. However, the
- * expected lifetime of the device data is the same as the
- * HDEVINFO; once that is closed, the data are no longer valid.
- */
DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
Found = TRUE;
}
return TRUE;
}
+static BOOL DestroyClassInstallParams(struct ClassInstallParams* installParams)
+{
+ HeapFree(GetProcessHeap(), 0, installParams->PropChange);
+ return TRUE;
+}
+
static BOOL DestroyDeviceInfoElement(struct DeviceInfoElement* deviceInfo)
{
PLIST_ENTRY ListEntry;
ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
HeapFree(GetProcessHeap(), 0, ListEntry);
}
+ DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
HeapFree(GetProcessHeap(), 0, deviceInfo);
return TRUE;
}
}
if (list->HKLM != HKEY_LOCAL_MACHINE)
RegCloseKey(list->HKLM);
+ CM_Disconnect_Machine(list->hMachine);
+ DestroyClassInstallParams(&list->ClassInstallParams);
HeapFree(GetProcessHeap(), 0, list);
return TRUE;
}
DWORD sizeW = 0, sizeA;
BOOL ret = FALSE;
- TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
+ TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
DeviceInterfaceData, DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
{
BOOL ret = FALSE;
- TRACE("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet,
+ TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
DeviceInterfaceData, DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
memcpy(&DeviceInfoData->ClassGuid,
&deviceInterface->DeviceInfo->ClassGuid,
sizeof(GUID));
- DeviceInfoData->DevInst = 0; /* FIXME */
- /* Note: this appears to be dangerous, passing a private
- * pointer a heap-allocated datum to the caller. However, the
- * expected lifetime of the device data is the same as the
- * HDEVINFO; once that is closed, the data are no longer valid.
- */
+ DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
}
ret = TRUE;
{
LPCWSTR RegistryPropertyName;
DWORD BufferSize;
-
+
switch (Property)
{
case SPDRP_CAPABILITIES:
default:
{
- FIXME("Property 0x%lx not implemented\n", Property);
+ ERR("Property 0x%lx not implemented\n", Property);
SetLastError(ERROR_NOT_SUPPORTED);
}
}
SetLastError(ERROR_INVALID_HANDLE);
else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
SetLastError(ERROR_INVALID_HANDLE);
- else if (DeviceInfoData)
+ else if (!DeviceInfoData)
SetLastError(ERROR_INVALID_HANDLE);
else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
default:
{
- FIXME("Property 0x%lx not implemented\n", Property);
+ ERR("Property 0x%lx not implemented\n", Property);
SetLastError(ERROR_NOT_SUPPORTED);
}
}
0,
NULL,
REG_OPTION_NON_VOLATILE,
- KEY_ALL_ACCESS,
+ KEY_SET_VALUE,
NULL,
&hClassKey,
NULL))
BOOL bFileQueueCreated = FALSE;
HKEY hClassKey;
+ TRACE("%p %s 0x%lx %p\n", hwndParent, debugstr_w(InfFileName),
+ Flags, FileQueue);
+
FIXME("not fully implemented\n");
if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
INVALID_HANDLE_VALUE,
NULL);
- /* FIXME: More code! */
+ /* FIXME: Process InterfaceInstall32 section */
if (bFileQueueCreated)
SetupCloseFileQueue(FileQueue);
* SetupDiOpenClassRegKeyExA (SETUPAPI.@)
*/
HKEY WINAPI SetupDiOpenClassRegKeyExA(
- const GUID* ClassGuid,
+ const GUID* ClassGuid OPTIONAL,
REGSAM samDesired,
DWORD Flags,
- PCSTR MachineName,
+ PCSTR MachineName OPTIONAL,
PVOID Reserved)
{
PWSTR MachineNameW = NULL;
* SetupDiOpenClassRegKeyExW (SETUPAPI.@)
*/
HKEY WINAPI SetupDiOpenClassRegKeyExW(
- const GUID* ClassGuid,
+ const GUID* ClassGuid OPTIONAL,
REGSAM samDesired,
DWORD Flags,
- PCWSTR MachineName,
+ PCWSTR MachineName OPTIONAL,
PVOID Reserved)
{
LPWSTR lpGuidString;
DWORD rc;
LPCWSTR lpKeyName;
+ TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
+ Flags, debugstr_w(MachineName), Reserved);
+
if (Flags == DIOCR_INSTALLER)
{
lpKeyName = ControlClass;
else
{
ERR("Invalid Flags parameter!\n");
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetLastError(ERROR_INVALID_FLAGS);
return INVALID_HANDLE_VALUE;
}
rc = RegOpenKeyExW(HKLM,
lpKeyName,
0,
- KEY_ALL_ACCESS,
+ ClassGuid ? KEY_ENUMERATE_SUB_KEYS : samDesired,
&hClassesKey);
if (MachineName != NULL) RegCloseKey(HKLM);
if (rc != ERROR_SUCCESS)
rc = RegOpenKeyExW(hClassesKey,
lpFullGuidString,
0,
- KEY_ALL_ACCESS,
+ samDesired,
&hClassKey);
if (rc != ERROR_SUCCESS)
{
return FALSE;
}
-static DWORD
+/***********************************************************************
+ * SetupDiSetClassInstallParamsW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiSetClassInstallParamsW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p %lu\n", DeviceInfoSet, DeviceInfoData,
+ ClassInstallParams, ClassInstallParamsSize);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (ClassInstallParams && ClassInstallParams->cbSize != sizeof(SP_CLASSINSTALL_HEADER))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (ClassInstallParams && ClassInstallParamsSize < sizeof(SP_CLASSINSTALL_HEADER))
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (!ClassInstallParams && ClassInstallParamsSize != 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ SP_DEVINSTALL_PARAMS_W InstallParams;
+ BOOL Result;
+
+ InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS);
+ Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ if (!Result)
+ goto done;
+
+ if (ClassInstallParams)
+ {
+ /* Check parameters in ClassInstallParams */
+ if (ClassInstallParams->InstallFunction < DIF_SELECTDEVICE
+ || ClassInstallParams->InstallFunction - DIF_SELECTDEVICE >= sizeof(UpdateClassInstallParamHandlers)/sizeof(UpdateClassInstallParamHandlers[0]))
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ goto done;
+ }
+ else if (UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE] == NULL)
+ {
+ FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams->InstallFunction);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ goto done;
+ }
+ ret = UpdateClassInstallParamHandlers[ClassInstallParams->InstallFunction - DIF_SELECTDEVICE](DeviceInfoSet, DeviceInfoData, ClassInstallParams, ClassInstallParamsSize);
+ if (!ret)
+ goto done;
+ InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
+ }
+ else
+ {
+ InstallParams.Flags &= ~DI_CLASSINSTALLPARAMS;
+ }
+
+ ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
+ }
+
+done:
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+static BOOL PropertyChangeHandler(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL,
+ IN DWORD ClassInstallParamsSize)
+{
+ PSP_PROPCHANGE_PARAMS PropChangeParams = (PSP_PROPCHANGE_PARAMS)ClassInstallParams;
+ BOOL ret = FALSE;
+
+ if (!DeviceInfoData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (ClassInstallParamsSize != sizeof(SP_PROPCHANGE_PARAMS))
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (PropChangeParams && PropChangeParams->StateChange != DICS_ENABLE
+ && PropChangeParams->StateChange != DICS_DISABLE && PropChangeParams->StateChange != DICS_PROPCHANGE
+ && PropChangeParams->StateChange != DICS_START && PropChangeParams->StateChange != DICS_STOP)
+ SetLastError(ERROR_INVALID_FLAGS);
+ else if (PropChangeParams && PropChangeParams->Scope != DICS_FLAG_GLOBAL
+ && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
+ SetLastError(ERROR_INVALID_FLAGS);
+ else if (PropChangeParams
+ && (PropChangeParams->StateChange == DICS_START || PropChangeParams->StateChange == DICS_STOP)
+ && PropChangeParams->Scope != DICS_FLAG_CONFIGSPECIFIC)
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ PSP_PROPCHANGE_PARAMS *CurrentPropChangeParams;
+ if (!DeviceInfoData)
+ {
+ struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
+ CurrentPropChangeParams = &list->ClassInstallParams.PropChange;
+ }
+ else
+ {
+ struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ CurrentPropChangeParams = &deviceInfo->ClassInstallParams.PropChange;
+ }
+ if (*CurrentPropChangeParams)
+ {
+ MyFree(*CurrentPropChangeParams);
+ *CurrentPropChangeParams = NULL;
+ }
+ if (PropChangeParams)
+ {
+ *CurrentPropChangeParams = MyMalloc(sizeof(SP_PROPCHANGE_PARAMS));
+ if (!*CurrentPropChangeParams)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto done;
+ }
+ memcpy(*CurrentPropChangeParams, PropChangeParams, sizeof(SP_PROPCHANGE_PARAMS));
+ }
+ ret = TRUE;
+ }
+
+done:
+ return ret;
+}
+
+static DWORD
GetFunctionPointer(
IN PWSTR InstallerName,
OUT HMODULE* ModulePointer,
{
BOOL ret = FALSE;
- TRACE("%ld %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
+ TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
if (!DeviceInfoSet)
SetLastError(ERROR_INVALID_PARAMETER);
case DIF_NEWDEVICEWIZARD_PREANALYZE:
CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
break;
+ case DIF_PROPERTYCHANGE:
+ CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
+ DefaultHandler = SetupDiChangeState;
+ break;
case DIF_REGISTER_COINSTALLERS:
CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
DefaultHandler = SetupDiRegisterCoDeviceInstallers;
DefaultHandler = SetupDiSelectBestCompatDrv;
break;
default:
- FIXME("Install function %ld not implemented\n", InstallFunction);
- SetLastError(ERROR_INVALID_PARAMETER);
+ ERR("Install function %u not supported\n", InstallFunction);
+ SetLastError(ERROR_NOT_SUPPORTED);
}
InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
return ret;
}
+/***********************************************************************
+ * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
+ IN HDEVINFO DeviceInfoSet,
+ OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoListDetailData);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!DeviceInfoListDetailData)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoListDetailData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else
+ {
+ memcpy(
+ &DeviceInfoListDetailData->ClassGuid,
+ &list->ClassGuid,
+ sizeof(GUID));
+ DeviceInfoListDetailData->RemoteMachineHandle = list->hMachine;
+ if (list->MachineName)
+ strcpyW(DeviceInfoListDetailData->RemoteMachineName, list->MachineName + 2);
+ else
+ DeviceInfoListDetailData->RemoteMachineName[0] = 0;
+
+ ret = TRUE;
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
/***********************************************************************
* SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
*/
return ret;
}
+/***********************************************************************
+ * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInstanceIdA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ OUT PSTR DeviceInstanceId OPTIONAL,
+ IN DWORD DeviceInstanceIdSize,
+ OUT PDWORD RequiredSize OPTIONAL)
+{
+ PWSTR DeviceInstanceIdW = NULL;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
+ DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
+
+ if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ if (DeviceInstanceIdSize != 0)
+ {
+ DeviceInstanceIdW = MyMalloc(DeviceInstanceIdSize * sizeof(WCHAR));
+ if (DeviceInstanceIdW == NULL)
+ return FALSE;
+ }
+
+ ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet, DeviceInfoData,
+ DeviceInstanceIdW, DeviceInstanceIdSize,
+ RequiredSize);
+
+ if (ret && DeviceInstanceIdW != NULL)
+ {
+ if (WideCharToMultiByte(CP_ACP, 0, DeviceInstanceIdW, -1,
+ DeviceInstanceId, DeviceInstanceIdSize, NULL, NULL) == 0)
+ {
+ DeviceInstanceId[0] = '\0';
+ ret = FALSE;
+ }
+ }
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInstanceIdW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData,
+ OUT PWSTR DeviceInstanceId OPTIONAL,
+ IN DWORD DeviceInstanceIdSize,
+ OUT PDWORD RequiredSize OPTIONAL)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p %lu %p\n", DeviceInfoSet, DeviceInfoData,
+ DeviceInstanceId, DeviceInstanceIdSize, RequiredSize);
+
+ if (!DeviceInfoSet)
+ 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 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInstanceId && DeviceInstanceIdSize == 0)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ struct DeviceInfoElement *DevInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+ DWORD required;
+
+ required = (wcslen(DevInfo->DeviceName) + 1) * sizeof(WCHAR);
+ if (RequiredSize)
+ *RequiredSize = required;
+
+ if (required <= DeviceInstanceIdSize)
+ {
+ wcscpy(DeviceInstanceId, DevInfo->DeviceName);
+ ret = TRUE;
+ }
+ else
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDevPropertySheetsA(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN LPPROPSHEETHEADERA PropertySheetHeader,
+ IN DWORD PropertySheetHeaderPageListSize,
+ OUT PDWORD RequiredSize OPTIONAL,
+ IN DWORD PropertySheetType)
+{
+ PROPSHEETHEADERW psh;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
+ PropertySheetHeader, PropertySheetHeaderPageListSize,
+ RequiredSize, PropertySheetType);
+
+ psh.dwFlags = PropertySheetHeader->dwFlags;
+ psh.phpage = PropertySheetHeader->phpage;
+ psh.nPages = PropertySheetHeader->nPages;
+
+ ret = SetupDiGetClassDevPropertySheetsW(DeviceInfoSet, DeviceInfoData, PropertySheetHeader ? &psh : NULL,
+ PropertySheetHeaderPageListSize, RequiredSize,
+ PropertySheetType);
+ if (ret)
+ {
+ PropertySheetHeader->nPages = psh.nPages;
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
+struct ClassDevPropertySheetsData
+{
+ HPROPSHEETPAGE *PropertySheetPages;
+ DWORD MaximumNumberOfPages;
+ DWORD NumberOfPages;
+};
+
+static BOOL WINAPI GetClassDevPropertySheetsCallback(
+ IN HPROPSHEETPAGE hPropSheetPage,
+ IN OUT LPARAM lParam)
+{
+ struct ClassDevPropertySheetsData *PropPageData;
+
+ PropPageData = (struct ClassDevPropertySheetsData *)lParam;
+
+ if (PropPageData->NumberOfPages < PropPageData->MaximumNumberOfPages)
+ {
+ *PropPageData->PropertySheetPages = hPropSheetPage;
+ PropPageData->PropertySheetPages++;
+ }
+
+ PropPageData->NumberOfPages++;
+ return TRUE;
+}
+
+/***********************************************************************
+ * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetClassDevPropertySheetsW(
+ IN HDEVINFO DeviceInfoSet,
+ IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
+ IN OUT LPPROPSHEETHEADERW PropertySheetHeader,
+ IN DWORD PropertySheetHeaderPageListSize,
+ OUT PDWORD RequiredSize OPTIONAL,
+ IN DWORD PropertySheetType)
+{
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
+ PropertySheetHeader, PropertySheetHeaderPageListSize,
+ RequiredSize, PropertySheetType);
+
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (!PropertySheetHeader)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (PropertySheetHeader->dwFlags & PSH_PROPSHEETPAGE)
+ SetLastError(ERROR_INVALID_FLAGS);
+ else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (!DeviceInfoData && IsEqualIID(&list->ClassGuid, &GUID_NULL))
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (!PropertySheetHeader)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (PropertySheetType != DIGCDP_FLAG_ADVANCED
+ && PropertySheetType != DIGCDP_FLAG_BASIC
+ && PropertySheetType != DIGCDP_FLAG_REMOTE_ADVANCED
+ && PropertySheetType != DIGCDP_FLAG_REMOTE_BASIC)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ SP_PROPSHEETPAGE_REQUEST Request;
+ LPWSTR PropPageProvider = NULL;
+ HMODULE hModule = NULL;
+ PROPERTY_PAGE_PROVIDER pPropPageProvider = NULL;
+ struct ClassDevPropertySheetsData PropPageData;
+ DWORD dwLength, dwRegType;
+ DWORD rc;
+
+ if (DeviceInfoData)
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
+ else
+ {
+ hKey = SetupDiOpenClassRegKeyExW(&list->ClassGuid, KEY_QUERY_VALUE,
+ DIOCR_INSTALLER, list->MachineName + 2, NULL);
+ }
+ if (hKey == INVALID_HANDLE_VALUE)
+ goto cleanup;
+
+ rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, &dwRegType, NULL, &dwLength);
+ if (rc == ERROR_FILE_NOT_FOUND)
+ {
+ /* No registry key. As it is optional, don't say it's a bad error */
+ if (RequiredSize)
+ *RequiredSize = 0;
+ ret = TRUE;
+ goto cleanup;
+ }
+ else if (rc != ERROR_SUCCESS && dwRegType != REG_SZ)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+
+ PropPageProvider = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR));
+ if (!PropPageProvider)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hKey, L"EnumPropPages32", NULL, NULL, (LPBYTE)PropPageProvider, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ PropPageProvider[dwLength / sizeof(WCHAR)] = 0;
+
+ rc = GetFunctionPointer(PropPageProvider, &hModule, (PVOID*)&pPropPageProvider);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER);
+ goto cleanup;
+ }
+
+ Request.cbSize = sizeof(SP_PROPSHEETPAGE_REQUEST);
+ Request.PageRequested = SPPSR_ENUM_ADV_DEVICE_PROPERTIES;
+ Request.DeviceInfoSet = DeviceInfoSet;
+ Request.DeviceInfoData = DeviceInfoData;
+ PropPageData.PropertySheetPages = &PropertySheetHeader->phpage[PropertySheetHeader->nPages];
+ PropPageData.MaximumNumberOfPages = PropertySheetHeaderPageListSize - PropertySheetHeader->nPages;
+ PropPageData.NumberOfPages = 0;
+ ret = pPropPageProvider(&Request, GetClassDevPropertySheetsCallback, (LPARAM)&PropPageData);
+ if (!ret)
+ goto cleanup;
+
+ if (RequiredSize)
+ *RequiredSize = PropPageData.NumberOfPages + PropertySheetHeader->nPages;
+ if (PropPageData.NumberOfPages <= PropPageData.MaximumNumberOfPages)
+ {
+ PropertySheetHeader->nPages += PropPageData.NumberOfPages;
+ ret = TRUE;
+ }
+ else
+ {
+ PropertySheetHeader->nPages += PropPageData.MaximumNumberOfPages;
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ }
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+ HeapFree(GetProcessHeap(), 0, PropPageProvider);
+ FreeFunctionPointer(hModule, pPropPageProvider);
+ }
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
/***********************************************************************
* SetupDiCreateDevRegKeyA (SETUPAPI.@)
*/
LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
DWORD Index; /* Index used in the DriverKey name */
DWORD rc;
+ HKEY hHWProfilesKey = INVALID_HANDLE_VALUE;
+ HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
+ HKEY hEnumKey = INVALID_HANDLE_VALUE;
HKEY hClassKey = INVALID_HANDLE_VALUE;
HKEY hDeviceKey = INVALID_HANDLE_VALUE;
HKEY hKey = INVALID_HANDLE_VALUE;
+ HKEY RootKey;
- if (Scope == DICS_FLAG_CONFIGSPECIFIC)
+ if (Scope == DICS_FLAG_GLOBAL)
+ RootKey = list->HKLM;
+ else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
{
- FIXME("DICS_FLAG_CONFIGSPECIFIC case unimplemented\n");
- goto cleanup;
+ rc = RegOpenKeyExW(list->HKLM,
+ L"SYSTEM\\CurrentControlSet\\Hardware Profiles",
+ 0,
+ 0,
+ &hHWProfilesKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ if (HwProfile == 0)
+ {
+ rc = RegOpenKeyExW(
+ hHWProfilesKey,
+ REGSTR_KEY_CURRENT,
+ 0,
+ KEY_CREATE_SUB_KEY,
+ &hHWProfileKey);
+ }
+ else
+ {
+ WCHAR subKey[5];
+ snprintfW(subKey, 4, L"%04lu", HwProfile);
+ subKey[4] = '\0';
+ rc = RegOpenKeyExW(
+ hHWProfilesKey,
+ subKey,
+ 0,
+ KEY_CREATE_SUB_KEY,
+ &hHWProfileKey);
+ }
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ RootKey = hHWProfileKey;
}
if (KeyType == DIREG_DEV)
{
- FIXME("DIREG_DEV case unimplemented\n");
+ struct DeviceInfoElement *deviceInfo = (struct DeviceInfoElement *)DeviceInfoData->Reserved;
+
+ rc = RegCreateKeyExW(
+ RootKey,
+ EnumKeyName,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ KEY_CREATE_SUB_KEY,
+ NULL,
+ &hEnumKey,
+ NULL);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ rc = RegCreateKeyExW(
+ hEnumKey,
+ deviceInfo->DeviceName,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+#if _WIN32_WINNT >= 0x502
+ KEY_READ | KEY_WRITE,
+#else
+ KEY_ALL_ACCESS,
+#endif
+ NULL,
+ &hKey,
+ NULL);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
}
else /* KeyType == DIREG_DRV */
{
if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
goto cleanup;
- /* The driver key is in HKLM\System\CurrentControlSet\Control\Class\{GUID}\Index */
+ /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
DriverKey = HeapAlloc(GetProcessHeap(), 0, (wcslen(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_STRING));
if (!DriverKey)
{
wcscat(DriverKey, lpGuidString);
wcscat(DriverKey, L"}\\");
pDeviceInstance = &DriverKey[wcslen(DriverKey)];
- rc = RegOpenKeyExW(list->HKLM,
+ rc = RegOpenKeyExW(RootKey,
ControlClass,
0,
KEY_CREATE_SUB_KEY,
if (lpGuidString)
RpcStringFreeW(&lpGuidString);
HeapFree(GetProcessHeap(), 0, DriverKey);
+ if (hHWProfilesKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hHWProfilesKey);
+ if (hHWProfileKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hHWProfileKey);
+ if (hEnumKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hEnumKey);
if (hClassKey != INVALID_HANDLE_VALUE)
RegCloseKey(hClassKey);
if (hDeviceKey != INVALID_HANDLE_VALUE)
else if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
{
TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetLastError(ERROR_INVALID_FLAGS);
}
else
{
if (CreationFlags & DICD_GENERATE_ID)
{
/* Generate a new unique ID for this device */
- SetLastError(ERROR_GEN_FAILURE);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
FIXME("not implemented\n");
}
else
{
struct DeviceInfoElement *deviceInfo;
- /* FIXME: ClassGuid can be NULL */
- if (CreateDeviceInfoElement(DeviceName, ClassGuid, &deviceInfo))
+ if (CreateDeviceInfoElement(list, DeviceName, ClassGuid, &deviceInfo))
{
InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
else
{
memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
- DeviceInfoData->DevInst = 0; /* FIXME */
+ DeviceInfoData->DevInst = deviceInfo->dnDevInst;
DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
ret = TRUE;
}
driverInfo->Details.DrvDescription, InfFile, InfInstallSection, Rank);
driverInfo->DriverRank = Rank;
+ memcpy(&driverInfo->DriverDate, &DriverDate, sizeof(FILETIME));
memcpy(&driverInfo->ClassGuid, ClassGuid, sizeof(GUID));
driverInfo->Info.DriverType = DriverType;
driverInfo->Info.Reserved = (ULONG_PTR)driverInfo;
PreviousEntry = DriverListHead->Flink;
while (PreviousEntry != DriverListHead)
{
- if (((struct DriverInfoElement *)PreviousEntry)->DriverRank >= Rank)
+ struct DriverInfoElement *CurrentDriver;
+ CurrentDriver = CONTAINING_RECORD(PreviousEntry, struct DriverInfoElement, ListEntry);
+ if (CurrentDriver->DriverRank > Rank ||
+ (CurrentDriver->DriverRank == Rank && CurrentDriver->DriverDate.QuadPart > driverInfo->DriverDate.QuadPart))
{
/* Insert before the current item */
InsertHeadList(PreviousEntry, &driverInfo->ListEntry);
}
/* Get driver version. Invalid version = 0.0.0.0 */
*DriverVersion = 0;
- /* FIXME: use pVersion to fill DriverVersion variable */
+ if (pVersion)
+ {
+ WORD Major, Minor = 0, Revision = 0, Build = 0;
+ LPWSTR pMinor = NULL, pRevision = NULL, pBuild = NULL;
+ LARGE_INTEGER fullVersion;
+
+ pMinor = strchrW(pVersion, '.');
+ if (pMinor)
+ {
+ *pMinor = 0;
+ pRevision = strchrW(++pMinor, '.');
+ Minor = atoiW(pMinor);
+ }
+ if (pRevision)
+ {
+ *pRevision = 0;
+ pBuild = strchrW(++pRevision, '.');
+ Revision = atoiW(pRevision);
+ }
+ if (pBuild)
+ {
+ *pBuild = 0;
+ pBuild++;
+ Build = atoiW(pBuild);
+ }
+ Major = atoiW(pVersion);
+ fullVersion.u.HighPart = Major << 16 | Minor;
+ fullVersion.u.LowPart = Revision << 16 | Build;
+ memcpy(DriverVersion, &fullVersion, sizeof(LARGE_INTEGER));
+ }
ret = TRUE;
HeapFree(GetProcessHeap(), 0, ProviderName);
HeapFree(GetProcessHeap(), 0, DriverVer);
- TRACE("Returning %d\n", ret);
return ret;
}
DriverAlreadyAdded = FALSE;
for (DriverRank = 0, currentId = (LPCWSTR)HardwareIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
{
- if (wcscmp(DeviceId, currentId) == 0)
+ if (wcsicmp(DeviceId, currentId) == 0)
{
AddDriverToList(
&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
{
for (DriverRank = 0, currentId = (LPCWSTR)CompatibleIDs; !DriverAlreadyAdded && *currentId; currentId += wcslen(currentId) + 1, DriverRank++)
{
- if (wcscmp(DeviceId, currentId) == 0)
+ if (wcsicmp(DeviceId, currentId) == 0)
{
AddDriverToList(
&((struct DeviceInfoElement *)DeviceInfoData->Reserved)->DriverListHead,
TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
FIXME("not implemented\n");
- SetLastError(ERROR_GEN_FAILURE);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
{
TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetLastError(ERROR_INVALID_FLAGS);
}
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
SetLastError(ERROR_INVALID_USER_BUFFER);
RegCloseKey(hEnumKey);
if (rc != ERROR_SUCCESS)
{
+ if (rc == ERROR_FILE_NOT_FOUND)
+ rc = ERROR_NO_SUCH_DEVINST;
SetLastError(rc);
return FALSE;
}
- /* FIXME: GUID_NULL is not allowed */
- if (!CreateDeviceInfoElement(DeviceInstanceId, &GUID_NULL /* FIXME */, &deviceInfo))
+ /* FIXME: try to get ClassGUID from registry, instead of
+ * sending GUID_NULL to CreateDeviceInfoElement
+ */
+ if (!CreateDeviceInfoElement(list, DeviceInstanceId, &GUID_NULL, &deviceInfo))
{
RegCloseKey(hKey);
return FALSE;
if (ret && deviceInfo && DeviceInfoData)
{
memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
- DeviceInfoData->DevInst = 0; /* FIXME */
+ DeviceInfoData->DevInst = deviceInfo->dnDevInst;
DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
}
}
DWORD BufSize = 0;
DWORD HardwareIDLen = 0;
BOOL ret = FALSE;
-
+
/* do some sanity checks, the unicode version might do more thorough checks */
if (DriverInfoData == NULL ||
(DriverInfoDetailData == NULL && DriverInfoDetailDataSize != 0) ||
}
DriverInfoDataW.DriverType = DriverInfoData->DriverType;
DriverInfoDataW.Reserved = DriverInfoData->Reserved;
-
+
/* convert the strings to unicode */
if (MultiByteToWideChar(CP_ACP,
0,
}
}
}
-
+
Cleanup:
if (DriverInfoDetailDataW != NULL)
{
return ret;
}
+/* Return the current hardware profile id, or -1 if error */
+static DWORD
+GetCurrentHwProfile(
+ IN HDEVINFO DeviceInfoSet)
+{
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ DWORD dwRegType, dwLength;
+ DWORD hwProfile;
+ LONG rc;
+ DWORD ret = (DWORD)-1;
+
+ rc = RegOpenKeyExW(
+ ((struct DeviceInfoSet *)DeviceInfoSet)->HKLM,
+ REGSTR_PATH_IDCONFIGDB,
+ 0, /* Options */
+ KEY_QUERY_VALUE,
+ &hKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+
+ dwLength = sizeof(DWORD);
+ rc = RegQueryValueExW(
+ hKey,
+ REGSTR_VAL_CURRENTCONFIG,
+ NULL,
+ &dwRegType,
+ (LPBYTE)&hwProfile, &dwLength);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+
+ ret = hwProfile;
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+
+ return hwProfile;
+}
+
+/***********************************************************************
+ * SetupDiChangeState (SETUPAPI.@)
+ */
+static BOOL StartDevice(VOID) { FIXME("Stub"); return TRUE; }
+static BOOL StopDevice(VOID) { FIXME("Stub"); return TRUE; }
+BOOL WINAPI
+SetupDiChangeState(
+ IN HDEVINFO DeviceInfoSet,
+ IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+{
+ PSP_PROPCHANGE_PARAMS PropChange;
+ HKEY hKey = INVALID_HANDLE_VALUE;
+ LPCWSTR RegistryValueName;
+ DWORD dwConfigFlags, dwLength, dwRegType;
+ LONG rc;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
+
+ if (!DeviceInfoData)
+ PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChange;
+ else
+ PropChange = ((struct DeviceInfoElement *)DeviceInfoData->Reserved)->ClassInstallParams.PropChange;
+ if (!PropChange)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ goto cleanup;
+ }
+
+ if (PropChange->Scope == DICS_FLAG_GLOBAL)
+ RegistryValueName = REGSTR_VAL_CONFIGFLAGS;
+ else
+ RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS;
+
+ switch (PropChange->StateChange)
+ {
+ case DICS_ENABLE:
+ case DICS_DISABLE:
+ {
+ /* Enable/disable device in registry */
+ hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
+ if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
+ hKey = SetupDiCreateDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
+ if (hKey == INVALID_HANDLE_VALUE)
+ break;
+ dwLength = sizeof(DWORD);
+ rc = RegQueryValueExW(
+ hKey,
+ RegistryValueName,
+ NULL,
+ &dwRegType,
+ (LPBYTE)&dwConfigFlags, &dwLength);
+ if (rc == ERROR_FILE_NOT_FOUND)
+ dwConfigFlags = 0;
+ else if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ if (PropChange->StateChange == DICS_ENABLE)
+ dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
+ else
+ dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
+ rc = RegSetValueEx(
+ hKey,
+ RegistryValueName,
+ 0,
+ REG_DWORD,
+ (LPBYTE)&dwConfigFlags, sizeof(DWORD));
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+
+ /* Enable/disable device if needed */
+ if (PropChange->Scope == DICS_FLAG_GLOBAL
+ || PropChange->HwProfile == 0
+ || PropChange->HwProfile == GetCurrentHwProfile(DeviceInfoSet))
+ {
+ if (PropChange->StateChange == DICS_ENABLE)
+ ret = StartDevice();
+ else
+ ret = StopDevice();
+ }
+ else
+ ret = TRUE;
+ break;
+ }
+ case DICS_PROPCHANGE:
+ {
+ ret = StopDevice() && StartDevice();
+ break;
+ }
+ default:
+ {
+ FIXME("Unknown StateChange 0x%lx\n", PropChange->StateChange);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ }
+ }
+
+cleanup:
+ if (hKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hKey);
+
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
+
/***********************************************************************
* SetupDiSelectBestCompatDrv (SETUPAPI.@)
*/
DWORD DoAction;
WCHAR SectionName[MAX_PATH];
DWORD SectionNameLength = 0;
- HKEY hKey = INVALID_HANDLE_VALUE;;
+ HKEY hKey = INVALID_HANDLE_VALUE;
InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
HKEY hKey = INVALID_HANDLE_VALUE;
HKEY hClassKey = INVALID_HANDLE_VALUE;
BOOL NeedtoCopyFile;
+ LARGE_INTEGER fullVersion;
LONG rc;
BOOL ret = FALSE; /* Return value */
/* Write information to driver key */
*pSectionName = UNICODE_NULL;
+ memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
TRACE("Write information to driver key\n");
TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
TRACE("DriverDesc : '%S'\n", SelectedDriver->Info.Description);
- TRACE("DriverVersion : '%u.%u.%u.%u'\n", SelectedDriver->Info.DriverVersion & 0xff, (SelectedDriver->Info.DriverVersion >> 8) & 0xff, (SelectedDriver->Info.DriverVersion >> 16) & 0xff, (SelectedDriver->Info.DriverVersion >> 24) & 0xff);
+ TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
TRACE("InfPath : '%S'\n", SelectedDriver->Details.InfFileName);
TRACE("InfSection : '%S'\n", SelectedDriver->Details.SectionName);
TRACE("InfSectionExt : '%S'\n", &SectionName[wcslen(SelectedDriver->Details.SectionName)]);
rc = RegSetValueEx(hKey, L"DriverDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
{
- swprintf(Buffer, L"%u.%u.%u.%u", SelectedDriver->Info.DriverVersion & 0xff, (SelectedDriver->Info.DriverVersion >> 8) & 0xff, (SelectedDriver->Info.DriverVersion >> 16) & 0xff, (SelectedDriver->Info.DriverVersion >> 24) & 0xff);
+ swprintf(Buffer, L"%u.%u.%u.%u", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
rc = RegSetValueEx(hKey, L"DriverVersion", 0, REG_SZ, (const BYTE *)Buffer, (wcslen(Buffer) + 1) * sizeof(WCHAR));
}
if (rc == ERROR_SUCCESS)
NULL, 0,
&RequiredSize);
if (!Result)
- goto nextfile;
+ goto nextservice;
if (RequiredSize > 0)
{
/* We got the needed size for the buffer */
if (!ServiceName)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto nextfile;
+ goto nextservice;
}
Result = SetupGetStringFieldW(
&ContextService,
ServiceName, RequiredSize,
&RequiredSize);
if (!Result)
- goto nextfile;
+ goto nextservice;
}
Result = SetupGetIntField(
&ContextService,
NULL, 0,
&RequiredSize);
if (!Result)
- goto nextfile;
+ {
+ if (GetLastError() == ERROR_INVALID_PARAMETER)
+ {
+ /* This first is probably missing. It is not
+ * required, so ignore the error */
+ RequiredSize = 0;
+ Result = TRUE;
+ }
+ else
+ goto nextservice;
+ }
if (RequiredSize > 0)
{
/* We got the needed size for the buffer */
if (!ServiceSection)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto nextfile;
+ goto nextservice;
}
Result = SetupGetStringFieldW(
&ContextService,
ServiceSection, RequiredSize,
&RequiredSize);
if (!Result)
- goto nextfile;
+ goto nextservice;
+
+ SetLastError(ERROR_SUCCESS);
+ Result = SetupInstallServicesFromInfSectionExW(
+ SelectedDriver->InfFileDetails->hInf,
+ ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
}
- SetLastError(ERROR_SUCCESS);
- Result = SetupInstallServicesFromInfSectionExW(
- SelectedDriver->InfFileDetails->hInf,
- ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName, NULL);
if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
{
AssociatedService = ServiceName;
if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
RebootRequired = TRUE;
}
-nextfile:
+nextservice:
HeapFree(GetProcessHeap(), 0, ServiceName);
HeapFree(GetProcessHeap(), 0, ServiceSection);
if (!Result)
/* Write information to enum key */
TRACE("Write information to enum key\n");
- TRACE("Service : '%S'\n", AssociatedService);
TRACE("Class : '%S'\n", ClassName);
TRACE("ClassGUID : '%S'\n", lpFullGuidString);
TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
TRACE("Mfg : '%S'\n", SelectedDriver->Info.MfgName);
- rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
- if (rc == ERROR_SUCCESS)
- rc = RegSetValueEx(hKey, L"Class", 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
+ TRACE("Service : '%S'\n", AssociatedService);
+ rc = RegSetValueEx(hKey, L"Class", 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
rc = RegSetValueEx(hKey, L"ClassGUID", 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
rc = RegSetValueEx(hKey, L"DeviceDesc", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
rc = RegSetValueEx(hKey, L"Mfg", 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
+ if (rc == ERROR_SUCCESS && *AssociatedService)
+ rc = RegSetValueEx(hKey, L"Service", 0, REG_SZ, (const BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) * sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);