From 9132d199da757e596a5908f98992a5c19592ed3d Mon Sep 17 00:00:00 2001 From: Alexander Morozov Date: Tue, 23 Jun 2009 16:16:51 +0400 Subject: [PATCH] setupapi: Implement CM_Get_Parent for USB and USBSTOR devices. --- dlls/cfgmgr32/cfgmgr32.spec | 2 +- dlls/setupapi/devinst.c | 167 ++++++++++++++++++++++++++++++++++++ dlls/setupapi/setupapi.spec | 2 +- dlls/setupapi/stubs.c | 10 --- 4 files changed, 169 insertions(+), 12 deletions(-) diff --git a/dlls/cfgmgr32/cfgmgr32.spec b/dlls/cfgmgr32/cfgmgr32.spec index f080e7d8f5..d109b2b606 100644 --- a/dlls/cfgmgr32/cfgmgr32.spec +++ b/dlls/cfgmgr32/cfgmgr32.spec @@ -105,7 +105,7 @@ @ stub CM_Get_Next_Res_Des @ stub CM_Get_Next_Res_Des_Ex @ stdcall CM_Get_Parent(ptr long long) setupapi.CM_Get_Parent -@ stub CM_Get_Parent_Ex +@ stdcall CM_Get_Parent_Ex(ptr long long ptr) setupapi.CM_Get_Parent_Ex @ stub CM_Get_Res_Des_Data @ stub CM_Get_Res_Des_Data_Ex @ stub CM_Get_Res_Des_Data_Size diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 8a181381a8..9f56663870 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -23,6 +23,8 @@ #include +#define INITGUID + #include "windef.h" #include "winbase.h" #include "winnt.h" @@ -39,6 +41,10 @@ #include "winioctl.h" #include "rpc.h" #include "rpcdce.h" +#define WINE_MOUNTMGR_EXTENSIONS +#include "ntddstor.h" +#define WINE_USBHUB_EXTENSIONS +#include "ddk/usbioctl.h" #include "setupapi_private.h" @@ -130,6 +136,7 @@ struct InterfaceInstances struct DeviceInfo { struct DeviceInfoSet *set; + struct DeviceInfo *parent; HKEY key; BOOL phantom; DWORD devId; @@ -465,6 +472,7 @@ static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(struct DeviceInfoSet *set, if (devInfo) { devInfo->set = set; + devInfo->parent = NULL; devInfo->devId = (DWORD)devInst; devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0, @@ -499,6 +507,8 @@ static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo) { struct InterfaceInstances *iface, *next; + if (devInfo->parent) + SETUPDI_FreeDeviceInfo(devInfo->parent); if (devInfo->key != INVALID_HANDLE_VALUE) RegCloseKey(devInfo->key); if (devInfo->phantom) @@ -3973,3 +3983,160 @@ CONFIGRET WINAPI CM_Get_Device_ID_Size( PULONG pulLen, DEVINST dnDevInst, GlobalUnlock((HANDLE)dnDevInst); return CR_SUCCESS; } + +static const WCHAR usbpdoW[] = {'\\','D','e','v','i','c','e','\\', + 'U','S','B','P','D','O','-','%','u',0}; + +static BOOL SETUPDI_GetUsbstorParent( struct DeviceInfo *devInfo, LPWSTR Buffer ) +{ + static const WCHAR usbstorW[] = {'u','s','b','s','t','o','r','\\',0}; + struct InterfaceInstances *iface; + struct InterfaceInfo *ifaceInfo; + struct usb_device_address usbda; + struct usb_device_info usbDevInfo; + OBJECT_ATTRIBUTES attr; + UNICODE_STRING name; + IO_STATUS_BLOCK io; + HANDLE dev; + WCHAR *pdoName; + BOOL ret; + + if (strncmpiW(devInfo->instanceId, usbstorW, strlenW(usbstorW))) + return FALSE; + + if (!SETUPDI_FindInterface(devInfo, &GUID_DEVINTERFACE_DISK, &iface) || + !iface->cInstances || !iface->instances[0].Reserved) + return FALSE; + ifaceInfo = (struct InterfaceInfo *)iface->instances[0].Reserved; + dev = CreateFileW(ifaceInfo->symbolicLink, GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + if (dev == INVALID_HANDLE_VALUE) return FALSE; + ret = DeviceIoControl(dev, IOCTL_STORAGE_USB_DEVICE_ADDRESS, + &usbda, sizeof(usbda), &usbda, sizeof(usbda), NULL, NULL); + CloseHandle(dev); + if (!ret) return FALSE; + + pdoName = HeapAlloc(GetProcessHeap(), 0, 30 * sizeof(WCHAR)); + if (!pdoName) return FALSE; + snprintfW(pdoName, 30, usbpdoW, usbda.bus - 1); + RtlInitUnicodeString(&name, pdoName); + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &name; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + if (NtOpenFile(&dev, GENERIC_READ|GENERIC_WRITE, &attr, &io, + FILE_SHARE_READ|FILE_SHARE_WRITE, 0)) + { + HeapFree(GetProcessHeap(), 0, pdoName); + return FALSE; + } + ret = FALSE; + usbDevInfo.connection_index = 1; + while (!ret && !NtDeviceIoControlFile(dev, NULL, NULL, NULL, &io, + IOCTL_USB_GET_DEVICE_INFO, &usbDevInfo, sizeof(usbDevInfo), + &usbDevInfo, sizeof(usbDevInfo))) + { + if (usbDevInfo.device_address == usbda.addr) + { + memcpy(Buffer, usbDevInfo.device_id, MAX_DEVICE_ID_LEN * sizeof(WCHAR)); + ret = TRUE; + } + ++usbDevInfo.connection_index; + } + NtClose(dev); + HeapFree(GetProcessHeap(), 0, pdoName); + return ret; +} + +static BOOL SETUPDI_GetUsbParent( struct DeviceInfo *devInfo, LPWSTR Buffer ) +{ + static const WCHAR usbW[] = {'u','s','b','\\',0}; + struct usb_device_info usbDevInfo; + WCHAR *pdoName; + UNICODE_STRING name; + OBJECT_ATTRIBUTES attr; + IO_STATUS_BLOCK io; + HANDLE dev; + BOOL ret = FALSE; + ULONG k = 0; + + if (strncmpiW(devInfo->instanceId, usbW, strlenW(usbW))) + return FALSE; + + attr.Length = sizeof(attr); + attr.RootDirectory = 0; + attr.Attributes = OBJ_CASE_INSENSITIVE; + attr.ObjectName = &name; + attr.SecurityDescriptor = NULL; + attr.SecurityQualityOfService = NULL; + pdoName = HeapAlloc(GetProcessHeap(), 0, 30 * sizeof(WCHAR)); + if (!pdoName) return FALSE; + while (!ret) + { + snprintfW(pdoName, 30, usbpdoW, k++); + RtlInitUnicodeString(&name, pdoName); + if (NtOpenFile(&dev, GENERIC_READ|GENERIC_WRITE, &attr, &io, + FILE_SHARE_READ|FILE_SHARE_WRITE, 0)) + { + HeapFree(GetProcessHeap(), 0, pdoName); + return FALSE; + } + usbDevInfo.connection_index = 1; + while (!ret && !NtDeviceIoControlFile(dev, NULL, NULL, NULL, &io, + IOCTL_USB_GET_DEVICE_INFO, &usbDevInfo, sizeof(usbDevInfo), + &usbDevInfo, sizeof(usbDevInfo))) + { + if (!strcmpiW(devInfo->instanceId, usbDevInfo.device_id)) + { + memcpy(Buffer, usbDevInfo.root_hub_id, + MAX_DEVICE_ID_LEN * sizeof(WCHAR)); + ret = TRUE; + } + ++usbDevInfo.connection_index; + } + NtClose(dev); + } + HeapFree(GetProcessHeap(), 0, pdoName); + return TRUE; +} + +/*********************************************************************** + * CM_Get_Parent_Ex (SETUPAPI.@) + */ +CONFIGRET WINAPI CM_Get_Parent_Ex( PDEVINST pdnDevInst, DEVINST dnDevInst, + ULONG ulFlags, HMACHINE hMachine ) +{ + struct DeviceInfo *devInfo = GlobalLock((HANDLE)dnDevInst); + WCHAR instanceId[MAX_DEVICE_ID_LEN]; + + TRACE("%p %08x %08x %p\n", pdnDevInst, dnDevInst, ulFlags, hMachine); + + if (!devInfo) + return CR_INVALID_DEVNODE; + if (!SETUPDI_GetUsbstorParent(devInfo, instanceId) && + !SETUPDI_GetUsbParent(devInfo, instanceId)) + { + GlobalUnlock((HANDLE)dnDevInst); + return CR_NO_SUCH_DEVNODE; + } + if (!devInfo->parent && !(devInfo->parent = + SETUPDI_AllocateDeviceInfo(NULL, 0, instanceId, FALSE))) + { + GlobalUnlock((HANDLE)dnDevInst); + return CR_FAILURE; + } + *pdnDevInst = devInfo->parent->devId; + GlobalUnlock((HANDLE)dnDevInst); + return CR_SUCCESS; +} + +/*********************************************************************** + * CM_Get_Parent (SETUPAPI.@) + */ +DWORD WINAPI CM_Get_Parent( PDEVINST pdnDevInst, DEVINST dnDevInst, + ULONG ulFlags ) +{ + return CM_Get_Parent_Ex(pdnDevInst, dnDevInst, ulFlags, NULL); +} diff --git a/dlls/setupapi/setupapi.spec b/dlls/setupapi/setupapi.spec index b2b0239351..602e1bba28 100644 --- a/dlls/setupapi/setupapi.spec +++ b/dlls/setupapi/setupapi.spec @@ -116,7 +116,7 @@ @ stub CM_Get_Next_Res_Des @ stub CM_Get_Next_Res_Des_Ex @ stdcall CM_Get_Parent(ptr long long) -@ stub CM_Get_Parent_Ex +@ stdcall CM_Get_Parent_Ex(ptr long long ptr) @ stub CM_Get_Res_Des_Data @ stub CM_Get_Res_Des_Data_Ex @ stub CM_Get_Res_Des_Data_Size diff --git a/dlls/setupapi/stubs.c b/dlls/setupapi/stubs.c index 51c7b95aa8..bce244647c 100644 --- a/dlls/setupapi/stubs.c +++ b/dlls/setupapi/stubs.c @@ -131,16 +131,6 @@ CONFIGRET WINAPI CM_Reenumerate_DevNode_Ex( return CR_SUCCESS; } -/*********************************************************************** - * CM_Get_Parent (SETUPAPI.@) - */ -DWORD WINAPI CM_Get_Parent(PDEVINST pdnDevInst, DEVINST dnDevInst, ULONG ulFlags) -{ - FIXME("%p 0x%08x 0x%08x stub\n", pdnDevInst, dnDevInst, ulFlags); - *pdnDevInst = dnDevInst; - return CR_SUCCESS; -} - /*********************************************************************** * SetupInitializeFileLogW(SETUPAPI.@) */ -- 2.33.8