[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [win-pv-devel] [PATCH 2/6] Add device list to track XenIface device(s)
> -----Original Message----- > From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On > Behalf Of Owen Smith > Sent: 05 July 2016 11:38 > To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx > Cc: Owen Smith > Subject: [win-pv-devel] [PATCH 2/6] Add device list to track XenIface > device(s) > > Uses RegisterDeviceNotificationA and SetupApi to track > GUID_INTERFACE_XENIFACE device(s). Calls service base class > after insertion and before remove complete. > > Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx> > --- > src/xenagent/devicelist.cpp | 296 > +++++++++++++++++++++++++++++++++++++++ > src/xenagent/devicelist.h | 92 ++++++++++++ > src/xenagent/service.cpp | 20 ++- > src/xenagent/service.h | 11 +- > vs2012/xenagent/xenagent.vcxproj | 2 + > vs2013/xenagent/xenagent.vcxproj | 2 + > 6 files changed, 421 insertions(+), 2 deletions(-) > create mode 100644 src/xenagent/devicelist.cpp > create mode 100644 src/xenagent/devicelist.h > > diff --git a/src/xenagent/devicelist.cpp b/src/xenagent/devicelist.cpp > new file mode 100644 > index 0000000..5e948c1 > --- /dev/null > +++ b/src/xenagent/devicelist.cpp > @@ -0,0 +1,296 @@ > +/* Copyright (c) Citrix Systems Inc. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, > + * with or without modification, are permitted provided > + * that the following conditions are met: > + * > + * * Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the > + * following disclaimer. > + * * Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the > + * following disclaimer in the documentation and/or other > + * materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#include <windows.h> > +#include <string> > +#include <setupapi.h> > +#pragma comment (lib , "setupapi.lib" ) > + > +#include "devicelist.h" > + > +// deal with SetupApi and RegisterDeviceNotification using different string > types > +static std::wstring Convert(const char* str) > +{ > + std::wstring wstr; > + wstr.reserve(strlen(str) + 1); > + MultiByteToWideChar(CP_ACP, 0, str, -1, (LPWSTR)wstr.data(), > (int)wstr.capacity()); > + return wstr; > +} > + > +static std::wstring Convert(const wchar_t* wstr) > +{ > + return std::wstring(wstr); > +} > + > +CDevice::CDevice(const wchar_t* path) : > + m_handle(INVALID_HANDLE_VALUE), m_path(path), m_notify(NULL) > +{ > +} > + > +/*virtual*/ CDevice::~CDevice() > +{ > + Close(); > +} > + > +const wchar_t* CDevice::Path() const > +{ > + return m_path.c_str(); > +} > + > +HANDLE CDevice::Open(HANDLE svc) > +{ > + 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; > + > + DEV_BROADCAST_HANDLE devhdl = { 0 }; > + devhdl.dbch_size = sizeof(devhdl); > + devhdl.dbch_devicetype = DBT_DEVTYP_HANDLE; > + 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; > +} > + > +void CDevice::Close() > +{ > + if (m_handle == INVALID_HANDLE_VALUE) > + return; > + CloseHandle(m_handle); > + m_handle = INVALID_HANDLE_VALUE; > +} > + > +bool CDevice::Ioctl(DWORD ioctl, void* in, DWORD insz, void* out, DWORD > outsz, DWORD* bytes /*= NULL*/) > +{ > + if (m_handle == INVALID_HANDLE_VALUE) > + return false; > + > + DWORD _bytes; > + if (!DeviceIoControl(m_handle, > + ioctl, > + in, > + insz, > + out, > + outsz, > + (bytes == NULL) ? &_bytes : bytes, > + NULL)) > + return false; > + > + return true; > +} > + > +CDeviceList::CDeviceList(const GUID& itf) : > + m_guid(itf), m_notify(NULL), m_handle(NULL), m_impl(NULL) > +{ > +} > + > +CDeviceList::~CDeviceList() > +{ > + Stop(); > +} > + > +bool CDeviceList::Start(HANDLE handle, IDeviceCreator* impl) > +{ > + Stop(); > + > + m_handle = handle; > + m_impl = impl; > + > + DEV_BROADCAST_DEVICEINTERFACE dev = { 0 }; > + dev.dbcc_size = sizeof(dev); > + dev.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; > + dev.dbcc_classguid = m_guid; > + > + m_notify = RegisterDeviceNotificationA(handle, &dev, > DEVICE_NOTIFY_SERVICE_HANDLE); > + if (m_notify == NULL) > + return false; > + > + HDEVINFO info; > + SP_DEVICE_INTERFACE_DATA itf; > + PSP_DEVICE_INTERFACE_DETAIL_DATA detail; > + ULONG idx; > + ULONG len; > + > + info = SetupDiGetClassDevs(&m_guid, > + NULL, > + NULL, > + DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); > + if (info == INVALID_HANDLE_VALUE) > + return true; // non fatal, just missing already present device(s) > + > + itf.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); > + for (idx = 0; > + SetupDiEnumDeviceInterfaces(info, NULL, &m_guid, idx, &itf); > + ++idx) { > + SetupDiGetDeviceInterfaceDetail(info, > + &itf, > + NULL, > + 0, > + &len, > + NULL); > + detail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)new BYTE[len]; > + if (detail == NULL) > + continue; > + detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); > + if (SetupDiGetDeviceInterfaceDetail(info, > + &itf, > + detail, > + len, > + NULL, > + NULL)) { > + OnDeviceAdded(Convert((const char*)detail->DevicePath)); > + } > + delete [] detail; > + itf.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); > + } > + SetupDiDestroyDeviceInfoList(info); > + return true; > +} > + > +void CDeviceList::Stop() > +{ > + if (m_notify != NULL) > + UnregisterDeviceNotification(m_notify); > + m_notify = NULL; > + > + for (DeviceMap::iterator it = m_devs.begin(); > + it != m_devs.end(); > + ++it) { > + delete it->second; > + } > + m_devs.clear(); > +} > + > +void CDeviceList::OnDeviceEvent(DWORD evt, LPVOID data) > +{ > + PDEV_BROADCAST_HDR hdr; > + PDEV_BROADCAST_DEVICEINTERFACE itf; > + PDEV_BROADCAST_HANDLE hdl; > + > + hdr = (PDEV_BROADCAST_HDR)data; > + switch (evt) { > + case DBT_DEVICEARRIVAL: > + if (hdr->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { > + itf = (PDEV_BROADCAST_DEVICEINTERFACE)hdr; > + 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; > + > + default: > + break; > + } > +} > + > +CDevice* CDeviceList::GetFirstDevice() > +{ > + DeviceMap::iterator it = m_devs.begin(); > + if (it == m_devs.end()) > + return NULL; > + return it->second; > +} > + > +void CDeviceList::OnDeviceAdded(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 > + } > + > + DeviceMap::iterator it = m_devs.find(handle); > + if (it != m_devs.end()) { > + delete dev; > + return; > + } > + > + m_devs[handle] = dev; > + if (m_impl) > + m_impl->OnDeviceAdded(dev); > +} > + > +void CDeviceList::OnDeviceQueryRemove(HANDLE handle) > +{ > + DeviceMap::iterator it = m_devs.find(handle); > + if (it == m_devs.end()) > + return; // spurious event? > + > + CDevice* dev = it->second; > + if (m_impl) > + m_impl->OnDeviceRemoved(dev); > + dev->Close(); > +} > + > +void CDeviceList::OnDeviceRemoved(HANDLE handle) > +{ > + DeviceMap::iterator it = m_devs.find(handle); > + if (it == m_devs.end()) > + return; // spurious event? > + > + CDevice* dev = it->second; > + delete dev; > + m_devs.erase(it); > +} > diff --git a/src/xenagent/devicelist.h b/src/xenagent/devicelist.h > new file mode 100644 > index 0000000..a421e58 > --- /dev/null > +++ b/src/xenagent/devicelist.h > @@ -0,0 +1,92 @@ > +/* Copyright (c) Citrix Systems Inc. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, > + * with or without modification, are permitted provided > + * that the following conditions are met: > + * > + * * Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the > + * following disclaimer. > + * * Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the > + * following disclaimer in the documentation and/or other > + * materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, > + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR > + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, > + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING > + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#ifndef __XENAGENT_DEVICELIST_H__ > +#define __XENAGENT_DEVICELIST_H__ > + > +#include <windows.h> > +#include <dbt.h> > +#include <map> > +#include <string> > + > +class CDevice > +{ > +public: > + CDevice(const wchar_t* path); > + virtual ~CDevice(); > + > + const wchar_t* Path() const; > + > + HANDLE Open(HANDLE svc); > + void Close(); > + > +protected: > + bool Ioctl(DWORD ioctl, void* in, DWORD insz, void* out, DWORD outsz, > DWORD* bytes = NULL); > + > +private: > + std::wstring m_path; > + HANDLE m_handle; > + HDEVNOTIFY m_notify; > +}; > + > +interface IDeviceCreator > +{ > + virtual CDevice* Create(const wchar_t* path) = 0; > + virtual void OnDeviceAdded(CDevice* dev) = 0; > + virtual void OnDeviceRemoved(CDevice* dev) = 0; > +}; > + > +class CDeviceList > +{ > +public: > + CDeviceList(const GUID& itf); > + ~CDeviceList(); > + > + bool Start(HANDLE svc, IDeviceCreator* impl); > + void Stop(); > + void OnDeviceEvent(DWORD evt, LPVOID data); > + CDevice* GetFirstDevice(); > + > +private: > + void OnDeviceAdded(const std::wstring& path); > + void OnDeviceQueryRemove(HANDLE handle); > + void OnDeviceRemoved(HANDLE dev); > + > + typedef std::map< HANDLE, CDevice* > DeviceMap; > + > + GUID m_guid; > + DeviceMap m_devs; > + HDEVNOTIFY m_notify; > + HANDLE m_handle; > + IDeviceCreator* m_impl; > +}; > + > +#endif > diff --git a/src/xenagent/service.cpp b/src/xenagent/service.cpp > index b794544..fec8e95 100644 > --- a/src/xenagent/service.cpp > +++ b/src/xenagent/service.cpp > @@ -151,7 +151,7 @@ static CXenAgent s_service; > return s_service.__ServiceControlHandlerEx(req, evt, data, ctxt); > } > > -CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL) > +CXenAgent::CXenAgent() : m_handle(NULL), m_evtlog(NULL), > m_devlist(GUID_INTERFACE_XENIFACE) > { > m_status.dwServiceType = SERVICE_WIN32; > m_status.dwCurrentState = SERVICE_START_PENDING; > @@ -169,18 +169,36 @@ CXenAgent::~CXenAgent() > CloseHandle(m_svc_stop); > } > > +/*virtual*/ CDevice* CXenAgent::Create(const wchar_t* path) > +{ > + return new CDevice(path); > +} > + > +/*virtual*/ void CXenAgent::OnDeviceAdded(CDevice* dev) > +{ > + CXenAgent::Log("OnDeviceAdded(%ws)\n", dev->Path()); > +} > + > +/*virtual*/ void CXenAgent::OnDeviceRemoved(CDevice* dev) > +{ > + CXenAgent::Log("OnDeviceRemoved(%ws)\n", dev->Path()); > +} > + > void CXenAgent::OnServiceStart() > { > CXenAgent::Log("OnServiceStart()\n"); > + m_devlist.Start(m_handle, this); > } > > void CXenAgent::OnServiceStop() > { > CXenAgent::Log("OnServiceStop()\n"); > + m_devlist.Stop(); > } > > void CXenAgent::OnDeviceEvent(DWORD evt, LPVOID data) > { > + m_devlist.OnDeviceEvent(evt, data); > } > > bool CXenAgent::ServiceMainLoop() > diff --git a/src/xenagent/service.h b/src/xenagent/service.h > index 7446e41..ba3f430 100644 > --- a/src/xenagent/service.h > +++ b/src/xenagent/service.h > @@ -38,7 +38,9 @@ > #define SVC_DISPLAYNAME PRODUCT_NAME_STR ## "Interface Service" > #define SVC_DESC "Monitors and provides various metrics to XenStore" > > -class CXenAgent > +#include "devicelist.h" > + > +class CXenAgent : public IDeviceCreator > { > public: // statics > static void Log(const char* fmt, ...); > @@ -54,6 +56,11 @@ public: // ctor/dtor > CXenAgent(); > ~CXenAgent(); > > +public: // IDeviceCreator > + virtual CDevice* Create(const wchar_t* path); > + virtual void OnDeviceAdded(CDevice* dev); > + virtual void OnDeviceRemoved(CDevice* dev); > + > private: // service events > void OnServiceStart(); > void OnServiceStop(); > @@ -69,6 +76,8 @@ private: // service support > SERVICE_STATUS_HANDLE m_handle; > HANDLE m_evtlog; > HANDLE m_svc_stop; > + > + CDeviceList m_devlist; > }; > > #endif > diff --git a/vs2012/xenagent/xenagent.vcxproj > b/vs2012/xenagent/xenagent.vcxproj > index af99f9d..6c9c91c 100644 > --- a/vs2012/xenagent/xenagent.vcxproj > +++ b/vs2012/xenagent/xenagent.vcxproj > @@ -194,9 +194,11 @@ > </ItemDefinitionGroup> > <ItemGroup> > <ClCompile Include="..\..\src\xenagent\service.cpp"/> > + <ClCompile Include="..\..\src\xenagent\devicelist.cpp"/> > </ItemGroup> > <ItemGroup> > <ClInclude Include="..\..\src\xenagent\service.h" /> > + <ClInclude Include="..\..\src\xenagent\devicelist.h" /> > </ItemGroup> > <ItemGroup> > <CustomBuild Include="..\..\src\xenagent\messages.mc"> > diff --git a/vs2013/xenagent/xenagent.vcxproj > b/vs2013/xenagent/xenagent.vcxproj > index 48ef3fc..d312626 100644 > --- a/vs2013/xenagent/xenagent.vcxproj > +++ b/vs2013/xenagent/xenagent.vcxproj > @@ -198,9 +198,11 @@ > </ItemDefinitionGroup> > <ItemGroup> > <ClCompile Include="..\..\src\xenagent\service.cpp"/> > + <ClCompile Include="..\..\src\xenagent\devicelist.cpp"/> > </ItemGroup> > <ItemGroup> > <ClInclude Include="..\..\src\xenagent\service.h" /> > + <ClInclude Include="..\..\src\xenagent\devicelist.h" /> > </ItemGroup> > <ItemGroup> > <CustomBuild Include="..\..\src\xenagent\xenagent.mc"> > -- > 1.9.4.msysgit.1 > > > _______________________________________________ > win-pv-devel mailing list > win-pv-devel@xxxxxxxxxxxxxxxxxxxx > http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |