#include "winnls.h"
#include "setupapi.h"
#include "wine/debug.h"
+#include "wine/list.h"
#include "wine/unicode.h"
#include "cfgmgr32.h"
-#include "initguid.h"
#include "winioctl.h"
#include "rpc.h"
#include "rpcdce.h"
'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
'E','n','u','m',0};
static const WCHAR DeviceDesc[] = {'D','e','v','i','c','e','D','e','s','c',0};
+static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
static const WCHAR HardwareId[] = {'H','a','r','d','w','a','r','e','I','D',0};
static const WCHAR CompatibleIDs[] = {'C','o','m','p','a','t','i','b','l','e','I','d','s',0};
static const WCHAR Service[] = {'S','e','r','v','i','c','e',0};
static const WCHAR UINumber[] = {'U','I','N','u','m','b','e','r',0};
static const WCHAR UpperFilters[] = {'U','p','p','e','r','F','i','l','t','e','r','s',0};
static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r','s',0};
+static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0};
+static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
/* is used to identify if a DeviceInfoSet pointer is
valid or not */
GUID ClassGuid;
HWND hwndParent;
DWORD cDevices;
- SP_DEVINFO_DATA *devices;
+ struct list devices;
+};
+
+struct DeviceInstance
+{
+ struct list entry;
+ SP_DEVINFO_DATA data;
+};
+
+/* Pointed to by SP_DEVICE_INTERFACE_DATA's Reserved member */
+struct InterfaceInfo
+{
+ LPWSTR referenceString;
+ LPWSTR symbolicLink;
+ PSP_DEVINFO_DATA device;
+};
+
+/* A device may have multiple instances of the same interface, so this holds
+ * each instance belonging to a particular interface.
+ */
+struct InterfaceInstances
+{
+ GUID guid;
+ DWORD cInstances;
+ DWORD cInstancesAllocated;
+ SP_DEVICE_INTERFACE_DATA *instances;
+ struct list entry;
};
/* Pointed to by SP_DEVINFO_DATA's Reserved member */
struct DeviceInfo
{
- HKEY key;
- LPWSTR instanceId;
+ struct DeviceInfoSet *set;
+ HKEY key;
+ BOOL phantom;
+ DWORD devId;
+ LPWSTR instanceId;
+ struct list interfaces;
};
-static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(LPCWSTR instanceId)
+static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
+{
+ static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
+ '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
+ 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
+ '0','2','X','}',0};
+
+ sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
+ guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+ guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+}
+
+static void SETUPDI_FreeInterfaceInstances(struct InterfaceInstances *instances)
+{
+ DWORD i;
+
+ for (i = 0; i < instances->cInstances; i++)
+ {
+ struct InterfaceInfo *ifaceInfo =
+ (struct InterfaceInfo *)instances->instances[i].Reserved;
+
+ if (ifaceInfo->device && ifaceInfo->device->Reserved)
+ {
+ struct DeviceInfo *devInfo =
+ (struct DeviceInfo *)ifaceInfo->device->Reserved;
+
+ if (devInfo->phantom)
+ SetupDiDeleteDeviceInterfaceRegKey(devInfo->set,
+ &instances->instances[i], 0);
+ }
+ HeapFree(GetProcessHeap(), 0, ifaceInfo->referenceString);
+ HeapFree(GetProcessHeap(), 0, ifaceInfo->symbolicLink);
+ HeapFree(GetProcessHeap(), 0, ifaceInfo);
+ }
+ HeapFree(GetProcessHeap(), 0, instances->instances);
+}
+
+/* Finds the interface with interface class InterfaceClassGuid in the device.
+ * Returns TRUE if found, and updates *interface to point to device's
+ * interfaces member where the given interface was found.
+ * Returns FALSE if not found.
+ */
+static BOOL SETUPDI_FindInterface(const struct DeviceInfo *devInfo,
+ const GUID *InterfaceClassGuid, struct InterfaceInstances **iface_ret)
+{
+ BOOL found = FALSE;
+ struct InterfaceInstances *iface;
+
+ TRACE("%s\n", debugstr_guid(InterfaceClassGuid));
+
+ LIST_FOR_EACH_ENTRY(iface, &devInfo->interfaces, struct InterfaceInstances,
+ entry)
+ {
+ if (IsEqualGUID(&iface->guid, InterfaceClassGuid))
+ {
+ *iface_ret = iface;
+ found = TRUE;
+ break;
+ }
+ }
+ TRACE("returning %d (%p)\n", found, found ? *iface_ret : NULL);
+ return found;
+}
+
+/* Finds the interface instance with reference string ReferenceString in the
+ * interface instance map. Returns TRUE if found, and updates instanceIndex to
+ * the index of the interface instance's instances member
+ * where the given instance was found. Returns FALSE if not found.
+ */
+static BOOL SETUPDI_FindInterfaceInstance(
+ const struct InterfaceInstances *instances,
+ LPCWSTR ReferenceString, DWORD *instanceIndex)
+{
+ BOOL found = FALSE;
+ DWORD i;
+
+ TRACE("%s\n", debugstr_w(ReferenceString));
+
+ for (i = 0; !found && i < instances->cInstances; i++)
+ {
+ SP_DEVICE_INTERFACE_DATA *ifaceData = &instances->instances[i];
+ struct InterfaceInfo *ifaceInfo =
+ (struct InterfaceInfo *)ifaceData->Reserved;
+
+ if (!ReferenceString && !ifaceInfo->referenceString)
+ {
+ *instanceIndex = i;
+ found = TRUE;
+ }
+ else if (ReferenceString && ifaceInfo->referenceString &&
+ !lstrcmpiW(ifaceInfo->referenceString, ReferenceString))
+ {
+ *instanceIndex = i;
+ found = TRUE;
+ }
+ }
+ TRACE("returning %d (%d)\n", found, found ? *instanceIndex : 0);
+ return found;
+}
+
+static LPWSTR SETUPDI_CreateSymbolicLinkPath(LPCWSTR instanceId,
+ const GUID *InterfaceClassGuid, LPCWSTR ReferenceString)
+{
+ static const WCHAR fmt[] = {'\\','\\','?','\\','%','s','#','%','s',0};
+ WCHAR guidStr[39];
+ DWORD len;
+ LPWSTR ret;
+
+ SETUPDI_GuidToString(InterfaceClassGuid, guidStr);
+ /* omit length of format specifiers, but include NULL terminator: */
+ len = lstrlenW(fmt) - 4 + 1;
+ len += lstrlenW(instanceId) + lstrlenW(guidStr);
+ if (ReferenceString && *ReferenceString)
+ {
+ /* space for a hash between string and reference string: */
+ len += lstrlenW(ReferenceString) + 1;
+ }
+ ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (ret)
+ {
+ int printed = sprintfW(ret, fmt, instanceId, guidStr);
+ LPWSTR ptr;
+
+ /* replace '\\' with '#' after the "\\\\?\\" beginning */
+ for (ptr = strchrW(ret + 4, '\\'); ptr; ptr = strchrW(ptr + 1, '\\'))
+ *ptr = '#';
+ if (ReferenceString && *ReferenceString)
+ {
+ ret[printed] = '\\';
+ lstrcpyW(ret + printed + 1, ReferenceString);
+ }
+ }
+ return ret;
+}
+
+/* Adds an interface with the given interface class and reference string to
+ * the device, if it doesn't already exist in the device. If iface is not
+ * NULL, returns a pointer to the newly added (or already existing) interface.
+ */
+static BOOL SETUPDI_AddInterfaceInstance(PSP_DEVINFO_DATA DeviceInfoData,
+ const GUID *InterfaceClassGuid, LPCWSTR ReferenceString,
+ SP_DEVICE_INTERFACE_DATA **ifaceData)
+{
+ struct DeviceInfo *devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+ BOOL newInterface = FALSE, ret;
+ struct InterfaceInstances *iface = NULL;
+
+ TRACE("%p %s %s %p\n", devInfo, debugstr_guid(InterfaceClassGuid),
+ debugstr_w(ReferenceString), iface);
+
+ if (!(ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
+ {
+ iface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(struct InterfaceInstances));
+ if (iface)
+ {
+ list_add_tail(&devInfo->interfaces, &iface->entry);
+ newInterface = TRUE;
+ }
+ }
+ if (iface)
+ {
+ DWORD instanceIndex = 0;
+
+ if (!(ret = SETUPDI_FindInterfaceInstance(iface, ReferenceString,
+ &instanceIndex)))
+ {
+ SP_DEVICE_INTERFACE_DATA *instance = NULL;
+
+ if (!iface->cInstancesAllocated)
+ {
+ iface->instances = HeapAlloc(GetProcessHeap(), 0,
+ sizeof(SP_DEVICE_INTERFACE_DATA));
+ if (iface->instances)
+ instance = &iface->instances[iface->cInstancesAllocated++];
+ }
+ else if (iface->cInstances == iface->cInstancesAllocated)
+ {
+ iface->instances = HeapReAlloc(GetProcessHeap(), 0,
+ iface->instances,
+ (iface->cInstancesAllocated + 1) *
+ sizeof(SP_DEVICE_INTERFACE_DATA));
+ if (iface->instances)
+ instance = &iface->instances[iface->cInstancesAllocated++];
+ }
+ else
+ instance = &iface->instances[iface->cInstances];
+ if (instance)
+ {
+ struct InterfaceInfo *ifaceInfo = HeapAlloc(GetProcessHeap(),
+ 0, sizeof(struct InterfaceInfo));
+
+ if (ifaceInfo)
+ {
+ ret = TRUE;
+ ifaceInfo->device = DeviceInfoData;
+ ifaceInfo->symbolicLink = SETUPDI_CreateSymbolicLinkPath(
+ devInfo->instanceId, InterfaceClassGuid,
+ ReferenceString);
+ if (ReferenceString)
+ {
+ ifaceInfo->referenceString =
+ HeapAlloc(GetProcessHeap(), 0,
+ (lstrlenW(ReferenceString) + 1) *
+ sizeof(WCHAR));
+ if (ifaceInfo->referenceString)
+ lstrcpyW(ifaceInfo->referenceString,
+ ReferenceString);
+ else
+ ret = FALSE;
+ }
+ else
+ ifaceInfo->referenceString = NULL;
+ if (ret)
+ {
+ HKEY key;
+
+ iface->cInstances++;
+ instance->cbSize =
+ sizeof(SP_DEVICE_INTERFACE_DATA);
+ instance->InterfaceClassGuid = *InterfaceClassGuid;
+ instance->Flags = SPINT_ACTIVE; /* FIXME */
+ instance->Reserved = (ULONG_PTR)ifaceInfo;
+ if (newInterface)
+ iface->guid = *InterfaceClassGuid;
+ key = SetupDiCreateDeviceInterfaceRegKeyW(devInfo->set,
+ instance, 0, KEY_WRITE, NULL, NULL);
+ if (key != INVALID_HANDLE_VALUE)
+ {
+ RegSetValueExW(key, SymbolicLink, 0, REG_SZ,
+ (BYTE *)ifaceInfo->symbolicLink,
+ lstrlenW(ifaceInfo->symbolicLink) *
+ sizeof(WCHAR));
+ RegCloseKey(key);
+ }
+ if (ifaceData)
+ *ifaceData = instance;
+ }
+ else
+ HeapFree(GetProcessHeap(), 0, ifaceInfo);
+ }
+ }
+ }
+ else
+ {
+ if (ifaceData)
+ *ifaceData = &iface->instances[instanceIndex];
+ }
+ }
+ else
+ ret = FALSE;
+ TRACE("returning %d\n", ret);
+ return ret;
+}
+
+static BOOL SETUPDI_SetInterfaceSymbolicLink(SP_DEVICE_INTERFACE_DATA *iface,
+ LPCWSTR symbolicLink)
+{
+ struct InterfaceInfo *info = (struct InterfaceInfo *)iface->Reserved;
+ BOOL ret = FALSE;
+
+ if (info)
+ {
+ HeapFree(GetProcessHeap(), 0, info->symbolicLink);
+ info->symbolicLink = HeapAlloc(GetProcessHeap(), 0,
+ (lstrlenW(symbolicLink) + 1) * sizeof(WCHAR));
+ if (info->symbolicLink)
+ {
+ lstrcpyW(info->symbolicLink, symbolicLink);
+ ret = TRUE;
+ }
+ }
+ return ret;
+}
+
+static HKEY SETUPDI_CreateDevKey(struct DeviceInfo *devInfo)
+{
+ HKEY enumKey, key = INVALID_HANDLE_VALUE;
+ LONG l;
+
+ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
+ NULL, &enumKey, NULL);
+ if (!l)
+ {
+ RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
+ KEY_READ | KEY_WRITE, NULL, &key, NULL);
+ RegCloseKey(enumKey);
+ }
+ return key;
+}
+
+static HKEY SETUPDI_CreateDrvKey(struct DeviceInfo *devInfo)
{
- struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
- sizeof(struct DeviceInfo));
+ static const WCHAR slash[] = { '\\',0 };
+ WCHAR classKeyPath[MAX_PATH];
+ HKEY classKey, key = INVALID_HANDLE_VALUE;
+ LONG l;
+
+ lstrcpyW(classKeyPath, ControlClass);
+ lstrcatW(classKeyPath, slash);
+ SETUPDI_GuidToString(&devInfo->set->ClassGuid,
+ classKeyPath + lstrlenW(classKeyPath));
+ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
+ KEY_ALL_ACCESS, NULL, &classKey, NULL);
+ if (!l)
+ {
+ static const WCHAR fmt[] = { '%','0','4','u',0 };
+ WCHAR devId[10];
+
+ sprintfW(devId, fmt, devInfo->devId);
+ RegCreateKeyExW(classKey, devId, 0, NULL, 0, KEY_READ | KEY_WRITE,
+ NULL, &key, NULL);
+ RegCloseKey(classKey);
+ }
+ return key;
+}
+
+static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set,
+ DWORD devId, LPCWSTR instanceId, BOOL phantom)
+{
+ struct DeviceInfo *devInfo = NULL;
+ HANDLE devInst = GlobalAlloc(GMEM_FIXED, sizeof(struct DeviceInfo));
+ if (devInst)
+ devInfo = GlobalLock(devInst);
if (devInfo)
{
+ devInfo->set = set;
+ devInfo->devId = (DWORD)devInst;
+
devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
(lstrlenW(instanceId) + 1) * sizeof(WCHAR));
if (devInfo->instanceId)
{
- HKEY enumKey;
- LONG l;
-
devInfo->key = INVALID_HANDLE_VALUE;
+ devInfo->phantom = phantom;
lstrcpyW(devInfo->instanceId, instanceId);
struprW(devInfo->instanceId);
- l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
- KEY_ALL_ACCESS, NULL, &enumKey, NULL);
- if (!l)
+ devInfo->key = SETUPDI_CreateDevKey(devInfo);
+ if (devInfo->key != INVALID_HANDLE_VALUE)
{
- RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
- KEY_ALL_ACCESS, NULL, &devInfo->key, NULL);
- RegCloseKey(enumKey);
+ if (phantom)
+ RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
+ (LPBYTE)&phantom, sizeof(phantom));
}
+ list_init(&devInfo->interfaces);
+ GlobalUnlock(devInst);
}
else
{
- HeapFree(GetProcessHeap(), 0, devInfo);
+ GlobalUnlock(devInst);
+ GlobalFree(devInst);
devInfo = NULL;
}
}
static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
{
+ struct InterfaceInstances *iface, *next;
+
if (devInfo->key != INVALID_HANDLE_VALUE)
RegCloseKey(devInfo->key);
- HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
- HeapFree(GetProcessHeap(), 0, devInfo);
-}
-
-static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
-{
- static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
- '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
- 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
- '0','2','X','}',0};
+ if (devInfo->phantom)
+ {
+ HKEY enumKey;
+ LONG l;
- sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
- guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
- guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
+ KEY_ALL_ACCESS, NULL, &enumKey, NULL);
+ if (!l)
+ {
+ RegDeleteTreeW(enumKey, devInfo->instanceId);
+ RegCloseKey(enumKey);
+ }
+ }
+ HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
+ LIST_FOR_EACH_ENTRY_SAFE(iface, next, &devInfo->interfaces,
+ struct InterfaceInstances, entry)
+ {
+ list_remove(&iface->entry);
+ SETUPDI_FreeInterfaceInstances(iface);
+ HeapFree(GetProcessHeap(), 0, iface);
+ }
+ GlobalFree((HANDLE)devInfo->devId);
}
/* Adds a device with GUID guid and identifer devInst to set. Allocates a
* struct DeviceInfo, and points the returned device info's Reserved member
- * to it.
+ * to it. "Phantom" devices are deleted from the registry when closed.
* Returns a pointer to the newly allocated device info.
*/
static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
const GUID *guid,
DWORD devInst,
LPCWSTR instanceId,
+ BOOL phantom,
SP_DEVINFO_DATA **dev)
{
BOOL ret = FALSE;
- struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(instanceId);
+ struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(set, set->cDevices,
+ instanceId, phantom);
+
+ TRACE("%p, %s, %d, %s, %d\n", set, debugstr_guid(guid), devInst,
+ debugstr_w(instanceId), phantom);
if (devInfo)
{
- if (set->devices)
- set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
- (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
- else
- set->devices = HeapAlloc(GetProcessHeap(), 0,
- sizeof(SP_DEVINFO_DATA));
- if (set->devices)
+ struct DeviceInstance *devInst =
+ HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInstance));
+
+ if (devInst)
{
- *dev = &set->devices[set->cDevices++];
- (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
- memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
- (*dev)->DevInst = devInst;
- (*dev)->Reserved = (ULONG_PTR)devInfo;
+ WCHAR classGuidStr[39];
+
+ list_add_tail(&set->devices, &devInst->entry);
+ set->cDevices++;
+ devInst->data.cbSize = sizeof(SP_DEVINFO_DATA);
+ devInst->data.ClassGuid = *guid;
+ devInst->data.DevInst = devInfo->devId;
+ devInst->data.Reserved = (ULONG_PTR)devInfo;
+ SETUPDI_GuidToString(guid, classGuidStr);
+ SetupDiSetDeviceRegistryPropertyW(set, &devInst->data,
+ SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
+ lstrlenW(classGuidStr) * sizeof(WCHAR));
+ if (dev) *dev = &devInst->data;
ret = TRUE;
}
else
LPWSTR MachineNameW = NULL;
BOOL bResult;
- FIXME("\n");
-
ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
if (ClassNameW == NULL)
return FALSE;
{
MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
if (MachineNameW == NULL)
- return (HDEVINFO)INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
}
hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
* Create an empty DeviceInfoSet list.
*
* PARAMS
- * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
+ * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
* with this list.
* hwndParent [I] hwnd needed for interface related actions.
* MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
{
FIXME("remote support is not implemented\n");
SetLastError(ERROR_INVALID_MACHINENAME);
- return (HDEVINFO)INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
}
if (Reserved != NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
- return (HDEVINFO)INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
}
list = HeapAlloc(GetProcessHeap(), 0, size);
if (!list)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return (HDEVINFO)INVALID_HANDLE_VALUE;
+ return INVALID_HANDLE_VALUE;
}
list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
ClassGuid ? ClassGuid : &GUID_NULL,
sizeof(list->ClassGuid));
list->cDevices = 0;
- list->devices = NULL;
+ list_init(&list->devices);
+
+ return list;
+}
+
+/***********************************************************************
+ * SetupDiCreateDevRegKeyA (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDevRegKeyA(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_DATA DeviceInfoData,
+ DWORD Scope,
+ DWORD HwProfile,
+ DWORD KeyType,
+ HINF InfHandle,
+ PCSTR InfSectionName)
+{
+ PWSTR InfSectionNameW = NULL;
+ HKEY key;
+
+ TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
+ HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
+
+ if (InfHandle)
+ {
+ if (!InfSectionName)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+ else
+ {
+ InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
+ if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
+ }
+ }
+ key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
+ HwProfile, KeyType, InfHandle, InfSectionNameW);
+ MyFree(InfSectionNameW);
+ return key;
+}
+
+/***********************************************************************
+ * SetupDiCreateDevRegKeyW (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDevRegKeyW(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_DATA DeviceInfoData,
+ DWORD Scope,
+ DWORD HwProfile,
+ DWORD KeyType,
+ HINF InfHandle,
+ PCWSTR InfSectionName)
+{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ struct DeviceInfo *devInfo;
+ HKEY key = INVALID_HANDLE_VALUE;
+
+ TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
+ HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
- return (HDEVINFO)list;
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+ || !DeviceInfoData->Reserved)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+ devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+ if (devInfo->set != set)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
+ {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
+ {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (devInfo->phantom)
+ {
+ SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (Scope != DICS_FLAG_GLOBAL)
+ FIXME("unimplemented for scope %d\n", Scope);
+ switch (KeyType)
+ {
+ case DIREG_DEV:
+ key = SETUPDI_CreateDevKey(devInfo);
+ break;
+ case DIREG_DRV:
+ key = SETUPDI_CreateDrvKey(devInfo);
+ break;
+ default:
+ WARN("unknown KeyType %d\n", KeyType);
+ }
+ if (InfHandle)
+ SetupInstallFromInfSectionW(NULL, InfHandle, InfSectionName, SPINST_ALL,
+ NULL, NULL, SP_COPY_NEWER_ONLY, NULL, NULL, DeviceInfoSet,
+ DeviceInfoData);
+ return key;
}
/***********************************************************************
static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
{
LPCWSTR ptr;
- DWORD devNameLen = lstrlenW(devName), devInst = 0;
+ int devNameLen = lstrlenW(devName);
+ DWORD devInst = 0;
BOOL valid = TRUE;
TRACE("%s\n", debugstr_w(devName));
DWORD CreationFlags,
PSP_DEVINFO_DATA DeviceInfoData)
{
- struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+ struct DeviceInfoSet *set = DeviceInfoSet;
BOOL ret = FALSE, allocatedInstanceId = FALSE;
LPCWSTR instanceId = NULL;
SetLastError(ERROR_INVALID_DEVINST_NAME);
return FALSE;
}
- if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
{
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
if (set->cDevices)
{
- DWORD i, highestDevID = 0;
+ DWORD highestDevID = 0;
+ struct DeviceInstance *devInst;
- for (i = 0; i < set->cDevices; i++)
+ LIST_FOR_EACH_ENTRY(devInst, &set->devices, struct DeviceInstance, entry)
{
- struct DeviceInfo *devInfo =
- (struct DeviceInfo *)set->devices[i].Reserved;
+ struct DeviceInfo *devInfo = (struct DeviceInfo *)devInst->data.Reserved;
LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
DWORD id;
}
else
{
- DWORD i;
+ struct DeviceInstance *devInst;
ret = TRUE;
instanceId = DeviceName;
- for (i = 0; ret && i < set->cDevices; i++)
+ LIST_FOR_EACH_ENTRY(devInst, &set->devices, struct DeviceInstance, entry)
{
- struct DeviceInfo *devInfo =
- (struct DeviceInfo *)set->devices[i].Reserved;
+ struct DeviceInfo *devInfo = (struct DeviceInfo *)devInst->data.Reserved;
if (!lstrcmpiW(DeviceName, devInfo->instanceId))
{
SP_DEVINFO_DATA *dev = NULL;
ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
- instanceId, &dev);
- if (ret && DeviceInfoData)
+ instanceId, TRUE, &dev);
+ if (ret)
{
- if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ if (DeviceDescription)
+ SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
+ dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
+ lstrlenW(DeviceDescription) * sizeof(WCHAR));
+ if (DeviceInfoData)
{
- SetLastError(ERROR_INVALID_USER_BUFFER);
- ret = FALSE;
+ if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ ret = FALSE;
+ }
+ else
+ *DeviceInfoData = *dev;
}
- else
- memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
}
}
if (allocatedInstanceId)
}
/***********************************************************************
- * SetupDiEnumDeviceInfo (SETUPAPI.@)
+ * SetupDiRegisterDeviceInfo (SETUPAPI.@)
*/
-BOOL WINAPI SetupDiEnumDeviceInfo(
- HDEVINFO devinfo,
- DWORD index,
- PSP_DEVINFO_DATA info)
+BOOL WINAPI SetupDiRegisterDeviceInfo(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_DATA DeviceInfoData,
+ DWORD Flags,
+ PSP_DETSIG_CMPPROC CompareProc,
+ PVOID CompareContext,
+ PSP_DEVINFO_DATA DupDeviceInfoData)
{
- BOOL ret = FALSE;
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ struct DeviceInfo *devInfo;
- TRACE("%p %d %p\n", devinfo, index, info);
+ TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
+ CompareProc, CompareContext, DupDeviceInfoData);
- if(info==NULL)
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
- if(info->cbSize < sizeof(*info))
+ }
+ if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
- if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
+ }
+ if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+ || !DeviceInfoData->Reserved)
{
- struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
- if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
- {
- if (index < list->cDevices)
- {
- if (info->cbSize == sizeof(SP_DEVINFO_DATA))
- {
- memcpy(info, &list->devices[index], info->cbSize);
- ret = TRUE;
- }
- else
- SetLastError(ERROR_INVALID_USER_BUFFER);
- }
- else
- SetLastError(ERROR_NO_MORE_ITEMS);
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+ if (devInfo->set != set)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (devInfo->phantom)
+ {
+ devInfo->phantom = FALSE;
+ RegDeleteValueW(devInfo->key, Phantom);
+ }
+ return TRUE;
+}
+
+/***********************************************************************
+ * SetupDiRemoveDevice (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiRemoveDevice(
+ HDEVINFO devinfo,
+ PSP_DEVINFO_DATA info)
+{
+ FIXME("(%p, %p): stub\n", devinfo, info);
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ return FALSE;
+}
+
+/***********************************************************************
+ * SetupDiEnumDeviceInfo (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiEnumDeviceInfo(
+ HDEVINFO devinfo,
+ DWORD index,
+ PSP_DEVINFO_DATA info)
+{
+ BOOL ret = FALSE;
+
+ TRACE("%p %d %p\n", devinfo, index, info);
+
+ if(info==NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (devinfo && devinfo != INVALID_HANDLE_VALUE)
+ {
+ struct DeviceInfoSet *list = devinfo;
+ if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ if (index < list->cDevices)
+ {
+ if (info->cbSize == sizeof(SP_DEVINFO_DATA))
+ {
+ struct DeviceInstance *devInst;
+ DWORD i = 0;
+
+ LIST_FOR_EACH_ENTRY(devInst, &list->devices,
+ struct DeviceInstance, entry)
+ {
+ if (i++ == index)
+ {
+ *info = devInst->data;
+ break;
+ }
+ }
+ ret = TRUE;
+ }
+ else
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ }
+ else
+ SetLastError(ERROR_NO_MORE_ITEMS);
}
else
SetLastError(ERROR_INVALID_HANDLE);
DWORD DeviceInstanceIdSize,
PDWORD RequiredSize)
{
- struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+ struct DeviceInfoSet *set = DeviceInfoSet;
struct DeviceInfo *devInfo;
TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
return FALSE;
}
devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+ if (devInfo->set != set)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
- if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
+ if (DeviceInstanceIdSize < strlenW(devInfo->instanceId) + 1)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
if (RequiredSize)
PCSTR MachineName,
PVOID Reserved)
{
- FIXME("\n");
- return FALSE;
+ HKEY hKey;
+ DWORD dwLength;
+ BOOL ret;
+
+ hKey = SetupDiOpenClassRegKeyExA(ClassGuid,
+ KEY_ALL_ACCESS,
+ DIOCR_INSTALLER,
+ MachineName,
+ Reserved);
+ if (hKey == INVALID_HANDLE_VALUE)
+ {
+ WARN("SetupDiOpenClassRegKeyExA() failed (Error %u)\n", GetLastError());
+ return FALSE;
+ }
+
+ dwLength = ClassDescriptionSize;
+ ret = !RegQueryValueExA( hKey, NULL, NULL, NULL,
+ (LPBYTE)ClassDescription, &dwLength );
+ if (RequiredSize) *RequiredSize = dwLength;
+ RegCloseKey(hKey);
+ return ret;
}
/***********************************************************************
{
HKEY hKey;
DWORD dwLength;
+ BOOL ret;
hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
KEY_ALL_ACCESS,
return FALSE;
}
- if (RequiredSize != NULL)
- {
- dwLength = 0;
- if (RegQueryValueExW(hKey,
- NULL,
- NULL,
- NULL,
- NULL,
- &dwLength))
- {
- RegCloseKey(hKey);
- return FALSE;
- }
-
- *RequiredSize = dwLength / sizeof(WCHAR);
- }
-
dwLength = ClassDescriptionSize * sizeof(WCHAR);
- if (RegQueryValueExW(hKey,
- NULL,
- NULL,
- NULL,
- (LPBYTE)ClassDescription,
- &dwLength))
- {
- RegCloseKey(hKey);
- return FALSE;
- }
-
+ ret = !RegQueryValueExW( hKey, NULL, NULL, NULL,
+ (LPBYTE)ClassDescription, &dwLength );
+ if (RequiredSize) *RequiredSize = dwLength / sizeof(WCHAR);
RegCloseKey(hKey);
-
- return TRUE;
+ return ret;
}
/***********************************************************************
enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (!enumstrW)
{
- ret = (HDEVINFO)INVALID_HANDLE_VALUE;
+ ret = INVALID_HANDLE_VALUE;
goto end;
}
MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
}
- ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
+ ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, NULL, NULL,
+ NULL);
HeapFree(GetProcessHeap(), 0, enumstrW);
end:
return ret;
}
+/***********************************************************************
+ * SetupDiGetClassDevsExA (SETUPAPI.@)
+ */
+HDEVINFO WINAPI SetupDiGetClassDevsExA(
+ const GUID *class,
+ PCSTR enumstr,
+ HWND parent,
+ DWORD flags,
+ HDEVINFO deviceset,
+ PCSTR machine,
+ PVOID reserved)
+{
+ HDEVINFO ret;
+ LPWSTR enumstrW = NULL, machineW = NULL;
+
+ if (enumstr)
+ {
+ int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
+ enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!enumstrW)
+ {
+ ret = INVALID_HANDLE_VALUE;
+ goto end;
+ }
+ MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
+ }
+ if (machine)
+ {
+ int len = MultiByteToWideChar(CP_ACP, 0, machine, -1, NULL, 0);
+ machineW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ if (!machineW)
+ {
+ HeapFree(GetProcessHeap(), 0, enumstrW);
+ ret = INVALID_HANDLE_VALUE;
+ goto end;
+ }
+ MultiByteToWideChar(CP_ACP, 0, machine, -1, machineW, len);
+ }
+ ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
+ machineW, reserved);
+ HeapFree(GetProcessHeap(), 0, enumstrW);
+ HeapFree(GetProcessHeap(), 0, machineW);
+
+end:
+ return ret;
+}
+
+static void SETUPDI_AddDeviceInterfaces(SP_DEVINFO_DATA *dev, HKEY key,
+ const GUID *guid)
+{
+ DWORD i, len;
+ WCHAR subKeyName[MAX_PATH];
+ LONG l = ERROR_SUCCESS;
+
+ for (i = 0; !l; i++)
+ {
+ len = sizeof(subKeyName) / sizeof(subKeyName[0]);
+ l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
+ if (!l)
+ {
+ HKEY subKey;
+ SP_DEVICE_INTERFACE_DATA *iface = NULL;
+
+ if (*subKeyName == '#')
+ {
+ /* The subkey name is the reference string, with a '#' prepended */
+ SETUPDI_AddInterfaceInstance(dev, guid, subKeyName + 1, &iface);
+ l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
+ if (!l)
+ {
+ WCHAR symbolicLink[MAX_PATH];
+ DWORD dataType;
+
+ len = sizeof(symbolicLink);
+ l = RegQueryValueExW(subKey, SymbolicLink, NULL, &dataType,
+ (BYTE *)symbolicLink, &len);
+ if (!l && dataType == REG_SZ)
+ SETUPDI_SetInterfaceSymbolicLink(iface, symbolicLink);
+ RegCloseKey(subKey);
+ }
+ }
+ /* Allow enumeration to continue */
+ l = ERROR_SUCCESS;
+ }
+ }
+ /* FIXME: find and add all the device's interfaces to the device */
+}
+
+static void SETUPDI_EnumerateMatchingInterfaces(HDEVINFO DeviceInfoSet,
+ HKEY key, const GUID *guid, LPCWSTR enumstr)
+{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ DWORD i, len;
+ WCHAR subKeyName[MAX_PATH];
+ LONG l;
+ HKEY enumKey = INVALID_HANDLE_VALUE;
+
+ TRACE("%s\n", debugstr_w(enumstr));
+
+ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
+ &enumKey, NULL);
+ for (i = 0; !l; i++)
+ {
+ len = sizeof(subKeyName) / sizeof(subKeyName[0]);
+ l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
+ if (!l)
+ {
+ HKEY subKey;
+
+ l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
+ if (!l)
+ {
+ WCHAR deviceInst[MAX_PATH * 3];
+ DWORD dataType;
+
+ len = sizeof(deviceInst);
+ l = RegQueryValueExW(subKey, DeviceInstance, NULL, &dataType,
+ (BYTE *)deviceInst, &len);
+ if (!l && dataType == REG_SZ)
+ {
+ TRACE("found instance ID %s\n", debugstr_w(deviceInst));
+ if (!enumstr || !lstrcmpiW(enumstr, deviceInst))
+ {
+ HKEY deviceKey;
+
+ l = RegOpenKeyExW(enumKey, deviceInst, 0, KEY_READ,
+ &deviceKey);
+ if (!l)
+ {
+ WCHAR deviceClassStr[40];
+
+ len = sizeof(deviceClassStr);
+ l = RegQueryValueExW(deviceKey, ClassGUID, NULL,
+ &dataType, (BYTE *)deviceClassStr, &len);
+ if (!l && dataType == REG_SZ &&
+ deviceClassStr[0] == '{' &&
+ deviceClassStr[37] == '}')
+ {
+ GUID deviceClass;
+ SP_DEVINFO_DATA *dev;
+
+ deviceClassStr[37] = 0;
+ UuidFromStringW(&deviceClassStr[1],
+ &deviceClass);
+ if (SETUPDI_AddDeviceToSet(set, &deviceClass,
+ 0 /* FIXME: DevInst */, deviceInst,
+ FALSE, &dev))
+ SETUPDI_AddDeviceInterfaces(dev, subKey, guid);
+ }
+ RegCloseKey(deviceKey);
+ }
+ }
+ }
+ RegCloseKey(subKey);
+ }
+ /* Allow enumeration to continue */
+ l = ERROR_SUCCESS;
+ }
+ }
+ if (enumKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(enumKey);
+}
+
+static void SETUPDI_EnumerateInterfaces(HDEVINFO DeviceInfoSet,
+ const GUID *guid, LPCWSTR enumstr, DWORD flags)
+{
+ HKEY interfacesKey = SetupDiOpenClassRegKeyExW(guid, KEY_READ,
+ DIOCR_INTERFACE, NULL, NULL);
+
+ TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(guid),
+ debugstr_w(enumstr), flags);
+
+ if (interfacesKey != INVALID_HANDLE_VALUE)
+ {
+ if (flags & DIGCF_ALLCLASSES)
+ {
+ DWORD i, len;
+ WCHAR interfaceGuidStr[40];
+ LONG l = ERROR_SUCCESS;
+
+ for (i = 0; !l; i++)
+ {
+ len = sizeof(interfaceGuidStr) / sizeof(interfaceGuidStr[0]);
+ l = RegEnumKeyExW(interfacesKey, i, interfaceGuidStr, &len,
+ NULL, NULL, NULL, NULL);
+ if (!l)
+ {
+ if (interfaceGuidStr[0] == '{' &&
+ interfaceGuidStr[37] == '}')
+ {
+ HKEY interfaceKey;
+ GUID interfaceGuid;
+
+ interfaceGuidStr[37] = 0;
+ UuidFromStringW(&interfaceGuidStr[1], &interfaceGuid);
+ l = RegOpenKeyExW(interfacesKey, interfaceGuidStr, 0,
+ KEY_READ, &interfaceKey);
+ if (!l)
+ {
+ SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
+ interfaceKey, &interfaceGuid, enumstr);
+ RegCloseKey(interfaceKey);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* In this case, SetupDiOpenClassRegKeyExW opened the specific
+ * interface's key, so just pass that long
+ */
+ SETUPDI_EnumerateMatchingInterfaces(DeviceInfoSet,
+ interfacesKey, guid, enumstr);
+ }
+ RegCloseKey(interfacesKey);
+ }
+}
+
+static void SETUPDI_EnumerateMatchingDeviceInstances(struct DeviceInfoSet *set,
+ LPCWSTR enumerator, LPCWSTR deviceName, HKEY deviceKey,
+ const GUID *class, DWORD flags)
+{
+ DWORD i, len;
+ WCHAR deviceInstance[MAX_PATH];
+ LONG l = ERROR_SUCCESS;
+
+ TRACE("%s %s\n", debugstr_w(enumerator), debugstr_w(deviceName));
+
+ for (i = 0; !l; i++)
+ {
+ len = sizeof(deviceInstance) / sizeof(deviceInstance[0]);
+ l = RegEnumKeyExW(deviceKey, i, deviceInstance, &len, NULL, NULL, NULL,
+ NULL);
+ if (!l)
+ {
+ HKEY subKey;
+
+ l = RegOpenKeyExW(deviceKey, deviceInstance, 0, KEY_READ, &subKey);
+ if (!l)
+ {
+ WCHAR classGuid[40];
+ DWORD dataType;
+
+ len = sizeof(classGuid);
+ l = RegQueryValueExW(subKey, ClassGUID, NULL, &dataType,
+ (BYTE *)classGuid, &len);
+ if (!l && dataType == REG_SZ)
+ {
+ if (classGuid[0] == '{' && classGuid[37] == '}')
+ {
+ GUID deviceClass;
+
+ classGuid[37] = 0;
+ UuidFromStringW(&classGuid[1], &deviceClass);
+ if ((flags & DIGCF_ALLCLASSES) ||
+ IsEqualGUID(class, &deviceClass))
+ {
+ static const WCHAR fmt[] =
+ {'%','s','\\','%','s','\\','%','s',0};
+ LPWSTR instanceId;
+
+ instanceId = HeapAlloc(GetProcessHeap(), 0,
+ (lstrlenW(enumerator) + lstrlenW(deviceName) +
+ lstrlenW(deviceInstance) + 3) * sizeof(WCHAR));
+ if (instanceId)
+ {
+ sprintfW(instanceId, fmt, enumerator,
+ deviceName, deviceInstance);
+ SETUPDI_AddDeviceToSet(set, &deviceClass,
+ 0 /* FIXME: DevInst */, instanceId,
+ FALSE, NULL);
+ HeapFree(GetProcessHeap(), 0, instanceId);
+ }
+ }
+ }
+ }
+ RegCloseKey(subKey);
+ }
+ /* Allow enumeration to continue */
+ l = ERROR_SUCCESS;
+ }
+ }
+}
+
+static void SETUPDI_EnumerateMatchingDevices(HDEVINFO DeviceInfoSet,
+ LPCWSTR parent, HKEY key, const GUID *class, DWORD flags)
+{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ DWORD i, len;
+ WCHAR subKeyName[MAX_PATH];
+ LONG l = ERROR_SUCCESS;
+
+ TRACE("%s\n", debugstr_w(parent));
+
+ for (i = 0; !l; i++)
+ {
+ len = sizeof(subKeyName) / sizeof(subKeyName[0]);
+ l = RegEnumKeyExW(key, i, subKeyName, &len, NULL, NULL, NULL, NULL);
+ if (!l)
+ {
+ HKEY subKey;
+
+ l = RegOpenKeyExW(key, subKeyName, 0, KEY_READ, &subKey);
+ if (!l)
+ {
+ TRACE("%s\n", debugstr_w(subKeyName));
+ SETUPDI_EnumerateMatchingDeviceInstances(set, parent,
+ subKeyName, subKey, class, flags);
+ RegCloseKey(subKey);
+ }
+ /* Allow enumeration to continue */
+ l = ERROR_SUCCESS;
+ }
+ }
+}
+
+static void SETUPDI_EnumerateDevices(HDEVINFO DeviceInfoSet, const GUID *class,
+ LPCWSTR enumstr, DWORD flags)
+{
+ HKEY enumKey;
+ LONG l;
+
+ TRACE("%p, %s, %s, %08x\n", DeviceInfoSet, debugstr_guid(class),
+ debugstr_w(enumstr), flags);
+
+ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_READ, NULL,
+ &enumKey, NULL);
+ if (enumKey != INVALID_HANDLE_VALUE)
+ {
+ if (enumstr)
+ {
+ HKEY enumStrKey;
+
+ l = RegOpenKeyExW(enumKey, enumstr, 0, KEY_READ,
+ &enumStrKey);
+ if (!l)
+ {
+ SETUPDI_EnumerateMatchingDevices(DeviceInfoSet, enumstr,
+ enumStrKey, class, flags);
+ RegCloseKey(enumStrKey);
+ }
+ }
+ else
+ {
+ DWORD i, len;
+ WCHAR subKeyName[MAX_PATH];
+
+ l = ERROR_SUCCESS;
+ for (i = 0; !l; i++)
+ {
+ len = sizeof(subKeyName) / sizeof(subKeyName[0]);
+ l = RegEnumKeyExW(enumKey, i, subKeyName, &len, NULL,
+ NULL, NULL, NULL);
+ if (!l)
+ {
+ HKEY subKey;
+
+ l = RegOpenKeyExW(enumKey, subKeyName, 0, KEY_READ,
+ &subKey);
+ if (!l)
+ {
+ SETUPDI_EnumerateMatchingDevices(DeviceInfoSet,
+ subKeyName, subKey, class, flags);
+ RegCloseKey(subKey);
+ }
+ /* Allow enumeration to continue */
+ l = ERROR_SUCCESS;
+ }
+ }
+ }
+ RegCloseKey(enumKey);
+ }
+}
+
/***********************************************************************
* SetupDiGetClassDevsW (SETUPAPI.@)
*/
HWND parent,
DWORD flags)
{
- TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags);
-
- /* WinXP always succeeds, returns empty list for unknown classes */
- FIXME("returning empty list\n");
- return SetupDiCreateDeviceInfoList(class, parent);
+ return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
+ NULL);
}
/***********************************************************************
PCWSTR machine,
PVOID reserved)
{
- FIXME("stub\n");
- return NULL;
+ static const DWORD unsupportedFlags = DIGCF_DEFAULT | DIGCF_PRESENT |
+ DIGCF_PROFILE;
+ HDEVINFO set;
+
+ TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
+ debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
+ reserved);
+
+ if (!(flags & DIGCF_ALLCLASSES) && !class)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+ if (flags & unsupportedFlags)
+ WARN("unsupported flags %08x\n", flags & unsupportedFlags);
+ if (deviceset)
+ set = deviceset;
+ else
+ set = SetupDiCreateDeviceInfoListExW(class, parent, machine, reserved);
+ if (set)
+ {
+ if (machine)
+ FIXME("%s: unimplemented for remote machines\n",
+ debugstr_w(machine));
+ else if (flags & DIGCF_DEVICEINTERFACE)
+ SETUPDI_EnumerateInterfaces(set, class, enumstr, flags);
+ else
+ SETUPDI_EnumerateDevices(set, class, enumstr, flags);
+ }
+ return set;
+}
+
+/***********************************************************************
+ * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
+{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+
+ TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
+
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (!DevInfoData ||
+ DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ DevInfoData->ClassGuid = set->ClassGuid;
+ DevInfoData->RemoteMachineHandle = NULL;
+ DevInfoData->RemoteMachineName[0] = '\0';
+ return TRUE;
+}
+
+/***********************************************************************
+ * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
+{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+
+ TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
+
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (!DevInfoData ||
+ DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ DevInfoData->ClassGuid = set->ClassGuid;
+ DevInfoData->RemoteMachineHandle = NULL;
+ DevInfoData->RemoteMachineName[0] = '\0';
+ return TRUE;
+}
+
+/***********************************************************************
+ * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiCreateDeviceInterfaceA(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_DATA DeviceInfoData,
+ const GUID *InterfaceClassGuid,
+ PCSTR ReferenceString,
+ DWORD CreationFlags,
+ PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+{
+ BOOL ret;
+ LPWSTR ReferenceStringW = NULL;
+
+ TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
+ debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
+ CreationFlags, DeviceInterfaceData);
+
+ if (ReferenceString)
+ {
+ ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
+ if (ReferenceStringW == NULL) return FALSE;
+ }
+
+ ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
+ InterfaceClassGuid, ReferenceStringW, CreationFlags,
+ DeviceInterfaceData);
+
+ MyFree(ReferenceStringW);
+
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiCreateDeviceInterfaceW(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_DATA DeviceInfoData,
+ const GUID *InterfaceClassGuid,
+ PCWSTR ReferenceString,
+ DWORD CreationFlags,
+ PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ struct DeviceInfo *devInfo;
+ SP_DEVICE_INTERFACE_DATA *iface = NULL;
+ BOOL ret;
+
+ TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
+ debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
+ CreationFlags, DeviceInterfaceData);
+
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+ || !DeviceInfoData->Reserved)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+ if (devInfo->set != set)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (!InterfaceClassGuid)
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ return FALSE;
+ }
+ if ((ret = SETUPDI_AddInterfaceInstance(DeviceInfoData, InterfaceClassGuid,
+ ReferenceString, &iface)))
+ {
+ if (DeviceInterfaceData)
+ {
+ if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ ret = FALSE;
+ }
+ else
+ *DeviceInterfaceData = *iface;
+ }
+ }
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+ DWORD Reserved,
+ REGSAM samDesired,
+ HINF InfHandle,
+ PCSTR InfSectionName)
+{
+ HKEY key;
+ PWSTR InfSectionNameW = NULL;
+
+ TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
+ samDesired, InfHandle, InfSectionName);
+ if (InfHandle)
+ {
+ if (!InfSectionName)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+ InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
+ if (!InfSectionNameW)
+ return INVALID_HANDLE_VALUE;
+ }
+ key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
+ DeviceInterfaceData, Reserved, samDesired, InfHandle,
+ InfSectionNameW);
+ MyFree(InfSectionNameW);
+ return key;
+}
+
+static PWSTR SETUPDI_GetInstancePath(struct InterfaceInfo *ifaceInfo)
+{
+ static const WCHAR hash[] = {'#',0};
+ PWSTR instancePath = NULL;
+
+ if (ifaceInfo->referenceString)
+ {
+ instancePath = HeapAlloc(GetProcessHeap(), 0,
+ (lstrlenW(ifaceInfo->referenceString) + 2) * sizeof(WCHAR));
+ if (instancePath)
+ {
+ lstrcpyW(instancePath, hash);
+ lstrcatW(instancePath, ifaceInfo->referenceString);
+ }
+ else
+ SetLastError(ERROR_OUTOFMEMORY);
+ }
+ else
+ {
+ instancePath = HeapAlloc(GetProcessHeap(), 0,
+ (lstrlenW(hash) + 1) * sizeof(WCHAR));
+ if (instancePath)
+ lstrcpyW(instancePath, hash);
+ }
+ return instancePath;
+}
+
+/***********************************************************************
+ * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
+ */
+HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+ DWORD Reserved,
+ REGSAM samDesired,
+ HINF InfHandle,
+ PCWSTR InfSectionName)
+{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ HKEY key = INVALID_HANDLE_VALUE, interfacesKey;
+ LONG l;
+
+ TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
+ samDesired, InfHandle, InfSectionName);
+
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+ set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (!DeviceInterfaceData ||
+ DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
+ !DeviceInterfaceData->Reserved)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (InfHandle && !InfSectionName)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (!(l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, DeviceClasses, 0, NULL, 0,
+ samDesired, NULL, &interfacesKey, NULL)))
+ {
+ HKEY parent;
+ WCHAR bracedGuidString[39];
+
+ SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid,
+ bracedGuidString);
+ if (!(l = RegCreateKeyExW(interfacesKey, bracedGuidString, 0, NULL, 0,
+ samDesired, NULL, &parent, NULL)))
+ {
+ struct InterfaceInfo *ifaceInfo =
+ (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
+ PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
+ PWSTR interfKeyName = HeapAlloc(GetProcessHeap(), 0,
+ (lstrlenW(ifaceInfo->symbolicLink) + 1) * sizeof(WCHAR));
+ HKEY interfKey;
+ WCHAR *ptr;
+
+ lstrcpyW(interfKeyName, ifaceInfo->symbolicLink);
+ if (lstrlenW(ifaceInfo->symbolicLink) > 3)
+ {
+ interfKeyName[0] = '#';
+ interfKeyName[1] = '#';
+ interfKeyName[3] = '#';
+ }
+ ptr = strchrW(interfKeyName, '\\');
+ if (ptr)
+ *ptr = 0;
+ l = RegCreateKeyExW(parent, interfKeyName, 0, NULL, 0,
+ samDesired, NULL, &interfKey, NULL);
+ if (!l)
+ {
+ struct DeviceInfo *devInfo =
+ (struct DeviceInfo *)ifaceInfo->device->Reserved;
+
+ l = RegSetValueExW(interfKey, DeviceInstance, 0, REG_SZ,
+ (BYTE *)devInfo->instanceId,
+ (lstrlenW(devInfo->instanceId) + 1) * sizeof(WCHAR));
+ if (!l)
+ {
+ if (instancePath)
+ {
+ LONG l;
+
+ l = RegCreateKeyExW(interfKey, instancePath, 0, NULL, 0,
+ samDesired, NULL, &key, NULL);
+ if (l)
+ {
+ SetLastError(l);
+ key = INVALID_HANDLE_VALUE;
+ }
+ else if (InfHandle)
+ FIXME("INF section installation unsupported\n");
+ }
+ }
+ else
+ SetLastError(l);
+ RegCloseKey(interfKey);
+ }
+ else
+ SetLastError(l);
+ HeapFree(GetProcessHeap(), 0, interfKeyName);
+ HeapFree(GetProcessHeap(), 0, instancePath);
+ RegCloseKey(parent);
+ }
+ else
+ SetLastError(l);
+ RegCloseKey(interfacesKey);
+ }
+ else
+ SetLastError(l);
+ return key;
+}
+
+/***********************************************************************
+ * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
+ DWORD Reserved)
+{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ HKEY parent;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
+
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+ set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (!DeviceInterfaceData ||
+ DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
+ !DeviceInterfaceData->Reserved)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ parent = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid,
+ KEY_ALL_ACCESS, DIOCR_INTERFACE, NULL, NULL);
+ if (parent != INVALID_HANDLE_VALUE)
+ {
+ struct InterfaceInfo *ifaceInfo =
+ (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
+ PWSTR instancePath = SETUPDI_GetInstancePath(ifaceInfo);
+
+ if (instancePath)
+ {
+ LONG l = RegDeleteKeyW(parent, instancePath);
+
+ if (l)
+ SetLastError(l);
+ else
+ ret = TRUE;
+ HeapFree(GetProcessHeap(), 0, instancePath);
+ }
+ RegCloseKey(parent);
+ }
+ return ret;
}
/***********************************************************************
* SetupDiEnumDeviceInterfaces (SETUPAPI.@)
+ *
+ * PARAMS
+ * DeviceInfoSet [I] Set of devices from which to enumerate
+ * interfaces
+ * DeviceInfoData [I] (Optional) If specified, a specific device
+ * instance from which to enumerate interfaces.
+ * If it isn't specified, all interfaces for all
+ * devices in the set are enumerated.
+ * InterfaceClassGuid [I] The interface class to enumerate.
+ * MemberIndex [I] An index of the interface instance to enumerate.
+ * A caller should start with MemberIndex set to 0,
+ * and continue until the function fails with
+ * ERROR_NO_MORE_ITEMS.
+ * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
+ * member must be set to
+ * sizeof(SP_DEVICE_INTERFACE_DATA).
+ *
+ * RETURNS
+ * Success: non-zero value.
+ * Failure: FALSE. Call GetLastError() for more info.
*/
BOOL WINAPI SetupDiEnumDeviceInterfaces(
- HDEVINFO devinfo,
+ HDEVINFO DeviceInfoSet,
PSP_DEVINFO_DATA DeviceInfoData,
CONST GUID * InterfaceClassGuid,
DWORD MemberIndex,
PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
{
+ struct DeviceInfoSet *set = DeviceInfoSet;
BOOL ret = FALSE;
- FIXME("%p, %p, %s, 0x%08x, %p\n", devinfo, DeviceInfoData,
+ TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
- if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
- {
- struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
- if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+ set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
+ !DeviceInfoData->Reserved))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (!DeviceInterfaceData ||
+ DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (DeviceInfoData)
+ {
+ struct DeviceInfo *devInfo =
+ (struct DeviceInfo *)DeviceInfoData->Reserved;
+ struct InterfaceInstances *iface;
+
+ if ((ret = SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface)))
+ {
+ if (MemberIndex < iface->cInstances)
+ *DeviceInterfaceData = iface->instances[MemberIndex];
+ else
+ {
+ SetLastError(ERROR_NO_MORE_ITEMS);
+ ret = FALSE;
+ }
+ }
+ else
+ SetLastError(ERROR_NO_MORE_ITEMS);
+ }
+ else
+ {
+ struct DeviceInstance *devInst;
+ DWORD cEnumerated = 0;
+ BOOL found = FALSE;
+
+ LIST_FOR_EACH_ENTRY(devInst, &set->devices, struct DeviceInstance, entry)
+ {
+ struct DeviceInfo *devInfo = (struct DeviceInfo *)devInst->data.Reserved;
+ struct InterfaceInstances *iface;
+
+ if (found || cEnumerated >= MemberIndex + 1)
+ break;
+ if (SETUPDI_FindInterface(devInfo, InterfaceClassGuid, &iface))
+ {
+ if (cEnumerated + iface->cInstances < MemberIndex + 1)
+ cEnumerated += iface->cInstances;
+ else
+ {
+ DWORD instanceIndex = MemberIndex - cEnumerated;
+
+ *DeviceInterfaceData = iface->instances[instanceIndex];
+ cEnumerated += instanceIndex + 1;
+ found = TRUE;
+ ret = TRUE;
+ }
+ }
+ }
+ if (!found)
SetLastError(ERROR_NO_MORE_ITEMS);
- else
- SetLastError(ERROR_INVALID_HANDLE);
}
- else
- SetLastError(ERROR_INVALID_HANDLE);
return ret;
}
BOOL ret = FALSE;
TRACE("%p\n", devinfo);
- if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
+ if (devinfo && devinfo != INVALID_HANDLE_VALUE)
{
- struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
+ struct DeviceInfoSet *list = devinfo;
if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
{
- DWORD i;
+ struct DeviceInstance *devInst, *devInst2;
- for (i = 0; i < list->cDevices; i++)
- SETUPDI_FreeDeviceInfo(
- (struct DeviceInfo *)list->devices[i].Reserved);
- HeapFree(GetProcessHeap(), 0, list->devices);
+ LIST_FOR_EACH_ENTRY_SAFE(devInst, devInst2, &list->devices,
+ struct DeviceInstance, entry)
+ {
+ SETUPDI_FreeDeviceInfo( (struct DeviceInfo *)devInst->data.Reserved );
+ list_remove(&devInst->entry);
+ HeapFree(GetProcessHeap(), 0, devInst);
+ }
HeapFree(GetProcessHeap(), 0, list);
ret = TRUE;
}
PDWORD RequiredSize,
PSP_DEVINFO_DATA DeviceInfoData)
{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ struct InterfaceInfo *info;
+ DWORD bytesNeeded = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath[1]);
BOOL ret = FALSE;
- FIXME("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
+ TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
DeviceInterfaceData, DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
- SetLastError(ERROR_INVALID_HANDLE);
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+ set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (!DeviceInterfaceData ||
+ DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
+ !DeviceInterfaceData->Reserved)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (DeviceInterfaceDetailData &&
+ DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ return FALSE;
+ }
+ if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ return FALSE;
+ }
+ info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
+ if (info->symbolicLink)
+ bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
+ NULL, 0, NULL, NULL);
+ if (DeviceInterfaceDetailDataSize >= bytesNeeded)
+ {
+ if (info->symbolicLink)
+ WideCharToMultiByte(CP_ACP, 0, info->symbolicLink, -1,
+ DeviceInterfaceDetailData->DevicePath,
+ DeviceInterfaceDetailDataSize -
+ offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
+ NULL, NULL);
+ else
+ DeviceInterfaceDetailData->DevicePath[0] = '\0';
+ if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
+ *DeviceInfoData = *info->device;
+ ret = TRUE;
+ }
+ else
+ {
+ if (RequiredSize)
+ *RequiredSize = bytesNeeded;
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ }
return ret;
}
PDWORD RequiredSize,
PSP_DEVINFO_DATA DeviceInfoData)
{
- FIXME("(%p, %p, %p, %d, %p, %p): stub\n", DeviceInfoSet,
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ struct InterfaceInfo *info;
+ DWORD bytesNeeded = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
+ + sizeof(WCHAR); /* include NULL terminator */
+ BOOL ret = FALSE;
+
+ TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
DeviceInterfaceData, DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
- return FALSE;
+
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
+ set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (!DeviceInterfaceData ||
+ DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
+ !DeviceInterfaceData->Reserved)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
+ offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR) ||
+ DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)))
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ return FALSE;
+ }
+ if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
+ {
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ return FALSE;
+ }
+ info = (struct InterfaceInfo *)DeviceInterfaceData->Reserved;
+ if (info->symbolicLink)
+ bytesNeeded += sizeof(WCHAR)*lstrlenW(info->symbolicLink);
+ if (DeviceInterfaceDetailDataSize >= bytesNeeded)
+ {
+ if (info->symbolicLink)
+ lstrcpyW(DeviceInterfaceDetailData->DevicePath, info->symbolicLink);
+ else
+ DeviceInterfaceDetailData->DevicePath[0] = '\0';
+ if (DeviceInfoData && DeviceInfoData->cbSize == sizeof(SP_DEVINFO_DATA))
+ *DeviceInfoData = *info->device;
+ ret = TRUE;
+ }
+ else
+ {
+ if (RequiredSize)
+ *RequiredSize = bytesNeeded;
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ }
+ return ret;
}
struct PropertyMapEntry
LPCWSTR nameW;
};
-static struct PropertyMapEntry PropertyMap[] = {
+static const struct PropertyMapEntry PropertyMap[] = {
{ REG_SZ, "DeviceDesc", DeviceDesc },
{ REG_MULTI_SZ, "HardwareId", HardwareId },
{ REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
PDWORD RequiredSize)
{
BOOL ret = FALSE;
- struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+ struct DeviceInfoSet *set = DeviceInfoSet;
struct DeviceInfo *devInfo;
TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
+ if (PropertyBufferSize && PropertyBuffer == NULL)
+ {
+ SetLastError(ERROR_INVALID_DATA);
+ return FALSE;
+ }
devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
&& PropertyMap[Property].nameA)
LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
NULL, PropertyRegDataType, PropertyBuffer, &size);
- if (RequiredSize)
- *RequiredSize = size;
- if (!l)
+ if (l == ERROR_MORE_DATA || !PropertyBufferSize)
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ else if (!l)
ret = TRUE;
else
SetLastError(l);
+ if (RequiredSize)
+ *RequiredSize = size;
}
return ret;
}
PDWORD RequiredSize)
{
BOOL ret = FALSE;
- struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+ struct DeviceInfoSet *set = DeviceInfoSet;
struct DeviceInfo *devInfo;
TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
+ if (PropertyBufferSize && PropertyBuffer == NULL)
+ {
+ SetLastError(ERROR_INVALID_DATA);
+ return FALSE;
+ }
devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
&& PropertyMap[Property].nameW)
LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
NULL, PropertyRegDataType, PropertyBuffer, &size);
- if (RequiredSize)
- *RequiredSize = size;
- if (!l)
+ if (l == ERROR_MORE_DATA || !PropertyBufferSize)
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ else if (!l)
ret = TRUE;
else
SetLastError(l);
+ if (RequiredSize)
+ *RequiredSize = size;
}
return ret;
}
DWORD PropertyBufferSize)
{
BOOL ret = FALSE;
- struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+ struct DeviceInfoSet *set = DeviceInfoSet;
struct DeviceInfo *devInfo;
TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
DWORD PropertyBufferSize)
{
BOOL ret = FALSE;
- struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
+ struct DeviceInfoSet *set = DeviceInfoSet;
struct DeviceInfo *devInfo;
TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
UNICODE_STRING FileNameW;
BOOL Result;
+ if (!InfFileName)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
static HKEY CreateClassKey(HINF hInf)
{
+ static const WCHAR slash[] = { '\\',0 };
WCHAR FullBuffer[MAX_PATH];
WCHAR Buffer[MAX_PATH];
DWORD RequiredSize;
}
lstrcpyW(FullBuffer, ControlClass);
+ lstrcatW(FullBuffer, slash);
lstrcatW(FullBuffer, Buffer);
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
FIXME("\n");
+ if (!InfFileName)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
{
SetLastError(ERROR_INVALID_PARAMETER);
/* Try to append a layout file */
-#if 0
SetupOpenAppendInfFileW(NULL, hInf, NULL);
-#endif
/* Retrieve the actual section name */
SetupDiGetActualSectionToInstallW(hInf,
SetupInstallFromInfSectionW(NULL,
hInf,
SectionName,
- SPINST_REGISTRY,
+ SPINST_COPYINF | SPINST_FILES | SPINST_REGISTRY,
hClassKey,
NULL,
0,
PCWSTR MachineName,
PVOID Reserved)
{
- WCHAR bracedGuidString[39];
HKEY hClassesKey;
- HKEY hClassKey;
+ HKEY key;
LPCWSTR lpKeyName;
+ LONG l;
if (MachineName != NULL)
{
return INVALID_HANDLE_VALUE;
}
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
- lpKeyName,
- 0,
- KEY_ALL_ACCESS,
- &hClassesKey))
+ if (!ClassGuid)
{
- return INVALID_HANDLE_VALUE;
+ if ((l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ lpKeyName,
+ 0,
+ samDesired,
+ &hClassesKey)))
+ {
+ SetLastError(l);
+ hClassesKey = INVALID_HANDLE_VALUE;
+ }
+ key = hClassesKey;
}
-
- if (ClassGuid == NULL)
- return hClassesKey;
-
- SETUPDI_GuidToString(ClassGuid, bracedGuidString);
-
- if (RegOpenKeyExW(hClassesKey,
- bracedGuidString,
- 0,
- KEY_ALL_ACCESS,
- &hClassKey))
+ else
{
- RegCloseKey(hClassesKey);
- return INVALID_HANDLE_VALUE;
- }
+ WCHAR bracedGuidString[39];
- RegCloseKey(hClassesKey);
+ SETUPDI_GuidToString(ClassGuid, bracedGuidString);
- return hClassKey;
+ if (!(l = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+ lpKeyName,
+ 0,
+ samDesired,
+ &hClassesKey)))
+ {
+ if ((l = RegOpenKeyExW(hClassesKey,
+ bracedGuidString,
+ 0,
+ samDesired,
+ &key)))
+ {
+ SetLastError(l);
+ key = INVALID_HANDLE_VALUE;
+ }
+ RegCloseKey(hClassesKey);
+ }
+ else
+ {
+ SetLastError(l);
+ key = INVALID_HANDLE_VALUE;
+ }
+ }
+ return key;
}
/***********************************************************************
return FALSE;
}
+static HKEY SETUPDI_OpenDevKey(struct DeviceInfo *devInfo, REGSAM samDesired)
+{
+ HKEY enumKey, key = INVALID_HANDLE_VALUE;
+ LONG l;
+
+ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
+ NULL, &enumKey, NULL);
+ if (!l)
+ {
+ RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key);
+ RegCloseKey(enumKey);
+ }
+ return key;
+}
+
+static HKEY SETUPDI_OpenDrvKey(struct DeviceInfo *devInfo, REGSAM samDesired)
+{
+ static const WCHAR slash[] = { '\\',0 };
+ WCHAR classKeyPath[MAX_PATH];
+ HKEY classKey, key = INVALID_HANDLE_VALUE;
+ LONG l;
+
+ lstrcpyW(classKeyPath, ControlClass);
+ lstrcatW(classKeyPath, slash);
+ SETUPDI_GuidToString(&devInfo->set->ClassGuid,
+ classKeyPath + lstrlenW(classKeyPath));
+ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
+ KEY_ALL_ACCESS, NULL, &classKey, NULL);
+ if (!l)
+ {
+ static const WCHAR fmt[] = { '%','0','4','u',0 };
+ WCHAR devId[10];
+
+ sprintfW(devId, fmt, devInfo->devId);
+ RegOpenKeyExW(classKey, devId, 0, samDesired, &key);
+ RegCloseKey(classKey);
+ }
+ return key;
+}
+
/***********************************************************************
* SetupDiOpenDevRegKey (SETUPAPI.@)
*/
DWORD KeyType,
REGSAM samDesired)
{
- FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ struct DeviceInfo *devInfo;
+ HKEY key = INVALID_HANDLE_VALUE;
+
+ TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
Scope, HwProfile, KeyType, samDesired);
- return INVALID_HANDLE_VALUE;
+
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+ || !DeviceInfoData->Reserved)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
+ {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
+ {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return INVALID_HANDLE_VALUE;
+ }
+ devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+ if (devInfo->set != set)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (devInfo->phantom)
+ {
+ SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
+ return INVALID_HANDLE_VALUE;
+ }
+ if (Scope != DICS_FLAG_GLOBAL)
+ FIXME("unimplemented for scope %d\n", Scope);
+ switch (KeyType)
+ {
+ case DIREG_DEV:
+ key = SETUPDI_OpenDevKey(devInfo, samDesired);
+ break;
+ case DIREG_DRV:
+ key = SETUPDI_OpenDrvKey(devInfo, samDesired);
+ break;
+ default:
+ WARN("unknown KeyType %d\n", KeyType);
+ }
+ return key;
+}
+
+static BOOL SETUPDI_DeleteDevKey(struct DeviceInfo *devInfo)
+{
+ HKEY enumKey;
+ BOOL ret = FALSE;
+ LONG l;
+
+ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0, KEY_ALL_ACCESS,
+ NULL, &enumKey, NULL);
+ if (!l)
+ {
+ ret = RegDeleteTreeW(enumKey, devInfo->instanceId);
+ RegCloseKey(enumKey);
+ }
+ else
+ SetLastError(l);
+ return ret;
+}
+
+static BOOL SETUPDI_DeleteDrvKey(struct DeviceInfo *devInfo)
+{
+ static const WCHAR slash[] = { '\\',0 };
+ WCHAR classKeyPath[MAX_PATH];
+ HKEY classKey;
+ LONG l;
+ BOOL ret = FALSE;
+
+ lstrcpyW(classKeyPath, ControlClass);
+ lstrcatW(classKeyPath, slash);
+ SETUPDI_GuidToString(&devInfo->set->ClassGuid,
+ classKeyPath + lstrlenW(classKeyPath));
+ l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, classKeyPath, 0, NULL, 0,
+ KEY_ALL_ACCESS, NULL, &classKey, NULL);
+ if (!l)
+ {
+ static const WCHAR fmt[] = { '%','0','4','u',0 };
+ WCHAR devId[10];
+
+ sprintfW(devId, fmt, devInfo->devId);
+ ret = RegDeleteTreeW(classKey, devId);
+ RegCloseKey(classKey);
+ }
+ else
+ SetLastError(l);
+ return ret;
+}
+
+/***********************************************************************
+ * SetupDiDeleteDevRegKey (SETUPAPI.@)
+ */
+BOOL WINAPI SetupDiDeleteDevRegKey(
+ HDEVINFO DeviceInfoSet,
+ PSP_DEVINFO_DATA DeviceInfoData,
+ DWORD Scope,
+ DWORD HwProfile,
+ DWORD KeyType)
+{
+ struct DeviceInfoSet *set = DeviceInfoSet;
+ struct DeviceInfo *devInfo;
+ BOOL ret = FALSE;
+
+ TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile,
+ KeyType);
+
+ if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
+ {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
+ if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
+ || !DeviceInfoData->Reserved)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
+ {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return FALSE;
+ }
+ if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH)
+ {
+ SetLastError(ERROR_INVALID_FLAGS);
+ return FALSE;
+ }
+ devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+ if (devInfo->set != set)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+ if (devInfo->phantom)
+ {
+ SetLastError(ERROR_DEVINFO_NOT_REGISTERED);
+ return FALSE;
+ }
+ if (Scope != DICS_FLAG_GLOBAL)
+ FIXME("unimplemented for scope %d\n", Scope);
+ switch (KeyType)
+ {
+ case DIREG_DEV:
+ ret = SETUPDI_DeleteDevKey(devInfo);
+ break;
+ case DIREG_DRV:
+ ret = SETUPDI_DeleteDrvKey(devInfo);
+ break;
+ case DIREG_BOTH:
+ ret = SETUPDI_DeleteDevKey(devInfo);
+ if (ret)
+ ret = SETUPDI_DeleteDrvKey(devInfo);
+ break;
+ default:
+ WARN("unknown KeyType %d\n", KeyType);
+ }
+ return ret;
+}
+
+/***********************************************************************
+ * CM_Get_Device_IDA (SETUPAPI.@)
+ */
+CONFIGRET WINAPI CM_Get_Device_IDA( DEVINST dnDevInst, PSTR Buffer,
+ ULONG BufferLen, ULONG ulFlags)
+{
+ struct DeviceInfo *devInfo = GlobalLock((HANDLE)dnDevInst);
+
+ TRACE("%x->%p, %p, %u %u\n", dnDevInst, devInfo, Buffer, BufferLen, ulFlags);
+
+ if (!devInfo)
+ return CR_NO_SUCH_DEVINST;
+
+ WideCharToMultiByte(CP_ACP, 0, devInfo->instanceId, -1, Buffer, BufferLen, 0, 0);
+ TRACE("Returning %s\n", debugstr_a(Buffer));
+ return CR_SUCCESS;
+}
+
+/***********************************************************************
+ * CM_Get_Device_IDW (SETUPAPI.@)
+ */
+CONFIGRET WINAPI CM_Get_Device_IDW( DEVINST dnDevInst, LPWSTR Buffer,
+ ULONG BufferLen, ULONG ulFlags)
+{
+ struct DeviceInfo *devInfo = GlobalLock((HANDLE)dnDevInst);
+
+ TRACE("%x->%p, %p, %u %u\n", dnDevInst, devInfo, Buffer, BufferLen, ulFlags);
+
+ if (!devInfo)
+ {
+ WARN("dev instance %d not found!\n", dnDevInst);
+ return CR_NO_SUCH_DEVINST;
+ }
+
+ lstrcpynW(Buffer, devInfo->instanceId, BufferLen);
+ TRACE("Returning %s\n", debugstr_w(Buffer));
+ GlobalUnlock((HANDLE)dnDevInst);
+ return CR_SUCCESS;
+}
+
+
+
+/***********************************************************************
+ * CM_Get_Device_ID_Size (SETUPAPI.@)
+ */
+CONFIGRET WINAPI CM_Get_Device_ID_Size( PULONG pulLen, DEVINST dnDevInst,
+ ULONG ulFlags)
+{
+ struct DeviceInfo *ppdevInfo = GlobalLock((HANDLE)dnDevInst);
+
+ TRACE("%x->%p, %p, %u\n", dnDevInst, ppdevInfo, pulLen, ulFlags);
+
+ if (!ppdevInfo)
+ {
+ WARN("dev instance %d not found!\n", dnDevInst);
+ return CR_NO_SUCH_DEVINST;
+ }
+
+ *pulLen = lstrlenW(ppdevInfo->instanceId);
+ GlobalUnlock((HANDLE)dnDevInst);
+ return CR_SUCCESS;
}