From 8a8e79622eadb6c2577e77f5a3d7655e743dd219 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. Introduces C++ dependency for Windows port only --- configure.ac | 22 ++ modules/Makefile.am | 7 +- modules/windows-sens/Makefile.am | 19 ++ modules/windows-sens/evolution-windows-sens.cxx | 257 ++++++++++++++++++++++++ 4 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 modules/windows-sens/Makefile.am create mode 100644 modules/windows-sens/evolution-windows-sens.cxx diff --git a/configure.ac b/configure.ac index fc9ef87738..6a2ee14bec 100644 --- a/configure.ac +++ b/configure.ac @@ -1142,6 +1142,27 @@ 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]) +AC_MSG_CHECKING([if Windows SENS support is enabled]) +AC_MSG_RESULT([$enable_sens]) +if test "$enable_sens" = yes; then + AC_PROG_CXX + AC_CHECK_HEADERS([eventsys.h sensevts.h],[ enable_sens="yes" ],[ enable_sens="no" ]) +fi +if test "$enable_sens" = yes; then + SENS_LIBS="-lole32 -loleaut32 -luuid" + 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 +1714,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 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..29b027fcf3 --- /dev/null +++ b/modules/windows-sens/Makefile.am @@ -0,0 +1,19 @@ +module_LTLIBRARIES = libevolution-module-windows-sens.la + +libevolution_module_windows_sens_la_CPPFLAGS = \ + -I$(top_srcdir) \ + -DG_LOG_DOMAIN=\"evolution-windows-sens\" \ + $(GNOME_PLATFORM_CFLAGS) + +libevolution_module_windows_sens_la_SOURCES = \ + evolution-windows-sens.cxx + +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.cxx b/modules/windows-sens/evolution-windows-sens.cxx new file mode 100644 index 0000000000..b6328e9c28 --- /dev/null +++ b/modules/windows-sens/evolution-windows-sens.cxx @@ -0,0 +1,257 @@ +/* + * 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 +extern "C" { +#endif + +#define INITGUID +#include +#include +#include +#include + + +#include +#include + +/* 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); +} + +class MySensNetwork : public IDispatch +{ +private: + long ref; + EWindowsSENS *mpEWS; + +public: + MySensNetwork (EWindowsSENS *ews) : + ref(1), + mpEWS(ews) + {} + + HRESULT WINAPI QueryInterface (REFIID iid, void ** ppv) + { + if (IsEqualIID (iid, IID_IUnknown) || IsEqualIID (iid, IID_IDispatch) || IsEqualIID (iid, IID_ISensNetwork)) { + *ppv = this; + AddRef(); + return S_OK; + } + *ppv = NULL; + return E_NOINTERFACE; + } + + ULONG WINAPI AddRef () + { + return InterlockedIncrement (&ref); + } + + ULONG WINAPI Release () + { + int tmp = InterlockedDecrement (&ref); + return tmp; + } + + HRESULT WINAPI GetTypeInfoCount (unsigned FAR*) + { + return E_NOTIMPL; + } + + HRESULT WINAPI GetTypeInfo (unsigned, LCID, ITypeInfo FAR* FAR*) + { + return E_NOTIMPL; + } + + HRESULT WINAPI GetIDsOfNames (REFIID, OLECHAR FAR* FAR*, unsigned, LCID, DISPID FAR*) + { + return E_NOTIMPL; + } + + HRESULT WINAPI Invoke (DISPID, REFIID, LCID, WORD, DISPPARAMS FAR*, VARIANT FAR*, EXCEPINFO FAR*, unsigned FAR*) + { + return E_NOTIMPL; + } + +// ISensNetwork methods: + virtual HRESULT WINAPI ConnectionMade (BSTR, ULONG ulType, LPSENS_QOCINFO*) + { + if (ulType) { + EShell *shell = windows_sens_get_shell (mpEWS); + e_shell_set_network_available (shell, TRUE); + } + return S_OK; + } + + virtual HRESULT WINAPI ConnectionMadeNoQOCInfo (BSTR, ULONG) + { + //Always followed by ConnectionMade + return S_OK; + } + + virtual HRESULT WINAPI ConnectionLost (BSTR, ULONG ulType) + { + if (ulType) { + EShell *shell = windows_sens_get_shell (mpEWS); + e_shell_set_network_available (shell, FALSE); + } + return S_OK; + } +}; + +/* 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); + +static void +windows_sens_constructed (GObject *object) +{ + static IEventSystem *pIEventSystem =0; + static IEventSubscription* pIEventSubscription = 0; + WCHAR buffer[64]; + static const char* eventclassid="{D5978620-5B9F-11D1-8DD2-00AA004ABD5E}"; + static const char* methods[]={"ConnectionMade","ConnectionMadeNoQOCInfo","ConnectionLost"}; + static const char* names[]={"EWS_ConnectionMade","EWS_ConnectionMadeNoQOCInfo","EWS_ConnectionLost"}; + static const char* subids[]={"{cd1dcbd6-a14d-4823-a0d2-8473afde360f}","{a82f0e80-1305-400c-ba56-375ae04264a1}", + "{45233130-b6c3-44fb-a6af-487c47cee611}"}; + + EWindowsSENS *extension = (E_WINDOWS_SENS (object)); + static MySensNetwork *pISensNetwork = new MySensNetwork (extension); + + CoInitialize(0); + + HRESULT res=CoCreateInstance (CLSID_CEventSystem, 0,CLSCTX_SERVER,IID_IEventSystem,(void**)&pIEventSystem); + + for (int i=0; i<3; i++) + { + res=CoCreateInstance (CLSID_CEventSubscription, 0, CLSCTX_SERVER, IID_IEventSubscription, (LPVOID*)&pIEventSubscription); + MultiByteToWideChar (0, 0, eventclassid, -1, buffer, 64); + res=pIEventSubscription->put_EventClassID (buffer); + res=pIEventSubscription->put_SubscriberInterface ((IUnknown*)pISensNetwork); + MultiByteToWideChar (0, 0, methods[i], -1, buffer, 64); + res=pIEventSubscription->put_MethodName (buffer); + MultiByteToWideChar (0, 0, names[i], -1, buffer, 64); + res=pIEventSubscription->put_SubscriptionName (buffer); + MultiByteToWideChar (0, 0, subids[i], -1, buffer, 64); + res=pIEventSubscription->put_SubscriptionID (buffer); + res=pIEventSystem->Store (PROGID_EventSubscription, (IUnknown*)pIEventSubscription); + pIEventSubscription->Release (); + pIEventSubscription=0; + } + + typedef BOOL (WINAPI* IsNetworkAlive_t) (LPDWORD); + + IsNetworkAlive_t pIsNetworkAlive = NULL; + + HMODULE hDLL=LoadLibrary ("sensapi.dll"); + + BOOL alive = TRUE; + if ((pIsNetworkAlive=(IsNetworkAlive_t) GetProcAddress (hDLL, "IsNetworkAlive"))) { + DWORD Network; + alive=pIsNetworkAlive (&Network); + } + + FreeLibrary(hDLL); + + EShell *shell = windows_sens_get_shell (extension); + + 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) +{ + CoUninitialize(); +} + +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) +{ +} + +#ifdef __cplusplus +} +#endif -- cgit v1.2.3