/* * 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 #define NUM_ELEMENTS(x) (sizeof((x)) / sizeof((x)[0])) /* 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) { } #ifdef __cplusplus } #endif