setupapi: Implement SetupDiCreateDeviceInfoListExW.

This commit is contained in:
Christian Gmeiner 2006-06-13 19:13:32 +02:00 committed by Alexandre Julliard
parent 682679b07c
commit 8f5d90b44d
5 changed files with 148 additions and 194 deletions

View File

@ -7,7 +7,7 @@ MODULE = setupapi.dll
IMPORTLIB = libsetupapi.$(IMPLIBEXT) IMPORTLIB = libsetupapi.$(IMPLIBEXT)
IMPORTS = user32 version advapi32 rpcrt4 kernel32 ntdll IMPORTS = user32 version advapi32 rpcrt4 kernel32 ntdll
DELAYIMPORTS = shell32 DELAYIMPORTS = shell32
EXTRALIBS = $(LIBUNICODE) EXTRALIBS = $(LIBUNICODE) -luuid
C_SRCS = \ C_SRCS = \
devinst.c \ devinst.c \

View File

@ -68,6 +68,16 @@ static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\',
'C','o','n','t','r','o','l','\\', 'C','o','n','t','r','o','l','\\',
'D','e','v','i','c','e','C','l','a','s','s','e','s',0}; 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
/* is used to identify if a DeviceInfoSet pointer is
valid or not */
#define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
struct DeviceInfoSet
{
DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
GUID ClassGuid;
HWND hwndParent;
};
/*********************************************************************** /***********************************************************************
* SetupDiBuildClassInfoList (SETUPAPI.@) * SetupDiBuildClassInfoList (SETUPAPI.@)
@ -634,6 +644,20 @@ SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
/*********************************************************************** /***********************************************************************
* SetupDiCreateDeviceInfoListExW (SETUPAPI.@) * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
*
* Create an empty DeviceInfoSet list.
*
* PARAMS
* ClassGuid [I] if not NULL only devices with GUID ClcassGuid 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
* local regestry will be used.
* Reserved [I] must be NULL
*
* RETURNS
* Success: empty list.
* Failure: INVALID_HANDLE_VALUE.
*/ */
HDEVINFO WINAPI HDEVINFO WINAPI
SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid, SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
@ -641,8 +665,39 @@ SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
PCWSTR MachineName, PCWSTR MachineName,
PVOID Reserved) PVOID Reserved)
{ {
FIXME("\n"); struct DeviceInfoSet *list = NULL;
return (HDEVINFO)INVALID_HANDLE_VALUE; DWORD size = sizeof(struct DeviceInfoSet);
TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
debugstr_w(MachineName), Reserved);
if (MachineName != NULL)
{
FIXME("remote support is not implemented");
SetLastError(ERROR_INVALID_MACHINENAME);
return (HDEVINFO)INVALID_HANDLE_VALUE;
}
if (Reserved != NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return (HDEVINFO)INVALID_HANDLE_VALUE;
}
list = HeapAlloc(GetProcessHeap(), 0, size);
if (!list)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return (HDEVINFO)INVALID_HANDLE_VALUE;
}
list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
list->hwndParent = hwndParent;
memcpy(&list->ClassGuid,
ClassGuid ? ClassGuid : &GUID_NULL,
sizeof(list->ClassGuid));
return (HDEVINFO)list;
} }
/*********************************************************************** /***********************************************************************
@ -887,91 +942,6 @@ end:
return ret; return ret;
} }
#define SETUP_SERIAL_PORT_MAGIC 0xd00ff055
typedef struct _SerialPortName
{
WCHAR name[5];
} SerialPortName;
typedef struct _SerialPortList
{
DWORD magic;
UINT numPorts;
SerialPortName names[1];
} SerialPortList;
static HDEVINFO SETUP_CreateSerialDeviceList(void)
{
static const size_t initialSize = 100;
size_t size;
WCHAR buf[initialSize];
LPWSTR devices;
HDEVINFO ret;
BOOL failed = FALSE;
devices = buf;
size = initialSize;
do {
if (QueryDosDeviceW(NULL, devices, size) == 0)
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
size *= 2;
if (devices != buf)
HeapFree(GetProcessHeap(), 0, devices);
devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
if (!devices)
failed = TRUE;
else
*devices = 0;
}
else
failed = TRUE;
}
} while (!*devices && !failed);
if (!failed)
{
static const WCHAR comW[] = { 'C','O','M',0 };
LPWSTR ptr;
UINT numSerialPorts = 0;
SerialPortList *list;
for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
{
if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1))
numSerialPorts++;
}
list = HeapAlloc(GetProcessHeap(), 0, sizeof(SerialPortList) +
numSerialPorts ? (numSerialPorts - 1) * sizeof(SerialPortName) : 0);
if (list)
{
list->magic = SETUP_SERIAL_PORT_MAGIC;
list->numPorts = 0;
for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
{
if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1))
{
lstrcpynW(list->names[list->numPorts].name, ptr,
sizeof(list->names[list->numPorts].name) /
sizeof(list->names[list->numPorts].name[0]));
TRACE("Adding %s to list\n",
debugstr_w(list->names[list->numPorts].name));
list->numPorts++;
}
}
TRACE("list->numPorts is %d\n", list->numPorts);
}
ret = (HDEVINFO)list;
}
else
ret = (HDEVINFO)INVALID_HANDLE_VALUE;
if (devices != buf)
HeapFree(GetProcessHeap(), 0, devices);
TRACE("returning %p\n", ret);
return ret;
}
/*********************************************************************** /***********************************************************************
* SetupDiGetClassDevsW (SETUPAPI.@) * SetupDiGetClassDevsW (SETUPAPI.@)
*/ */
@ -993,12 +963,7 @@ HDEVINFO WINAPI SetupDiGetClassDevsW(
FIXME(": unimplemented for DIGCF_ALLCLASSES\n"); FIXME(": unimplemented for DIGCF_ALLCLASSES\n");
else else
{ {
if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT)) FIXME("(%s): stub\n", debugstr_guid(class));
ret = SETUP_CreateSerialDeviceList();
else if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR))
ret = SETUP_CreateSerialDeviceList();
else
FIXME("(%s): stub\n", debugstr_guid(class));
} }
return ret; return ret;
} }
@ -1015,50 +980,24 @@ BOOL WINAPI SetupDiEnumDeviceInterfaces(
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
TRACE("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData, FIXME("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData,
debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
if (!DeviceInterfaceData)
SetLastError(ERROR_INVALID_PARAMETER);
else if (DeviceInfoData)
FIXME(": unimplemented with PSP_DEVINFO_DATA set\n");
else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
{
/* FIXME: this assumes the only possible enumeration is of serial
* ports.
*/
SerialPortList *list = (SerialPortList *)DeviceInfoSet;
if (list->magic == SETUP_SERIAL_PORT_MAGIC) SetLastError(ERROR_INVALID_HANDLE);
{
if (MemberIndex >= list->numPorts)
SetLastError(ERROR_NO_MORE_ITEMS);
else
{
DeviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
memcpy(&DeviceInterfaceData->InterfaceClassGuid,
&GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
sizeof(DeviceInterfaceData->InterfaceClassGuid));
DeviceInterfaceData->Flags = 0;
/* 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)&list->names[MemberIndex].name;
ret = TRUE;
}
}
else
SetLastError(ERROR_INVALID_HANDLE);
}
else
SetLastError(ERROR_INVALID_HANDLE);
return ret; return ret;
} }
/*********************************************************************** /***********************************************************************
* SetupDiDestroyDeviceInfoList (SETUPAPI.@) * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
*
* Destroy a DeviceInfoList and free all used memory of the list.
*
* PARAMS
* devinfo [I] DeviceInfoList pointer to list to destroy
*
* RETURNS
* Success: non zero value.
* Failure: zero value.
*/ */
BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo) BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
{ {
@ -1067,21 +1006,18 @@ BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
TRACE("%p\n", devinfo); TRACE("%p\n", devinfo);
if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE) if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
{ {
/* FIXME: this assumes the only possible enumeration is of serial struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
* ports.
*/
SerialPortList *list = (SerialPortList *)devinfo;
if (list->magic == SETUP_SERIAL_PORT_MAGIC) if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
{ {
HeapFree(GetProcessHeap(), 0, list); HeapFree(GetProcessHeap(), 0, list);
ret = TRUE; ret = TRUE;
} }
else
SetLastError(ERROR_INVALID_HANDLE);
} }
else
if (ret == FALSE)
SetLastError(ERROR_INVALID_HANDLE); SetLastError(ERROR_INVALID_HANDLE);
return ret; return ret;
} }
@ -1098,64 +1034,11 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet, FIXME("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
DeviceInterfaceData, DeviceInterfaceDetailData, DeviceInterfaceData, DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
if (!DeviceInterfaceData)
SetLastError(ERROR_INVALID_PARAMETER);
else if ((DeviceInterfaceDetailDataSize && !DeviceInterfaceDetailData) ||
(DeviceInterfaceDetailData && !DeviceInterfaceDetailDataSize))
SetLastError(ERROR_INVALID_PARAMETER);
else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
{
/* FIXME: this assumes the only possible enumeration is of serial
* ports.
*/
SerialPortList *list = (SerialPortList *)DeviceInfoSet;
if (list->magic == SETUP_SERIAL_PORT_MAGIC) SetLastError(ERROR_INVALID_HANDLE);
{
LPCWSTR devName = (LPCWSTR)DeviceInterfaceData->Reserved;
DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A) +
lstrlenW(devName);
if (sizeRequired > DeviceInterfaceDetailDataSize)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
if (RequiredSize)
*RequiredSize = sizeRequired;
}
else
{
LPSTR dst = DeviceInterfaceDetailData->DevicePath;
LPCWSTR src = devName;
/* MSDN claims cbSize must be set by the caller, but it lies */
DeviceInterfaceDetailData->cbSize =
sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
for ( ; *src; src++, dst++)
*dst = *src;
*dst = '\0';
TRACE("DevicePath is %s\n",
debugstr_a(DeviceInterfaceDetailData->DevicePath));
if (DeviceInfoData)
{
DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
memcpy(&DeviceInfoData->ClassGuid,
&GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
sizeof(DeviceInfoData->ClassGuid));
DeviceInfoData->DevInst = 0;
DeviceInfoData->Reserved = (ULONG_PTR)devName;
}
ret = TRUE;
}
}
else
SetLastError(ERROR_INVALID_HANDLE);
}
else
SetLastError(ERROR_INVALID_HANDLE);
TRACE("Returning %d\n", ret);
return ret; return ret;
} }

View File

@ -1,4 +1,5 @@
Makefile Makefile
devinst.ok
parser.ok parser.ok
query.ok query.ok
stringtable.ok stringtable.ok

View File

@ -6,6 +6,7 @@ TESTDLL = setupapi.dll
IMPORTS = setupapi kernel32 IMPORTS = setupapi kernel32
CTESTS = \ CTESTS = \
devinst.c \
parser.c \ parser.c \
query.c \ query.c \
stringtable.c stringtable.c

View File

@ -0,0 +1,69 @@
/*
* Devinst tests
*
* Copyright 2006 Christian Gmeiner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <assert.h>
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "setupapi.h"
#include "wine/test.h"
static void test_Device_Info_List(void)
{
HDEVINFO devlist;
BOOL ret;
DWORD error;
static const WCHAR machine[] = { 'd','u','m','m','y',0 };
SetLastError(0xdeadbeef);
/* create empty DeviceInfoList, but set Reserved to a value, which is not NULL */
devlist = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, "NotNull");
error = GetLastError();
ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %ld (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
ok(error == ERROR_INVALID_PARAMETER, "GetLastError returned wrong value : %ld, (expected %d)", error, ERROR_INVALID_PARAMETER);
SetLastError(0xdeadbeef);
/* create empty DeviceInfoList, but set MachineName to something */
devlist = SetupDiCreateDeviceInfoListExW(NULL, NULL, machine, NULL);
error = GetLastError();
ok(devlist == INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %ld (expected %p)\n", devlist, error, INVALID_HANDLE_VALUE);
ok(error == ERROR_INVALID_MACHINENAME, "GetLastError returned wrong value : %ld, (expected %d)", error, ERROR_INVALID_MACHINENAME);
/* create empty DeviceInfoList */
devlist = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
ok(devlist && devlist != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed : %p %ld (expected != %p)\n", devlist, error, INVALID_HANDLE_VALUE);
/* destroy DeviceInfoList */
ret = SetupDiDestroyDeviceInfoList(devlist);
ok(ret, "SetupDiDestroyDeviceInfoList failed : %ld", error);
}
START_TEST(devinst)
{
test_Device_Info_List();
}