[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH] Handle QueryRemoveFailed



Its possible for the QueryRemove to fail, in which case, the xenagent
should re-open the device and inform the client code.
This allows a the XenIface device to re-write the control/feature-*
flags if XenIface failed the QueryRemove

Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx>
---
 src/xenagent/devicelist.cpp | 225 ++++++++++++++++++++++++++++----------------
 src/xenagent/devicelist.h   |  13 ++-
 2 files changed, 151 insertions(+), 87 deletions(-)

diff --git a/src/xenagent/devicelist.cpp b/src/xenagent/devicelist.cpp
index e0583f9..de54c01 100644
--- a/src/xenagent/devicelist.cpp
+++ b/src/xenagent/devicelist.cpp
@@ -36,6 +36,8 @@
 
 #include "devicelist.h"
 
+#define BUFFER_SIZE 127
+
 // deal with SetupApi and RegisterDeviceNotification using different string 
types
 static std::wstring Convert(const char* str)
 {
@@ -50,6 +52,19 @@ static std::wstring Convert(const wchar_t* wstr)
     return std::wstring(wstr);
 }
 
+static void DebugPrint(const wchar_t* fmt, ...)
+{
+       wchar_t buffer[BUFFER_SIZE+1];
+       va_list args;
+
+       va_start(args, fmt);
+       _vsnwprintf(buffer, BUFFER_SIZE, fmt, args);
+       va_end(args);
+
+       buffer[BUFFER_SIZE] = 0;
+       OutputDebugStringW(buffer);
+}
+
 CDevice::CDevice(const wchar_t* path) :
     m_handle(INVALID_HANDLE_VALUE), m_path(path), m_notify(NULL)
 {
@@ -58,6 +73,7 @@ CDevice::CDevice(const wchar_t* path) :
 /*virtual*/ CDevice::~CDevice()
 {
     Close();
+       Unregister();
 }
 
 const wchar_t* CDevice::Path() const
@@ -65,19 +81,32 @@ const wchar_t* CDevice::Path() const
     return m_path.c_str();
 }
 
-HANDLE CDevice::Open(HANDLE svc)
+bool CDevice::Open()
 {
-    Close();
+       Close();
 
-    m_handle = CreateFileW(m_path.c_str(),
-                           GENERIC_READ | GENERIC_WRITE,
-                           FILE_SHARE_READ | FILE_SHARE_WRITE,
-                           NULL,
-                           OPEN_EXISTING,
-                           0,
-                           NULL);
-    if (m_handle == INVALID_HANDLE_VALUE)
-        return INVALID_HANDLE_VALUE;
+       m_handle = CreateFileW(m_path.c_str(),
+                                                  GENERIC_READ | GENERIC_WRITE,
+                                                  FILE_SHARE_READ | 
FILE_SHARE_WRITE,
+                                                  NULL,
+                                                  OPEN_EXISTING,
+                                                  0,
+                                                  NULL);
+
+       return (m_handle != INVALID_HANDLE_VALUE);
+}
+
+void CDevice::Close()
+{
+       if (m_handle == INVALID_HANDLE_VALUE)
+               return;
+       CloseHandle(m_handle);
+       m_handle = INVALID_HANDLE_VALUE;
+}
+
+HDEVNOTIFY CDevice::Register(HANDLE svc)
+{
+       Unregister();
 
     DEV_BROADCAST_HANDLE devhdl = { 0 };
     devhdl.dbch_size = sizeof(devhdl);
@@ -85,20 +114,16 @@ HANDLE CDevice::Open(HANDLE svc)
     devhdl.dbch_handle = m_handle;
 
     m_notify = RegisterDeviceNotification(svc, &devhdl, 
DEVICE_NOTIFY_SERVICE_HANDLE);
-    if (m_notify == NULL) {
-        Close();
-        return INVALID_HANDLE_VALUE;
-    }
-
-    return m_handle;
+       return m_notify;
 }
 
-void CDevice::Close()
+void CDevice::Unregister()
 {
-    if (m_handle == INVALID_HANDLE_VALUE)
-        return;
-    CloseHandle(m_handle);
-    m_handle = INVALID_HANDLE_VALUE;
+       if (m_notify == NULL)
+               return;
+
+       UnregisterDeviceNotification(m_notify);
+       m_notify = NULL;
 }
 
 bool CDevice::Write(void *buf, DWORD bufsz, DWORD *bytes /* = NULL*/)
@@ -198,7 +223,7 @@ bool CDeviceList::Start(HANDLE handle, IDeviceCreator* impl)
                                             len,
                                             NULL,
                                             NULL)) {
-            OnDeviceAdded(Convert((const char*)detail->DevicePath));
+            DeviceArrival(Convert((const char*)detail->DevicePath));
         }
         delete [] detail;
         itf.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
@@ -233,28 +258,35 @@ void CDeviceList::OnDeviceEvent(DWORD evt, LPVOID data)
 
     hdr = (PDEV_BROADCAST_HDR)data;
     switch (evt) {
-    case DBT_DEVICEARRIVAL:
-        if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) {
-            itf = (PDEV_BROADCAST_DEVICEINTERFACE)hdr;
-            if (itf->dbcc_classguid == m_guid)
-                OnDeviceAdded(Convert((const wchar_t*)itf->dbcc_name));
-        }
-        break;
-
-    case DBT_DEVICEQUERYREMOVE:
-        if (hdr->dbch_devicetype == DBT_DEVTYP_HANDLE) {
-            hdl = (PDEV_BROADCAST_HANDLE)hdr;
-            OnDeviceQueryRemove(hdl->dbch_handle);
-        }
-        break;
-
-    case DBT_DEVICEREMOVEPENDING:
-        if (hdr->dbch_devicetype == DBT_DEVTYP_HANDLE) {
-            hdl = (PDEV_BROADCAST_HANDLE)hdr;
-            UnregisterDeviceNotification(hdl->dbch_hdevnotify);
-            OnDeviceRemoved(hdl->dbch_handle);
-        }
-        break;
+       case DBT_DEVICEARRIVAL:
+               if (hdr->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
+                       break;
+               itf = (PDEV_BROADCAST_DEVICEINTERFACE)hdr;
+               if (itf->dbcc_classguid != m_guid)
+                       break;
+               DeviceArrival(Convert((const wchar_t*)itf->dbcc_name));
+               break;
+
+       case DBT_DEVICEREMOVEPENDING:
+               if (hdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
+                       break;
+               hdl = (PDEV_BROADCAST_HANDLE)hdr;
+               DeviceRemoved(hdl->dbch_hdevnotify);
+               break;
+
+       case DBT_DEVICEQUERYREMOVE:
+               if (hdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
+                       break;
+               hdl = (PDEV_BROADCAST_HANDLE)hdr;
+               DeviceRemovePending(hdl->dbch_hdevnotify);
+               break;
+
+       case DBT_DEVICEQUERYREMOVEFAILED:
+               if (hdr->dbch_devicetype != DBT_DEVTYP_HANDLE)
+                       break;
+               hdl = (PDEV_BROADCAST_HANDLE)hdr;
+               DeviceRemoveFailed(hdl->dbch_hdevnotify);
+               break;
 
     default:
         break;
@@ -293,52 +325,81 @@ CDevice* CDeviceList::GetFirstDevice()
     return it->second;
 }
 
-void CDeviceList::OnDeviceAdded(const std::wstring& path)
+void CDeviceList::DeviceArrival(const std::wstring& path)
 {
-    CDevice* dev;
-    if (m_impl == NULL)
-        dev = new CDevice(path.c_str());
-    else
-        dev = m_impl->Create(path.c_str());
-    if (dev == NULL)
-        return; // create failed
-
-    HANDLE handle = dev->Open(m_handle);
-    if (handle == INVALID_HANDLE_VALUE) {
-        delete dev;
-        return; // open failed
-    }
+       DebugPrint(L"DeviceArrival(%ws)\n", path.c_str());
+       CDevice* dev;
+       if (m_impl)
+               dev = m_impl->Create(path.c_str());
+       else
+               dev = new CDevice(path.c_str());
+       if (dev == NULL)
+               goto fail1;
+
+       if (!dev->Open())
+               goto fail2;
+
+       HDEVNOTIFY nfy = dev->Register(m_handle);
+       if (nfy == NULL)
+               goto fail3;
+
+       m_devs[nfy] = dev;
+
+       if (m_impl)
+               m_impl->OnDeviceAdded(dev);
+
+       return;
+
+fail3:
+       DebugPrint(L"fail3\n");
+fail2:
+       DebugPrint(L"fail2\n");
+       delete dev; // handles close() and unregister()
+fail1:
+       DebugPrint(L"fail1\n");
+       return;
+}
 
-    DeviceMap::iterator it = m_devs.find(handle);
-    if (it != m_devs.end()) {
-        delete dev;
-        return;
-    }
+void CDeviceList::DeviceRemoved(HDEVNOTIFY nfy)
+{
+       DeviceMap::iterator it = m_devs.find(nfy);
+       if (it == m_devs.end())
+               return; // spurious event?
 
-    m_devs[handle] = dev;
-    if (m_impl)
-        m_impl->OnDeviceAdded(dev);
+       CDevice* dev = it->second;
+       DebugPrint(L"DeviceRemoved(%ws)\n", dev->Path());
+
+       delete dev; // handles unregister()
+       m_devs.erase(it);
 }
 
-void CDeviceList::OnDeviceQueryRemove(HANDLE handle)
+void CDeviceList::DeviceRemovePending(HDEVNOTIFY nfy)
 {
-    DeviceMap::iterator it = m_devs.find(handle);
-    if (it == m_devs.end())
-        return; // spurious event?
+       DeviceMap::iterator it = m_devs.find(nfy);
+       if (it == m_devs.end())
+               return; // spurious event?
 
-    CDevice* dev = it->second;
-    if (m_impl)
-        m_impl->OnDeviceRemoved(dev);
-    dev->Close();
+       CDevice* dev = it->second;
+       DebugPrint(L"DeviceRemovePending(%ws)\n", dev->Path());
+
+       if (m_impl)
+               m_impl->OnDeviceRemoved(dev);
+
+       dev->Close();
 }
 
-void CDeviceList::OnDeviceRemoved(HANDLE handle)
+void CDeviceList::DeviceRemoveFailed(HDEVNOTIFY nfy)
 {
-    DeviceMap::iterator it = m_devs.find(handle);
-    if (it == m_devs.end())
-        return; // spurious event?
+       DeviceMap::iterator it = m_devs.find(nfy);
+       if (it == m_devs.end())
+               return; // spurious event?
+
+       CDevice* dev = it->second;
+       DebugPrint(L"DeviceRemoveFailed(%ws)\n", dev->Path());
+
+       if (!dev->Open())
+               DeviceRemoved(nfy);
 
-    CDevice* dev = it->second;
-    delete dev;
-    m_devs.erase(it);
+       if (m_impl)
+               m_impl->OnDeviceAdded(dev);
 }
diff --git a/src/xenagent/devicelist.h b/src/xenagent/devicelist.h
index 5535ad5..75deefb 100644
--- a/src/xenagent/devicelist.h
+++ b/src/xenagent/devicelist.h
@@ -45,8 +45,10 @@ public:
 
     const wchar_t* Path() const;
 
-    HANDLE Open(HANDLE svc);
+    bool Open();
     void Close();
+       HDEVNOTIFY Register(HANDLE svc);
+       void Unregister();
 
 protected:
     bool Write(void *buf, DWORD bufsz, DWORD *bytes = NULL);
@@ -81,11 +83,12 @@ public:
     CDevice* GetFirstDevice();
 
 private:
-    void OnDeviceAdded(const std::wstring& path);
-    void OnDeviceQueryRemove(HANDLE handle);
-    void OnDeviceRemoved(HANDLE dev);
+       void DeviceArrival(const std::wstring& path);
+       void DeviceRemoved(HDEVNOTIFY nfy);
+       void DeviceRemovePending(HDEVNOTIFY nfy);
+       void DeviceRemoveFailed(HDEVNOTIFY nfy);
 
-    typedef std::map< HANDLE, CDevice* > DeviceMap;
+    typedef std::map< HDEVNOTIFY, CDevice* > DeviceMap;
 
     GUID        m_guid;
     DeviceMap   m_devs;
-- 
2.16.2.windows.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.