From 47f1c88817d03d43b72dd11418dc8c33edcc5469 Mon Sep 17 00:00:00 2001 From: Juan Lang Date: Tue, 1 Mar 2005 11:44:27 +0000 Subject: [PATCH] Implement SetupDiGetClassDevsA/W, SetupDiEnumDeviceInterfaces, SetupDiDestroyDeviceInfoList, and SetupDiGetDeviceInterfaceDetailA for serial ports. --- dlls/setupapi/devinst.c | 302 +++++++++++++++++++++++++++++++++++----- include/winioctl.h | 12 ++ 2 files changed, 283 insertions(+), 31 deletions(-) diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 8b78832f20d..3f6ce9d38c0 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -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; } diff --git a/include/winioctl.h b/include/winioctl.h index 20e3417b6a4..4aff99eebfa 100644 --- a/include/winioctl.h +++ b/include/winioctl.h @@ -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