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/StdAfx.cpp | 8 + ping_protocol/StdAfx.h | 28 ++ ping_protocol/common.h | 122 ++++++++ ping_protocol/icmp.cpp | 83 ++++++ ping_protocol/icmp.h | 66 +++++ ping_protocol/icon1.ico | Bin 0 -> 1078 bytes ping_protocol/log.cpp | 58 ++++ ping_protocol/log.h | 13 + ping_protocol/menu.cpp | 96 ++++++ ping_protocol/menu.h | 10 + ping_protocol/options.cpp | 654 +++++++++++++++++++++++++++++++++++++++++ ping_protocol/options.h | 23 ++ ping_protocol/pinggraph.cpp | 250 ++++++++++++++++ ping_protocol/pinggraph.h | 21 ++ ping_protocol/pinglist.cpp | 249 ++++++++++++++++ ping_protocol/pinglist.h | 39 +++ ping_protocol/pingproto.cpp | 468 +++++++++++++++++++++++++++++ ping_protocol/pingproto.dsp | 217 ++++++++++++++ ping_protocol/pingproto.dsw | 29 ++ ping_protocol/pingproto.h | 43 +++ ping_protocol/pingproto.mdsp | 117 ++++++++ ping_protocol/pingproto.plg | 80 +++++ ping_protocol/pingproto.rc | 226 ++++++++++++++ ping_protocol/pingproto.sln | 20 ++ ping_protocol/pingproto.vcproj | 544 ++++++++++++++++++++++++++++++++++ ping_protocol/pingthread.cpp | 309 +++++++++++++++++++ ping_protocol/pingthread.h | 21 ++ ping_protocol/rawping.cpp | 206 +++++++++++++ ping_protocol/rawping.h | 61 ++++ ping_protocol/resource.h | 65 ++++ ping_protocol/utils.cpp | 324 ++++++++++++++++++++ ping_protocol/utils.h | 38 +++ 32 files changed, 4488 insertions(+) create mode 100644 ping_protocol/StdAfx.cpp create mode 100644 ping_protocol/StdAfx.h create mode 100644 ping_protocol/common.h create mode 100644 ping_protocol/icmp.cpp create mode 100644 ping_protocol/icmp.h create mode 100644 ping_protocol/icon1.ico create mode 100644 ping_protocol/log.cpp create mode 100644 ping_protocol/log.h create mode 100644 ping_protocol/menu.cpp create mode 100644 ping_protocol/menu.h create mode 100644 ping_protocol/options.cpp create mode 100644 ping_protocol/options.h create mode 100644 ping_protocol/pinggraph.cpp create mode 100644 ping_protocol/pinggraph.h create mode 100644 ping_protocol/pinglist.cpp create mode 100644 ping_protocol/pinglist.h create mode 100644 ping_protocol/pingproto.cpp create mode 100644 ping_protocol/pingproto.dsp create mode 100644 ping_protocol/pingproto.dsw create mode 100644 ping_protocol/pingproto.h create mode 100644 ping_protocol/pingproto.mdsp create mode 100644 ping_protocol/pingproto.plg create mode 100644 ping_protocol/pingproto.rc create mode 100644 ping_protocol/pingproto.sln create mode 100644 ping_protocol/pingproto.vcproj create mode 100644 ping_protocol/pingthread.cpp create mode 100644 ping_protocol/pingthread.h create mode 100644 ping_protocol/rawping.cpp create mode 100644 ping_protocol/rawping.h create mode 100644 ping_protocol/resource.h create mode 100644 ping_protocol/utils.cpp create mode 100644 ping_protocol/utils.h (limited to 'ping_protocol') diff --git a/ping_protocol/StdAfx.cpp b/ping_protocol/StdAfx.cpp new file mode 100644 index 0000000..b9237ff --- /dev/null +++ b/ping_protocol/StdAfx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : source file that includes just the standard includes +// pingproto.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/ping_protocol/StdAfx.h b/ping_protocol/StdAfx.h new file mode 100644 index 0000000..826118a --- /dev/null +++ b/ping_protocol/StdAfx.h @@ -0,0 +1,28 @@ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__76631AC9_579A_456F_9BBB_708AF45BA0B8__INCLUDED_) +#define AFX_STDAFX_H__76631AC9_579A_456F_9BBB_708AF45BA0B8__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define VC_EXTRALEAN + +#define _WIN32_WINNT 0x0400 +#include +#include +#include +#include +#include +#include + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__76631AC9_579A_456F_9BBB_708AF45BA0B8__INCLUDED_) diff --git a/ping_protocol/common.h b/ping_protocol/common.h new file mode 100644 index 0000000..0cf5f60 --- /dev/null +++ b/ping_protocol/common.h @@ -0,0 +1,122 @@ +#ifndef _COMMON_H +#define _COMMON_H + +#define MAX_HISTORY (1440) // 12 hrs at 30 sec intervals + +#define PROTO "PING" + +#define DEFAULT_PING_PERIOD 30 +#define DEFAULT_PING_TIMEOUT 2 +#define DEFAULT_SHOW_POPUP false +#define DEFAULT_SHOW_POPUP2 false +#define DEFAULT_BLOCK_REPS true +#define DEFAULT_LOGGING_ENABLED false +#define DEFAULT_LOG_FILENAME "ping_log.txt" +#define DEFAULT_NO_TEST_STATUS true +#define DEFAULT_HIDE_PROTOCOL false +#define DEFAULT_USE_STATUS_MESSAGE false + + +#define MAX_PINGADDRESS_STRING_LENGTH 256 + +#include + +#include "../../include/newpluginapi.h" +#include "../../include/statusmodes.h" +#include "../../include/m_options.h" +#include "../../include/m_langpack.h" +#include "../../include/m_popup.h" +#include "../../include/m_system.h" +#include "../../include/m_skin.h" +#include "../../include/m_netlib.h" +#include "../../include/m_database.h" +#include "../../include/m_protocols.h" +#include "../../include/m_protomod.h" +#include "../../include/m_protosvc.h" +#include "../../include/m_ignore.h" +#include "../../include/m_clist.h" +#include "../../include/m_clui.h" +#include "../../include/m_utils.h" + +#include "../updater/m_updater.h" + +typedef struct { + int ping_period, ping_timeout; + bool show_popup, show_popup2, block_reps, logging; + char log_filename[MAX_PATH]; + WORD rstatus, nrstatus, tstatus, off_status; + bool no_test_status; + bool hide_proto; + int retries; + bool use_status_msg; +} PingOptions; + +#include +// deque of pairs - round trip time and timestamp +typedef std::vector > HistoryList; + +typedef struct PINGADDRESS_tag { + + /* + PINGADDRESS_tag() { + pszName[0] = 0; + pszLabel[0] = 0; + pszProto[0] = 0; + pszCommand[0] = 0; + pszParams[0] = 0; + } + + PINGADDRESS_tag(const PINGADDRESS_tag &src) { + } + */ + const PINGADDRESS_tag operator=(const PINGADDRESS_tag &src) { + cbSize = src.cbSize; + hContact = src.hContact; + strcpy(pszName, src.pszName); + strcpy(pszLabel, src.pszLabel); + responding = src.responding; + status = src.status; + round_trip_time = src.round_trip_time; + miss_count = src.miss_count; + port = src.port; + strcpy(pszProto, src.pszProto); + strcpy(pszCommand, src.pszCommand); + strcpy(pszParams, src.pszParams); + get_status = src.get_status; + set_status = src.set_status; + if(src.history.size()) + history = src.history; + else + history.clear(); + index = src.index; + strcpy(pszCListGroup, src.pszCListGroup); + + return *this; + } + + int cbSize; //size in bytes of this structure + HANDLE hContact; + char pszName[MAX_PINGADDRESS_STRING_LENGTH]; //IP address or domain name + char pszLabel[MAX_PINGADDRESS_STRING_LENGTH]; + bool responding; + int status; + short round_trip_time; + int miss_count; + int port; // -1 for ICMP, non-zero for TCP + char pszProto[MAX_PINGADDRESS_STRING_LENGTH]; + char pszCommand[MAX_PATH]; + char pszParams[MAX_PATH]; + unsigned int get_status; // on success, if status equals this + unsigned int set_status; // set it to this + HistoryList history; + int index; + char pszCListGroup[MAX_PINGADDRESS_STRING_LENGTH]; +} PINGADDRESS; + +extern HANDLE hNetlibUser; +extern HINSTANCE hInst; + +extern int previousMode; +extern int mcStatus; + +#endif diff --git a/ping_protocol/icmp.cpp b/ping_protocol/icmp.cpp new file mode 100644 index 0000000..a9cd296 --- /dev/null +++ b/ping_protocol/icmp.cpp @@ -0,0 +1,83 @@ +#include "stdafx.h" +#include "icmp.h" + +ICMP ICMP::instance; + +ICMP::ICMP(): + timeout(2000), + functions_loaded(false) +{ + hDLL = LoadLibrary("ICMP.DLL"); + if(!hDLL) return; + + pIcmpCreateFile = (pfnHV)GetProcAddress(hDLL, "IcmpCreateFile"); + pIcmpCloseHandle = (pfnBH)GetProcAddress(hDLL, "IcmpCloseHandle"); + pIcmpSendEcho = (pfnDHDPWPipPDD)GetProcAddress(hDLL, "IcmpSendEcho"); + if ((pIcmpCreateFile == 0) || (pIcmpCloseHandle == 0) || (pIcmpSendEcho == 0)) { + return; + } + + WSAData wsaData; + if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) { + WSACleanup(); + FreeLibrary((HMODULE)hDLL); + return; + } + + functions_loaded = true; +} + +void ICMP::stop() { + if(hIP) { + pIcmpCloseHandle(hIP); + hIP = 0; + } +} + +ICMP::~ICMP() { + if(hIP) pIcmpCloseHandle(hIP); + WSACleanup(); + if(hDLL) + FreeLibrary(hDLL); +} + +bool ICMP::ping(char *host, IP_ECHO_REPLY &reply) { + if(!functions_loaded) return false; + + DWORD address; + struct in_addr dest; + HOSTENT *rec; + IP_OPTION_INFORMATION ipoi; + + hIP = pIcmpCreateFile(); + if (hIP == INVALID_HANDLE_VALUE) { + return false; + } + + + dest.s_addr = inet_addr(host); + if (dest.s_addr == INADDR_NONE) { + rec = gethostbyname(host); + if(rec) address = *(DWORD *)(*rec->h_addr_list); + else return false; + } else { + address = dest.s_addr; + } + + ipoi.Ttl = 255; + ipoi.Tos = 0; + ipoi.Flags = 0; + ipoi.OptionsSize = 0; + ipoi.OptionsData = 0; + + reply.Status = 0; + + pIcmpSendEcho(hIP, address, (void *)"PINGPONG", 8, &ipoi, &reply, sizeof(reply), timeout); + + if(hIP) { + pIcmpCloseHandle(hIP); + hIP = 0; + } + + return (reply.Status == 0); +} \ No newline at end of file diff --git a/ping_protocol/icmp.h b/ping_protocol/icmp.h new file mode 100644 index 0000000..19aca1d --- /dev/null +++ b/ping_protocol/icmp.h @@ -0,0 +1,66 @@ +// adapted 23/9/2004 from public domain code at http://tangentsoft.net/wskfaq/examples/dllping.html + +#ifndef _ICMP_H +#define _ICMP_H + +#include + +// Structures required to use functions in ICMP.DLL + +typedef struct { + unsigned char Ttl; // Time To Live + unsigned char Tos; // Type Of Service + unsigned char Flags; // IP header flags + unsigned char OptionsSize; // Size in bytes of options data + unsigned char *OptionsData; // Pointer to options data +} IP_OPTION_INFORMATION, * PIP_OPTION_INFORMATION; + +typedef struct { + DWORD Address; // Replying address + unsigned long Status; // Reply status + unsigned long RoundTripTime; // RTT in milliseconds + unsigned short DataSize; // Echo data size + unsigned short Reserved; // Reserved for system use + void *Data; // Pointer to the echo data + IP_OPTION_INFORMATION Options; // Reply options + unsigned char ReplyData[8]; +} IP_ECHO_REPLY, * PIP_ECHO_REPLY; + + +typedef HANDLE (WINAPI* pfnHV)(VOID); +typedef BOOL (WINAPI* pfnBH)(HANDLE); +typedef DWORD (WINAPI* pfnDHDPWPipPDD)(HANDLE, DWORD, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD); // evil, no? + +class ICMP { +protected: + pfnHV pIcmpCreateFile; + pfnBH pIcmpCloseHandle; + pfnDHDPWPipPDD pIcmpSendEcho; + + HMODULE hDLL; + + HANDLE hIP; + + unsigned int timeout; + bool functions_loaded; + + // protected constructor - singleton class + ICMP(); + static ICMP instance; + +public: + ~ICMP(); + static ICMP *get_instance() {return &instance;} + + bool ping(char *host, IP_ECHO_REPLY &reply); + + void set_timeout(unsigned int t) { + timeout = t; + } + + void stop(); + + unsigned int get_timeout() {return timeout;} + +}; +#endif //_ICMP_H \ No newline at end of file diff --git a/ping_protocol/icon1.ico b/ping_protocol/icon1.ico new file mode 100644 index 0000000..17ef694 Binary files /dev/null and b/ping_protocol/icon1.ico differ diff --git a/ping_protocol/log.cpp b/ping_protocol/log.cpp new file mode 100644 index 0000000..608db44 --- /dev/null +++ b/ping_protocol/log.cpp @@ -0,0 +1,58 @@ +#include "stdafx.h" +#include "log.h" + +int Log(WPARAM wParam, LPARAM lParam) { + + char buf[1024]; + CallService(PROTO "/GetLogFilename", (WPARAM)1024, (LPARAM)buf); + + char TBcapt[255]; + SYSTEMTIME systime; + + GetLocalTime(&systime); + + wsprintf(TBcapt,"%02d:%02d:%02d",systime.wHour,systime.wMinute,systime.wSecond); + + std::string timestring = TBcapt; + + std::string line = (char *)wParam; + + std::ofstream out(buf, std::ios_base::out | std::ios_base::app); + if(out.is_open()) { + out << timestring << ": " << line << std::endl; + out.close(); + } + + return 0; +} + +int GetLogFilename(WPARAM wParam, LPARAM lParam) { + DBVARIANT dbv; + std::string filename; + if(DBGetContactSetting(0, PROTO, "LogFilename", &dbv)) { + char buf[MAX_PATH]; + CallService(MS_DB_GETPROFILEPATH, (WPARAM)MAX_PATH, (LPARAM)buf); + filename = buf; + filename += "\\"; + filename += "ping_log.txt"; + } else { + filename = dbv.pszVal; + } + + strncpy((char *)lParam, filename.c_str(), (size_t)wParam); + + DBFreeVariant(&dbv); + return 0; +} + +int SetLogFilename(WPARAM wParam, LPARAM lParam) { + DBWriteContactSettingString(0, PROTO, "LogFilename", (char *)lParam); + return 0; +} + +int ViewLogData(WPARAM wParam, LPARAM lParam) { + char buf[1024]; + CallService(PROTO "/GetLogFilename", (WPARAM)MAX_PATH, (LPARAM)buf); + return (int)ShellExecute((HWND)wParam, "edit", buf, "", "", SW_SHOW); +} + diff --git a/ping_protocol/log.h b/ping_protocol/log.h new file mode 100644 index 0000000..d19d5c9 --- /dev/null +++ b/ping_protocol/log.h @@ -0,0 +1,13 @@ +#ifndef _PING_LOG +#define _PING_LOG + +#include +#include +#include "common.h" + +int Log(WPARAM wParam, LPARAM lParam); +int GetLogFilename(WPARAM wParam, LPARAM lParam); +int SetLogFilename(WPARAM wParam, LPARAM lParam); +int ViewLogData(WPARAM wParam, LPARAM lParam); + +#endif \ No newline at end of file diff --git a/ping_protocol/menu.cpp b/ping_protocol/menu.cpp new file mode 100644 index 0000000..b05f849 --- /dev/null +++ b/ping_protocol/menu.cpp @@ -0,0 +1,96 @@ +#include "stdafx.h" +#include "menu.h" + +HANDLE hMenuDisable, hMenuGraph, hMenuEdit; +HANDLE hEventMenuBuild; + +int MenuBuild(WPARAM wParam, LPARAM lParam) { + CLISTMENUITEM menu; + ZeroMemory(&menu,sizeof(menu)); + menu.cbSize=sizeof(menu); + + menu.flags = CMIM_NAME | CMIM_ICON; + bool disable = DBGetContactSettingWord((HANDLE)wParam, PROTO, "Status", ID_STATUS_OFFLINE) != options.off_status; + if(disable) { + menu.hIcon = LoadSkinnedProtoIcon(PROTO, options.off_status); + menu.pszName = Translate("Disable"); + } else { + menu.hIcon = LoadSkinnedProtoIcon(PROTO, options.rstatus); + menu.pszName = Translate("Enable"); + } + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuDisable, (LPARAM)&menu); + + // hide graph menu item if window displayed + //menu.flags = CMIM_FLAGS | (DBGetContactSettingDword((HANDLE)wParam, PROTO, "WindowHandle", 0) == 0 ? 0 : CMIF_HIDDEN); + //CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuGraph, (LPARAM)&menu); + + return 0; +} + +void InitMenus() { + + CLISTMENUITEM menu; + ZeroMemory(&menu,sizeof(menu)); + menu.cbSize=sizeof(menu); + + // main menu + menu.flags = 0; + menu.popupPosition = 500099900; + menu.pszPopupName = Translate( "PING" ); + menu.cbSize = sizeof( menu ); + menu.position = 2000060000; + menu.hIcon = LoadSkinnedProtoIcon(PROTO, options.rstatus); + menu.pszName = Translate( "Enable All Pings" ); + menu.pszService = PROTO "/EnableAll"; + CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu ); + + menu.flags = 0; + menu.popupPosition = 500299901; + menu.pszPopupName = Translate( "PING" ); + menu.cbSize = sizeof( menu ); + menu.position = 2000060001; + menu.popupPosition = 0; + menu.hIcon = LoadSkinnedProtoIcon(PROTO, options.off_status); + menu.pszName = Translate( "Disable All Pings" ); + menu.pszService = PROTO "/DisableAll"; + CallService( MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu ); + + // contact + menu.flags = 0; + menu.popupPosition = 0; + menu.pszPopupName = 0; + menu.cbSize = sizeof( menu ); + menu.position =-300100; + //menu.popupPosition = 0; + menu.hIcon = LoadSkinnedProtoIcon(PROTO, options.off_status); + menu.pszName = Translate( "Disable" ); + menu.pszService = PROTO "/ToggleEnabled"; + menu.pszContactOwner = PROTO; + hMenuDisable = (HANDLE)CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&menu ); + + menu.flags = 0; + menu.popupPosition = 0; + menu.pszPopupName = 0; + menu.cbSize = sizeof( menu ); + menu.position =-300090; + //menu.popupPosition = 0; + menu.hIcon = LoadSkinnedProtoIcon(PROTO, options.rstatus); + menu.pszName = Translate( "Graph" ); + menu.pszService = PROTO "/ShowGraph"; + menu.pszContactOwner = PROTO; + hMenuGraph = (HANDLE)CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&menu ); + + menu.flags = 0; + menu.popupPosition = 0; + menu.pszPopupName = 0; + menu.cbSize = sizeof( menu ); + menu.position =-300080; + //menu.popupPosition = 0; + menu.hIcon = LoadSkinnedProtoIcon(PROTO, options.rstatus); + menu.pszName = Translate( "Edit..." ); + menu.pszService = PROTO "/Edit"; + menu.pszContactOwner = PROTO; + hMenuGraph = (HANDLE)CallService( MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&menu ); + + hEventMenuBuild = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, MenuBuild); +} \ No newline at end of file diff --git a/ping_protocol/menu.h b/ping_protocol/menu.h new file mode 100644 index 0000000..f302259 --- /dev/null +++ b/ping_protocol/menu.h @@ -0,0 +1,10 @@ +#ifndef _MENU_H +#define _MENU_H + +#include "common.h" +#include "pinglist.h" +#include "pinggraph.h" + +void InitMenus(); + +#endif \ No newline at end of file diff --git a/ping_protocol/options.cpp b/ping_protocol/options.cpp new file mode 100644 index 0000000..50e1061 --- /dev/null +++ b/ping_protocol/options.cpp @@ -0,0 +1,654 @@ +#include "stdafx.h" +#include "options.h" + +PingOptions options; + +// main ping options +static BOOL CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hw; + OPENFILENAME ofn = {0}; + char *strptr; + + switch ( msg ) { + case WM_INITDIALOG: { + TranslateDialogDefault( hwndDlg ); + + SetDlgItemInt(hwndDlg, IDC_PPM, options.ping_period, FALSE); + SetDlgItemInt(hwndDlg, IDC_PT, options.ping_timeout, FALSE); + CheckDlgButton(hwndDlg, IDC_CHECKPOPUP, options.show_popup); + CheckDlgButton(hwndDlg, IDC_CHECKPOPUP2, options.show_popup2); + CheckDlgButton(hwndDlg, IDC_CHK_BLOCK, options.block_reps); + CheckDlgButton(hwndDlg, IDC_CHK_LOG, options.logging); + CheckDlgButton(hwndDlg, IDC_CHK_NOTESTSTATUS, options.no_test_status); + CheckDlgButton(hwndDlg, IDC_CHK_HIDEPROTO, options.hide_proto); + CheckDlgButton(hwndDlg, IDC_CHK_USESTATUSMSG, options.use_status_msg); + hw = GetDlgItem(hwndDlg, IDC_TSTATUS); + EnableWindow(hw, options.no_test_status? FALSE : TRUE); + + for(int i = ID_STATUS_OFFLINE; i != ID_STATUS_OUTTOLUNCH; i++) { + strptr = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)i, (LPARAM)0); + hw = GetDlgItem(hwndDlg, IDC_RSTATUS); + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)strptr); + hw = GetDlgItem(hwndDlg, IDC_NRSTATUS); + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)strptr); + hw = GetDlgItem(hwndDlg, IDC_TSTATUS); + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)strptr); + hw = GetDlgItem(hwndDlg, IDC_DSTATUS); + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)strptr); + } + hw = GetDlgItem(hwndDlg, IDC_RSTATUS); + SendMessage(hw, CB_SETCURSEL, (WPARAM)(options.rstatus - ID_STATUS_OFFLINE), 0); + hw = GetDlgItem(hwndDlg, IDC_NRSTATUS); + SendMessage(hw, CB_SETCURSEL, (WPARAM)(options.nrstatus - ID_STATUS_OFFLINE), 0); + hw = GetDlgItem(hwndDlg, IDC_TSTATUS); + SendMessage(hw, CB_SETCURSEL, (WPARAM)(options.tstatus - ID_STATUS_OFFLINE), 0); + hw = GetDlgItem(hwndDlg, IDC_DSTATUS); + SendMessage(hw, CB_SETCURSEL, (WPARAM)(options.off_status - ID_STATUS_OFFLINE), 0); + + SetDlgItemInt(hwndDlg, IDC_RPT, options.retries, FALSE); + + SetDlgItemText(hwndDlg, IDC_ED_FILENAME, options.log_filename); + if(!options.logging) { + hw = GetDlgItem(hwndDlg, IDC_ED_FILENAME); + EnableWindow(hw, FALSE); + hw = GetDlgItem(hwndDlg, IDC_BTN_LOGBROWSE); + EnableWindow(hw, FALSE); + } + + if(!ServiceExists( MS_POPUP_ADDPOPUP )) { + hw = GetDlgItem(hwndDlg, IDC_CHECKPOPUP); + EnableWindow(hw, FALSE); + hw = GetDlgItem(hwndDlg, IDC_CHECKPOPUP2); + EnableWindow(hw, FALSE); + hw = GetDlgItem(hwndDlg, IDC_CHK_BLOCK); + EnableWindow(hw, FALSE); + } + return TRUE; + } + case WM_COMMAND: + if ( HIWORD( wParam ) == EN_CHANGE && ( HWND )lParam == GetFocus()) { + switch( LOWORD( wParam )) { + case IDC_PPM: + case IDC_PT: + case IDC_ED_FILENAME: + case IDC_RPT: + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + + if (HIWORD( wParam ) == CBN_SELCHANGE) { + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + + if ( HIWORD( wParam ) == BN_CLICKED ) { + switch( LOWORD( wParam )) { + case IDC_CHK_LOG: + hw = GetDlgItem(hwndDlg, IDC_ED_FILENAME); + EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_CHK_LOG)); + hw = GetDlgItem(hwndDlg, IDC_BTN_LOGBROWSE); + EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_CHK_LOG)); + // drop through + case IDC_CHECKPOPUP: + case IDC_CHECKPOPUP2: + case IDC_CHK_BLOCK: + case IDC_CHK_MINMAX: + case IDC_CHK_HIDEPROTO: + case IDC_CHK_USESTATUSMSG: + SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 ); + break; + case IDC_BTN_VIEWLOG: + CallService(PROTO "/ViewLogData", 0, 0); + break; + case IDC_BTN_LOGBROWSE: + ofn.lStructSize = sizeof(ofn); + ofn.lpstrFile = options.log_filename; + ofn.hwndOwner = hwndDlg; + ofn.Flags = CC_FULLOPEN; + //ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = sizeof(options.log_filename); + ofn.lpstrFilter = "All\0*.*\0Text\0*.TXT\0"; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST; + + if(GetOpenFileName(&ofn) == TRUE) { + SetDlgItemText(hwndDlg, IDC_ED_FILENAME, ofn.lpstrFile); + SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 ); + } + break; + case IDC_CHK_NOTESTSTATUS: + hw = GetDlgItem(hwndDlg, IDC_TSTATUS); + EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_CHK_NOTESTSTATUS) ? FALSE : TRUE); + SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 ); + break; + } + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->code == PSN_APPLY ) { + + { + int sel1, sel2, sel3, sel4; + + hw = GetDlgItem(hwndDlg, IDC_RSTATUS); + sel1 = SendMessage(hw, CB_GETCURSEL, 0, 0); + hw = GetDlgItem(hwndDlg, IDC_NRSTATUS); + sel2 = SendMessage(hw, CB_GETCURSEL, 0, 0); + hw = GetDlgItem(hwndDlg, IDC_TSTATUS); + sel3 = SendMessage(hw, CB_GETCURSEL, 0, 0); + hw = GetDlgItem(hwndDlg, IDC_DSTATUS); + sel4 = SendMessage(hw, CB_GETCURSEL, 0, 0); + + if(sel1 == sel4 || sel2 == sel4 || sel3 == sel4) { + MessageBox(hwndDlg, Translate("You cannot set any status to the same as 'disabled'"), Translate("Error"), MB_OK | MB_ICONWARNING); + SetWindowLong(hwndDlg, DWL_MSGRESULT, PSNRET_INVALID); + return TRUE; + } + + if(sel1 != -1) + options.rstatus = ID_STATUS_OFFLINE + sel1; + if(sel2 != -1) + options.nrstatus = ID_STATUS_OFFLINE + sel2; + if(sel4 != -1) + options.off_status = ID_STATUS_OFFLINE + sel4; + if(sel3 != -1) + options.tstatus = ID_STATUS_OFFLINE + sel3; + } + + BOOL trans_success; + + DWORD new_ping_period = GetDlgItemInt( hwndDlg, IDC_PPM, &trans_success, FALSE); + if(trans_success) { + options.ping_period = new_ping_period; + } + DWORD new_ping_timeout = GetDlgItemInt( hwndDlg, IDC_PT, &trans_success, FALSE); + if(trans_success) { + options.ping_timeout = new_ping_timeout; + } + options.show_popup = IsDlgButtonChecked(hwndDlg, IDC_CHECKPOPUP) == BST_CHECKED; + options.show_popup2 = IsDlgButtonChecked(hwndDlg, IDC_CHECKPOPUP2) == BST_CHECKED; + options.block_reps = IsDlgButtonChecked(hwndDlg, IDC_CHK_BLOCK) == BST_CHECKED; + options.logging = IsDlgButtonChecked(hwndDlg, IDC_CHK_LOG) == BST_CHECKED; + GetDlgItemText(hwndDlg, IDC_ED_FILENAME, options.log_filename, MAX_PATH); + + options.no_test_status = IsDlgButtonChecked(hwndDlg, IDC_CHK_NOTESTSTATUS) == BST_CHECKED; + options.hide_proto = IsDlgButtonChecked(hwndDlg, IDC_CHK_HIDEPROTO) == BST_CHECKED; + options.use_status_msg = IsDlgButtonChecked(hwndDlg, IDC_CHK_USESTATUSMSG) == BST_CHECKED; + DWORD new_retries = GetDlgItemInt( hwndDlg, IDC_RPT, &trans_success, FALSE); + if(trans_success) { + options.retries = new_retries; + } + SaveOptions(); + + if(options.use_status_msg) + reset_myhandle(); + + if(options.logging) CallService(PROTO "/Log", (WPARAM)"options changed", 0); + if(hWakeEvent) SetEvent(hWakeEvent); + return TRUE; + } + break; + } + + return FALSE; +} + +PINGLIST temp_list; +PINGADDRESS add_edit_addr; + +BOOL CALLBACK DlgProcDestEdit(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + HWND hw; + int sel; + char *strptr; + + switch ( msg ) { + case WM_INITDIALOG: + { + bool selgroup = false; + for(int i = ID_STATUS_OFFLINE; i <= ID_STATUS_OUTTOLUNCH; i++) { + strptr = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, (WPARAM)i, (LPARAM)0); + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT); + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)strptr); + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2); + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)strptr); + } + + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT); + SendMessage(hw, CB_SETCURSEL, 1, 0); + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2); + SendMessage(hw, CB_SETCURSEL, 0, 0); + + hw = GetDlgItem(hwndDlg, IDC_COMBO_GROUP); + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)Translate("")); + DBVARIANT dbv; + if(!DBGetContactSetting(0, PROTO, "DefaultPingGroup", &dbv)) + selgroup = true; + int gi = 1, selind = -1, selind_defgroup; + do { + strptr = (char *)CallService(MS_CLIST_GROUPGETNAME2, (WPARAM)gi, 0); + if(strptr) { + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)strptr); + if(!strncmp(strptr, add_edit_addr.pszCListGroup, MAX_PINGADDRESS_STRING_LENGTH)) + selind = gi; + if(selgroup && !strncmp(strptr, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH)) + selind_defgroup = gi; + } + gi++; + } while(strptr != 0); + if(selgroup) DBFreeVariant(&dbv); + + if(selind != -1) SendMessage(hw, CB_SETCURSEL, (WPARAM)selind, 0); + else if(selind_defgroup != -1) SendMessage(hw, CB_SETCURSEL, (WPARAM)selind_defgroup, 0); + else SendMessage(hw, CB_SETCURSEL, 0, 0); + + SetDlgItemText(hwndDlg, IDC_ED_DESTADDR, add_edit_addr.pszName); + SetDlgItemText(hwndDlg, IDC_ED_DESTLAB, add_edit_addr.pszLabel); + SetDlgItemText(hwndDlg, IDC_ED_COMMAND, add_edit_addr.pszCommand); + SetDlgItemText(hwndDlg, IDC_ED_PARAMS, add_edit_addr.pszParams); + + CheckDlgButton(hwndDlg, IDC_CHK_DESTTCP, add_edit_addr.port != -1); + if(add_edit_addr.port != -1) { + hw = GetDlgItem(hwndDlg, IDC_ED_DESTPORT); + EnableWindow(hw, TRUE); + SetDlgItemInt(hwndDlg, IDC_ED_DESTPORT, add_edit_addr.port, FALSE); + } + { + int num_protocols; + PROTOCOLDESCRIPTOR **pppDesc; + + CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc); + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTPROTO); + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)Translate("")); + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)Translate("")); + for(int i = 0; i < num_protocols; i++) { + if(pppDesc[i]->type == PROTOTYPE_PROTOCOL) + SendMessage(hw, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)pppDesc[i]->szName); + } + + if(add_edit_addr.pszProto[0] == '\0') { + SendMessage(hw, CB_SETCURSEL, 0, 0); + } else { + SendMessage(hw, CB_SELECTSTRING, 0, (LPARAM)add_edit_addr.pszProto); + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT); + EnableWindow(hw, TRUE); + SendMessage(hw, CB_SETCURSEL, (WPARAM)(add_edit_addr.set_status - ID_STATUS_OFFLINE), 0); + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2); + EnableWindow(hw, TRUE); + SendMessage(hw, CB_SETCURSEL, (WPARAM)(add_edit_addr.get_status - ID_STATUS_OFFLINE), 0); + } + } + // ? doesn't work? ? + hw = GetDlgItem(hwndDlg, IDC_ED_DESTADDR); + SetFocus(hw); + } + return TRUE; + case WM_COMMAND: + if (HIWORD( wParam ) == LBN_SELCHANGE && LOWORD(wParam) == IDC_COMBO_DESTPROTO) { + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTPROTO); + sel = SendMessage(hw, CB_GETCURSEL, 0, 0); + if(sel != CB_ERR) { + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT); + EnableWindow(hw, sel != 0); + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2); + EnableWindow(hw, sel != 0); + } + } + + if ( HIWORD( wParam ) == BN_CLICKED ) { + switch( LOWORD( wParam )) { + case IDC_CHK_DESTTCP: + hw = GetDlgItem(hwndDlg, IDC_ED_DESTPORT); + EnableWindow(hw, IsDlgButtonChecked(hwndDlg, IDC_CHK_DESTTCP)); + break; + case IDOK: + GetDlgItemText(hwndDlg, IDC_ED_DESTADDR, add_edit_addr.pszName, MAX_PINGADDRESS_STRING_LENGTH); + GetDlgItemText(hwndDlg, IDC_ED_DESTLAB, add_edit_addr.pszLabel, MAX_PINGADDRESS_STRING_LENGTH); + GetDlgItemText(hwndDlg, IDC_ED_COMMAND, add_edit_addr.pszCommand, MAX_PATH); + GetDlgItemText(hwndDlg, IDC_ED_PARAMS, add_edit_addr.pszParams, MAX_PATH); + + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTPROTO); + if(SendMessage(hw, CB_GETCURSEL, 0, 0) != -1) { + GetDlgItemText(hwndDlg, IDC_COMBO_DESTPROTO, add_edit_addr.pszProto, MAX_PINGADDRESS_STRING_LENGTH); + if(!strcmp(add_edit_addr.pszProto, Translate(""))) add_edit_addr.pszProto[0] = '\0'; + else { + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT); + sel = SendMessage(hw, CB_GETCURSEL, 0, 0); + if(sel != -1) + add_edit_addr.set_status = ID_STATUS_OFFLINE + sel; + hw = GetDlgItem(hwndDlg, IDC_COMBO_DESTSTAT2); + sel = SendMessage(hw, CB_GETCURSEL, 0, 0); + if(sel != -1) + add_edit_addr.get_status = ID_STATUS_OFFLINE + sel; + } + } else + add_edit_addr.pszProto[0] = '\0'; + + hw = GetDlgItem(hwndDlg, IDC_COMBO_GROUP); + GetDlgItemText(hwndDlg, IDC_COMBO_GROUP, add_edit_addr.pszCListGroup, MAX_PINGADDRESS_STRING_LENGTH); + if(!strcmp(add_edit_addr.pszCListGroup, Translate(""))) add_edit_addr.pszCListGroup[0] = '\0'; + DBWriteContactSettingString(0, PROTO, "DefaultPingGroup", add_edit_addr.pszCListGroup); + + if(IsDlgButtonChecked(hwndDlg, IDC_CHK_DESTTCP)) { + BOOL tr; + int port = GetDlgItemInt(hwndDlg, IDC_ED_DESTPORT, &tr, FALSE); + if(tr) add_edit_addr.port = port; + else add_edit_addr.port = -1; + } else + add_edit_addr.port = -1; + + EndDialog(hwndDlg, IDOK); + break; + case IDCANCEL: + EndDialog(hwndDlg, IDCANCEL); + break; + } + + } + + return TRUE; + } + return FALSE; +} + +// ping destinations list window +static BOOL CALLBACK DlgProcOpts2(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + OPENFILENAME ofn = {0}; + HWND hw; + int sel; + + switch ( msg ) { + case WM_INITDIALOG: + { + TranslateDialogDefault( hwndDlg ); + + Lock(&data_list_cs, "init options dialog"); + temp_list = data_list; + Unlock(&data_list_cs); + + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + for(PINGLIST::iterator i = temp_list.begin(); i != temp_list.end(); i++) { + int index = SendMessage(hw, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)i->pszLabel); + } + + } + return TRUE; + + case WM_COMMAND: + if (HIWORD( wParam ) == LBN_SELCHANGE && LOWORD(wParam) == IDC_LST_DEST) { + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + sel = SendMessage(hw, LB_GETCURSEL, 0, 0); + if(sel != LB_ERR) { + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTREM); + EnableWindow(hw, TRUE); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTEDIT); + EnableWindow(hw, TRUE); + + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP); + EnableWindow(hw, (sel > 0)); + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + int count = SendMessage(hw, LB_GETCOUNT, 0, 0); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN); + EnableWindow(hw, (sel < count - 1)); + } + } + + if ( HIWORD( wParam ) == BN_CLICKED ) { + switch( LOWORD( wParam )) { + case IDC_BTN_DESTEDIT: + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + sel = SendMessage(hw, LB_GETCURSEL, 0, 0); + if(sel != LB_ERR) { + add_edit_addr = temp_list[sel]; + + if(DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG3), hwndDlg, DlgProcDestEdit) == IDOK) { + + temp_list[sel] = add_edit_addr; + SendMessage(hw, LB_DELETESTRING, (WPARAM)sel, (LPARAM)0); + SendMessage(hw, LB_INSERTSTRING, (WPARAM)sel, (LPARAM)temp_list[sel].pszLabel); + SendMessage(hw, LB_SETCURSEL, (WPARAM)sel, 0); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTREM); + EnableWindow(hw, TRUE); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTEDIT); + EnableWindow(hw, TRUE); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP); + EnableWindow(hw, TRUE); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN); + EnableWindow(hw, TRUE); + + SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 ); + } + } + break; + case IDC_BTN_DESTADD: + + memset(&add_edit_addr,0,sizeof(add_edit_addr)); + add_edit_addr.cbSize = sizeof(add_edit_addr); + add_edit_addr.port = -1; + add_edit_addr.set_status = ID_STATUS_ONLINE; + add_edit_addr.get_status = ID_STATUS_OFFLINE; + add_edit_addr.status = options.nrstatus; + + if(DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG3), hwndDlg, DlgProcDestEdit) == IDOK) { + + temp_list.push_back(add_edit_addr); + + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + int index = SendMessage(hw, LB_INSERTSTRING, (WPARAM)-1, (LPARAM)add_edit_addr.pszLabel); + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + SendMessage(hw, LB_SETCURSEL, (WPARAM)index, 0); + + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTREM); + EnableWindow(hw, TRUE); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTEDIT); + EnableWindow(hw, TRUE); + + sel = temp_list.size() - 1; + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP); + EnableWindow(hw, (sel > 0)); + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + int count = SendMessage(hw, LB_GETCOUNT, 0, 0); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN); + EnableWindow(hw, (sel < count - 1)); + + SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 ); + } + + break; + case IDC_BTN_DESTREM: + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + sel = SendMessage(hw, LB_GETCURSEL, 0, 0); + if(sel != LB_ERR) { + SendMessage(hw, LB_DELETESTRING, (WPARAM)sel, 0); + PINGLIST::iterator i = temp_list.begin(); + while(sel > 0 && i != temp_list.end()) { + sel--; + i++; + } + if(i != temp_list.end()) + temp_list.erase(i); + } + + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTREM); + EnableWindow(hw, FALSE); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTEDIT); + EnableWindow(hw, FALSE); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP); + EnableWindow(hw, FALSE); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN); + EnableWindow(hw, FALSE); + + SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 ); + break; + case IDC_BTN_DESTDOWN: + { + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + int sel2 = SendMessage(hw, LB_GETCURSEL, 0, 0); + if(sel2 != LB_ERR) { + add_edit_addr = temp_list[sel2]; + temp_list[sel2] = temp_list[sel2 + 1]; + temp_list[sel2 + 1] = add_edit_addr; + + SendMessage(hw, LB_DELETESTRING, (WPARAM)sel2, (LPARAM)0); + SendMessage(hw, LB_INSERTSTRING, (WPARAM)sel2, (LPARAM)temp_list[sel2].pszLabel); + SendMessage(hw, LB_DELETESTRING, (WPARAM)(sel2 + 1), (LPARAM)0); + SendMessage(hw, LB_INSERTSTRING, (WPARAM)(sel2 + 1), (LPARAM)temp_list[sel2 + 1].pszLabel); + SendMessage(hw, LB_SETCURSEL, (WPARAM)(sel2 + 1), 0); + + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP); + EnableWindow(hw, (sel2 + 1 > 0)); + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + int count = SendMessage(hw, LB_GETCOUNT, 0, 0); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN); + EnableWindow(hw, (sel2 + 1 < count - 1)); + + SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 ); + } + } + break; + case IDC_BTN_DESTUP: + { + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + int sel2 = SendMessage(hw, LB_GETCURSEL, 0, 0); + if(sel2 != LB_ERR) { + add_edit_addr = temp_list[sel2 - 1]; + temp_list[sel2 - 1] = temp_list[sel2]; + temp_list[sel2] = add_edit_addr; + + SendMessage(hw, LB_DELETESTRING, (WPARAM)sel2, (LPARAM)0); + SendMessage(hw, LB_INSERTSTRING, (WPARAM)sel2, (LPARAM)temp_list[sel2].pszLabel); + + SendMessage(hw, LB_DELETESTRING, (WPARAM)(sel2 - 1), (LPARAM)0); + SendMessage(hw, LB_INSERTSTRING, (WPARAM)(sel2 - 1), (LPARAM)temp_list[sel2 - 1].pszLabel); + + SendMessage(hw, LB_SETCURSEL, (WPARAM)(sel2 - 1), 0); + + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTUP); + EnableWindow(hw, (sel2 - 1 > 0)); + hw = GetDlgItem(hwndDlg, IDC_LST_DEST); + int count = SendMessage(hw, LB_GETCOUNT, 0, 0); + hw = GetDlgItem(hwndDlg, IDC_BTN_DESTDOWN); + EnableWindow(hw, (sel2 - 1 < count - 1)); + + SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 ); + } + } + + break; + } + } + break; + + case WM_NOTIFY: + if (((LPNMHDR)lParam)->code == PSN_APPLY ) { + CallService(PROTO "/SetAndSavePingList", (WPARAM)&temp_list, 0); + CallService(PROTO "/GetPingList", 0, (LPARAM)&temp_list); + // the following will be affected due to list rebuild event + //if(hWakeEvent) SetEvent(hWakeEvent); + return TRUE; + } + break; + + } + return FALSE; +} + +int PingOptInit(WPARAM wParam,LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp = { 0 }; + odp.cbSize = sizeof(odp); + odp.position = -790000000; + odp.hInstance = hInst; + odp.pszTemplate = MAKEINTRESOURCE(IDD_DIALOG1); + odp.pszTitle = Translate("PING"); + odp.pszGroup = Translate("Network"); + odp.flags = ODPF_BOLDGROUPS; + odp.nIDBottomSimpleControl = IDC_PPM; + odp.pfnDlgProc = DlgProcOpts; + CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp ); + + OPTIONSDIALOGPAGE odp2 = { 0 }; + odp2.cbSize = sizeof(odp); + odp2.position = -790000100; + odp2.hInstance = hInst; + odp2.pszTemplate = MAKEINTRESOURCE(IDD_DIALOG2); + odp2.pszTitle = Translate("PING Destinations"); + odp2.pszGroup = Translate("Network"); + odp2.flags = ODPF_BOLDGROUPS; + odp2.nIDBottomSimpleControl = IDC_PPM; + odp2.pfnDlgProc = DlgProcOpts2; + CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp2 ); + return 0; +} + +void LoadOptions() { + options.ping_period = DBGetContactSettingDword(NULL, PROTO, "PingPeriod", DEFAULT_PING_PERIOD); + + options.ping_timeout = DBGetContactSettingDword(NULL, PROTO, "PingTimeout", DEFAULT_PING_TIMEOUT); + //CallService(PROTO "/SetPingTimeout", (WPARAM)options.ping_timeout, 0); + options.show_popup = (DBGetContactSettingByte(NULL, PROTO, "ShowPopup", DEFAULT_SHOW_POPUP ? 1 : 0) == 1); + options.show_popup2 = (DBGetContactSettingByte(NULL, PROTO, "ShowPopup2", DEFAULT_SHOW_POPUP2 ? 1 : 0) == 1); + options.block_reps = (DBGetContactSettingByte(NULL, PROTO, "BlockReps", DEFAULT_BLOCK_REPS ? 1 : 0) == 1); + options.logging = (DBGetContactSettingByte(NULL, PROTO, "LoggingEnabled", DEFAULT_LOGGING_ENABLED ? 1 : 0) == 1); + + options.rstatus = DBGetContactSettingWord(NULL, PROTO, "RespondingStatus", ID_STATUS_ONLINE); + options.nrstatus = DBGetContactSettingWord(NULL, PROTO, "NotRespondingStatus", ID_STATUS_AWAY); + options.tstatus = DBGetContactSettingWord(NULL, PROTO, "TestingStatus", ID_STATUS_OCCUPIED); + options.off_status = DBGetContactSettingWord(NULL, PROTO, "DisabledStatus", ID_STATUS_DND); + + if(options.rstatus == options.off_status) { + options.rstatus = ID_STATUS_ONLINE; + if(options.off_status == ID_STATUS_ONLINE) + options.off_status = ID_STATUS_DND; + } + if(options.nrstatus == options.off_status) { + options.rstatus = ID_STATUS_AWAY; + if(options.off_status == ID_STATUS_AWAY) + options.off_status = ID_STATUS_DND; + } + if(options.tstatus == options.off_status) { + options.tstatus = ID_STATUS_OCCUPIED; + if(options.off_status == ID_STATUS_OCCUPIED) + options.off_status = ID_STATUS_DND; + } + + options.no_test_status = (DBGetContactSettingByte(NULL, PROTO, "NoTestStatus", DEFAULT_NO_TEST_STATUS ? 1 : 0) == 1); + options.hide_proto = (DBGetContactSettingByte(NULL, PROTO, "HideProtocol", DEFAULT_HIDE_PROTOCOL ? 1 : 0) == 1); + options.use_status_msg = (DBGetContactSettingByte(NULL, PROTO, "UseStatusMessage", DEFAULT_USE_STATUS_MESSAGE ? 1 : 0) == 1); + + options.retries = DBGetContactSettingDword(NULL, PROTO, "Retries", 0); + + CallService(PROTO "/GetLogFilename", (WPARAM)MAX_PATH, (LPARAM)options.log_filename); + + ICMP::get_instance()->set_timeout(options.ping_timeout * 1000); + +} + +void SaveOptions() { + DBWriteContactSettingDword(NULL, PROTO, "PingPeriod", options.ping_period); + DBWriteContactSettingDword(NULL, PROTO, "PingTimeout", options.ping_timeout); + //CallService(PROTO "/SetPingTimeout", (WPARAM)options.ping_timeout, 0); + DBWriteContactSettingByte(NULL, PROTO, "ShowPopup", options.show_popup ? 1 : 0); + DBWriteContactSettingByte(NULL, PROTO, "ShowPopup2", options.show_popup2 ? 1 : 0); + DBWriteContactSettingByte(NULL, PROTO, "BlockReps", options.block_reps ? 1 : 0); + DBWriteContactSettingByte(NULL, PROTO, "LoggingEnabled", options.logging ? 1 : 0); + + DBWriteContactSettingWord(NULL, PROTO, "RespondingStatus", options.rstatus); + DBWriteContactSettingWord(NULL, PROTO, "NotRespondingStatus", options.nrstatus); + DBWriteContactSettingWord(NULL, PROTO, "TestingStatus", options.tstatus); + DBWriteContactSettingWord(NULL, PROTO, "DisabledStatus", options.off_status); + + DBWriteContactSettingByte(NULL, PROTO, "NoTestStatus", options.no_test_status ? 1 : 0); + DBWriteContactSettingByte(NULL, PROTO, "HideProtocol", options.hide_proto ? 1 : 0); + DBWriteContactSettingByte(NULL, PROTO, "UseStatusMessage", options.use_status_msg ? 1 : 0); + + DBWriteContactSettingDword(NULL, PROTO, "Retries", options.retries); + + CallService(PROTO "/SetLogFilename", (WPARAM)MAX_PATH, (LPARAM)options.log_filename); + + ICMP::get_instance()->set_timeout(options.ping_timeout * 1000); +} diff --git a/ping_protocol/options.h b/ping_protocol/options.h new file mode 100644 index 0000000..0360b47 --- /dev/null +++ b/ping_protocol/options.h @@ -0,0 +1,23 @@ +#ifndef _PING_OPTIONS +#define _PING_OPTIONS + +#include "common.h" +#include "pinglist.h" +#include "utils.h" +#include "icmp.h" + +#include "resource.h" + +// wake event for ping thread +extern HANDLE hWakeEvent; + +extern PingOptions options; +extern PINGADDRESS add_edit_addr; + +BOOL CALLBACK DlgProcDestEdit(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + +int PingOptInit(WPARAM wParam,LPARAM lParam); +void LoadOptions(); +void SaveOptions(); + +#endif \ No newline at end of file diff --git a/ping_protocol/pinggraph.cpp b/ping_protocol/pinggraph.cpp new file mode 100644 index 0000000..f6a9da5 --- /dev/null +++ b/ping_protocol/pinggraph.cpp @@ -0,0 +1,250 @@ +#include "stdafx.h" +#include "pinggraph.h" + +#include + +#define ID_REPAINT_TIMER 10101 + +struct WindowData { + HANDLE hContact; + HistoryList list; +}; + +#define WM_REBUILDLIST (WM_USER + 1) + +LRESULT CALLBACK GraphWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + switch(msg) { + case WM_REBUILDLIST: + { + WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA); + + bool found = false; + EnterCriticalSection(&data_list_cs); + for(PINGLIST::iterator i = data_list.begin(); i != data_list.end(); i++) { + if(i->hContact == wd->hContact) { + wd->list = i->history; + found = true; + break; + } + } + LeaveCriticalSection(&data_list_cs); + + if(!found) { + PostMessage(hwnd, WM_CLOSE, 0, 0); + return TRUE; + } + + InvalidateRect(hwnd, 0, FALSE); + } + return TRUE; + case WM_SHOWWINDOW: + if(wParam == TRUE && lParam == 0) { + WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA); + + KillTimer(hwnd, ID_REPAINT_TIMER); +#ifdef min + SetTimer(hwnd, ID_REPAINT_TIMER, min(options.ping_period * 1000, 5000), 0); +#else + SetTimer(hwnd, ID_REPAINT_TIMER, std::min(options.ping_period * 1000, 5000), 0); +#endif + + SendMessage(hwnd, WM_REBUILDLIST, 0, 0); + } + break; + + case WM_TIMER: + { + SendMessage(hwnd, WM_REBUILDLIST, 0, 0); + } + return TRUE; + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc; + RECT r; + WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA); + if(hdc = BeginPaint(hwnd, &ps)) { + GetClientRect(hwnd, &r); + FillRect(hdc, &r, GetSysColorBrush(COLOR_WINDOW)); + + short max_value = -1; // this is minimum graph height, in ms + for(HistoryList::iterator hli = wd->list.begin(); hli != wd->list.end(); hli++) { + if(hli->first > max_value) max_value = hli->first; + } + + max_value = (int)(max_value * 1.2f); + if(max_value < MIN_GRAPH_HEIGHT) max_value = MIN_GRAPH_HEIGHT; + +#ifdef max + float unit_width = (r.right - r.left) / (float)max((int)wd->list.size(), MIN_BARS), // space for at least MIN_BARS bars +#else + float unit_width = (r.right - r.left) / (float)std::max((int)wd->list.size(), MIN_BARS), // space for at least MIN_BARS bars +#endif + unit_height = (r.bottom - r.top) / (float)max_value; + + RECT bar; + bar.bottom = r.bottom; + float x = r.right - (unit_width * wd->list.size() + 0.5f); + bar.left = (int)(x + 0.5f); + bar.right = (int)(x + unit_width + 0.5f); + + DWORD last_time = 0, time, start_time = 0; + if(wd->list.size()) + start_time = wd->list.begin()->second; + + HPEN hPenOld, hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW)); + hPenOld = (HPEN)SelectObject(hdc, hPen); + + for(HistoryList::iterator hi = wd->list.begin(); hi != wd->list.end(); hi++) { + if(hi->first != -1) { + bar.top = bar.bottom - (int)(hi->first * unit_height + 0.5f); + FillRect(hdc, &bar, GetSysColorBrush(COLOR_HOTLIGHT)); + } + + time = hi->second - start_time; + if(time / MARK_PERIOD != last_time / MARK_PERIOD) { + MoveToEx(hdc, bar.left, r.bottom, 0); + LineTo(hdc, bar.left, r.top); + } + + last_time = time; + + x += unit_width; + bar.left = bar.right; + bar.right = (int)(x + unit_width + 0.5f); + } + + // draw horizontal lines to mark every 100ms + for(int li = 0; li < max_value; li += MARK_TIME) { + MoveToEx(hdc, r.left, r.bottom - (int)(li * unit_height + 0.5f), 0); + LineTo(hdc, r.right, r.bottom - (int)(li * unit_height + 0.5f)); + } + + SelectObject(hdc, hPenOld); + DeleteObject(hPen); + + SetBkMode(hdc, TRANSPARENT); + SetTextColor(hdc, GetSysColor(COLOR_3DDKSHADOW)); + char buff[64]; + sprintf(buff, "%dms", MARK_TIME); + TextOut(hdc, r.left + 10, r.bottom - (int)(unit_height * MARK_TIME + 0.5f), buff, 5); + + EndPaint(hwnd, &ps); + } + } + return TRUE; + + case WM_ERASEBKGND: + return TRUE; + + case WM_SIZE: + InvalidateRect(hwnd, 0, FALSE); + break; + case WM_CLOSE: + { + KillTimer(hwnd, ID_REPAINT_TIMER); + WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA); + if(CallService(MS_DB_CONTACT_IS, (WPARAM)wd->hContact, 0)) + Utils_SaveWindowPosition(hwnd, wd->hContact, PROTO, "pinggraphwnd"); + } + break; + case WM_DESTROY: + { + WindowData *wd = (WindowData *)GetWindowLong(hwnd, GWL_USERDATA); + DBDeleteContactSetting(wd->hContact, PROTO, "WindowHandle"); + delete wd; + } + // drop through + }; + + return DefWindowProc(hwnd, msg, wParam, lParam); +} + +int ShowGraph(WPARAM wParam, LPARAM lParam) { + HWND hGraphWnd = (HWND)DBGetContactSettingDword((HANDLE)wParam, PROTO, "WindowHandle", 0); + if(hGraphWnd) { + ShowWindow(hGraphWnd, SW_SHOW); + SetWindowPos(hGraphWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + return 0; + } + + WNDCLASS wndclass; + wndclass.style = 0; + wndclass.lpfnWndProc = GraphWindowProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = hInst; + wndclass.hIcon = LoadSkinnedProtoIcon(PROTO, ID_STATUS_ONLINE); + wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)(COLOR_3DFACE+1); + wndclass.lpszMenuName = NULL; + wndclass.lpszClassName = PROTO "GraphWindow"; + RegisterClass(&wndclass); + + DBVARIANT dbv; + char title[256]; + strcpy(title, "Ping Graph"); + if(!DBGetContactSetting((HANDLE)wParam, PROTO, "Nick", &dbv)) { + strcat(title, " - "); + strncat(title, dbv.pszVal, 256 - 13); + DBFreeVariant(&dbv); + } + + HWND parent = 0; + hGraphWnd = CreateWindowEx(0, PROTO "GraphWindow", title, + (WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN) & ~CS_VREDRAW & ~CS_HREDRAW, + 0,0,800,600,parent,NULL,hInst,NULL); + + DBWriteContactSettingDword((HANDLE)wParam, PROTO, "WindowHandle", (DWORD)hGraphWnd); + + WindowData *wd = new WindowData; + wd->hContact = (HANDLE)wParam; // wParam is contact handle + + SetWindowLong(hGraphWnd, GWL_USERDATA, (LONG)wd); + + if(CallService(MS_DB_CONTACT_IS, (WPARAM)wd->hContact, 0)) + Utils_RestoreWindowPosition(hGraphWnd, wd->hContact, PROTO, "pinggraphwnd"); + + if(!IsWindowVisible(hGraphWnd)) + ShowWindow(hGraphWnd, SW_SHOW); + + return 0; +} + +// save window positions, close windows +void graphs_cleanup() { + HWND hwnd; + 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) { + if((hwnd = (HWND)DBGetContactSettingDword(hContact, PROTO, "WindowHandle", 0)) != 0) { + DestroyWindow(hwnd); + DBWriteContactSettingByte(hContact, PROTO, "WindowWasOpen", 1); + } + } + + hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 ); + } +} + +// restore windows that were open when cleanup was called last +void graphs_init() { + 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) { + if(DBGetContactSettingByte(hContact, PROTO, "WindowWasOpen", 0) != 0) { + ShowGraph((WPARAM)hContact, 0); + DBWriteContactSettingByte(hContact, PROTO, "WindowWasOpen", 0); + } + } + + hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 ); + } +} diff --git a/ping_protocol/pinggraph.h b/ping_protocol/pinggraph.h new file mode 100644 index 0000000..d38f99f --- /dev/null +++ b/ping_protocol/pinggraph.h @@ -0,0 +1,21 @@ +#ifndef _PINGGRAPH_H +#define _PINGGRAPH_H + +#include "common.h" +#include "pinglist.h" +#include "pingthread.h" + +#define MIN_GRAPH_HEIGHT 120 // minimum braph height, ms +#define MIN_BARS 20 // space for at least this many bars +#define MARK_PERIOD 3600 // vertical lines every this many secs (3600 == 1 hour) +#define MARK_TIME 100 // horizontal lines every this many ms + +int ShowGraph(WPARAM wParam, LPARAM lParam); + +// save window positions, close windows +void graphs_cleanup(); + +// restore windows that were open when cleanup was called last? +void graphs_init(); + +#endif diff --git a/ping_protocol/pinglist.cpp b/ping_protocol/pinglist.cpp new file mode 100644 index 0000000..086fb3e --- /dev/null +++ b/ping_protocol/pinglist.cpp @@ -0,0 +1,249 @@ +#include "stdafx.h" +#include "pinglist.h" + +#include "options.h" + +PINGLIST list_items; +CRITICAL_SECTION list_cs; +HANDLE reload_event_handle; + + +BOOL clist_handle_changing = FALSE; + +BOOL changing_clist_handle() { + return clist_handle_changing; +} + +void set_changing_clist_handle(BOOL flag) { + clist_handle_changing = flag; +} + +// lParam is address of pointer to a std::list +// copies data into this structure +int GetPingList(WPARAM wParam,LPARAM lParam) +{ + PINGLIST *pa = (PINGLIST *)lParam; + + EnterCriticalSection(&list_cs); + *pa = list_items; + LeaveCriticalSection(&list_cs); + + return 0; +} + +void reset_myhandle() { + EnterCriticalSection(&list_cs); + set_changing_clist_handle(true); + for(PINGLIST::iterator i = list_items.begin(); i != list_items.end(); i++) { + DBWriteContactSettingString(i->hContact, "CList", "MyHandle", i->pszLabel); + } + set_changing_clist_handle(false); + LeaveCriticalSection(&list_cs); +} + + +void write_ping_address(PINGADDRESS *i) { + bool is_contact = (bool)(CallService(MS_DB_CONTACT_IS, (WPARAM)i->hContact, 0) != 0); + + if(!is_contact) { + //MessageBox(0, "Creating contact", "Ping", MB_OK); + i->hContact = (HANDLE)CallService(MS_DB_CONTACT_ADD, 0, 0); + CallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )i->hContact, ( LPARAM )PROTO ); + CallService(MS_IGNORE_IGNORE, (WPARAM)i->hContact, (WPARAM)IGNOREEVENT_USERONLINE); + } + DBWriteContactSettingString(i->hContact, PROTO, "Address", i->pszName); + set_changing_clist_handle(TRUE); + DBWriteContactSettingString(i->hContact, "CList", "MyHandle", i->pszLabel); + set_changing_clist_handle(FALSE); + DBWriteContactSettingString(i->hContact, PROTO, "Nick", i->pszLabel); + DBWriteContactSettingWord(i->hContact, PROTO, "Status", i->status); + DBWriteContactSettingDword(i->hContact, PROTO, "Port", i->port); + DBWriteContactSettingString(i->hContact, PROTO, "Proto", i->pszProto); + if(strlen(i->pszCommand)) + DBWriteContactSettingString(i->hContact, PROTO, "Command", i->pszCommand); + else + DBDeleteContactSetting(i->hContact, PROTO, "Command"); + if(strlen(i->pszParams)) + DBWriteContactSettingString(i->hContact, PROTO, "CommandParams", i->pszParams); + else + DBDeleteContactSetting(i->hContact, PROTO, "CommandParams"); + DBWriteContactSettingWord(i->hContact, PROTO, "SetStatus", i->set_status); + DBWriteContactSettingWord(i->hContact, PROTO, "GetStatus", i->get_status); + DBWriteContactSettingWord(i->hContact, PROTO, "Index", i->index); + if(strlen(i->pszCListGroup)) + DBWriteContactSettingString(i->hContact, "CList", "Group", i->pszCListGroup); + else + DBDeleteContactSetting(i->hContact, "CList", "Group"); +} + +// call with list_cs locked +void write_ping_addresses() { + int index = 0; + for(PINGLIST::iterator i = list_items.begin(); i != list_items.end(); i++, index++) { + i->index = index; + write_ping_address(&(*i)); + } +} + +void read_ping_address(PINGADDRESS &pa) { + DBVARIANT dbv; + DBGetContactSetting(pa.hContact, PROTO, "Address", &dbv); + strncpy(pa.pszName, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH); + DBFreeVariant(&dbv); + if(!DBGetContactSetting(pa.hContact, PROTO, "Nick", &dbv)) { + strncpy(pa.pszLabel, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH); + DBFreeVariant(&dbv); + set_changing_clist_handle(TRUE); + DBWriteContactSettingString(pa.hContact, "CList", "MyHandle", pa.pszLabel); + set_changing_clist_handle(FALSE); + } else { + if(!DBGetContactSetting(pa.hContact, PROTO, "Label", &dbv)) { + strncpy(pa.pszLabel, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH); + DBFreeVariant(&dbv); + set_changing_clist_handle(TRUE); + DBWriteContactSettingString(pa.hContact, "CList", "MyHandle", pa.pszLabel); + set_changing_clist_handle(FALSE); + DBWriteContactSettingString(pa.hContact, PROTO, "Nick", pa.pszLabel); + DBDeleteContactSetting(pa.hContact, PROTO, "Label"); + } else { + if(!DBGetContactSetting(pa.hContact, "CList", "MyHandle", &dbv)) { + strncpy(pa.pszLabel, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH); + DBFreeVariant(&dbv); + } else + pa.pszLabel[0] = '\0'; + } + } + + pa.status = DBGetContactSettingWord(pa.hContact, PROTO, "Status", options.nrstatus); + pa.port = (int)DBGetContactSettingDword(pa.hContact, PROTO, "Port", -1); + + if(!DBGetContactSetting(pa.hContact, PROTO, "Proto", &dbv)) { + strncpy(pa.pszProto, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH); + DBFreeVariant(&dbv); + } else pa.pszProto[0] = '\0'; + + if(!DBGetContactSetting(pa.hContact, PROTO, "Command", &dbv)) { + strncpy(pa.pszCommand, dbv.pszVal, MAX_PATH); + DBFreeVariant(&dbv); + } else + pa.pszCommand[0] = '\0'; + if(!DBGetContactSetting(pa.hContact, PROTO, "CommandParams", &dbv)) { + strncpy(pa.pszParams, dbv.pszVal, MAX_PATH); + DBFreeVariant(&dbv); + } else + pa.pszParams[0] = '\0'; + + pa.set_status = DBGetContactSettingWord(pa.hContact, PROTO, "SetStatus", ID_STATUS_ONLINE); + pa.get_status = DBGetContactSettingWord(pa.hContact, PROTO, "GetStatus", ID_STATUS_OFFLINE); + + pa.responding = false; + pa.round_trip_time = 0; + pa.miss_count = 0; + pa.index = DBGetContactSettingWord(pa.hContact, PROTO, "Index", 0); + + if(!DBGetContactSetting(pa.hContact, "CList", "Group", &dbv)) { + strncpy(pa.pszCListGroup, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH); + DBFreeVariant(&dbv); + } else + pa.pszCListGroup[0] = '\0'; +} + +// call with list_cs locked +void read_ping_addresses() { + HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 ); + PINGADDRESS pa; + + list_items.clear(); + while ( hContact != NULL ) { + char *proto = ( char* )CallService( MS_PROTO_GETCONTACTBASEPROTO, ( WPARAM )hContact,0 ); + if ( proto && lstrcmp( PROTO, proto) == 0) { + pa.hContact = hContact; + read_ping_address(pa); + list_items.push_back(pa); + } + + hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 ); + } + std::sort(list_items.begin(), list_items.end(), SAscendingSort()); +} + +int LoadPingList(WPARAM wParam, LPARAM lParam) { + EnterCriticalSection(&list_cs); + read_ping_addresses(); + LeaveCriticalSection(&list_cs); + NotifyEventHooks(reload_event_handle, 0, 0); + return 0; +} + +// wParam is zero +// lParam is zero +int SavePingList(WPARAM wParam, LPARAM lParam) { + EnterCriticalSection(&list_cs); + write_ping_addresses(); + LeaveCriticalSection(&list_cs); + NotifyEventHooks(reload_event_handle, 0, 0); + + return 0; +} + +// wParam is address of a PINGLIST structure to replace the current one +// lParam is zero +int SetPingList(WPARAM wParam, LPARAM lParam) { + PINGLIST *pli = (PINGLIST *)wParam; + + EnterCriticalSection(&list_cs); + list_items = *pli; + LeaveCriticalSection(&list_cs); + NotifyEventHooks(reload_event_handle, 0, 0); + + return 0; +} + +// wParam is address of a PINGLIST structure to replace the current one +// lParam is zero +int SetAndSavePingList(WPARAM wParam, LPARAM lParam) { + PINGLIST *pli = (PINGLIST *)wParam; + + EnterCriticalSection(&list_cs); + // delete items that aren't in the new list + bool found; + for(PINGLIST::iterator i = list_items.begin(); i != list_items.end(); i++) { + found = false; + for(PINGLIST::iterator j = pli->begin(); j != pli->end(); j++) { + if(i->hContact == j->hContact) { + found = true; + break; + } + + } + if(!found) { + //MessageBox(0, "Deleting contact", "Ping", MB_OK); + // remove prot first, so that our contact deleted event handler isn't activated + CallService(MS_PROTO_REMOVEFROMCONTACT, (WPARAM)i->hContact, (LPARAM)PROTO); + CallService(MS_DB_CONTACT_DELETE, (WPARAM)i->hContact, 0); + } + } + + // set new list + if(pli->size()) + list_items = *pli; + else + list_items.clear(); + + write_ping_addresses(); + LeaveCriticalSection(&list_cs); + + NotifyEventHooks(reload_event_handle, 0, 0); + + return 0; +} + +int ClearPingList(WPARAM wParam, LPARAM lParam) { + EnterCriticalSection(&list_cs); + list_items.clear(); + LeaveCriticalSection(&list_cs); + + NotifyEventHooks(reload_event_handle, 0, 0); + return 0; +} + diff --git a/ping_protocol/pinglist.h b/ping_protocol/pinglist.h new file mode 100644 index 0000000..fd5bd8a --- /dev/null +++ b/ping_protocol/pinglist.h @@ -0,0 +1,39 @@ +#ifndef _PINGLIST_H +#define _PINGLIST_H + +#include "common.h" + +#include +typedef std::vector PINGLIST; + +#include // for sort + +extern PINGLIST list_items; +extern HANDLE reload_event_handle; +extern CRITICAL_SECTION list_cs; + +int LoadPingList(WPARAM wParam, LPARAM lParam); +int GetPingList(WPARAM wParam,LPARAM lParam); +int SavePingList(WPARAM wParam, LPARAM lParam); +int SetPingList(WPARAM wParam, LPARAM lParam); // use when you modified db yourself +int SetAndSavePingList(WPARAM wParam, LPARAM lParam); +int ClearPingList(WPARAM wParam, LPARAM lParam); + +struct SAscendingSort +{ + bool operator()(const PINGADDRESS &rpStart, const PINGADDRESS &rpEnd) + { + return rpStart.index < rpEnd.index; + } +}; + +// only call with list_cs locked! +void write_ping_addresses(); + + +BOOL changing_clist_handle(); +void set_changing_clist_handle(BOOL flag); + +void reset_myhandle(); + +#endif 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; +} diff --git a/ping_protocol/pingproto.dsp b/ping_protocol/pingproto.dsp new file mode 100644 index 0000000..d18a330 --- /dev/null +++ b/ping_protocol/pingproto.dsp @@ -0,0 +1,217 @@ +# Microsoft Developer Studio Project File - Name="pingproto" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=pingproto - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "pingproto.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "pingproto.mak" CFG="pingproto - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "pingproto - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "pingproto - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "pingproto - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PINGPROTO_VC6_EXPORTS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PINGPROTO_EXPORTS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc09 /d "NDEBUG" +# ADD RSC /l 0xc09 /d "NDEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 ws2_32.lib wsock32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib /nologo /base:"0x22050000" /dll /machine:I386 /out:"../../bin/release/plugins/pingproto.dll" +# SUBTRACT LINK32 /nodefaultlib + +!ELSEIF "$(CFG)" == "pingproto - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 2 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PINGPROTO_VC6_EXPORTS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PINGPROTO_EXPORTS" /D "_WINDLL" /D "_AFXDLL" /Yu"stdafx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0xc09 /d "_DEBUG" +# ADD RSC /l 0xc09 /d "_DEBUG" /d "_AFXDLL" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 user32.lib gdi32.lib ws2_32.lib shell32.lib comdlg32.lib /nologo /dll /debug /machine:I386 /out:"../../bin/debug/plugins/pingproto.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "pingproto - Win32 Release" +# Name "pingproto - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\icmp.cpp +# End Source File +# Begin Source File + +SOURCE=.\log.cpp +# End Source File +# Begin Source File + +SOURCE=.\menu.cpp +# End Source File +# Begin Source File + +SOURCE=.\options.cpp +# End Source File +# Begin Source File + +SOURCE=.\pinggraph.cpp +# End Source File +# Begin Source File + +SOURCE=.\pinglist.cpp +# End Source File +# Begin Source File + +SOURCE=.\pingproto.cpp +# End Source File +# Begin Source File + +SOURCE=.\pingthread.cpp +# End Source File +# Begin Source File + +SOURCE=.\rawping.cpp +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc"stdafx.h" +# End Source File +# Begin Source File + +SOURCE=.\utils.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\common.h +# End Source File +# Begin Source File + +SOURCE=.\icmp.h +# End Source File +# Begin Source File + +SOURCE=.\log.h +# End Source File +# Begin Source File + +SOURCE=.\menu.h +# End Source File +# Begin Source File + +SOURCE=.\options.h +# End Source File +# Begin Source File + +SOURCE=.\pinggraph.h +# End Source File +# Begin Source File + +SOURCE=.\pinglist.h +# End Source File +# Begin Source File + +SOURCE=.\pingproto.h +# End Source File +# Begin Source File + +SOURCE=.\pingthread.h +# End Source File +# Begin Source File + +SOURCE=.\rawping.h +# End Source File +# Begin Source File + +SOURCE=.\resource.h +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# Begin Source File + +SOURCE=.\utils.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\icon1.ico +# End Source File +# Begin Source File + +SOURCE=.\pingproto.rc +# End Source File +# End Group +# Begin Source File + +SOURCE=.\cut_code.txt +# End Source File +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/ping_protocol/pingproto.dsw b/ping_protocol/pingproto.dsw new file mode 100644 index 0000000..345ac5c --- /dev/null +++ b/ping_protocol/pingproto.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "pingproto"=".\pingproto.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/ping_protocol/pingproto.h b/ping_protocol/pingproto.h new file mode 100644 index 0000000..cb70bd6 --- /dev/null +++ b/ping_protocol/pingproto.h @@ -0,0 +1,43 @@ +/* +Based on the +Miranda plugin template, originally by Richard Hughes +http://miranda-icq.sourceforge.net/ + +© 2004 Scott Ellis + +*/ + +#ifndef _PINGPROTO +#define _PINGPROTO + + +// The following ifdef block is the standard way of creating macros which make exporting +// from a DLL simpler. All files within this DLL are compiled with the PINGPROTO_EXPORTS +// symbol defined on the command line. this symbol should not be defined on any project +// that uses this DLL. This way any other project whose source files include this file see +// PINGPROTO_API functions as being imported from a DLL, wheras this DLL sees symbols +// defined with this macro as being exported. +#ifdef PINGPROTO_EXPORTS +#define PINGPROTO_API __declspec(dllexport) +#else +#define PINGPROTO_API __declspec(dllimport) +#endif + +#include "common.h" +#include "utils.h" +#include "options.h" +#include "pinglist.h" +#include "log.h" +#include "pingthread.h" +#include "menu.h" +#include "rawping.h" + +// globals +extern PLUGINLINK *pluginLink; +extern PLUGININFO pluginInfo; + +extern "C" PINGPROTO_API PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion); +extern "C" PINGPROTO_API int Load(PLUGINLINK *link); +extern "C" PINGPROTO_API int Unload(void); + +#endif diff --git a/ping_protocol/pingproto.mdsp b/ping_protocol/pingproto.mdsp new file mode 100644 index 0000000..0396fac --- /dev/null +++ b/ping_protocol/pingproto.mdsp @@ -0,0 +1,117 @@ +[Project] +name=pingproto +type=2 +defaultConfig=1 + + +[Debug] +// compiler +workingDirectory= +arguments= +intermediateFilesDirectory=Debug +outputFilesDirectory=Debug +compilerPreprocessor=PINGPROTO_EXPORTS +extraCompilerOptions= +compilerIncludeDirectory= +noWarning=0 +defaultWarning=0 +allWarning=1 +extraWarning=0 +isoWarning=0 +warningsAsErrors=0 +debugType=1 +debugLevel=2 +exceptionEnabled=1 +runtimeTypeEnabled=1 +optimizeLevel=0 + +// linker +libraryPath= +outputFilename=Debug\pingproto.dll +libraries=ws2_32,gdi32,comdlg32 +extraLinkerOptions= +ignoreStartupFile=0 +ignoreDefaultLibs=0 +stripExecutableFile=0 + +// archive +extraArchiveOptions= + +//resource +resourcePreprocessor= +resourceIncludeDirectory= +extraResourceOptions= + +[Release] +// compiler +workingDirectory= +arguments= +intermediateFilesDirectory=Release +outputFilesDirectory=Release +compilerPreprocessor=PINGPROTO_EXPORTS +extraCompilerOptions= +compilerIncludeDirectory= +noWarning=0 +defaultWarning=0 +allWarning=1 +extraWarning=0 +isoWarning=0 +warningAsErrors=0 +debugType=0 +debugLevel=1 +exceptionEnabled=1 +runtimeTypeEnabled=1 +optimizeLevel=2 + +// linker +libraryPath= +outputFilename=Release\pingproto.dll +libraries=ws2_32,gdi32,comdlg32 +extraLinkerOptions= +ignoreStartupFile=0 +ignoreDefaultLibs=0 +stripExecutableFile=1 + +// archive +extraArchiveOptions= + +//resource +resourcePreprocessor= +resourceIncludeDirectory= +extraResourceOptions= + +[Source] +1=StdAfx.cpp +2=icmp.cpp +3=log.cpp +4=menu.cpp +5=options.cpp +6=pinggraph.cpp +7=pinglist.cpp +8=pingproto.cpp +9=pingthread.cpp +10=rawping.cpp +11=utils.cpp +[Header] +1=StdAfx.h +2=common.h +3=icmp.h +4=log.h +5=menu.h +6=options.h +7=pinggraph.h +8=pinglist.h +9=pingproto.h +10=pingthread.h +11=rawping.h +12=resource.h +13=utils.h +[Resource] +1=pingproto.rc +[Other] +[History] +pinglist.h,604 +pinglist.cpp,0 +common.h,2379 +pingproto.h,757 +pingproto.rc,8940 diff --git a/ping_protocol/pingproto.plg b/ping_protocol/pingproto.plg new file mode 100644 index 0000000..96ec617 --- /dev/null +++ b/ping_protocol/pingproto.plg @@ -0,0 +1,80 @@ + + +
+

Build Log

+

+--------------------Configuration: pingproto - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\sje\LOCALS~1\Temp\RSP4C.tmp" with contents +[ +/nologo /MD /W3 /GX /O1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PINGPROTO_EXPORTS" /D "_WINDLL" /D "_AFXDLL" /Fp"Release/pingproto.pch" /Yu"stdafx.h" /Fo"Release/" /Fd"Release/" /FD /c +"C:\Documents and Settings\sje\My Documents\MyProjects\miranda\plugins\pingproto\options.cpp" +] +Creating command line "cl.exe @C:\DOCUME~1\sje\LOCALS~1\Temp\RSP4C.tmp" +Creating temporary file "C:\DOCUME~1\sje\LOCALS~1\Temp\RSP4D.tmp" with contents +[ +ws2_32.lib wsock32.lib user32.lib gdi32.lib shell32.lib comdlg32.lib /nologo /base:"0x22050000" /dll /incremental:no /pdb:"Release/pingproto.pdb" /machine:I386 /out:"../../bin/release/plugins/pingproto.dll" /implib:"Release/pingproto.lib" +".\Release\icmp.obj" +".\Release\log.obj" +".\Release\menu.obj" +".\Release\options.obj" +".\Release\pinggraph.obj" +".\Release\pinglist.obj" +".\Release\pingproto.obj" +".\Release\pingthread.obj" +".\Release\rawping.obj" +".\Release\StdAfx.obj" +".\Release\utils.obj" +".\Release\pingproto.res" +] +Creating command line "link.exe @C:\DOCUME~1\sje\LOCALS~1\Temp\RSP4D.tmp" +

Output Window

+Compiling... +options.cpp +Linking... + Creating library Release/pingproto.lib and object Release/pingproto.exp + + + +

Results

+pingproto.dll - 0 error(s), 0 warning(s) +

+--------------------Configuration: pingproto - Win32 Debug-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\sje\LOCALS~1\Temp\RSP51.tmp" with contents +[ +/nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PINGPROTO_EXPORTS" /D "_WINDLL" /D "_AFXDLL" /Fp"Debug/pingproto.pch" /Yu"stdafx.h" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c +"C:\Documents and Settings\sje\My Documents\MyProjects\miranda\plugins\pingproto\options.cpp" +] +Creating command line "cl.exe @C:\DOCUME~1\sje\LOCALS~1\Temp\RSP51.tmp" +Creating temporary file "C:\DOCUME~1\sje\LOCALS~1\Temp\RSP52.tmp" with contents +[ +user32.lib gdi32.lib ws2_32.lib shell32.lib comdlg32.lib /nologo /dll /incremental:yes /pdb:"Debug/pingproto.pdb" /debug /machine:I386 /out:"../../bin/debug/plugins/pingproto.dll" /implib:"Debug/pingproto.lib" /pdbtype:sept +".\Debug\icmp.obj" +".\Debug\log.obj" +".\Debug\menu.obj" +".\Debug\options.obj" +".\Debug\pinggraph.obj" +".\Debug\pinglist.obj" +".\Debug\pingproto.obj" +".\Debug\pingthread.obj" +".\Debug\rawping.obj" +".\Debug\StdAfx.obj" +".\Debug\utils.obj" +".\Debug\pingproto.res" +] +Creating command line "link.exe @C:\DOCUME~1\sje\LOCALS~1\Temp\RSP52.tmp" +

Output Window

+Compiling... +options.cpp +Linking... + + + +

Results

+pingproto.dll - 0 error(s), 0 warning(s) +
+ + diff --git a/ping_protocol/pingproto.rc b/ping_protocol/pingproto.rc new file mode 100644 index 0000000..670e0fe --- /dev/null +++ b/ping_protocol/pingproto.rc @@ -0,0 +1,226 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON_PROTO ICON "icon1.ico" +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (Australia) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_DIALOG1 DIALOGEX 0, 0, 313, 183 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_SYSMENU +FONT 8, "MS Shell Dlg", 0, 0, 0x1 +BEGIN + RTEXT "Delay between pings (secs):",IDC_STATIC,12,20,121,8 + EDITTEXT IDC_PPM,138,16,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT + CONTROL "Timeout",IDC_CHECKPOPUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,226,21,74,10 + RTEXT "Ping timeout (secs):",IDC_STATIC,12,36,121,8 + EDITTEXT IDC_PT,138,34,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT + GROUPBOX "Logging",IDC_STATIC,7,121,299,55 + CONTROL "Log to File",IDC_CHK_LOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,99,134,61,10 + LTEXT "Log Filename:",IDC_STATIC,17,154,56,8 + EDITTEXT IDC_ED_FILENAME,77,151,158,14,ES_AUTOHSCROLL + GROUPBOX "Network",IDC_STATIC,7,8,211,62 + GROUPBOX "PopUps",IDC_STATIC,222,8,84,62 + CONTROL "Reply",IDC_CHECKPOPUP2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,226,35,73,10 + CONTROL "Block Repetitions",IDC_CHK_BLOCK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,226,53,73,10 + PUSHBUTTON "View Log",IDC_BTN_VIEWLOG,169,132,59,14 + PUSHBUTTON "Browse...",IDC_BTN_LOGBROWSE,241,150,54,16 + GROUPBOX "Status",IDC_STATIC,7,72,299,46 + CONTROL "Hide in status bar and status menu (requires restart - uncheck to set icons)",IDC_CHK_HIDEPROTO, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,101,272,10 + RTEXT "Repeats for success/failure:",IDC_STATIC,12,53,121,8 + EDITTEXT IDC_RPT,138,52,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER,WS_EX_RIGHT + CONTROL "Put details in status message",IDC_CHK_USESTATUSMSG, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,18,87,120,10 +END + +IDD_DIALOG2 DIALOG 0, 0, 303, 212 +STYLE DS_SETFONT | WS_POPUP +FONT 8, "MS Sans Serif" +BEGIN + GROUPBOX "Ping Destinations",IDC_STATIC,7,7,289,198 + PUSHBUTTON "Add",IDC_BTN_DESTADD,38,172,38,15 + LISTBOX IDC_LST_DEST,37,32,228,128,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Remove",IDC_BTN_DESTREM,132,172,38,15,WS_DISABLED + PUSHBUTTON "Edit",IDC_BTN_DESTEDIT,85,172,38,15,WS_DISABLED + PUSHBUTTON "Up",IDC_BTN_DESTUP,179,172,38,15,WS_DISABLED + PUSHBUTTON "Down",IDC_BTN_DESTDOWN,226,172,38,15,WS_DISABLED +END + +IDD_DIALOG3 DIALOGEX 0, 0, 264, 326 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Ping Destination" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,78,305,50,14 + PUSHBUTTON "Cancel",IDCANCEL,134,305,50,14 + RTEXT "Address:",IDC_STATIC,12,34,51,8 + RTEXT "Label:",IDC_STATIC,16,49,47,8 + EDITTEXT IDC_ED_DESTADDR,67,30,154,12,ES_AUTOHSCROLL | ES_WANTRETURN + EDITTEXT IDC_ED_DESTLAB,67,48,154,12,ES_AUTOHSCROLL | ES_WANTRETURN + CONTROL "TCP Connect",IDC_CHK_DESTTCP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,69,71,10 + LTEXT "Port:",IDC_STATIC,147,69,30,8,0,WS_EX_RIGHT + EDITTEXT IDC_ED_DESTPORT,181,67,40,12,ES_RIGHT | ES_AUTOHSCROLL | ES_WANTRETURN | ES_NUMBER | WS_DISABLED + CTEXT "Add to contact list group:",IDC_STATIC,63,90,138,8 + COMBOBOX IDC_COMBO_GROUP,70,104,122,148,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + CTEXT "Control Protocol:",IDC_STATIC,84,141,92,8 + COMBOBOX IDC_COMBO_DESTPROTO,83,154,97,106,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP + COMBOBOX IDC_COMBO_DESTSTAT,156,193,76,83,CBS_DROPDOWNLIST | WS_DISABLED | WS_VSCROLL | WS_TABSTOP + LTEXT "Set my status to:",IDC_STATIC,156,179,87,8 + LTEXT "On success, if my status is:",IDC_STATIC,33,179,111,8 + COMBOBOX IDC_COMBO_DESTSTAT2,33,193,90,76,CBS_DROPDOWNLIST | WS_DISABLED | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_ED_COMMAND,25,232,213,16,ES_AUTOHSCROLL + CTEXT "Execute the following command on double-click:",IDC_STATIC,28,217,207,8 + GROUPBOX "Contact",IDC_STATIC,7,7,250,119 + GROUPBOX "Protocols",IDC_STATIC,7,132,250,166 + EDITTEXT IDC_ED_PARAMS,25,271,213,16,ES_AUTOHSCROLL + CTEXT "(Optional) Command Parameters:",IDC_STATIC,27,256,207,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_DIALOG1, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 306 + TOPMARGIN, 7 + BOTTOMMARGIN, 176 + END + + IDD_DIALOG2, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 296 + TOPMARGIN, 7 + BOTTOMMARGIN, 205 + END + + IDD_DIALOG3, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 257 + TOPMARGIN, 7 + BOTTOMMARGIN, 319 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_MENU1 MENU +BEGIN + POPUP "Menu" + BEGIN + MENUITEM "Disable all pings", ID_MENU_DISABLEALLPINGS + MENUITEM "Enable all pings", ID_MENU_ENABLEALLPINGS + MENUITEM SEPARATOR + MENUITEM "Options...", ID_MENU_OPTIONS + MENUITEM "Destinations...", ID_MENU_DESTINATIONS + END +END + +#endif // English (Australia) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/ping_protocol/pingproto.sln b/ping_protocol/pingproto.sln new file mode 100644 index 0000000..80e300a --- /dev/null +++ b/ping_protocol/pingproto.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pingproto", "pingproto.vcproj", "{BEA1B271-574A-458C-A284-14F96E5180C4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BEA1B271-574A-458C-A284-14F96E5180C4}.Debug|Win32.ActiveCfg = Debug|Win32 + {BEA1B271-574A-458C-A284-14F96E5180C4}.Debug|Win32.Build.0 = Debug|Win32 + {BEA1B271-574A-458C-A284-14F96E5180C4}.Release|Win32.ActiveCfg = Release|Win32 + {BEA1B271-574A-458C-A284-14F96E5180C4}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ping_protocol/pingproto.vcproj b/ping_protocol/pingproto.vcproj new file mode 100644 index 0000000..d7ff013 --- /dev/null +++ b/ping_protocol/pingproto.vcproj @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ping_protocol/pingthread.cpp b/ping_protocol/pingthread.cpp new file mode 100644 index 0000000..c9a5fbd --- /dev/null +++ b/ping_protocol/pingthread.cpp @@ -0,0 +1,309 @@ +#include "stdafx.h" +#include "pingthread.h" + +int upCount, total = 0; + +HANDLE mainThread; +HANDLE hWakeEvent = 0; + +// thread protected variables +CRITICAL_SECTION thread_finished_cs, list_changed_cs, data_list_cs; +bool thread_finished = false, list_changed = false; +PINGLIST data_list; + +HANDLE status_update_thread = 0; + +bool get_thread_finished() { + Lock(&thread_finished_cs, "get_thread_finished"); + bool retval = thread_finished; + Unlock(&thread_finished_cs); + return retval; +} + +void set_thread_finished(bool f) { + Lock(&thread_finished_cs, "set_thread_finished"); + thread_finished = f; + Unlock(&thread_finished_cs); +} + +bool get_list_changed() { + Lock(&list_changed_cs, "get_list_changed"); + bool retval = list_changed; + Unlock(&list_changed_cs); + return retval; +} + +void set_list_changed(bool f) { + Lock(&list_changed_cs, "set_list_changed"); + list_changed = f; + Unlock(&list_changed_cs); +} + +void SetProtoStatus(char *pszLabel, char *pszProto, int if_status, int new_status) { + if(strcmp(pszProto, Translate("")) == 0) { + int num_protocols; + PROTOCOLDESCRIPTOR **pppDesc; + + CallService(MS_PROTO_ENUMPROTOCOLS, (LPARAM)&num_protocols, (WPARAM)&pppDesc); + for(int i = 0; i < num_protocols; i++) { + if(pppDesc[i]->type == PROTOTYPE_PROTOCOL) + SetProtoStatus(pszLabel, pppDesc[i]->szName, if_status, new_status); + } + } else { + std::ostringstream get_status, set_status; + get_status << pszProto << PS_GETSTATUS; + if(ServiceExists(get_status.str().c_str())) { + set_status << pszProto << PS_SETSTATUS; + + if(CallService(get_status.str().c_str(), 0, 0) == if_status) { + if(options.logging) { + std::ostringstream oss2; + oss2 << pszLabel << " - setting status of protocol '" << pszProto << "' (" << new_status << ")"; + CallService(PROTO "/Log", (WPARAM)oss2.str().c_str(), 0); + } + CallService(set_status.str().c_str(), new_status, 0); + } + } + } +} + +DWORD WINAPI sttCheckStatusThreadProc( void *vp) +{ + clock_t start_t = clock(), end_t; + while(!get_thread_finished()) { + + end_t = clock(); + + int wait = (options.ping_period - ((end_t - start_t) / (double)CLOCKS_PER_SEC)) * 1000; + if(wait > 0) + WaitForSingleObjectEx(hWakeEvent, wait, TRUE); + + if(get_thread_finished()) break; + + start_t = clock(); + + bool timeout = false; + bool reply = false; + int count = 0; + + PINGADDRESS pa; + //HANDLE next = 0; + + std::pair history_entry; + + Lock(&data_list_cs, "ping thread loop start"); + set_list_changed(false); + int size = data_list.size(); + Unlock(&data_list_cs); + + int ind; + for(ind = 0; ind < size; ind++) { + Lock(&data_list_cs, "ping thread loop start"); + int c = 0; + for(PINGLIST::iterator i = data_list.begin(); i != data_list.end() && c <= ind; i++, c++) { + if(c == ind) { + // copy just what we need - i.e. not history, not command + pa.get_status = i->get_status; + pa.hContact = i->hContact; + pa.miss_count = i->miss_count; + pa.port = i->port; + strcpy(pa.pszLabel, i->pszLabel); + strcpy(pa.pszName, i->pszName); + strcpy(pa.pszProto, i->pszProto); + pa.set_status = i->set_status; + pa.status = i->status; + break; + } + + } + Unlock(&data_list_cs); + + if(get_thread_finished()) break; + if(get_list_changed()) break; + + if(pa.status != options.off_status) { + if(CallService(MS_DB_CONTACT_IS, (WPARAM)pa.hContact, 0)) { + if(!options.no_test_status) + DBWriteContactSettingWord(pa.hContact, PROTO, "Status", options.tstatus); + + CallService(PROTO "/Ping", 0, (LPARAM)&pa); + } else + break; + + if(get_thread_finished()) break; + if(get_list_changed()) break; + + Lock(&data_list_cs, "ping thread loop start"); + for(PINGLIST::iterator i = data_list.begin(); i != data_list.end(); i++) { + if(i->hContact == pa.hContact) { + i->responding = pa.responding; + i->round_trip_time = pa.round_trip_time; + + history_entry.first = i->round_trip_time; + history_entry.second = time(0); + i->history.push_back(history_entry); + // maintain history (-1 represents no response) + while(i->history.size() >= MAX_HISTORY) { + i->history.erase(i->history.begin()); + //i->history.pop_front(); + } + + if(pa.responding) { + if(pa.miss_count > 0) + pa.miss_count = -1; + else + pa.miss_count--; + pa.status = options.rstatus; + } + else { + if(pa.miss_count < 0) + pa.miss_count = 1; + else + pa.miss_count++; + pa.status = options.nrstatus; + } + i->miss_count = pa.miss_count; + i->status = pa.status; + + break; + } + } + Unlock(&data_list_cs); + + if(pa.responding) { + count++; + + if(pa.miss_count == -1 - options.retries || + (((-pa.miss_count) % (options.retries + 1)) == 0 && !options.block_reps)) + { + reply = true; + if(options.show_popup2 && ServiceExists(MS_POPUP_SHOWMESSAGE)) { + ShowPopup("Ping Reply", pa.pszLabel, 1); + } + if(DBGetContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_OFFLINE) != pa.status) + DBWriteContactSettingWord(pa.hContact, PROTO, "Status", pa.status); + } + if(pa.miss_count == -1 - options.retries && options.logging) { + std::ostringstream oss2; + oss2 << pa.pszLabel << " - reply"; + CallService(PROTO "/Log", (WPARAM)oss2.str().c_str(), 0); + } + SetProtoStatus(pa.pszLabel, pa.pszProto, pa.get_status, pa.set_status); + if(options.use_status_msg) { + std::ostringstream msg; + char *mode_desc = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, options.rstatus, 0); + msg << (mode_desc ? mode_desc : Translate("Uknnown")) << " (" << pa.round_trip_time << ")"; + DBWriteContactSettingString(pa.hContact, "CList", "StatusMsg", msg.str().c_str()); + } else { + std::ostringstream handle; + handle << pa.pszLabel << " (" << pa.round_trip_time << ")"; + set_changing_clist_handle(TRUE); + DBWriteContactSettingString(pa.hContact, "CList", "MyHandle", handle.str().c_str()); + set_changing_clist_handle(FALSE); + } + } else { + + if(pa.miss_count == 1 + options.retries || + ((pa.miss_count % (options.retries + 1)) == 0 && !options.block_reps)) + { + timeout = true; + if(options.show_popup && ServiceExists(MS_POPUP_SHOWMESSAGE)) { + ShowPopup("Ping Timeout", pa.pszLabel, 0); + } + if(!timeout) timeout = true; + if(DBGetContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_OFFLINE) != pa.status) + DBWriteContactSettingWord(pa.hContact, PROTO, "Status", pa.status); + } + if(pa.miss_count == 1 + options.retries && options.logging) { + std::ostringstream oss2; + oss2 << pa.pszLabel << " - timeout"; + CallService(PROTO "/Log", (WPARAM)oss2.str().c_str(), 0); + } + if(options.use_status_msg) { + std::ostringstream msg; + char *mode_desc = (char *)CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, options.nrstatus, 0); + msg << (mode_desc ? mode_desc : Translate("Uknnown")) << " [" << pa.miss_count << "]"; + DBWriteContactSettingString(pa.hContact, "CList", "StatusMsg", msg.str().c_str()); + } else { + std::ostringstream handle; + handle << pa.pszLabel << " [" << pa.miss_count << "]"; + set_changing_clist_handle(TRUE); + DBWriteContactSettingString(pa.hContact, "CList", "MyHandle", handle.str().c_str()); + set_changing_clist_handle(FALSE); + } + } + if(!options.no_test_status && DBGetContactSettingWord(pa.hContact, PROTO, "Status", ID_STATUS_OFFLINE) != pa.status) + DBWriteContactSettingWord(pa.hContact, PROTO, "Status", pa.status); + } + } + + if(timeout) SkinPlaySound("PingProtoTimeout"); + if(reply) SkinPlaySound("PingProtoReply"); + + if(!get_list_changed()) { + upCount = count; + total = ind; + + if(DBGetContactSettingByte(0, PROTO, "SetProtoStatus", 0)) { + if(upCount == total) + CallService(PROTO PS_SETSTATUS, options.rstatus, 0); + else if(upCount == 0) + CallService(PROTO PS_SETSTATUS, options.nrstatus, 0); + } + } else { + total = 0; + } + } + + return 0; +} + +void start_ping_thread() { + DWORD tid; + + if(status_update_thread) CloseHandle(status_update_thread); + status_update_thread = CreateThread(0, 0, sttCheckStatusThreadProc, 0, 0, &tid); +} + +void stop_ping_thread() { + set_thread_finished(true); + SetEvent(hWakeEvent); + //ICMP::get_instance()->stop(); + WaitForSingleObject(status_update_thread, 2000); + TerminateThread(status_update_thread, 0); + CloseHandle(status_update_thread); + status_update_thread = 0; +} + +int FillList(WPARAM wParam, LPARAM lParam) { + + if(options.logging) + CallService(PROTO "/Log", (WPARAM)"ping address list reload", 0); + + PINGLIST pl; + CallService(PROTO "/GetPingList", 0, (LPARAM)&pl); + + Lock(&data_list_cs, "fill_list"); + + // copy history + for(PINGLIST::iterator i = data_list.begin(); i != data_list.end(); i++) { + for(PINGLIST::iterator j = pl.begin(); j != pl.end(); j++) { + if(i->hContact == j->hContact) { + if(i->history.size()) + j->history = i->history; + else + j->history.clear(); + } + } + } + + if(pl.size()) + data_list = pl; + + set_list_changed(true); + Unlock(&data_list_cs); + + SetEvent(hWakeEvent); + return 0; +} + diff --git a/ping_protocol/pingthread.h b/ping_protocol/pingthread.h new file mode 100644 index 0000000..c23b2dc --- /dev/null +++ b/ping_protocol/pingthread.h @@ -0,0 +1,21 @@ +#ifndef _PINGTHREAD_H +#define _PINGTHREAD_H + +#include +#include +#include "pinglist.h" +#include "utils.h" +#include "options.h" + +extern HANDLE mainThread; +extern HANDLE hWakeEvent; +extern CRITICAL_SECTION thread_finished_cs, list_changed_cs, data_list_cs; + +extern PINGLIST data_list; + +void start_ping_thread(); +void stop_ping_thread(); + +int FillList(WPARAM wParam, LPARAM lParam); + +#endif \ No newline at end of file diff --git a/ping_protocol/rawping.cpp b/ping_protocol/rawping.cpp new file mode 100644 index 0000000..008a2a8 --- /dev/null +++ b/ping_protocol/rawping.cpp @@ -0,0 +1,206 @@ +#include "stdafx.h" +#include "rawping.h" + +#include +#include + +#include "rawping.h" + +USHORT ip_checksum(USHORT* buffer, int size) +{ + unsigned long cksum = 0; + + // Sum all the words together, adding the final byte if size is odd + while (size > 1) { + cksum += *buffer++; + size -= sizeof(USHORT); + } + if (size) { + cksum += *(UCHAR*)buffer; + } + + // Do a little shuffling + cksum = (cksum >> 16) + (cksum & 0xffff); + cksum += (cksum >> 16); + + // Return the bitwise complement of the resulting mishmash + return (USHORT)(~cksum); +} + +SOCKET sd = -1; +char packet[1024]; +char recv_buff[1024]; +USHORT seq_no = 0; +bool inited = false; + +extern int init_raw_ping() { + WSAData wsaData; + if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) { + WSACleanup(); + return 1; + } + + if(sd != -1) + closesocket(sd); + + // Create the socket + //sd = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, 0, 0, 0); + sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sd == INVALID_SOCKET) { + return 2; + } + + int ttl = 255; + if (setsockopt(sd, IPPROTO_IP, IP_TTL, (const char*)&ttl, sizeof(ttl)) == SOCKET_ERROR) { + return 3; + } + + int our_recv_timeout = 100; // so we ca do multiple recv calls + if(setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (const char *)&our_recv_timeout, sizeof(int)) == SOCKET_ERROR) { + return 4; + } + + ICMPHeader *header = (ICMPHeader *)packet; + header->type = ICMP_ECHO_REQUEST; + header->code = 0; + header->id = (USHORT)GetCurrentProcessId(); + + inited = true; + if(raw_ping("127.0.0.1", 500) >= 0) { + return 0; + } + + inited = false; + return 5; +} + +extern int raw_ping(char *host, int timeout) { + if(!inited) return -1; + + // Initialize the destination host info block + sockaddr_in dest; + memset(&dest, 0, sizeof(dest)); + + // Turn first passed parameter into an IP address to ping + unsigned int addr = inet_addr(host); + if (addr != INADDR_NONE) { + // It was a dotted quad number, so save result + dest.sin_addr.s_addr = addr; + dest.sin_family = AF_INET; + } + else { + // Not in dotted quad form, so try and look it up + hostent* hp = gethostbyname(host); + if (hp != 0) { + // Found an address for that host, so save it + memcpy(&(dest.sin_addr), hp->h_addr, hp->h_length); + //dest.sin_family = hp->h_addrtype; + dest.sin_family = AF_INET; + } + else { + // Not a recognized hostname either! + return -1; + } + } + + ICMPHeader *header = (ICMPHeader *)packet; + header->seq = ++seq_no; + header->checksum = 0; + header->checksum = ip_checksum((USHORT*)header, sizeof(ICMPHeader)); + + bool use_hi_res = false; + LARGE_INTEGER hr_freq, hr_send_time; + DWORD send_time; + if(QueryPerformanceFrequency(&hr_freq)) { + use_hi_res = true; + QueryPerformanceCounter(&hr_send_time); + } else + send_time = GetTickCount(); + + // send packet + int bwrote = sendto(sd, (char*)packet, sizeof(ICMPHeader), 0, (sockaddr*)&dest, sizeof(dest)); + if (bwrote == SOCKET_ERROR) { + return -1; + } + + // Wait for the ping reply + sockaddr_in source; + int fromlen = sizeof(source); + IPHeader *reply_header = (IPHeader *)recv_buff; + ICMPHeader *reply; + DWORD start, current_time; + LARGE_INTEGER hr_start, hr_current_time, hr_timeout; + if(use_hi_res) { + hr_timeout.QuadPart = (timeout * hr_freq.QuadPart / 1000); + QueryPerformanceCounter(&hr_start); + hr_current_time = hr_start; + } else { + start = GetTickCount(); + current_time = start; + } + + while(((use_hi_res && (hr_current_time.QuadPart < hr_start.QuadPart + hr_timeout.QuadPart)) + || (!use_hi_res && current_time < start + timeout))) + { + int bread = recvfrom(sd, recv_buff, 1024, 0, (sockaddr*)&source, &fromlen); + + if(use_hi_res) + QueryPerformanceCounter(&hr_current_time); + else + current_time = GetTickCount(); + + if (bread == SOCKET_ERROR) { + if(WSAGetLastError() != WSAETIMEDOUT) { + if(options.logging) CallService(PROTO "/Log", (WPARAM)"rawping error: socket error", 0); + continue; + } + } + + if(reply_header->proto != ICMP_PROTO) + continue; + + if(reply_header->tos != 0) + continue; + + reply = (ICMPHeader *)(recv_buff + reply_header->h_len * 4); + if((unsigned)bread < reply_header->h_len * 4 + sizeof(ICMPHeader)) { + if(options.logging) CallService(PROTO "/Log", (WPARAM)"rawping error: short header", 0); + continue; + } + + if(reply->id != (USHORT)GetCurrentProcessId()) + continue; + + if(reply->type != ICMP_ECHO_REPLY && reply->type != ICMP_SOURCE_QUENCH) { + continue; + } + + //if(reply->seq < seq_no) continue; + //if(reply->seq > seq_no) return -1; + if(reply->seq != seq_no) continue; + + if(reply->type == ICMP_SOURCE_QUENCH) { + char buff[1024]; + sprintf(buff, Translate("Host %s requests that you reduce the amount of traffic you are sending."), host); + MessageBox(0, buff, Translate(PROTO " Warning"), MB_OK | MB_ICONWARNING); + } + + if(use_hi_res) { + LARGE_INTEGER ticks; + ticks.QuadPart = hr_current_time.QuadPart - hr_send_time.QuadPart; + return (int)(ticks.QuadPart * 1000 / hr_freq.QuadPart); + } else + return current_time - send_time; + } + + return -1; +} + +extern int cleanup_raw_ping() { + if(inited) { + closesocket(sd); + sd = -1; + WSACleanup(); + } + return 0; +} diff --git a/ping_protocol/rawping.h b/ping_protocol/rawping.h new file mode 100644 index 0000000..2201d19 --- /dev/null +++ b/ping_protocol/rawping.h @@ -0,0 +1,61 @@ +#ifndef _RAWPING_H +#define _RAWPING_H + +#include "common.h" // to translate 'SOURCE_QUENCH' warning +#include "options.h" +#include "log.h" + + +// ICMP protocol identifier +#define ICMP_PROTO 1 + +// ICMP packet types +#define ICMP_ECHO_REPLY 0 +#define ICMP_DEST_UNREACH 3 +#define ICMP_TTL_EXPIRE 11 +#define ICMP_ECHO_REQUEST 8 +#define ICMP_SOURCE_QUENCH 4 + +// Minimum ICMP packet size, in bytes +#define ICMP_MIN 8 + +#ifdef _MSC_VER +// The following two structures need to be packed tightly, but unlike +// Borland C++, Microsoft C++ does not do this by default. +#pragma pack(1) +#endif + +// The IP header +struct IPHeader { + BYTE h_len:4; // Length of the header in dwords + BYTE version:4; // Version of IP + BYTE tos; // Type of service + USHORT total_len; // Length of the packet in dwords + USHORT ident; // unique identifier + USHORT flags; // Flags + BYTE ttl; // Time to live + BYTE proto; // Protocol number (TCP, UDP etc) + USHORT checksum; // IP checksum + ULONG source_ip; + ULONG dest_ip; +}; + +// ICMP header +struct ICMPHeader { + BYTE type; // ICMP packet type + BYTE code; // Type sub code + USHORT checksum; + USHORT id; + USHORT seq; +}; + +#ifdef _MSC_VER +#pragma pack() +#endif + +extern USHORT ip_checksum(USHORT* buffer, int size); + +extern int init_raw_ping(); +extern int raw_ping(char *host, int timeout); +extern int cleanup_raw_ping(); +#endif \ No newline at end of file diff --git a/ping_protocol/resource.h b/ping_protocol/resource.h new file mode 100644 index 0000000..27544cc --- /dev/null +++ b/ping_protocol/resource.h @@ -0,0 +1,65 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by pingproto.rc +// +#define IDD_DIALOG1 101 +#define IDD_DIALOG2 102 +#define IDD_DIALOG3 103 +#define IDR_MENU1 106 +#define IDI_ICON_PROTO 108 +#define IDC_PPM 1001 +#define IDC_PT 1002 +#define IDC_RPT 1003 +#define IDC_CHECK1 1005 +#define IDC_CHECKPOPUP 1005 +#define IDC_CHK_DESTTCP 1005 +#define IDC_BUTTONEDIT 1006 +#define IDC_BUTTONRELOAD 1007 +#define IDC_CHK_LOG 1008 +#define IDC_ED_FILENAME 1009 +#define IDC_CHECKPOPUP2 1010 +#define IDC_CHK_MINMAX 1011 +#define IDC_CHK_BLOCK 1012 +#define IDC_BTN_VIEWLOG 1013 +#define IDC_ED_DATAFILENAME 1014 +#define IDC_BTN_LOGBROWSE 1015 +#define IDC_BTN_DATABROWSE 1016 +#define IDC_ED_DESTADDR 1016 +#define IDC_ED_DESTLAB 1017 +#define IDC_BTN_DESTADD 1018 +#define IDC_LST_DEST 1019 +#define IDC_BTN_DESTREM 1020 +#define IDC_ED_DESTPORT 1021 +#define IDC_BTN_DESTEDIT 1021 +#define IDC_ED_DESTPROTO 1022 +#define IDC_BTN_DESTUP 1022 +#define IDC_BTN_DESTDOWN 1023 +#define IDC_COMBO_DESTPROTO 1024 +#define IDC_COMBO_DESTSTAT 1025 +#define IDC_COMBO_DESTSTAT2 1026 +#define IDC_ED_COMMAND 1032 +#define IDC_RSTATUS 1033 +#define IDC_ED_PARAMS 1033 +#define IDC_NRSTATUS 1034 +#define IDC_TSTATUS 1035 +#define IDC_DSTATUS 1036 +#define IDC_CHK_NOTESTSTATUS 1037 +#define IDC_COMBO_GROUP 1038 +#define IDC_CHK_HIDEPROTO 1038 +#define IDC_CHK_USESTATUSMSG 1039 +#define ID_MENU_ENABLEALLPINGS 40002 +#define ID_MENU_OPTIONS 40003 +#define ID_MENU_DISABLEALLPINGS 40004 +#define ID_MENU_DESTINATIONS 40005 + +#define IDC_STATIC -1 +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 109 +#define _APS_NEXT_COMMAND_VALUE 40006 +#define _APS_NEXT_CONTROL_VALUE 1039 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/ping_protocol/utils.cpp b/ping_protocol/utils.cpp new file mode 100644 index 0000000..1f9c839 --- /dev/null +++ b/ping_protocol/utils.cpp @@ -0,0 +1,324 @@ +#include "stdafx.h" +#include "utils.h" + +bool use_raw_ping = true; +/* +std::string trim_string(const std::string &in) { + std::string out; + + int i = 0; + while(i < in.size() && in[i] == ' ') + i++; + for(; i < in.size(); i++) { + out += in[i]; + } + + while(out.size() && out[out.size() - 1] == ' ') { + out = out.substr(0, out.size() - 1); + } + + + return out; +} + +void capitalize(std::string &in) { + for(int i = 0; i < in.length(); i++) { + if(in[i] >= 'a' && in[i] <= 'z') + in[i] = 'A' + (in[i] - 'a'); + } +} +*/ +LRESULT CALLBACK NullWindowProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) +{ + switch( message ) { + case WM_COMMAND: { + PUDeletePopUp( hWnd ); + break; + } + + case WM_CONTEXTMENU: + PUDeletePopUp( hWnd ); + break; + } + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +void CALLBACK sttMainThreadCallback( ULONG dwParam ) +{ + POPUPDATAEX* ppd = ( POPUPDATAEX* )dwParam; + + if ( ServiceExists(MS_POPUP_ADDPOPUPEX) ) + CallService( MS_POPUP_ADDPOPUPEX, ( WPARAM )ppd, 0 ); + else + if ( ServiceExists(MS_POPUP_ADDPOPUP) ) + CallService( MS_POPUP_ADDPOPUP, ( WPARAM )ppd, 0 ); + + free( ppd ); +} + +void __stdcall ShowPopup( const char* line1, const char* line2, int flags ) +{ + if(CallService(MS_SYSTEM_TERMINATED, 0, 0)) return; + + if ( !ServiceExists( MS_POPUP_ADDPOPUP )) { + MessageBox( NULL, line2, PROTO " Message", MB_OK | MB_ICONINFORMATION ); + return; + } + + POPUPDATAEX* ppd = ( POPUPDATAEX* )calloc( sizeof( POPUPDATAEX ), 1 ); + + ppd->lchContact = NULL; + ppd->lchIcon = (flags ? LoadSkinnedProtoIcon(PROTO, options.rstatus) : LoadSkinnedProtoIcon(PROTO, options.nrstatus)); + strcpy( ppd->lpzContactName, line1 ); + strcpy( ppd->lpzText, line2 ); + + ppd->colorBack = GetSysColor( COLOR_BTNFACE ); + ppd->colorText = GetSysColor( COLOR_WINDOWTEXT ); + ppd->iSeconds = 10; + + ppd->PluginWindowProc = ( WNDPROC )NullWindowProc; + ppd->PluginData = NULL; + + QueueUserAPC( sttMainThreadCallback , mainThread, ( ULONG )ppd ); +} + +// service functions + +// wParam is zero +// lParam is address of PINGADDRESS structure where ping result is placed (i.e. modifies 'responding' +// and 'round_trip_time') +int PluginPing(WPARAM wParam,LPARAM lParam) +{ + PINGADDRESS *pa = (PINGADDRESS *)lParam; + + if(pa->port == -1) { + if(use_raw_ping) { + pa->round_trip_time = raw_ping(pa->pszName, options.ping_timeout * 1000); + pa->responding = (pa->round_trip_time != -1); + } else { + // ICMP echo + IP_ECHO_REPLY result; + pa->responding = ICMP::get_instance()->ping(pa->pszName, result); + if(pa->responding) + pa->round_trip_time = result.RoundTripTime; + else + pa->round_trip_time = -1; + } + } else if(hNetlibUser) { + // TCP connect + + clock_t start_tcp = clock(); + + //GetLocalTime(&systime); + NETLIBOPENCONNECTION conn = {0}; + conn.cbSize = sizeof(NETLIBOPENCONNECTION); + conn.szHost = pa->pszName; + conn.wPort = pa->port; + conn.flags = NLOCF_V2; + conn.timeout = options.ping_timeout; + + HANDLE s = (HANDLE)CallService(MS_NETLIB_OPENCONNECTION, (WPARAM)hNetlibUser, (LPARAM)&conn); + + clock_t end_tcp = clock(); + + if(s) { + LINGER l; + char buf[1024]; + SOCKET socket = (SOCKET)CallService(MS_NETLIB_GETSOCKET, (WPARAM)s, (LPARAM)NLOCF_HTTP); + if(socket != INVALID_SOCKET) { + l.l_onoff = 1; + l.l_linger = 0; + setsockopt(socket, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)); + + Netlib_Send(s, "OUT\r\n\r\n", 7, 0); //MSG_RAW); + + //Sleep(ICMP::get_instance()->get_timeout()); + Sleep(options.ping_timeout * 1000); + unsigned long bytes_remaining; + ioctlsocket(socket, FIONBIO, &bytes_remaining); + + if(bytes_remaining > 0) { + int retval, rx = 0; + while((retval = Netlib_Recv(s, buf, 1024, 0)) != SOCKET_ERROR && (retval > 0) && rx < 2048) { + rx += retval; // recv at most 2kb before closing connection + } + } + //closesocket(socket); + + } + + Netlib_CloseHandle(s); + + pa->responding = true; + pa->round_trip_time = (int)(((end_tcp - start_tcp) / (double)CLOCKS_PER_SEC) * 1000); + } else { + pa->responding = false; + pa->round_trip_time = -1; + } + + } + return 0; +} + +void Lock(CRITICAL_SECTION *cs, char *lab) { +// if(logging) { +// std::ostringstream oss1; +// oss1 << "Locking cs: " << cs << ", " << lab; +// CallService(PROTO "/Log", (WPARAM)oss1.str().c_str(), 0); +// } + EnterCriticalSection(cs); +// if(logging) { +// std::ostringstream oss2; +// oss2 << "Locked cs: " << cs; +// CallService(PROTO "/Log", (WPARAM)oss2.str().c_str(), 0); +// } +} + +void Unlock(CRITICAL_SECTION *cs) { +// if(logging) { +// std::ostringstream oss1; +// oss1 << "Unlocking cs: " << cs; +// CallService(PROTO "/Log", (WPARAM)oss1.str().c_str(), 0); +// } + LeaveCriticalSection(cs); +} + +int PingDisableAll(WPARAM wParam, LPARAM lParam) { + PINGLIST pl; + CallService(PROTO "/GetPingList", 0, (LPARAM)&pl); + for(PINGLIST::iterator i = pl.begin(); i != pl.end(); i++) { + i->status = options.off_status; + DBWriteContactSettingWord(i->hContact, PROTO, "Status", i->status); + set_changing_clist_handle(TRUE); + DBWriteContactSettingString(i->hContact, "CList", "MyHandle", i->pszLabel); + set_changing_clist_handle(FALSE); + } + CallService(PROTO "/SetPingList", (WPARAM)&pl, 0); + return 0; +} + +int PingEnableAll(WPARAM wParam, LPARAM lParam) { + PINGLIST pl; + CallService(PROTO "/GetPingList", 0, (LPARAM)&pl); + for(PINGLIST::iterator i = pl.begin(); i != pl.end(); i++) { + if(i->status == options.off_status) { + i->status = options.nrstatus; + DBWriteContactSettingWord(i->hContact, PROTO, "Status", i->status); + } + } + CallService(PROTO "/SetPingList", (WPARAM)&pl, 0); + return 0; +} + + +int ToggleEnabled(WPARAM wParam, LPARAM lParam) { + PINGLIST pl; + CallService(PROTO "/GetPingList", 0, (LPARAM)&pl); + for(PINGLIST::iterator i = pl.begin(); i != pl.end(); i++) { + if(i->hContact == (HANDLE)wParam) { + + if(i->status == options.off_status) + i->status = options.nrstatus; + else { + i->status = options.off_status; + set_changing_clist_handle(TRUE); + DBWriteContactSettingString(i->hContact, "CList", "MyHandle", i->pszLabel); + set_changing_clist_handle(FALSE); + } + DBWriteContactSettingWord(i->hContact, PROTO, "Status", i->status); + } + } + CallService(PROTO "/SetPingList", (WPARAM)&pl, 0); + return 0; +} + +int EditContact(WPARAM wParam, LPARAM lParam) { + PINGLIST pl; + HWND hwndList = (HWND)CallService(MS_CLUI_GETHWND, 0, 0); + + CallService(PROTO "/GetPingList", 0, (LPARAM)&pl); + for(PINGLIST::iterator i = pl.begin(); i != pl.end(); i++) { + if(i->hContact == (HANDLE)wParam) { + + add_edit_addr = *i; + + if(DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG3), hwndList, DlgProcDestEdit) == IDOK) { + + *i = add_edit_addr; + CallService(PROTO "/SetAndSavePingList", (WPARAM)&pl, 0); + return 0; + } + } + } + return 1; +} + +int ContactDblClick(WPARAM wParam, LPARAM lParam) { + PINGLIST pl; + CallService(PROTO "/GetPingList", 0, (LPARAM)&pl); + for(PINGLIST::iterator i = pl.begin(); i != pl.end(); i++) { + if(i->hContact == (HANDLE)wParam) { + if(strlen(i->pszCommand)) { + ShellExecute(0, "open", i->pszCommand, i->pszParams, 0, SW_SHOW); + } else { + CallService(PROTO "/ToggleEnabled", wParam, 0); + } + } + } + return 0; +} + + +void import_ping_address(int index, PINGADDRESS &pa) { + std::ostringstream os1, os2, os3, os4, os5, os6, os7; + os1 << "Address" << index; + os2 << "Label" << index; + os3 << "Enabled" << index; + os4 << "Port" << index; + os5 << "Proto" << index; + os6 << "Status" << index; + os7 << "Status2" << index; + + DBVARIANT dbv; + DBGetContactSetting(0, "PingPlug", os1.str().c_str(), &dbv); + strncpy(pa.pszName, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH); + DBFreeVariant(&dbv); + DBGetContactSetting(0, "PingPlug", os2.str().c_str(), &dbv); + strncpy(pa.pszLabel, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH); + DBFreeVariant(&dbv); + + pa.port = (int)DBGetContactSettingDword(0, "PingPlug", os4.str().c_str(), -1); + + DBGetContactSetting(0, "PingPlug", os5.str().c_str(), &dbv); + strncpy(pa.pszProto, dbv.pszVal, MAX_PINGADDRESS_STRING_LENGTH); + DBFreeVariant(&dbv); + + pa.set_status = DBGetContactSettingWord(0, "PingPlug", os6.str().c_str(), ID_STATUS_ONLINE); + pa.get_status = DBGetContactSettingWord(0, "PingPlug", os7.str().c_str(), ID_STATUS_OFFLINE); + + pa.responding = false; + pa.round_trip_time = 0; + pa.miss_count = 0; + pa.index = index; + pa.pszCommand[0] = '\0'; + + pa.hContact = 0; + pa.status = options.nrstatus; +} + +// read in addresses from old pingplug +void import_ping_addresses() { + int count = DBGetContactSettingDword(0, "PingPlug", "NumEntries", 0); + PINGADDRESS pa; + + EnterCriticalSection(&list_cs); + list_items.clear(); + for(int index = 0; index < count; index++) { + import_ping_address(index, pa); + list_items.push_back(pa); + } + std::sort(list_items.begin(), list_items.end(), SAscendingSort()); + write_ping_addresses(); + LeaveCriticalSection(&list_cs); +} diff --git a/ping_protocol/utils.h b/ping_protocol/utils.h new file mode 100644 index 0000000..cddcb82 --- /dev/null +++ b/ping_protocol/utils.h @@ -0,0 +1,38 @@ +#ifndef _PING_UTILS +#define _PING_UTILS + +//#include +#include + +#include "common.h" +#include "pingthread.h" // for mainthread, for popup +//#include "icmp.h" +#include "rawping.h" +#include "options.h" +#include "icmp.h" + +/* +std::string trim_string(const std::string &in); +void capitalize(std::string &in); +*/ +void __stdcall ShowPopup( const char* line1, const char* line2, int flags ); + +int PluginPing(WPARAM wParam,LPARAM lParam); + +void Lock(CRITICAL_SECTION *cs, char *lab); +void Unlock(CRITICAL_SECTION *cs); + +int PingDisableAll(WPARAM wParam, LPARAM lParam); +int PingEnableAll(WPARAM wParam, LPARAM lParam); + +int ToggleEnabled(WPARAM wParam, LPARAM lParam); + +int ContactDblClick(WPARAM wParam, LPARAM lParam); + +int EditContact(WPARAM wParam, LPARAM lParam); +// read in addresses from old pingplug +void import_ping_addresses(); + +extern bool use_raw_ping; + +#endif -- cgit v1.2.3