[Wine-patches] [eterhack 4/5] setupapi: Implement CM_Get_Parent for USB and USBSTOR devices.

Alexander Morozov amorozov на etersoft.ru
Вт Июн 23 16:16:51 MSD 2009


---
 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 da53b37..e176407 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 8a18138..9f56663 100644
--- a/dlls/setupapi/devinst.c
+++ b/dlls/setupapi/devinst.c
@@ -23,6 +23,8 @@
  
 #include <stdarg.h>
 
+#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 bdd78a7..be6fe99 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 314631c..c7be29d 100644
--- a/dlls/setupapi/stubs.c
+++ b/dlls/setupapi/stubs.c
@@ -132,16 +132,6 @@ CONFIGRET WINAPI CM_Reenumerate_DevNode_Ex(
 }
 
 /***********************************************************************
- *              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.@)
  */
 HSPFILELOG WINAPI SetupInitializeFileLogW(LPCWSTR LogFileName, DWORD Flags)
-- 
1.6.3.2



Подробная информация о списке рассылки Wine-patches