// DeviceConsole.h : Declaration of the CDeviceConsole #ifndef __DEVICECONSOLE_H_ #define __DEVICECONSOLE_H_ #include "resource.h" // main symbols #define UM_POSTEVENTS (WM_USER+101) #define UM_POSTGLOBALEVENT (WM_USER+102) class CEventsDispEntry; class CEventsMap; class CDispHandlerEvent; class CDispHandlerCallback; class CDispInterfaceHandlers; class CDeviceConsole; class CEventsDispPtr { private: CComQIPtr m_Dispatch; public: // // I have to use const due to way STL works // however I need to cast away const for ref-counting // *sigh* // CEventsDispPtr(const IDispatch*p) { m_Dispatch = (IDispatch*)p; } CEventsDispPtr(const CEventsDispPtr & p) { m_Dispatch = (IDispatch*)p.m_Dispatch; } bool operator==(const CEventsDispPtr & p) const { return m_Dispatch == p.m_Dispatch; } HRESULT Invoke(UINT argc,VARIANT * argv) { if(!m_Dispatch) { return S_FALSE; } DISPPARAMS DispParams; UINT Err; HRESULT hr; DispParams.cArgs = argc; DispParams.cNamedArgs = 0; DispParams.rgdispidNamedArgs = NULL; DispParams.rgvarg = argv; hr = m_Dispatch->Invoke(0,IID_NULL,0,DISPATCH_METHOD,&DispParams,NULL,NULL,&Err); return hr; } }; // // attachEvent detachEvent operation // class CEventsDispEntry : public std::list { public: HRESULT AttachEvent(LPDISPATCH pDisp,VARIANT_BOOL *pStatus); HRESULT DetachEvent(LPDISPATCH pDisp,VARIANT_BOOL *pStatus); HRESULT Invoke(UINT argc,VARIANT *argv); }; class CEventsMap : public std::map { public: HRESULT AttachEvent(LPWSTR Name,LPDISPATCH pDisp,VARIANT_BOOL *pStatus); HRESULT DetachEvent(LPWSTR Name,LPDISPATCH pDisp,VARIANT_BOOL *pStatus); HRESULT Invoke(LPWSTR Name,UINT argc,VARIANT *argv); CEventsDispEntry & LookupNc(LPWSTR Name) throw(std::bad_alloc); }; // // map of interface/handle and callbacks // class CDispInterfaceHandlers { public: CDispInterfaceHandlers *m_pPrev; CDispInterfaceHandlers *m_pNext; GUID m_InterfaceClass; HDEVNOTIFY m_hNotify; CDispHandlerCallback *m_pFirstCallback; CDispHandlerCallback *m_pLastCallback; CDispHandlerEvent *m_pFirstEvent; CDispHandlerEvent *m_pLastEvent; public: CDispInterfaceHandlers() { } ~CDispInterfaceHandlers() { } }; class CDispHandlerCallback { public: CDispHandlerCallback *m_pPrev; CDispHandlerCallback *m_pNext; public: CDispHandlerCallback() { } ~CDispHandlerCallback() { } virtual void DeviceEvent(CDispHandlerEvent * pEvent) = 0; }; class CDispHandlerEvent { public: CDispHandlerEvent *m_pNext; BSTR m_Device; WPARAM m_Event; CDispHandlerEvent() { } ~CDispHandlerEvent() { } }; typedef CWinTraits CPopupWinTraits; class CDevConNotifyWindow : public CWindowImpl { public: CDeviceConsole *m_pDevCon; public: CDevConNotifyWindow() { m_pDevCon = NULL; } BEGIN_MSG_MAP(CDevConNotifyWindow) MESSAGE_HANDLER(WM_DEVICECHANGE, OnDeviceChange) MESSAGE_HANDLER(UM_POSTEVENTS, OnPostEvents) MESSAGE_HANDLER(UM_POSTGLOBALEVENT, OnPostGlobalEvent) END_MSG_MAP() LRESULT OnDeviceChange(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnPostEvents(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnPostGlobalEvent(UINT nMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); }; ///////////////////////////////////////////////////////////////////////////// // CDeviceConsole class ATL_NO_VTABLE CDeviceConsole : public CComObjectRootEx, public CComCoClass, public IDispatchImpl { public: VARIANT_BOOL RebootRequired; CEventsMap m_Events; CDevConNotifyWindow *m_pNotifyWindow; CDispInterfaceHandlers *m_pFirstWatch; CDispInterfaceHandlers *m_pLastWatch; CDeviceConsole() { m_pNotifyWindow = NULL; m_pFirstWatch = NULL; m_pLastWatch = NULL; RebootRequired = VARIANT_FALSE; } ~CDeviceConsole() { if(m_pNotifyWindow) { m_pNotifyWindow->DestroyWindow(); delete m_pNotifyWindow; } } CDevConNotifyWindow *NotifyWindow(); DECLARE_REGISTRY_RESOURCEID(IDR_DEVICECONSOLE) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CDeviceConsole) COM_INTERFACE_ENTRY(IDeviceConsole) COM_INTERFACE_ENTRY(IDispatch) END_COM_MAP() // IDeviceConsole public: void FireGlobalEvent(WPARAM wParam); STDMETHOD(AttachEvent)(/*[in]*/ BSTR eventName,/*[in]*/ LPDISPATCH handler,/*[out, retval]*/ VARIANT_BOOL *pOk); STDMETHOD(DetachEvent)(/*[in]*/ BSTR eventName,/*[in]*/ LPDISPATCH handler,/*[out, retval]*/ VARIANT_BOOL *pOk); STDMETHOD(StringList)(/*[in]*/ VARIANT from,/*[out,retval]*/ LPDISPATCH *pDest); STDMETHOD(DevicesByInstanceIds)(/*[in]*/ VARIANT InstanceIdList,/*[in,optional]*/ VARIANT machine,/*[out,retval]*/ LPDISPATCH *pDevList); STDMETHOD(DevicesByInterfaceClasses)(/*[in]*/ VARIANT InterfaceClasses,/*[in,optional]*/ VARIANT machine,/*[out,retval]*/ LPDISPATCH * pDevices); STDMETHOD(DevicesBySetupClasses)(/*[in]*/ VARIANT SetupClasses,/*[in,optional]*/ VARIANT flags,/*[in,optional]*/ VARIANT machine,/*[out,retval]*/ LPDISPATCH * pDevices); STDMETHOD(CreateEmptySetupClassList)(/*[in,optional]*/ VARIANT machine,/*[out,retval]*/ LPDISPATCH * pResult); STDMETHOD(SetupClasses)(/*[in,optional]*/ VARIANT match,/*[in,optional]*/ VARIANT machine,/*[retval,out]*/ LPDISPATCH *pDevices); STDMETHOD(get_RebootRequired)(/*[out, retval]*/ VARIANT_BOOL *pVal); STDMETHOD(put_RebootRequired)(/*[in]*/ VARIANT_BOOL newVal); STDMETHOD(RebootReasonHardware)(); STDMETHOD(CheckReboot)(); STDMETHOD(UpdateDriver)(/*[in]*/ BSTR infname,/*[in]*/ BSTR hwid,/*[in,optional]*/ VARIANT flags); STDMETHOD(CreateEmptyDeviceList)(/*[in,optional]*/ VARIANT machine,/*[retval,out]*/ LPDISPATCH *pDevices); STDMETHOD(AllDevices)(/*[in]*/ VARIANT flags,/*[in]*/ VARIANT machine,/*[retval,out]*/ LPDISPATCH *pDevices); // // helpers // HRESULT BuildDeviceList(HDEVINFO hDevInfo, LPDISPATCH *pDevices); }; #endif //__DEVICECONSOLE_H_