From d358da9481a125e7eefa80cde88a6bed0c1b7fc3 Mon Sep 17 00:00:00 2001 From: Fridrich Strba Date: Tue, 23 Mar 2010 18:54:37 +0100 Subject: [win32] Implement network status detection The implementation is done using System Event Notification Service by implementing ConnectionMade ConnectionMadeNoQOCInfo and ConnectionLost methods of ISensNetwork interface. Make the subscription to the network status notification receive the event only if the ownerof the subscription is logged on to the same computer as the publisher. This makes this module work on Windows Vista and Windows 7 with normal user account. Don't try to build Windows SENS when not building for Windows. Extract the relevant COM structs and typedefs from mingw-w64 headers to allow to build the module with mingw.org toolchain and fix build breakages with Microsoft compilers. --- configure.ac | 38 ++ modules/Makefile.am | 7 +- modules/windows-sens/Makefile.am | 20 + modules/windows-sens/evolution-windows-sens.c | 602 ++++++++++++++++++++++++++ 4 files changed, 666 insertions(+), 1 deletion(-) create mode 100644 modules/windows-sens/Makefile.am create mode 100644 modules/windows-sens/evolution-windows-sens.c diff --git a/configure.ac b/configure.ac index 3f3a2bbef7..882dd1d3a8 100644 --- a/configure.ac +++ b/configure.ac @@ -1142,6 +1142,42 @@ fi AM_CONDITIONAL([ENABLE_NETWORK_MANAGER], [test "$enable_nm" = yes]) +dnl ****************************** +dnl Check for Windows SENS API +dnl ****************************** +AC_ARG_ENABLE([sens], + [AS_HELP_STRING([--enable-sens], + [enable Windows SENS support (default=yes)])], + [enable_sens=$enableval],[enable_sens=yes]) +if test "x$os_win32" = xyes; then + if test "x$enable_sens" = xyes; then + AC_CHECK_HEADER([rpc.h],[ enable_sens="yes" ],[ enable_sens="no" ]) + fi +else + enable_sens="no" +fi +AC_MSG_CHECKING([if Windows SENS support is enabled]) +AC_MSG_RESULT([$enable_sens]) +if test "$enable_sens" = yes; then + SENS_LIBS="-lole32 -loleaut32 -luuid -lrpcrt4" + AC_CHECK_HEADER([eventsys.h], + [AC_DEFINE([HAVE_EVENTSYS_H], 1, [Have ])],, + [[ #if HAVE_EVENTSYS_H + #include + #endif + ]]) + AC_CHECK_HEADER([sensevts.h], + [AC_DEFINE([HAVE_SENSEVTS_H], 1, [Have ])],, + [[ #if HAVE_SENSEVTS_H + #include + #endif + ]]) + AC_SUBST(HAVE_SENS) + AC_SUBST(SENS_LIBS) +fi + +AM_CONDITIONAL([ENABLE_WINDOWS_SENS], [test "$enable_sens" = yes]) + dnl ****************************** dnl Camel Flags dnl ****************************** @@ -1693,6 +1729,7 @@ modules/network-manager/Makefile modules/plugin-lib/Makefile modules/plugin-mono/Makefile modules/plugin-python/Makefile +modules/windows-sens/Makefile plugins/Makefile plugins/addressbook-file/Makefile plugins/attachment-reminder/Makefile @@ -1760,6 +1797,7 @@ fi echo " LDAP support: $msg_ldap NetworkManager: $enable_nm + Windows SENS: $enable_sens Pilot conduits: $msg_pilot Libnotify: $HAVE_LIBNOTIFY Kerberos 5: $msg_krb5 diff --git a/modules/Makefile.am b/modules/Makefile.am index 0b6ccf22ec..653d1b69c6 100644 --- a/modules/Makefile.am +++ b/modules/Makefile.am @@ -10,6 +10,10 @@ if ENABLE_NETWORK_MANAGER NETWORK_MANAGER_DIR = network-manager endif +if ENABLE_WINDOWS_SENS +WINDOWS_SENS_DIR = windows-sens +endif + SUBDIRS = \ addressbook \ calendar \ @@ -17,6 +21,7 @@ SUBDIRS = \ plugin-lib \ $(MONO_DIR) \ $(PYTHON_DIR) \ - $(NETWORK_MANAGER_DIR) + $(NETWORK_MANAGER_DIR) \ + $(WINDOWS_SENS_DIR) -include $(top_srcdir)/git.mk diff --git a/modules/windows-sens/Makefile.am b/modules/windows-sens/Makefile.am new file mode 100644 index 0000000000..5036642d09 --- /dev/null +++ b/modules/windows-sens/Makefile.am @@ -0,0 +1,20 @@ +module_LTLIBRARIES = libevolution-module-windows-sens.la + +libevolution_module_windows_sens_la_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(top_srcdir) \ + -DG_LOG_DOMAIN=\"evolution-windows-sens\" \ + $(GNOME_PLATFORM_CFLAGS) + +libevolution_module_windows_sens_la_SOURCES = \ + evolution-windows-sens.c + +libevolution_module_windows_sens_la_LIBADD = \ + $(top_builddir)/shell/libeshell.la \ + $(GNOME_PLATFORM_LIBS) \ + $(SENS_LIBS) + +libevolution_module_windows_sens_la_LDFLAGS = \ + -module -avoid-version $(NO_UNDEFINED) + +-include $(top_srcdir)/git.mk diff --git a/modules/windows-sens/evolution-windows-sens.c b/modules/windows-sens/evolution-windows-sens.c new file mode 100644 index 0000000000..d228fc02ac --- /dev/null +++ b/modules/windows-sens/evolution-windows-sens.c @@ -0,0 +1,602 @@ +/* + * evolution-windows-sens.c + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see + * + */ + +#ifdef __cplusplus +#error This file cannot be built with C++ compiler +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define INITGUID +#include +#include + +#ifdef HAVE_EVENTSYS_H +#include +#else + +/* Extract relevant typedefs from mingw-w64 headers */ + +typedef struct IEnumEventObject IEnumEventObject; + +const IID IID_IEnumEventObject; +typedef struct IEnumEventObjectVtbl { + BEGIN_INTERFACE + HRESULT (WINAPI *QueryInterface)(IEnumEventObject *This,REFIID riid,void **ppvObject); + ULONG (WINAPI *AddRef)(IEnumEventObject *This); + ULONG (WINAPI *Release)(IEnumEventObject *This); + HRESULT (WINAPI *Clone)(IEnumEventObject *This,IEnumEventObject **ppInterface); + HRESULT (WINAPI *Next)(IEnumEventObject *This,ULONG cReqElem,IUnknown **ppInterface,ULONG *cRetElem); + HRESULT (WINAPI *Reset)(IEnumEventObject *This); + HRESULT (WINAPI *Skip)(IEnumEventObject *This,ULONG cSkipElem); + END_INTERFACE +} IEnumEventObjectVtbl; +struct IEnumEventObject { + CONST_VTBL struct IEnumEventObjectVtbl *lpVtbl; +}; + +typedef struct IEventObjectCollection IEventObjectCollection; + +const IID IID_IEventObjectCollection; +typedef struct IEventObjectCollectionVtbl { + BEGIN_INTERFACE + HRESULT (WINAPI *QueryInterface)(IEventObjectCollection *This,REFIID riid,void **ppvObject); + ULONG (WINAPI *AddRef)(IEventObjectCollection *This); + ULONG (WINAPI *Release)(IEventObjectCollection *This); + HRESULT (WINAPI *GetTypeInfoCount)(IEventObjectCollection *This,UINT *pctinfo); + HRESULT (WINAPI *GetTypeInfo)(IEventObjectCollection *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); + HRESULT (WINAPI *GetIDsOfNames)(IEventObjectCollection *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); + HRESULT (WINAPI *Invoke)(IEventObjectCollection *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); + HRESULT (WINAPI *get__NewEnum)(IEventObjectCollection *This,IUnknown **ppUnkEnum); + HRESULT (WINAPI *get_Item)(IEventObjectCollection *This,BSTR objectID,VARIANT *pItem); + HRESULT (WINAPI *get_NewEnum)(IEventObjectCollection *This,IEnumEventObject **ppEnum); + HRESULT (WINAPI *get_Count)(IEventObjectCollection *This,long *pCount); + HRESULT (WINAPI *Add)(IEventObjectCollection *This,VARIANT *item,BSTR objectID); + HRESULT (WINAPI *Remove)(IEventObjectCollection *This,BSTR objectID); + END_INTERFACE +} IEventObjectCollectionVtbl; +struct IEventObjectCollection { + CONST_VTBL struct IEventObjectCollectionVtbl *lpVtbl; +}; + + +typedef struct IEventSystem IEventSystem; + +const IID IID_IEventSystem; +typedef struct IEventSystemVtbl { + BEGIN_INTERFACE + HRESULT (WINAPI *QueryInterface)(IEventSystem *This,REFIID riid,void **ppvObject); + ULONG (WINAPI *AddRef)(IEventSystem *This); + ULONG (WINAPI *Release)(IEventSystem *This); + HRESULT (WINAPI *GetTypeInfoCount)(IEventSystem *This,UINT *pctinfo); + HRESULT (WINAPI *GetTypeInfo)(IEventSystem *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); + HRESULT (WINAPI *GetIDsOfNames)(IEventSystem *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); + HRESULT (WINAPI *Invoke)(IEventSystem *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); + HRESULT (WINAPI *Query)(IEventSystem *This,BSTR progID,BSTR queryCriteria,int *errorIndex,IUnknown **ppInterface); + HRESULT (WINAPI *Store)(IEventSystem *This,BSTR ProgID,IUnknown *pInterface); + HRESULT (WINAPI *Remove)(IEventSystem *This,BSTR progID,BSTR queryCriteria,int *errorIndex); + HRESULT (WINAPI *get_EventObjectChangeEventClassID)(IEventSystem *This,BSTR *pbstrEventClassID); + HRESULT (WINAPI *QueryS)(IEventSystem *This,BSTR progID,BSTR queryCriteria,IUnknown **ppInterface); + HRESULT (WINAPI *RemoveS)(IEventSystem *This,BSTR progID,BSTR queryCriteria); + END_INTERFACE +} IEventSystemVtbl; +struct IEventSystem { + CONST_VTBL struct IEventSystemVtbl *lpVtbl; +}; + +typedef struct IEventSubscription IEventSubscription; + +const IID IID_IEventSubscription; +typedef struct IEventSubscriptionVtbl { + BEGIN_INTERFACE + HRESULT (WINAPI *QueryInterface)(IEventSubscription *This,REFIID riid,void **ppvObject); + ULONG (WINAPI *AddRef)(IEventSubscription *This); + ULONG (WINAPI *Release)(IEventSubscription *This); + HRESULT (WINAPI *GetTypeInfoCount)(IEventSubscription *This,UINT *pctinfo); + HRESULT (WINAPI *GetTypeInfo)(IEventSubscription *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); + HRESULT (WINAPI *GetIDsOfNames)(IEventSubscription *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); + HRESULT (WINAPI *Invoke)(IEventSubscription *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); + HRESULT (WINAPI *get_SubscriptionID)(IEventSubscription *This,BSTR *pbstrSubscriptionID); + HRESULT (WINAPI *put_SubscriptionID)(IEventSubscription *This,BSTR bstrSubscriptionID); + HRESULT (WINAPI *get_SubscriptionName)(IEventSubscription *This,BSTR *pbstrSubscriptionName); + HRESULT (WINAPI *put_SubscriptionName)(IEventSubscription *This,BSTR bstrSubscriptionName); + HRESULT (WINAPI *get_PublisherID)(IEventSubscription *This,BSTR *pbstrPublisherID); + HRESULT (WINAPI *put_PublisherID)(IEventSubscription *This,BSTR bstrPublisherID); + HRESULT (WINAPI *get_EventClassID)(IEventSubscription *This,BSTR *pbstrEventClassID); + HRESULT (WINAPI *put_EventClassID)(IEventSubscription *This,BSTR bstrEventClassID); + HRESULT (WINAPI *get_MethodName)(IEventSubscription *This,BSTR *pbstrMethodName); + HRESULT (WINAPI *put_MethodName)(IEventSubscription *This,BSTR bstrMethodName); + HRESULT (WINAPI *get_SubscriberCLSID)(IEventSubscription *This,BSTR *pbstrSubscriberCLSID); + HRESULT (WINAPI *put_SubscriberCLSID)(IEventSubscription *This,BSTR bstrSubscriberCLSID); + HRESULT (WINAPI *get_SubscriberInterface)(IEventSubscription *This,IUnknown **ppSubscriberInterface); + HRESULT (WINAPI *put_SubscriberInterface)(IEventSubscription *This,IUnknown *pSubscriberInterface); + HRESULT (WINAPI *get_PerUser)(IEventSubscription *This,WINBOOL *pfPerUser); + HRESULT (WINAPI *put_PerUser)(IEventSubscription *This,WINBOOL fPerUser); + HRESULT (WINAPI *get_OwnerSID)(IEventSubscription *This,BSTR *pbstrOwnerSID); + HRESULT (WINAPI *put_OwnerSID)(IEventSubscription *This,BSTR bstrOwnerSID); + HRESULT (WINAPI *get_Enabled)(IEventSubscription *This,WINBOOL *pfEnabled); + HRESULT (WINAPI *put_Enabled)(IEventSubscription *This,WINBOOL fEnabled); + HRESULT (WINAPI *get_Description)(IEventSubscription *This,BSTR *pbstrDescription); + HRESULT (WINAPI *put_Description)(IEventSubscription *This,BSTR bstrDescription); + HRESULT (WINAPI *get_MachineName)(IEventSubscription *This,BSTR *pbstrMachineName); + HRESULT (WINAPI *put_MachineName)(IEventSubscription *This,BSTR bstrMachineName); + HRESULT (WINAPI *GetPublisherProperty)(IEventSubscription *This,BSTR bstrPropertyName,VARIANT *propertyValue); + HRESULT (WINAPI *PutPublisherProperty)(IEventSubscription *This,BSTR bstrPropertyName,VARIANT *propertyValue); + HRESULT (WINAPI *RemovePublisherProperty)(IEventSubscription *This,BSTR bstrPropertyName); + HRESULT (WINAPI *GetPublisherPropertyCollection)(IEventSubscription *This,IEventObjectCollection **collection); + HRESULT (WINAPI *GetSubscriberProperty)(IEventSubscription *This,BSTR bstrPropertyName,VARIANT *propertyValue); + HRESULT (WINAPI *PutSubscriberProperty)(IEventSubscription *This,BSTR bstrPropertyName,VARIANT *propertyValue); + HRESULT (WINAPI *RemoveSubscriberProperty)(IEventSubscription *This,BSTR bstrPropertyName); + HRESULT (WINAPI *GetSubscriberPropertyCollection)(IEventSubscription *This,IEventObjectCollection **collection); + HRESULT (WINAPI *get_InterfaceID)(IEventSubscription *This,BSTR *pbstrInterfaceID); + HRESULT (WINAPI *put_InterfaceID)(IEventSubscription *This,BSTR bstrInterfaceID); + END_INTERFACE +} IEventSubscriptionVtbl; +struct IEventSubscription { + CONST_VTBL struct IEventSubscriptionVtbl *lpVtbl; +}; + +#define PROGID_EventSubscription OLESTR("EventSystem.EventSubscription") + +#endif + +#ifdef HAVE_SENSEVTS_H +#include +#else + +/* Extract relevant typedefs from mingw-w64 headers */ + +typedef struct { + DWORD dwSize; + DWORD dwFlags; + DWORD dwOutSpeed; + DWORD dwInSpeed; +} *LPSENS_QOCINFO; + +typedef struct ISensNetwork ISensNetwork; + +const IID IID_ISensNetwork; +typedef struct ISensNetworkVtbl { + BEGIN_INTERFACE + HRESULT (WINAPI *QueryInterface)(ISensNetwork *This,REFIID riid,void **ppvObject); + ULONG (WINAPI *AddRef)(ISensNetwork *This); + ULONG (WINAPI *Release)(ISensNetwork *This); + HRESULT (WINAPI *GetTypeInfoCount)(ISensNetwork *This,UINT *pctinfo); + HRESULT (WINAPI *GetTypeInfo)(ISensNetwork *This,UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo); + HRESULT (WINAPI *GetIDsOfNames)(ISensNetwork *This,REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId); + HRESULT (WINAPI *Invoke)(ISensNetwork *This,DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr); + HRESULT (WINAPI *ConnectionMade)(ISensNetwork *This,BSTR bstrConnection,ULONG ulType,LPSENS_QOCINFO lpQOCInfo); + HRESULT (WINAPI *ConnectionMadeNoQOCInfo)(ISensNetwork *This,BSTR bstrConnection,ULONG ulType); + HRESULT (WINAPI *ConnectionLost)(ISensNetwork *This,BSTR bstrConnection,ULONG ulType); + HRESULT (WINAPI *DestinationReachable)(ISensNetwork *This,BSTR bstrDestination,BSTR bstrConnection,ULONG ulType,LPSENS_QOCINFO lpQOCInfo); + HRESULT (WINAPI *DestinationReachableNoQOCInfo)(ISensNetwork *This,BSTR bstrDestination,BSTR bstrConnection,ULONG ulType); + END_INTERFACE +} ISensNetworkVtbl; +struct ISensNetwork { + CONST_VTBL struct ISensNetworkVtbl *lpVtbl; +}; + +#endif + +#include +#include + +/* 4E14FB9F-2E22-11D1-9964-00C04FBBB345 */ +DEFINE_GUID(IID_IEventSystem, 0x4E14FB9F, 0x2E22, 0x11D1, 0x99, 0x64, 0x00, 0xC0, 0x4F, 0xBB, 0xB3, 0x45); + +/* 4A6B0E15-2E38-11D1-9965-00C04FBBB345 */ +DEFINE_GUID(IID_IEventSubscription, 0x4A6B0E15, 0x2E38, 0x11D1, 0x99, 0x65, 0x00, 0xC0, 0x4F, 0xBB, 0xB3, 0x45); + +/* d597bab1-5b9f-11d1-8dd2-00aa004abd5e */ +DEFINE_GUID(IID_ISensNetwork, 0xd597bab1, 0x5b9f, 0x11d1, 0x8d, 0xd2, 0x00, 0xaa, 0x00, 0x4a, 0xbd, 0x5e); + +/* 4E14FBA2-2E22-11D1-9964-00C04FBBB345 */ +DEFINE_GUID(CLSID_CEventSystem, 0x4E14FBA2, 0x2E22, 0x11D1, 0x99, 0x64, 0x00, 0xC0, 0x4F, 0xBB, 0xB3, 0x45); + +/* 7542e960-79c7-11d1-88f9-0080c7d771bf */ +DEFINE_GUID(CLSID_CEventSubscription, 0x7542e960, 0x79c7, 0x11d1, 0x88, 0xf9, 0x00, 0x80, 0xc7, 0xd7, 0x71, 0xbf); + + +/* Standard GObject macros */ +#define E_TYPE_WINDOWS_SENS \ + (e_windows_sens_get_type ()) +#define E_WINDOWS_SENS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_WINDOWS_SENS, EWindowsSENS)) + +typedef struct _EWindowsSENS EWindowsSENS; +typedef struct _EWindowsSENSClass EWindowsSENSClass; + +struct _EWindowsSENS { + EExtension parent; +}; + +struct _EWindowsSENSClass { + EExtensionClass parent_class; +}; + +/* Module Entry Points */ +void e_module_load (GTypeModule *type_module); +void e_module_unload (GTypeModule *type_module); + +/* Forward Declarations */ +GType e_windows_sens_get_type (void); + +G_DEFINE_DYNAMIC_TYPE (EWindowsSENS, e_windows_sens, E_TYPE_EXTENSION) + +static EShell * +windows_sens_get_shell (EWindowsSENS *extension) +{ + EExtensible *extensible; + + extensible = e_extension_get_extensible (E_EXTENSION (extension)); + + return E_SHELL (extensible); +} + +/* Object to receive the ISensNetwork events */ + +typedef struct ESensNetworkListener { + ISensNetworkVtbl *lpVtbl; + long ref; + EWindowsSENS *ews_ptr; +} ESensNetworkListener; + +static void e_sens_network_listener_init(ESensNetworkListener**,EWindowsSENS*); + +/* Functions to implement ISensNetwork interface */ + +static HRESULT WINAPI e_sens_network_listener_queryinterface (ISensNetwork*,REFIID,void**); +static ULONG WINAPI e_sens_network_listener_addref (ISensNetwork*); +static ULONG WINAPI e_sens_network_listener_release (ISensNetwork*); +static HRESULT WINAPI e_sens_network_listener_gettypeinfocount (ISensNetwork*, UINT*); +static HRESULT WINAPI e_sens_network_listener_gettypeinfo (ISensNetwork*,UINT,LCID,ITypeInfo**); +static HRESULT WINAPI e_sens_network_listener_getidsofnames (ISensNetwork*,REFIID,LPOLESTR*,UINT,LCID, DISPID*); +static HRESULT WINAPI e_sens_network_listener_invoke (ISensNetwork*,DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*); +static HRESULT WINAPI e_sens_network_listener_connectionmade (ISensNetwork*,BSTR,ULONG,LPSENS_QOCINFO); +static HRESULT WINAPI e_sens_network_listener_connectionmadenoqocinfo (ISensNetwork*,BSTR,ULONG); +static HRESULT WINAPI e_sens_network_listener_connectionlost (ISensNetwork*,BSTR,ULONG); +static HRESULT WINAPI e_sens_network_listener_destinationreachable (ISensNetwork*,BSTR,BSTR,ULONG,LPSENS_QOCINFO); +static HRESULT WINAPI e_sens_network_listener_destinationreachablenoqocinfo (ISensNetwork*,BSTR,BSTR,ULONG); + +/* Initializing the VTable of our ESensNetworkListener object */ + +static ISensNetworkVtbl ESensNetworkListenerVtbl = { + e_sens_network_listener_queryinterface, + e_sens_network_listener_addref, + e_sens_network_listener_release, + e_sens_network_listener_gettypeinfocount, + e_sens_network_listener_gettypeinfo, + e_sens_network_listener_getidsofnames, + e_sens_network_listener_invoke, + e_sens_network_listener_connectionmade, + e_sens_network_listener_connectionmadenoqocinfo, + e_sens_network_listener_connectionlost, + e_sens_network_listener_destinationreachable, + e_sens_network_listener_destinationreachablenoqocinfo +}; + + +static HRESULT WINAPI +e_sens_network_listener_queryinterface (ISensNetwork *This, + REFIID iid, + void **ppv) +{ + if (IsEqualIID (iid, &IID_IUnknown) || IsEqualIID (iid, &IID_IDispatch) || IsEqualIID (iid, &IID_ISensNetwork)) { + *ppv = This; + ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv); + return S_OK; + } + *ppv = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI +e_sens_network_listener_addref (ISensNetwork *This) +{ + ESensNetworkListener *esnl_ptr=(ESensNetworkListener*)This; + return InterlockedIncrement(&(esnl_ptr->ref)); +} + +static ULONG WINAPI +e_sens_network_listener_release (ISensNetwork *This) +{ + ESensNetworkListener *esnl_ptr=(ESensNetworkListener*)This; + ULONG tmp = InterlockedDecrement(&(esnl_ptr->ref)); + return tmp; +} + +static HRESULT WINAPI +e_sens_network_listener_gettypeinfocount (ISensNetwork *This, + UINT *pctinfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +e_sens_network_listener_gettypeinfo (ISensNetwork *This, + UINT iTInfo, + LCID lcid, + ITypeInfo **ppTInfo) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +e_sens_network_listener_getidsofnames (ISensNetwork *This, + REFIID riid, + LPOLESTR *rgszNames, + UINT cNames, + LCID lcid, + DISPID *rgDispId) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +e_sens_network_listener_invoke (ISensNetwork *This, + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS *pDispParams, + VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, + UINT *puArgErr) +{ + return E_NOTIMPL; +} + +static HRESULT WINAPI +e_sens_network_listener_connectionmade (ISensNetwork *This, + BSTR bstrConnection, + ULONG ulType, + LPSENS_QOCINFO lpQOCInfo) +{ + if (ulType) { + ESensNetworkListener *esnl_ptr=(ESensNetworkListener*)This; + EShell *shell = windows_sens_get_shell (esnl_ptr->ews_ptr); + /* Wait a second so that the connection stabilizes */ + g_usleep(G_USEC_PER_SEC); + e_shell_set_network_available (shell, TRUE); + } + return S_OK; +} + +static HRESULT WINAPI +e_sens_network_listener_connectionmadenoqocinfo (ISensNetwork *This, + BSTR bstrConnection, + ULONG ulType) +{ + //Always followed by ConnectionMade + return S_OK; +} + +static HRESULT WINAPI +e_sens_network_listener_connectionlost (ISensNetwork *This, + BSTR bstrConnection, + ULONG ulType) +{ + if (ulType) { + ESensNetworkListener *esnl_ptr=(ESensNetworkListener*)This; + EShell *shell = windows_sens_get_shell (esnl_ptr->ews_ptr); + e_shell_set_network_available (shell, FALSE); + } + return S_OK; +} + +static HRESULT WINAPI +e_sens_network_listener_destinationreachable (ISensNetwork *This, + BSTR bstrDestination, + BSTR bstrConnection, + ULONG ulType, + LPSENS_QOCINFO lpQOCInfo) +{ + if (ulType) { + ESensNetworkListener *esnl_ptr=(ESensNetworkListener*)This; + EShell *shell = windows_sens_get_shell (esnl_ptr->ews_ptr); + /* Wait a second so that the connection stabilizes */ + g_usleep(G_USEC_PER_SEC); + e_shell_set_network_available (shell, TRUE); + } + return S_OK; +} + +static HRESULT WINAPI +e_sens_network_listener_destinationreachablenoqocinfo (ISensNetwork *This, + BSTR bstrDestination, + BSTR bstrConnection, + ULONG ulType) +{ + return S_OK; +} + +static void +e_sens_network_listener_init(ESensNetworkListener **esnl_ptr, + EWindowsSENS *ews) +{ + (*esnl_ptr) = g_new0(ESensNetworkListener,1); + (*esnl_ptr)->lpVtbl = &ESensNetworkListenerVtbl; + (*esnl_ptr)->ews_ptr = ews; + (*esnl_ptr)->ref = 1; +} + + +static BSTR +_mb2wchar (const char* a) +{ + static WCHAR b[64]; + MultiByteToWideChar (0, 0, a, -1, b, 64); + return b; +} + +static const char* add_curly_braces_to_uuid (const char* string_uuid) +{ + static char curly_braced_uuid_string[64]; + int i; + if (!string_uuid) + return NULL; + lstrcpy(curly_braced_uuid_string,"{"); + i = strlen(curly_braced_uuid_string); + lstrcat(curly_braced_uuid_string+i,string_uuid); + i = strlen(curly_braced_uuid_string); + lstrcat(curly_braced_uuid_string+i,"}"); + return curly_braced_uuid_string; +} + +static void +windows_sens_constructed (GObject *object) +{ + HRESULT res; + static IEventSystem *pEventSystem =0; + static IEventSubscription* pEventSubscription = 0; + static ESensNetworkListener *pESensNetworkListener = 0; + static const char* eventclassid="{D5978620-5B9F-11D1-8DD2-00AA004ABD5E}"; + static const char* methods[]={ + "ConnectionMade", + "ConnectionMadeNoQOCInfo", + "ConnectionLost", + "DestinationReachable", + "DestinationReachableNoQOCInfo" + }; + static const char* names[]={ + "EWS_ConnectionMade", + "EWS_ConnectionMadeNoQOCInfo", + "EWS_ConnectionLost", + "EWS_DestinationReachable", + "EWS_DestinationReachableNoQOCInfo" + }; + unsigned char* subids[] = { 0, 0, 0, 0, 0 }; + + EWindowsSENS *extension = (E_WINDOWS_SENS (object)); + e_sens_network_listener_init(&pESensNetworkListener, extension); + + CoInitialize(0); + + res=CoCreateInstance (&CLSID_CEventSystem, 0,CLSCTX_SERVER,&IID_IEventSystem,(LPVOID*)&pEventSystem); + + if (res == S_OK && pEventSystem) { + + unsigned i; + + for (i=0; ilpVtbl->put_SubscriptionID (pEventSubscription, _mb2wchar (add_curly_braces_to_uuid ((char*)subids[i]))); + if (res) { + RpcStringFree (&subids[i]); + break; + } + RpcStringFree (&subids[i]); + res=pEventSubscription->lpVtbl->put_SubscriptionName (pEventSubscription, _mb2wchar (names[i])); + if (res) + break; + res=pEventSubscription->lpVtbl->put_MethodName (pEventSubscription, _mb2wchar (methods[i])); + if (res) + break; + res=pEventSubscription->lpVtbl->put_EventClassID (pEventSubscription, _mb2wchar (eventclassid)); + if (res) + break; + res=pEventSubscription->lpVtbl->put_SubscriberInterface (pEventSubscription, (IUnknown*)pESensNetworkListener); + if (res) + break; + /* Make the subscription receive the event only if the owner of the subscription + * is logged on to the same computer as the publisher. This makes this module + * work with normal user account without administrative privileges. + */ + res=pEventSubscription->lpVtbl->put_PerUser (pEventSubscription, TRUE); + if (res) + break; + + res=pEventSystem->lpVtbl->Store (pEventSystem, (BSTR)PROGID_EventSubscription, (IUnknown*)pEventSubscription); + if (res) + break; + pEventSubscription->lpVtbl->Release (pEventSubscription); + pEventSubscription=0; + } + } + if (pEventSubscription) + pEventSubscription->lpVtbl->Release(pEventSubscription); + } + + /* Do not try to get initial state when we are sure we will not get system events. + * Like that we don't get stuck with Disconnected status if we were disconnected + * on start. + */ + if (res == S_OK) { + + typedef BOOL (WINAPI* IsNetworkAlive_t) (LPDWORD); + BOOL alive = TRUE; + EShell *shell = windows_sens_get_shell (extension); + + IsNetworkAlive_t pIsNetworkAlive = NULL; + + HMODULE hDLL=LoadLibrary ("sensapi.dll"); + + if ((pIsNetworkAlive=(IsNetworkAlive_t) GetProcAddress (hDLL, "IsNetworkAlive"))) { + DWORD Network; + alive=pIsNetworkAlive (&Network); + } + + FreeLibrary(hDLL); + + e_shell_set_network_available (shell, alive); + } +} + +static void +e_windows_sens_class_init (EWindowsSENSClass *_class) +{ + GObjectClass *object_class; + EExtensionClass *extension_class; + + object_class = G_OBJECT_CLASS (_class); + object_class->constructed = windows_sens_constructed; + + extension_class = E_EXTENSION_CLASS (_class); + extension_class->extensible_type = E_TYPE_SHELL; +} + +static void +e_windows_sens_class_finalize (EWindowsSENSClass *_class) +{ +} + +static void +e_windows_sens_init (EWindowsSENS *extension) +{ +} + +G_MODULE_EXPORT void +e_module_load (GTypeModule *type_module) +{ + e_windows_sens_register_type (type_module); +} + +G_MODULE_EXPORT void +e_module_unload (GTypeModule *type_module) +{ +} + -- cgit v1.2.3