Implement SetupDiGetClassDevsA/W, SetupDiEnumDeviceInterfaces,
SetupDiDestroyDeviceInfoList, and SetupDiGetDeviceInterfaceDetailA for serial ports.
This commit is contained in:
parent
10e3d96617
commit
47f1c88817
|
@ -34,7 +34,8 @@
|
|||
#include "setupapi.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
#include "initguid.h"
|
||||
#include "winioctl.h"
|
||||
#include "rpc.h"
|
||||
#include "rpcdce.h"
|
||||
|
||||
|
@ -583,15 +584,6 @@ SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
|
|||
return (HDEVINFO)INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiDestroyDeviceInfoList (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
|
||||
{
|
||||
FIXME("%p\n", devinfo);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiEnumDeviceInfo (SETUPAPI.@)
|
||||
*/
|
||||
|
@ -610,20 +602,6 @@ BOOL WINAPI SetupDiEnumDeviceInfo(
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiEnumDeviceInterfaces (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupDiEnumDeviceInterfaces(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
CONST GUID * InterfaceClassGuid,
|
||||
DWORD MemberIndex,
|
||||
PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
|
||||
{
|
||||
FIXME("\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiGetActualSectionToInstallA (SETUPAPI.@)
|
||||
*/
|
||||
|
@ -827,9 +805,111 @@ HDEVINFO WINAPI SetupDiGetClassDevsA(
|
|||
HWND parent,
|
||||
DWORD flags)
|
||||
{
|
||||
FIXME("%s %s %p %08lx\n",debugstr_guid(class),enumstr,parent,flags);
|
||||
HDEVINFO ret;
|
||||
LPWSTR enumstrW = NULL;
|
||||
|
||||
return (HDEVINFO) INVALID_HANDLE_VALUE;
|
||||
if (enumstr)
|
||||
{
|
||||
int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
|
||||
enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
|
||||
if (!enumstrW)
|
||||
{
|
||||
ret = (HDEVINFO)INVALID_HANDLE_VALUE;
|
||||
goto end;
|
||||
}
|
||||
MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
|
||||
}
|
||||
ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
|
||||
HeapFree(GetProcessHeap(), 0, enumstrW);
|
||||
|
||||
end:
|
||||
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 = (LPWSTR)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))
|
||||
{
|
||||
strncpyW(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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -841,9 +921,108 @@ HDEVINFO WINAPI SetupDiGetClassDevsW(
|
|||
HWND parent,
|
||||
DWORD flags)
|
||||
{
|
||||
FIXME("%s %s %p %08lx\n",debugstr_guid(class),debugstr_w(enumstr),parent,flags);
|
||||
HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;
|
||||
|
||||
return (HDEVINFO) INVALID_HANDLE_VALUE;
|
||||
TRACE("%s %s %p 0x%08lx\n", debugstr_guid(class), debugstr_w(enumstr),
|
||||
parent, flags);
|
||||
|
||||
if (enumstr)
|
||||
FIXME(": unimplemented for enumerator strings (%s)\n",
|
||||
debugstr_w(enumstr));
|
||||
else if (flags & DIGCF_ALLCLASSES)
|
||||
FIXME(": unimplemented for DIGCF_ALLCLASSES\n");
|
||||
else
|
||||
{
|
||||
if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT))
|
||||
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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiEnumDeviceInterfaces (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupDiEnumDeviceInterfaces(
|
||||
HDEVINFO DeviceInfoSet,
|
||||
PSP_DEVINFO_DATA DeviceInfoData,
|
||||
CONST GUID * InterfaceClassGuid,
|
||||
DWORD MemberIndex,
|
||||
PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData,
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetupDiDestroyDeviceInfoList (SETUPAPI.@)
|
||||
*/
|
||||
BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("%p\n", devinfo);
|
||||
if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* FIXME: this assumes the only possible enumeration is of serial
|
||||
* ports.
|
||||
*/
|
||||
SerialPortList *list = (SerialPortList *)devinfo;
|
||||
|
||||
if (list->magic == SETUP_SERIAL_PORT_MAGIC)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, list);
|
||||
ret = TRUE;
|
||||
}
|
||||
else
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
}
|
||||
else
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -857,8 +1036,67 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
|
|||
PDWORD RequiredSize,
|
||||
PSP_DEVINFO_DATA DeviceInfoData)
|
||||
{
|
||||
FIXME("\n");
|
||||
return FALSE;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
|
||||
DeviceInterfaceData, DeviceInterfaceDetailData,
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -872,7 +1110,9 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
|
|||
PDWORD RequiredSize,
|
||||
PSP_DEVINFO_DATA DeviceInfoData)
|
||||
{
|
||||
FIXME("\n");
|
||||
FIXME("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet,
|
||||
DeviceInterfaceData, DeviceInterfaceDetailData,
|
||||
DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -391,6 +391,18 @@ typedef struct _FILE_FS_ATTRIBUTE_INFORMATION {
|
|||
WCHAR FileSystemName[1];
|
||||
} FILE_FS_ATTRIBUTE_INFORMATION, *PFILE_FS_ATTRIBUTE_INFORMATION;
|
||||
|
||||
/* Device GUIDs */
|
||||
#ifdef DEFINE_GUID
|
||||
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_COMPORT, 0x86E0D1E0L, 0x8089,
|
||||
0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73);
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, 0x4D36E978L, 0xE325,
|
||||
0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
|
||||
|
||||
/* obsolete GUID names */
|
||||
#define GUID_CLASS_COMPORT GUID_DEVINTERFACE_COMPORT
|
||||
#define GUID_SERENUM_BUS_ENUMERATOR GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
|
||||
|
||||
#endif /* DEFINE_GUID */
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue