<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;"><DIV>since there are other changes, so I post here manual changes, instead of a pacth file.</DIV>
<DIV> </DIV>
<DIV>The patch is attached as a text file, also shown as below:</DIV>
<DIV> </DIV>
<DIV>UIMachineWindow.h:</DIV>
<DIV>public:<BR> /* usb support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32<BR> QStringList m_hostUSBDevices; <BR> void updateHostUSBDeviceList(); <BR> QString getDriverKey(QString devId);<BR> QString getDeviceIdFromDriverKey(QString driverKey);<BR>#endif</DIV>
<DIV><BR>protected:</DIV>
<DIV> /* vmlite, usb support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32 <BR> void registerUSBDeviceNotification();<BR> void onDeviceChange(MSG *aMsg); <BR>#endif</DIV>
<DIV>UIMachineWindow.cpp:</DIV>
<DIV>#ifdef Q_WS_WIN32<BR>#include <Dbt.h><BR>#include <setupapi.h><BR>#endif</DIV>
<DIV>/* vmlite, usb support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32<BR>void UIMachineWindow::registerUSBDeviceNotification()<BR>{<BR> //return; // this disables USB insertion detection</DIV>
<DIV> const GUID GUID_DEVINTERFACE_USB_DEVICE =<BR> { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };</DIV>
<DIV> const GUID GUID_DEVINTERFACE_HID =<BR> { 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } };</DIV>
<DIV> updateHostUSBDeviceList();</DIV>
<DIV>    DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;<BR>    ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );<BR>    NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);<BR>    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; <BR> NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_USB_DEVICE;<BR> HDEVNOTIFY hDevNotify = RegisterDeviceNotification(m_pMachineWindow->winId(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);</DIV>
<DIV> NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_HID;<BR> hDevNotify = RegisterDeviceNotification(m_pMachineWindow->winId(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);<BR>}</DIV>
<DIV>// sync the following with our usb drivers<BR>//#define VMLITE_USB_DEVICE_ID "USB\\VID_80EE&PID_CAFE"<BR>#define VMLITE_USB_DEVICE_ID   "USB\\VMLITEUSBSTUB"</DIV>
<DIV>typedef struct _DEVICE_CHANGE_PARAMETER<BR>{<BR> UIMachineWindow* pThis;<BR> DWORD dbch_devicetype;<BR> WPARAM kind;<BR> WCHAR dbcc_name[MAX_PATH];</DIV>
<DIV>} DEVICE_CHANGE_PARAMETER, *PDEVICE_CHANGE_PARAMETER;</DIV>
<DIV>static DWORD WINAPI deviceChangeThreadProc(LPVOID Parameter)<BR>{<BR> PDEVICE_CHANGE_PARAMETER pDeviceChange = (PDEVICE_CHANGE_PARAMETER)Parameter;<BR> UIMachineWindow* pThis = pDeviceChange->pThis;<BR> WPARAM kind = pDeviceChange->kind; <BR>  <BR> /* pDevInf->dbcc_name, e.g. <A href="file://\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed">\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed</A>}<BR>   szDevId: USB#VID_04e8&PID_503b#0002F9A9828E0F06<BR>   szClass: USB<BR>    */<BR> // extract the devId portion, covert '#' to '\'  <BR> QString devIdStr((QChar *)pDeviceChange->dbcc_name + 4, wcslen(pDeviceChange->dbcc_name + 4)); <BR> devIdStr = devIdStr.left(devIdStr.lastIndexOf('#'));<BR> devIdStr = devIdStr.replace('#', '\\');</DIV>
<DIV> free(pDeviceChange); </DIV>
<DIV> // address is the driver key, e.g., {36FC9E60-C465-11CF-8056-444553540000}\0025    <BR> QString address = pThis->getDriverKey(devIdStr);</DIV>
<DIV> // only hanlde devices that are really inserted, <BR> // when an attached device is released, arrival event will come here too, ignore such insertion<BR> if (pThis->m_hostUSBDevices.contains(address))<BR> {  <BR>  return -1;<BR> }<BR>    <BR> /* Get HOST: */<BR> CHost host = vboxGlobal().virtualBox().GetHost();<BR> <BR> /* find the host usb device, and attach it, try 180 secs */<BR> for (int i=0; i<2 * 180; i++)<BR> {<BR>  // this is extremely import, freezes otherwise<BR>  QCoreApplication::processEvents();</DIV>
<DIV>  /* Get USB devices list: */<BR>  CHostUSBDeviceVector devices = host.GetUSBDevices();</DIV>
<DIV>  foreach (const CHostUSBDevice hostDevice, devices)<BR>  {   <BR>   if (hostDevice.GetAddress() == address)<BR>   {<BR>    /* Get current console: */<BR>    CConsole console = pThis->session().GetConsole();<BR>    CUSBDevice attachedDevice = console.FindUSBDeviceById(hostDevice.GetId());<BR>    if (attachedDevice.isNull())<BR>    {<BR>     console.AttachUSBDevice(hostDevice.GetId());     <BR>     return console.isOk() ? 0 : -1;<BR>    }<BR>    else<BR>    {     <BR>     return -1;<BR>    }<BR>   }<BR>  }</DIV>
<DIV>  Sleep(500);<BR> }<BR> <BR> return -1;<BR>}</DIV>
<DIV>/* get driver key for the specified usb device id, from registry, so works even if device is off or deteched<BR> use registry to read the driver key, we don't use Setup api because the device is not active<BR>e.g., devId: USB\VID_046D&PID_C016\5&9e58382&0&1<BR>*/<BR>static QString getDriverKeyThroughRegistry(const QString& devId)<BR>{ <BR> WCHAR keyName[MAX_PATH];<BR> //e.g., HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_046D&PID_C016\5&9e58382&0&1<BR> swprintf(keyName, L"SYSTEM\\CurrentControlSet\\Enum\\%ls", (WCHAR *)devId.unicode());</DIV>
<DIV> HKEY hkey;<BR> long lret = RegOpenKeyW(HKEY_LOCAL_MACHINE, keyName, &hkey);<BR> if (lret != ERROR_SUCCESS) <BR>  return "";</DIV>
<DIV> WCHAR driver[MAX_PATH];<BR> DWORD type;<BR> DWORD size = sizeof(driver);<BR> lret = RegQueryValueExW(hkey, L"Driver", 0, &type, (PBYTE)driver, &size);<BR> RegCloseKey(hkey);<BR> if (lret == ERROR_SUCCESS) <BR> {<BR>  return QString((QChar *)driver, wcslen(driver));<BR> }<BR> else<BR> {<BR>  return "";<BR> } <BR>}</DIV>
<DIV>void UIMachineWindow::onDeviceChange(MSG *aMsg)<BR>{<BR> if (aMsg->wParam != DBT_DEVICEREMOVECOMPLETE && aMsg->wParam != DBT_DEVICEARRIVAL)<BR>  return;</DIV>
<DIV> PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)aMsg->lParam;</DIV>
<DIV> if ( pHdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE)<BR> {  <BR>  return;<BR> }</DIV>
<DIV> if ( DBT_DEVICEREMOVECOMPLETE == aMsg->wParam)<BR> {<BR>  updateHostUSBDeviceList();</DIV>
<DIV>  // need to remove the device that is just removed, in case our updated list still has it in the list<BR>  PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;<BR>  /* pDevInf->dbcc_name, e.g. <A href="file://\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed">\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed</A>}    <BR>  */   <BR>  // extract the devId portion, covert '#' to '\'  <BR>  QString devIdStr((QChar *)pDevInf->dbcc_name + 4, wcslen(pDevInf->dbcc_name + 4)); <BR>  devIdStr = devIdStr.left(devIdStr.lastIndexOf('#'));<BR>  devIdStr = devIdStr.replace('#', '\\');</DIV>
<DIV>  // address is the driver key, e.g., {36FC9E60-C465-11CF-8056-444553540000}\0025    <BR>  QString address = getDriverKeyThroughRegistry(devIdStr);  <BR>  if (!address.isEmpty() && m_hostUSBDevices.contains(address))<BR>  {  <BR>   m_hostUSBDevices.removeAll(address);<BR>  }  <BR> }<BR> else if ( DBT_DEVICEARRIVAL == aMsg->wParam)<BR> {<BR>  PDEV_BROADCAST_DEVICEINTERFACE pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;</DIV>
<DIV>  if (!m_pMachineWindow->isActiveWindow())<BR>  {<BR>   updateHostUSBDeviceList();<BR>   return;<BR>  }<BR>  <BR>  /* pDevInf->dbcc_name, e.g. <A href="file://\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed">\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed</A>}<BR>    szDevId: USB#VID_04e8&PID_503b#0002F9A9828E0F06<BR>    szClass: USB<BR>  */   <BR>  // extract the devId portion, covert '#' to '\'  <BR>  QString devIdStr((QChar *)pDevInf->dbcc_name + 4, wcslen(pDevInf->dbcc_name + 4)); <BR>  devIdStr = devIdStr.left(devIdStr.lastIndexOf('#'));<BR>  devIdStr = devIdStr.replace('#', '\\');<BR>  // when an usb device is attached, our vmlite virtualizazed usb will come here,
 ignore them<BR>  if (devIdStr.startsWith(VMLITE_USB_DEVICE_ID, Qt::CaseInsensitive))<BR>  {<BR>   updateHostUSBDeviceList();<BR>   return;<BR>  }</DIV>
<DIV>  DWORD ThreadId;<BR>  PDEVICE_CHANGE_PARAMETER param = (PDEVICE_CHANGE_PARAMETER)malloc(sizeof(DEVICE_CHANGE_PARAMETER));<BR>  if (param)<BR>  {   <BR>   param->pThis = this;<BR>   param->dbch_devicetype = pHdr->dbch_devicetype;<BR>   param->kind = aMsg->wParam;<BR>   wcscpy(param->dbcc_name, pDevInf->dbcc_name);<BR>   HANDLE ThreadHandle = CreateThread(<BR>         NULL,<BR>         0,<BR>         deviceChangeThreadProc,<BR>         param,<BR>         0,<BR>         &ThreadId
 <BR>        );<BR>  }<BR> }<BR>}</DIV>
<DIV>/* get driver key for the original host usb device being attached from the attached device<BR>*/<BR>static QString getDriverKeyForOriginalDevice(const CHostUSBDevice& attachedDevice)<BR>{<BR> // the attached device and the host device have same vendor id, product id, etc.<BR> unsigned short vid = attachedDevice.GetVendorId();<BR> unsigned short pid = attachedDevice.GetProductId();</DIV>
<DIV> // for non attached usb device, address is the driver key, e.g., {36FC9E60-C465-11CF-8056-444553540000}\0025  <BR> // attached host device has address of device name<BR> QString address = attachedDevice.GetAddress();<BR> if (!address.startsWith("<A>\\\\?\\</A>"))<BR> {<BR>  return address;<BR> }</DIV>
<DIV> /* pDevInf->dbcc_name, e.g. <A href="file://\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed">\\?\USB#VID_04e8&PID_503b#0002F9A9828E0F06#{a5dcbf10-6530-11d2-901f-00c04fb951ed</A>}<BR>   szDevId: USB#VID_04e8&PID_503b#0002F9A9828E0F06    <BR> */    <BR> address = address.right(address.length() - 4);</DIV>
<DIV> int pos = address.lastIndexOf('#');<BR> address = address.left(pos);</DIV>
<DIV> // the string after 2nd # is the serial #, same as the original device being attached<BR> pos = address.indexOf("#");<BR> address = address.right(address.length() - pos - 1);<BR> pos = address.indexOf("#");<BR> address = address.right(address.length() - pos - 1);</DIV>
<DIV> WCHAR *serial = (WCHAR *)address.unicode(); </DIV>
<DIV> // use registry to read the driver key, we don't use Setup api because the device is not active<BR> // e.g., HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_046D&PID_C016\5&9e58382&0&1<BR> WCHAR devId[MAX_PATH];<BR> swprintf(devId, L"SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_%04x&PID_%04x\\%ls", vid, pid, serial);</DIV>
<DIV> HKEY hkey;<BR> long lret = RegOpenKeyW(HKEY_LOCAL_MACHINE, devId, &hkey);<BR> if (lret != ERROR_SUCCESS) <BR>  return "";</DIV>
<DIV> WCHAR driver[MAX_PATH];<BR> DWORD type;<BR> DWORD size = sizeof(driver);<BR> lret = RegQueryValueExW(hkey, L"Driver", 0, &type, (PBYTE)driver, &size);<BR> RegCloseKey(hkey);<BR> if (lret == ERROR_SUCCESS) <BR> {<BR>  return QString((QChar *)driver, wcslen(driver));<BR> }<BR> else<BR> {<BR>  return "";<BR> } <BR>}</DIV>
<DIV>void UIMachineWindow::updateHostUSBDeviceList()<BR>{<BR> m_hostUSBDevices.clear();</DIV>
<DIV> /* Get HOST: */<BR> CHost host = vboxGlobal().virtualBox().GetHost();<BR> <BR> /* Get USB devices list: */<BR> CHostUSBDeviceVector devices = host.GetUSBDevices(); </DIV>
<DIV> foreach (const CHostUSBDevice hostDevice, devices)<BR> {<BR>  // address is the driver key, e.g., {36FC9E60-C465-11CF-8056-444553540000}\0025      <BR>  QString address = hostDevice.GetAddress();</DIV>
<DIV>  if (address.startsWith("<A>\\\\?\\</A>")) /* attached host device has address of device name */<BR>  {   <BR>   address = getDriverKeyForOriginalDevice(hostDevice); <BR>  }<BR>    <BR>  m_hostUSBDevices << address;<BR> }<BR>}</DIV>
<DIV>/* <BR>Get driver key from a usb id, devId: USB\Vid_04e8&Pid_503b\0002F9A9828E0F06<BR>we use driver key to identify a host usb device, as this is unique, <BR>vid/pid/serial is not unique because serial might be emppty<BR>*/<BR>QString UIMachineWindow::getDriverKey(QString devId)<BR>{<BR> HDEVINFO hDevInfo = SetupDiGetClassDevsW(NULL, L"USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);<BR> if( INVALID_HANDLE_VALUE == hDevInfo ) <BR> {<BR>  return "";<BR> }</DIV>
<DIV> WCHAR driverKey[MAX_PATH] = L"";<BR> SP_DEVINFO_DATA spDevInfoData;<BR> spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);<BR> for(int i=0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++) <BR> {<BR>  DWORD nSize = 0;<BR>  WCHAR buf[MAX_PATH];<BR>  if ( !SetupDiGetDeviceInstanceIdW(hDevInfo, &spDevInfoData, buf, sizeof(buf), &nSize) )    <BR>   return "";</DIV>
<DIV>  if (0 == QString((QChar *)buf, wcslen(buf)).compare(devId, Qt::CaseInsensitive))<BR>  {<BR>   nSize = 0;<BR>   if ( SetupDiGetDeviceRegistryPropertyW(hDevInfo, &spDevInfoData, <BR>     SPDRP_DRIVER, NULL, (PBYTE)buf, sizeof(buf), &nSize) ) <BR>   {<BR>    wcscpy(driverKey, buf);<BR>   }<BR>   break;<BR>  }<BR> }</DIV>
<DIV> SetupDiDestroyDeviceInfoList(hDevInfo);</DIV>
<DIV> if (driverKey[0])<BR>  return QString((QChar *)driverKey, wcslen(driverKey));<BR> else<BR>  return "";<BR>}</DIV>
<DIV>/* <BR>Get usb id from driver key, devId: USB\Vid_04e8&Pid_503b\0002F9A9828E0F06, driver key: {36FC9E60-C465-11CF-8056-444553540000}\0025<BR>*/<BR>QString UIMachineWindow::getDeviceIdFromDriverKey(QString driverKey)<BR>{<BR> HDEVINFO hDevInfo = SetupDiGetClassDevsW(NULL, L"USB", NULL, DIGCF_ALLCLASSES | DIGCF_PRESENT);<BR> if( INVALID_HANDLE_VALUE == hDevInfo ) <BR> {<BR>  return "";<BR> }</DIV>
<DIV> WCHAR deviceId[MAX_PATH] = L"";<BR> SP_DEVINFO_DATA spDevInfoData;<BR> spDevInfoData.cbSize = sizeof(SP_DEVINFO_DATA);<BR> for(int i=0; SetupDiEnumDeviceInfo(hDevInfo, i, &spDevInfoData); i++) <BR> {<BR>  DWORD nSize = 0;<BR>  WCHAR buf[MAX_PATH];<BR>  if ( !SetupDiGetDeviceInstanceIdW(hDevInfo, &spDevInfoData, buf, sizeof(buf), &nSize) )    <BR>   return "";</DIV>
<DIV>  wcscpy(deviceId, buf);</DIV>
<DIV>  nSize = 0;<BR>  if ( SetupDiGetDeviceRegistryPropertyW(hDevInfo, &spDevInfoData, <BR>    SPDRP_DRIVER, NULL, (PBYTE)buf, sizeof(buf), &nSize) ) <BR>  {<BR>   if (0 == QString((QChar *)buf, wcslen(buf)).compare(driverKey, Qt::CaseInsensitive))<BR>   {   <BR>    break;<BR>   }   <BR>  }</DIV>
<DIV>  deviceId[0] = 0;<BR> }</DIV>
<DIV> SetupDiDestroyDeviceInfoList(hDevInfo);</DIV>
<DIV> if (deviceId[0])<BR>  return QString((QChar *)deviceId, wcslen(deviceId));<BR> else<BR>  return "";<BR>}</DIV>
<DIV>#endif /* Q_WS_WIN32 */</DIV>
<DIV><BR>UIMachineWindowNormal.cpp:</DIV>
<DIV>UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic, ulong uScreenId)<BR>    : QIWithRetranslateUI2<QMainWindow>(0, Qt::Window)<BR>    , UIMachineWindow(pMachineLogic, uScreenId)<BR>    , m_pIndicatorsPool(new UIIndicatorsPool(pMachineLogic->uisession()->session(), this))<BR>    , m_pIdleTimer(0)<BR>{<BR>........</DIV>
<DIV>// add as last line</DIV>
<DIV>/* vmlite, usb and dnd support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32 <BR> registerUSBDeviceNotification();<BR>#endif<BR>}</DIV>
<DIV>UIMachineWindowFullscreen.cpp:</DIV>
<DIV>UIMachineWindowFullscreen::UIMachineWindowFullscreen(UIMachineLogic *pMachineLogic, ulong uScreenId)<BR>    : QIWithRetranslateUI2<QMainWindow>(0, Qt::FramelessWindowHint)<BR>    , UIMachineWindow(pMachineLogic, uScreenId)<BR>    , m_pMainMenu(0)<BR>    , m_pMiniToolBar(0)<BR>{<BR>........</DIV>
<DIV>// add as last line</DIV>
<DIV>/* vmlite, usb and dnd support, monitor usb device insertion */<BR>#ifdef Q_WS_WIN32 <BR> registerUSBDeviceNotification();<BR>#endif<BR>}<BR></DIV>
<DIV><BR>--- On <B>Thu, 9/15/11, Michael Thayer <I><michael.thayer@oracle.com></I></B> wrote:<BR></DIV>
<BLOCKQUOTE style="BORDER-LEFT: rgb(16,16,255) 2px solid; PADDING-LEFT: 5px; MARGIN-LEFT: 5px"><BR>From: Michael Thayer <michael.thayer@oracle.com><BR>Subject: Re: [vbox-dev] code patch to auto detect USB insertion<BR>To: "Huihong Luo" <huisinro@yahoo.com><BR>Cc: vbox-dev@virtualbox.org<BR>Date: Thursday, September 15, 2011, 2:31 AM<BR><BR>
<DIV class=plainMail>Hello Huihong,<BR><BR>On 09/13/2011 11:49 PM, Huihong Luo wrote:<BR>> I have some code (around 600 lines) that auto attaches usb device when<BR>> inserted to the windows host while vm window is on focus, similar to<BR>> vmware's handling.<BR>> not sure if vbox team wants to integrate this patch.<BR>We might do if it is something which can be enabled or disabled by the user, but we would have to see the patch first (the usual requirements apply [1]).  Would you like to include it?<BR><BR>Regards and thanks,<BR><BR>Michael<BR><BR>[1] <A href="http://www.virtualbox.org/wiki/Contributor_information" target=_blank>http://www.virtualbox.org/wiki/Contributor_information</A><BR>-- ORACLE Deutschland B.V. & Co. KG   Michael Thayer<BR>Werkstrasse 24                     VirtualBox engineering<BR>71384 Weinstadt, Germany       
    mailto:<A href="http://us.mc1603.mail.yahoo.com/mc/compose?to=michael.thayer@oracle.com" ymailto="mailto:michael.thayer@oracle.com">michael.thayer@oracle.com</A><BR><BR>Hauptverwaltung: Riesstr. 25, D-80992 München<BR>Registergericht: Amtsgericht München, HRA 95603<BR><BR>Komplementärin: ORACLE Deutschland Verwaltung B.V.<BR>Hertogswetering 163/167, 3543 AS Utrecht, Niederlande<BR>Handelsregister der Handelskammer Midden-Niederlande, Nr. 30143697<BR>Geschäftsführer: Jürgen Kunz, Marcel van de Molen, Alexander van der Ven<BR></DIV></BLOCKQUOTE></td></tr></table>