[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