From 49b4d6dd9d4d35adc9f02df4010a1a6b33faba63 Mon Sep 17 00:00:00 2001 From: sje Date: Wed, 1 Nov 2006 14:44:34 +0000 Subject: git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@12 4f64403b-2f21-0410-a795-97e2b3489a10 --- ping_protocol/pingproto.cpp | 468 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 468 insertions(+) create mode 100644 ping_protocol/pingproto.cpp (limited to 'ping_protocol/pingproto.cpp') diff --git a/ping_protocol/pingproto.cpp b/ping_protocol/pingproto.cpp new file mode 100644 index 0000000..9412233 --- /dev/null +++ b/ping_protocol/pingproto.cpp @@ -0,0 +1,468 @@ +#include "stdafx.h" +#include "pingproto.h" + +HINSTANCE hInst; +PLUGINLINK *pluginLink; + +HANDLE hNetlibUser = 0; +HANDLE hFillListEvent = 0, hContactDeleted = 0, hContactDblClick = 0, hContactSettingChanged; + +#define NUM_SERVICES 22 +HANDLE hServices[NUM_SERVICES] = {0}; + +int previousMode, + mcStatus = ID_STATUS_OFFLINE; + +// protocol related services +int GetCaps(WPARAM wParam,LPARAM lParam) +{ + int ret = 0; + switch (wParam) { + case PFLAGNUM_1: + //ret = PF1_IM | PF1_URL | PF1_FILE | PF1_MODEMSG | PF1_AUTHREQ | PF1_ADDED; + //ret = PF1_IMSEND | PF1_URLSEND | PF1_FILESEND | PF1_MODEMSGSEND; + //ret = 0; + break; + case PFLAGNUM_2: + if(!options.hide_proto) { + //ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND + // | PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE; //} + //ret = options.nrstatus | options.off_status | options.rstatus; + ret = Proto_Status2Flag(options.rstatus); + if(options.off_status != ID_STATUS_OFFLINE) + ret |= Proto_Status2Flag(options.off_status); + } + break; + case PFLAGNUM_3: + //ret = PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND; + //ret = PF2_ONLINE | PF2_LIGHTDND | PF2_HEAVYDND; + //ret = PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY | PF2_LONGAWAY | PF2_LIGHTDND + //| PF2_HEAVYDND | PF2_FREECHAT | PF2_OUTTOLUNCH | PF2_ONTHEPHONE; //} + //ret = options.nrstatus | options.off_status | options.rstatus; + //ret = Proto_Status2Flag(options.rstatus) | Proto_Status2Flag(options.off_status); + break; + case PFLAGNUM_4: + break; + case PFLAG_UNIQUEIDTEXT: + ret = (int) Translate(PROTO); + break; + case PFLAG_MAXLENOFMESSAGE: + ret = 2000; + break; + case PFLAG_UNIQUEIDSETTING: + ret = (int) "Address"; + break; + } + return ret; +} + +/** Copy the name of the protocole into lParam +* @param wParam : max size of the name +* @param lParam : reference to a char *, which will hold the name +*/ +int GetName(WPARAM wParam,LPARAM lParam) +{ + char *name = (char *)Translate(PROTO); +#ifdef min + size_t size = min(strlen(name),wParam-1); // copy only the first size bytes. +#else + size_t size = std::min(strlen(name),wParam-1); // copy only the first size bytes. +#endif + if(strncpy((char *)lParam,name,size)==NULL) + return 1; + ((char *)lParam)[size]='\0'; + return 0; +} + +/** Loads the icon corresponding to the status +* Called by the CList when the status changes. +* @param wParam : one of the following values : \n + PLI_PROTOCOL | PLI_ONLINE | PLI_OFFLINE +* @return an \c HICON in which the icon has been loaded. +*/ +int LoadIcon(WPARAM wParam,LPARAM lParam) +{ + + UINT id; + switch (wParam & 0xFFFF) + { + case PLI_PROTOCOL: + id = IDI_ICON_PROTO; + break; + case PLI_ONLINE: + id = IDI_ICON_PROTO; + break; + case PLI_OFFLINE: + id = IDI_ICON_PROTO; + break; + default: + return (int) (HICON) NULL; + } + + return (int) LoadImage(hInst, MAKEINTRESOURCE(id), IMAGE_ICON, + GetSystemMetrics(wParam & PLIF_SMALL ? SM_CXSMICON : SM_CXICON), + GetSystemMetrics(wParam & PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0); + return 0; +} + + +/** Changes the status and notifies everybody +* @param wParam : The new mode +* @param lParam : Allways set to 0. +*/ +int SetStatus(WPARAM wParam,LPARAM lParam) +{ + int new_status = (int)wParam; + + if(new_status == options.rstatus || options.nrstatus || options.off_status) { + previousMode = mcStatus; + mcStatus = new_status; + ProtoBroadcastAck(PROTO,NULL,ACKTYPE_STATUS,ACKRESULT_SUCCESS, (HANDLE)previousMode, mcStatus); + + if(new_status == options.off_status) + PingDisableAll(0, 0); + else if(previousMode == options.off_status) + PingEnableAll(0, 0); + } + + return 0; +} + +/** Returns the current status +*/ +int GetStatus(WPARAM wParam,LPARAM lParam) +{ + return mcStatus; +} + +// plugin stuff +PLUGININFO pluginInfo={ + sizeof(PLUGININFO), + "Ping Protocol", + PLUGIN_MAKE_VERSION(0, 4, 0, 0), + "Ping labelled IP addresses or domain names.", + "Scott Ellis", + "mail@scottellis.com.au", + "© 2005 Scott Ellis", + "http://www.scottellis.com.au/", + 0, //not transient + 0 //doesn't replace anything built-in +}; + +extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst=hinstDLL; + return TRUE; +} + +extern "C" PINGPROTO_API PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +int ContactDeleted(WPARAM wParam, LPARAM lParam) { + if ( CallService(MS_PROTO_ISPROTOONCONTACT, wParam, (LPARAM)PROTO) ) { + CallService(MS_PROTO_REMOVEFROMCONTACT, wParam, (LPARAM)PROTO); + HWND hGraphWnd = (HWND)DBGetContactSettingDword((HANDLE)wParam, PROTO, "WindowHandle", 0); + if(hGraphWnd) PostMessage(hGraphWnd, WM_CLOSE, 0, 0); + CallService(PROTO "/LoadPingList", 0, 0); + } + + return 0; +} + +int ContactSettingChanged(WPARAM wParam, LPARAM lParam) { + DBCONTACTWRITESETTING *dcws = (DBCONTACTWRITESETTING *)lParam; + + if ( CallService(MS_PROTO_ISPROTOONCONTACT, wParam, (LPARAM)PROTO) ) { + if(!strcmp(dcws->szModule, "CList") && !strcmp(dcws->szSetting, "MyHandle")) { + if(!changing_clist_handle()) { + if(!dcws->value.type == DBVT_DELETED) { + DBWriteContactSettingString((HANDLE)wParam, PROTO, "Nick", dcws->value.pszVal); + CallService(PROTO "/LoadPingList", 0, 0); + } + } + } + } + + return 0; +} + +////////////////////////////////////////////////////////// +/// Copied from MSN plugin - sent acks need to be from different thread :( +////////////////////////////////////////////////////////// +typedef struct tag_TFakeAckParams +{ + HANDLE hEvent; + HANDLE hContact; +} TFakeAckParams; + + +static DWORD CALLBACK sttFakeAckInfoSuccess( LPVOID param ) +{ + TFakeAckParams *tParam = ( TFakeAckParams* )param; + WaitForSingleObject( tParam->hEvent, INFINITE ); + + Sleep( 100 ); + ProtoBroadcastAck(PROTO, tParam->hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, ( HANDLE )1, 0 ); + + CloseHandle( tParam->hEvent ); + free(tParam); + return 0; +} + +int GetInfo(WPARAM wParam, LPARAM lParam) { + CCSDATA *ccs = (CCSDATA *) lParam; + DWORD dwThreadId; + HANDLE hEvent; + TFakeAckParams *tfap; + + hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); + + tfap = (TFakeAckParams *)malloc(sizeof(TFakeAckParams)); + tfap->hContact = ccs->hContact; + tfap->hEvent = hEvent; + + CloseHandle( CreateThread( NULL, 0, sttFakeAckInfoSuccess, tfap, 0, &dwThreadId )); + SetEvent( hEvent ); + + + return 0; +} + +void CreatePluginServices() { + int i = 0; + // protocol + hServices[i++] = CreateProtoServiceFunction(PROTO,PS_GETCAPS, GetCaps); + hServices[i++] = CreateProtoServiceFunction(PROTO,PS_GETNAME, GetName); + hServices[i++] = CreateProtoServiceFunction(PROTO,PS_SETSTATUS, SetStatus); + hServices[i++] = CreateProtoServiceFunction(PROTO,PS_GETSTATUS, GetStatus); + hServices[i++] = CreateProtoServiceFunction(PROTO,PS_LOADICON,LoadIcon); + hServices[i++] = CreateProtoServiceFunction(PROTO,PSS_GETINFO,GetInfo); + + // general + hServices[i++] = CreateServiceFunction(PROTO "/Ping", PluginPing); + + // list + hServices[i++] = CreateServiceFunction(PROTO "/ClearPingList", ClearPingList); + hServices[i++] = CreateServiceFunction(PROTO "/GetPingList", GetPingList); + hServices[i++] = CreateServiceFunction(PROTO "/SetPingList", SetPingList); + hServices[i++] = CreateServiceFunction(PROTO "/SetAndSavePingList", SetAndSavePingList); + hServices[i++] = CreateServiceFunction(PROTO "/LoadPingList", LoadPingList); + hServices[i++] = CreateServiceFunction(PROTO "/SavePingList", SavePingList); + + reload_event_handle = CreateHookableEvent(PROTO "/ListReload"); + + //log + hServices[i++] = CreateServiceFunction(PROTO "/Log", Log); + hServices[i++] = CreateServiceFunction(PROTO "/ViewLogData", ViewLogData); + hServices[i++] = CreateServiceFunction(PROTO "/GetLogFilename", GetLogFilename); + hServices[i++] = CreateServiceFunction(PROTO "/SetLogFilename", SetLogFilename); + + // menu + hServices[i++] = CreateServiceFunction(PROTO "/DisableAll", PingDisableAll); + hServices[i++] = CreateServiceFunction(PROTO "/EnableAll", PingEnableAll); + hServices[i++] = CreateServiceFunction(PROTO "/ToggleEnabled", ToggleEnabled); + hServices[i++] = CreateServiceFunction(PROTO "/ShowGraph", ShowGraph); + hServices[i++] = CreateServiceFunction(PROTO "/Edit", EditContact); + +} + +void DestroyPluginServices() { + /* + DestroyServiceFunction(PROTO PS_GETCAPS); + DestroyServiceFunction(PROTO PS_GETNAME); + DestroyServiceFunction(PROTO PS_SETSTATUS); + DestroyServiceFunction(PROTO PS_GETSTATUS); + DestroyServiceFunction(PROTO PS_LOADICON); + DestroyServiceFunction(PROTO PSS_GETINFO); + + DestroyServiceFunction(PROTO "/Ping"); + + DestroyServiceFunction(PROTO "/ClearPingList"); + DestroyServiceFunction(PROTO "/GetPingList"); + DestroyServiceFunction(PROTO "/SetPingList"); + DestroyServiceFunction(PROTO "/SetAndSavePingList"); + DestroyServiceFunction(PROTO "/LoadPingList"); + DestroyServiceFunction(PROTO "/SavePingList"); + + + DestroyServiceFunction(PROTO "/Log"); + DestroyServiceFunction(PROTO "/ViewLogData"); + DestroyServiceFunction(PROTO "/GetLogFilename"); + DestroyServiceFunction(PROTO "/SetLogFilename"); + + // menu + DestroyServiceFunction(PROTO "/DisableAll"); + DestroyServiceFunction(PROTO "/EnableAll"); + DestroyServiceFunction(PROTO "/ToggleEnabled"); + DestroyServiceFunction(PROTO "/ShowGraph"); + DestroyServiceFunction(PROTO "/Edit"); + */ + for(int i = 0; i < NUM_SERVICES; i++) + if(hServices[i]) DestroyServiceFunction(hServices[i]); + + DestroyHookableEvent(reload_event_handle); + +} + +int OnShutdown(WPARAM wParam, LPARAM lParam) { + graphs_cleanup(); + return 0; +} + +int OnModulesLoaded(WPARAM wParam, LPARAM lParam) { + + // register for autoupdates + CallService(MS_UPDATE_REGISTERFL, (WPARAM)1826, (LPARAM)&pluginInfo); + + NETLIBUSER nl_user = {0}; + nl_user.cbSize = sizeof(nl_user); + nl_user.szSettingsModule = PROTO; + //nl_user.flags = NUF_OUTGOING | NUF_HTTPGATEWAY | NUF_NOOPTIONS; + //nl_user.flags = NUF_OUTGOING | NUF_NOOPTIONS; + nl_user.flags = NUF_OUTGOING | NUF_HTTPCONNS; + nl_user.szDescriptiveName = "Ping Protocol Plugin"; + nl_user.szHttpGatewayHello = 0; + nl_user.szHttpGatewayUserAgent = 0; + nl_user.pfnHttpGatewayInit = 0; + nl_user.pfnHttpGatewayWrapSend = 0; + nl_user.pfnHttpGatewayUnwrapRecv = 0; + + hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nl_user); + + InitMenus(); + + hFillListEvent = HookEvent(PROTO "/ListReload", FillList); + + if(!DBGetContactSettingByte(0, PROTO, "PingPlugImport", 0)) { + if(DBGetContactSettingDword(0, "PingPlug", "NumEntries", 0)) { + if(MessageBox(0, Translate("Old PingPlug data detected in database.\nWould you like to import?"), Translate(PROTO "PingPlug Import"), MB_YESNO) == IDYES) { + import_ping_addresses(); + DBWriteContactSettingByte(0, PROTO, "PingPlugImport", 1); + } else { + if(MessageBox(0, Translate("Should I ask this question again\nnext time you start Miranda?"), Translate(PROTO "PingPlug Import"), MB_YESNO) == IDNO) { + DBWriteContactSettingByte(0, PROTO, "PingPlugImport", 1); + } + } + } + } + CallService(PROTO "/LoadPingList", 0, 0); + + //ignore status for all PING contacts + { + char *proto; + HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); + while ( hContact != NULL ) + { + proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + if (proto && lstrcmp(PROTO, proto) == 0) { + CallService(MS_IGNORE_IGNORE, (WPARAM)hContact, (WPARAM)IGNOREEVENT_USERONLINE); + DBDeleteContactSetting(hContact, PROTO, "WindowHandle"); // bugfix - windows left open when miranda closed never open again! + } + + hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 ); + } + } + + hContactDeleted = HookEvent(ME_DB_CONTACT_DELETED, ContactDeleted); + hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, ContactSettingChanged); + + hContactDblClick = HookEvent(ME_CLIST_DOUBLECLICKED, ContactDblClick); + + graphs_init(); + + start_ping_thread(); + + if(options.logging) CallService(PROTO "/Log", (WPARAM)"start", 0); + + return 0; +} + +extern "C" PINGPROTO_API int Load(PLUGINLINK *link) +{ + pluginLink=link; + + if(init_raw_ping()) { + //MessageBox(0, Translate("Failed to initialize. Plugin disabled."), Translate("PING Protocol"), MB_OK | MB_ICONERROR); + //return 1; + use_raw_ping = false; + } + DBWriteContactSettingByte(0, PROTO, "UsingRawSockets", (BYTE)use_raw_ping); + + DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &mainThread, THREAD_SET_CONTEXT, FALSE, 0 ); + hWakeEvent = CreateEvent(NULL, FALSE, FALSE, "Local\\ThreadWaitEvent"); + + previousMode = mcStatus = ID_STATUS_OFFLINE; + + InitializeCriticalSection(&list_cs); + InitializeCriticalSection(&thread_finished_cs); + InitializeCriticalSection(&list_changed_cs); + InitializeCriticalSection(&data_list_cs); + + PROTOCOLDESCRIPTOR pd = {0}; + pd.cbSize=sizeof(pd); + pd.szName=PROTO; + pd.type = PROTOTYPE_PROTOCOL; + CallService(MS_PROTO_REGISTERMODULE,0,(LPARAM)&pd); + + // create services before loading options - so we can have the 'getlogfilename' service! + CreatePluginServices(); + + LoadOptions(); + + //set all contacts to 'not responding' if not 'disabled' + { + char *proto; + HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); + while ( hContact != NULL ) + { + proto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 ); + if ( proto && !lstrcmp( PROTO, proto)) { + if(DBGetContactSettingWord( hContact, PROTO, "Status", options.nrstatus) != options.off_status) + DBWriteContactSettingWord( hContact, PROTO, "Status", options.nrstatus); + } + + hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 ); + } + } + + SkinAddNewSound("PingProtoTimeout", "Ping Timout", 0); + SkinAddNewSound("PingProtoReply", "Ping Reply", 0); + + HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded); + + HookEvent(ME_OPT_INITIALISE, PingOptInit ); + + //HookEvent(ME_SYSTEM_SHUTDOWN, OnShutdown); + HookEvent(ME_SYSTEM_PRESHUTDOWN, OnShutdown); + + return 0; +} + +extern "C" PINGPROTO_API int Unload(void) +{ + UnhookEvent(hContactDblClick); + UnhookEvent(hFillListEvent); + UnhookEvent(hContactDeleted); + UnhookEvent(hContactSettingChanged); + stop_ping_thread(); + + DestroyPluginServices(); + + DeleteCriticalSection(&list_cs); + DeleteCriticalSection(&thread_finished_cs); + DeleteCriticalSection(&list_changed_cs); + DeleteCriticalSection(&data_list_cs); + + CloseHandle( mainThread ); + + if(use_raw_ping) + cleanup_raw_ping(); + else + ICMP::get_instance()->stop(); + + if(options.logging) CallService(PROTO "/Log", (WPARAM)"stop", 0); + + return 0; +} -- cgit v1.2.3