diff options
Diffstat (limited to 'protocols/ConnectionNotify/src')
-rw-r--r-- | protocols/ConnectionNotify/src/ConnectionNotify.cpp | 880 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/debug.cpp | 13 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/debug.h | 9 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/filter.cpp | 141 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/filter.h | 9 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/netstat.cpp | 148 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/netstat.h | 18 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/pid2name.cpp | 21 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/pid2name.h | 8 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/resource.h | 34 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/stdafx.cxx | 18 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/stdafx.h | 51 | ||||
-rw-r--r-- | protocols/ConnectionNotify/src/version.h | 38 |
13 files changed, 1388 insertions, 0 deletions
diff --git a/protocols/ConnectionNotify/src/ConnectionNotify.cpp b/protocols/ConnectionNotify/src/ConnectionNotify.cpp new file mode 100644 index 0000000000..01f00983ca --- /dev/null +++ b/protocols/ConnectionNotify/src/ConnectionNotify.cpp @@ -0,0 +1,880 @@ +#include "stdafx.h" + +CMPlugin g_plugin; + +static HWND hTimerWnd = (HWND)nullptr; +static UINT TID = (UINT)12021; +HANDLE hCheckEvent = nullptr; +HANDLE hCheckHook = nullptr; +HANDLE hConnectionCheckThread = nullptr; +HANDLE hFilterOptionsThread = nullptr; +HANDLE killCheckThreadEvent = nullptr; +HANDLE hExceptionsMutex = nullptr; + +DWORD FilterOptionsThreadId; +DWORD ConnectionCheckThreadId; +BYTE settingSetColours = 0; +COLORREF settingBgColor; +COLORREF settingFgColor; +int settingInterval = 0; +int settingInterval1 = 0; +BYTE settingResolveIp = 0; +BOOL settingStatus[STATUS_COUNT]; +int settingFiltersCount = 0; +BOOL settingDefaultAction = TRUE; +WORD settingStatusMask = 0; + +struct CONNECTION *first = nullptr; +struct CONNECTION *connExceptions = nullptr; +struct CONNECTION *connCurrentEdit; +struct CONNECTION *connExceptionsTmp = nullptr; +struct CONNECTION *connCurrentEditModal = nullptr; +int currentStatus = ID_STATUS_OFFLINE, diffstat = 0; +BOOL bOptionsOpen = FALSE; +wchar_t *tcpStates[] = { L"CLOSED", L"LISTEN", L"SYN_SENT", L"SYN_RCVD", L"ESTAB", L"FIN_WAIT1", L"FIN_WAIT2", L"CLOSE_WAIT", L"CLOSING", L"LAST_ACK", L"TIME_WAIT", L"DELETE_TCB" }; + +///////////////////////////////////////////////////////////////////////////////////////// + +PLUGININFOEX pluginInfoEx = { + sizeof(PLUGININFOEX), + PLUGINNAME, + __VERSION_DWORD, + __DESCRIPTION, + __AUTHOR, + __COPYRIGHT, + __AUTHORWEB, + UNICODE_AWARE, //not transient + // 4BB5B4AA-C364-4F23-9746-D5B708A286A5 + { 0x4bb5b4aa, 0xc364, 0x4f23, { 0x97, 0x46, 0xd5, 0xb7, 0x8, 0xa2, 0x86, 0xa5 } } +}; + +CMPlugin::CMPlugin() : + PLUGIN<CMPlugin>(PLUGINNAME, pluginInfoEx) +{ + RegisterProtocol(PROTOTYPE_PROTOCOL); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_PROTOCOL, MIID_LAST }; + +///////////////////////////////////////////////////////////////////////////////////////// +// authentication callback futnction from extension manager + +BOOL strrep(wchar_t *src, wchar_t *needle, wchar_t *newstring) +{ + wchar_t *found, begining[MAX_SETTING_STR], tail[MAX_SETTING_STR]; + size_t pos = 0; + + //strset(begining, ' '); + //strset(tail, ' '); + if (!(found = wcsstr(src, needle))) + return FALSE; + + pos = (found - src); + wcsncpy_s(begining, src, pos); + begining[pos] = 0; + + pos = pos + mir_wstrlen(needle); + wcsncpy_s(tail, src + pos, _TRUNCATE); + begining[pos] = 0; + + pos = mir_snwprintf(src, mir_wstrlen(src), L"%s%s%s", begining, newstring, tail); + return TRUE; +} + +void saveSettingsConnections(struct CONNECTION *connHead) +{ + char buff[128]; + int i = 0; + struct CONNECTION *tmp = connHead; + while (tmp != nullptr) { + + mir_snprintf(buff, "%dFilterIntIp", i); + g_plugin.setWString(buff, tmp->strIntIp); + mir_snprintf(buff, "%dFilterExtIp", i); + g_plugin.setWString(buff, tmp->strExtIp); + mir_snprintf(buff, "%dFilterPName", i); + g_plugin.setWString(buff, tmp->PName); + mir_snprintf(buff, "%dFilterIntPort", i); + g_plugin.setDword(buff, tmp->intIntPort); + mir_snprintf(buff, "%dFilterExtPort", i); + g_plugin.setDword(buff, tmp->intExtPort); + mir_snprintf(buff, "%dFilterAction", i); + g_plugin.setDword(buff, tmp->Pid); + i++; + tmp = tmp->next; + } + settingFiltersCount = i; + g_plugin.setDword("FiltersCount", settingFiltersCount); + +} + +//load filters from db +struct CONNECTION* LoadSettingsConnections() +{ + struct CONNECTION *connHead = nullptr; + DBVARIANT dbv; + char buff[128]; + int i = 0; + for (i = settingFiltersCount - 1; i >= 0; i--) { + struct CONNECTION *conn = (struct CONNECTION*)mir_alloc(sizeof(struct CONNECTION)); + mir_snprintf(buff, "%dFilterIntIp", i); + if (!g_plugin.getWString(buff, &dbv)) + wcsncpy(conn->strIntIp, dbv.pwszVal, _countof(conn->strIntIp)); + db_free(&dbv); + mir_snprintf(buff, "%dFilterExtIp", i); + if (!g_plugin.getWString(buff, &dbv)) + wcsncpy(conn->strExtIp, dbv.pwszVal, _countof(conn->strExtIp)); + db_free(&dbv); + mir_snprintf(buff, "%dFilterPName", i); + if (!g_plugin.getWString(buff, &dbv)) + wcsncpy(conn->PName, dbv.pwszVal, _countof(conn->PName)); + db_free(&dbv); + + mir_snprintf(buff, "%dFilterIntPort", i); + conn->intIntPort = g_plugin.getDword(buff, -1); + + mir_snprintf(buff, "%dFilterExtPort", i); + conn->intExtPort = g_plugin.getDword(buff, -1); + + mir_snprintf(buff, "%dFilterAction", i); + conn->Pid = g_plugin.getDword(buff, 0); + + conn->next = connHead; + connHead = conn; + } + return connHead; +} +//called to load settings from database +void LoadSettings() +{ + settingInterval = g_plugin.getDword("Interval", 500); + settingInterval1 = g_plugin.getDword("PopupInterval", 0); + settingResolveIp = g_plugin.getByte("ResolveIp", TRUE); + settingDefaultAction = g_plugin.getByte("FilterDefaultAction", TRUE); + + settingSetColours = g_plugin.getByte("PopupSetColours", 0); + settingBgColor = g_plugin.getDword("PopupBgColor", (DWORD)0xFFFFFF); + settingFgColor = g_plugin.getDword("PopupFgColor", (DWORD)0x000000); + settingFiltersCount = g_plugin.getDword("FiltersCount", 0); + settingStatusMask = g_plugin.getWord("StatusMask", 16); + for (int i = 0; i < STATUS_COUNT; i++) { + char buff[128]; + mir_snprintf(buff, "Status%d", i); + settingStatus[i] = (g_plugin.getByte(buff, 0) == 1); + } +} + +void fillExceptionsListView(HWND hwndDlg) +{ + LVITEM lvI = { 0 }; + + int i = 0; + struct CONNECTION *tmp = connExceptionsTmp; + HWND hwndList = GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS); + ListView_DeleteAllItems(hwndList); + + // Some code to create the list-view control. + // Initialize LVITEM members that are common to all + // items. + lvI.mask = LVIF_TEXT; + while (tmp) { + wchar_t tmpAddress[25]; + lvI.iItem = i++; + lvI.iSubItem = 0; + lvI.pszText = tmp->PName; + ListView_InsertItem(hwndList, &lvI); + lvI.iSubItem = 1; + if (tmp->intIntPort == -1) + mir_snwprintf(tmpAddress, L"%s:*", tmp->strIntIp); + else + mir_snwprintf(tmpAddress, L"%s:%d", tmp->strIntIp, tmp->intIntPort); + lvI.pszText = tmpAddress; + ListView_SetItem(hwndList, &lvI); + lvI.iSubItem = 2; + if (tmp->intExtPort == -1) + mir_snwprintf(tmpAddress, L"%s:*", tmp->strExtIp); + else + mir_snwprintf(tmpAddress, L"%s:%d", tmp->strExtIp, tmp->intExtPort); + lvI.pszText = tmpAddress; + ListView_SetItem(hwndList, &lvI); + lvI.iSubItem = 3; + lvI.pszText = tmp->Pid ? LPGENW("Show") : LPGENW("Hide"); + ListView_SetItem(hwndList, &lvI); + + tmp = tmp->next; + } + +} +//filter editor dialog box procedure opened modally from options dialog +static INT_PTR CALLBACK FilterEditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_INITDIALOG: + { + struct CONNECTION *conn = (struct CONNECTION*)lParam; + TranslateDialogDefault(hWnd); + connCurrentEditModal = conn; + SetDlgItemText(hWnd, ID_TEXT_NAME, conn->PName); + SetDlgItemText(hWnd, ID_TXT_LOCAL_IP, conn->strIntIp); + SetDlgItemText(hWnd, ID_TXT_REMOTE_IP, conn->strExtIp); + + if (conn->intIntPort == -1) + SetDlgItemText(hWnd, ID_TXT_LOCAL_PORT, L"*"); + else + SetDlgItemInt(hWnd, ID_TXT_LOCAL_PORT, conn->intIntPort, FALSE); + + if (conn->intExtPort == -1) + SetDlgItemText(hWnd, ID_TXT_REMOTE_PORT, L"*"); + else + SetDlgItemInt(hWnd, ID_TXT_REMOTE_PORT, conn->intExtPort, FALSE); + + SendDlgItemMessage(hWnd, ID_CBO_ACTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("Always show popup")); + SendDlgItemMessage(hWnd, ID_CBO_ACTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("Never show popup")); + SendDlgItemMessage(hWnd, ID_CBO_ACTION, CB_SETCURSEL, conn->Pid == 0 ? 1 : 0, 0); + return TRUE; + } + case WM_COMMAND: + switch (LOWORD(wParam)) { + case ID_OK: + { + wchar_t tmpPort[6]; + GetDlgItemText(hWnd, ID_TXT_LOCAL_PORT, tmpPort, _countof(tmpPort)); + if (tmpPort[0] == '*') + connCurrentEditModal->intIntPort = -1; + else + connCurrentEditModal->intIntPort = GetDlgItemInt(hWnd, ID_TXT_LOCAL_PORT, nullptr, FALSE); + GetDlgItemText(hWnd, ID_TXT_REMOTE_PORT, tmpPort, _countof(tmpPort)); + if (tmpPort[0] == '*') + connCurrentEditModal->intExtPort = -1; + else + connCurrentEditModal->intExtPort = GetDlgItemInt(hWnd, ID_TXT_REMOTE_PORT, nullptr, FALSE); + + GetDlgItemText(hWnd, ID_TXT_LOCAL_IP, connCurrentEditModal->strIntIp, _countof(connCurrentEditModal->strIntIp)); + GetDlgItemText(hWnd, ID_TXT_REMOTE_IP, connCurrentEditModal->strExtIp, _countof(connCurrentEditModal->strExtIp)); + GetDlgItemText(hWnd, ID_TEXT_NAME, connCurrentEditModal->PName, _countof(connCurrentEditModal->PName)); + + connCurrentEditModal->Pid = !(BOOL)SendDlgItemMessage(hWnd, ID_CBO_ACTION, CB_GETCURSEL, 0, 0); + + connCurrentEditModal = nullptr; + EndDialog(hWnd, IDOK); + return TRUE; + } + case ID_CANCEL: + connCurrentEditModal = nullptr; + EndDialog(hWnd, IDCANCEL); + return TRUE; + } + return FALSE; + break; + case WM_CLOSE: + { + connCurrentEditModal = nullptr; + EndDialog(hWnd, IDCANCEL); + break; + } + } + return FALSE; +} + +//options page on miranda called +INT_PTR CALLBACK DlgProcConnectionNotifyOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HWND hwndList; + switch (msg) { + case WM_INITDIALOG://initialize dialog, so set properties from db. + { + LVCOLUMN lvc = { 0 }; + LVITEM lvI = { 0 }; + wchar_t buff[256]; + bOptionsOpen = TRUE; + TranslateDialogDefault(hwndDlg);//translate miranda function + #ifdef _WIN64 + mir_snwprintf(buff, L"%d.%d.%d.%d/64", HIBYTE(HIWORD(pluginInfoEx.version)), LOBYTE(HIWORD(pluginInfoEx.version)), HIBYTE(LOWORD(pluginInfoEx.version)), LOBYTE(LOWORD(pluginInfoEx.version))); + #else + mir_snwprintf(buff, L"%d.%d.%d.%d/32", HIBYTE(HIWORD(pluginInfoEx.version)), LOBYTE(HIWORD(pluginInfoEx.version)), HIBYTE(LOWORD(pluginInfoEx.version)), LOBYTE(LOWORD(pluginInfoEx.version))); + #endif + SetDlgItemText(hwndDlg, IDC_VERSION, buff); + LoadSettings(); + //connExceptionsTmp=LoadSettingsConnections(); + SetDlgItemInt(hwndDlg, IDC_INTERVAL, settingInterval, FALSE); + SetDlgItemInt(hwndDlg, IDC_INTERVAL1, settingInterval1, TRUE); + CheckDlgButton(hwndDlg, IDC_SETCOLOURS, settingSetColours ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_RESOLVEIP, settingResolveIp ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, ID_CHK_DEFAULTACTION, settingDefaultAction ? BST_CHECKED : BST_UNCHECKED); + + SendDlgItemMessage(hwndDlg, IDC_BGCOLOR, CPM_SETCOLOUR, 0, (LPARAM)settingBgColor); + SendDlgItemMessage(hwndDlg, IDC_FGCOLOR, CPM_SETCOLOUR, 0, (LPARAM)settingFgColor); + if (!settingSetColours) { + HWND hwnd = GetDlgItem(hwndDlg, IDC_BGCOLOR); + CheckDlgButton(hwndDlg, IDC_SETCOLOURS, BST_UNCHECKED); + EnableWindow(hwnd, FALSE); + hwnd = GetDlgItem(hwndDlg, IDC_FGCOLOR); + EnableWindow(hwnd, FALSE); + } + SendDlgItemMessage(hwndDlg, ID_ADD, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(g_plugin.getInst(), MAKEINTRESOURCE(IDI_ICON6), IMAGE_ICON, 16, 16, 0)); + SendDlgItemMessage(hwndDlg, ID_DELETE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(g_plugin.getInst(), MAKEINTRESOURCE(IDI_ICON3), IMAGE_ICON, 16, 16, 0)); + SendDlgItemMessage(hwndDlg, ID_DOWN, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(g_plugin.getInst(), MAKEINTRESOURCE(IDI_ICON4), IMAGE_ICON, 16, 16, 0)); + SendDlgItemMessage(hwndDlg, ID_UP, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadImage(g_plugin.getInst(), MAKEINTRESOURCE(IDI_ICON5), IMAGE_ICON, 16, 16, 0)); + // initialise and fill listbox + hwndList = GetDlgItem(hwndDlg, IDC_STATUS); + ListView_DeleteAllItems(hwndList); + SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES); + // Initialize the LVCOLUMN structure. + // The mask specifies that the format, width, text, and + // subitem members of the structure are valid. + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + lvc.iSubItem = 0; + lvc.pszText = TranslateT("Status"); + lvc.cx = 120; // width of column in pixels + ListView_InsertColumn(hwndList, 0, &lvc); + // Some code to create the list-view control. + // Initialize LVITEM members that are common to all + // items. + lvI.mask = LVIF_TEXT; + for (int i = 0; i < STATUS_COUNT; i++) { + lvI.pszText = Clist_GetStatusModeDescription(ID_STATUS_ONLINE + i, 0); + lvI.iItem = i; + ListView_InsertItem(hwndList, &lvI); + ListView_SetCheckState(hwndList, i, settingStatus[i]); + } + + connExceptionsTmp = LoadSettingsConnections(); + hwndList = GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS); + SendMessage(hwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT); + + lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; + lvc.fmt = LVCFMT_LEFT; + lvc.iSubItem = 0; + lvc.cx = 120; // width of column in pixels + lvc.pszText = TranslateT("Application"); + ListView_InsertColumn(hwndList, 1, &lvc); + lvc.pszText = TranslateT("Internal socket"); + ListView_InsertColumn(hwndList, 2, &lvc); + lvc.pszText = TranslateT("External socket"); + ListView_InsertColumn(hwndList, 3, &lvc); + lvc.pszText = TranslateT("Action"); + lvc.cx = 50; + ListView_InsertColumn(hwndList, 4, &lvc); + + //fill exceptions list + fillExceptionsListView(hwndDlg); + } + break; + + case WM_COMMAND://user changed something, so get changes to variables + PostMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + switch (LOWORD(wParam)) { + case IDC_INTERVAL: settingInterval = GetDlgItemInt(hwndDlg, IDC_INTERVAL, nullptr, FALSE); break; + case IDC_INTERVAL1: settingInterval1 = GetDlgItemInt(hwndDlg, IDC_INTERVAL1, nullptr, TRUE); break; + case IDC_RESOLVEIP: settingResolveIp = (BYTE)IsDlgButtonChecked(hwndDlg, IDC_RESOLVEIP); break; + case ID_CHK_DEFAULTACTION: settingDefaultAction = (BYTE)IsDlgButtonChecked(hwndDlg, ID_CHK_DEFAULTACTION); break; + case ID_ADD: + { + struct CONNECTION *cur = (struct CONNECTION *)mir_alloc(sizeof(struct CONNECTION)); + memset(cur, 0, sizeof(struct CONNECTION)); + cur->intExtPort = -1; + cur->intIntPort = -1; + cur->Pid = 0; + cur->PName[0] = '*'; + cur->strExtIp[0] = '*'; + cur->strIntIp[0] = '*'; + + if (DialogBoxParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILTER_DIALOG), hwndDlg, FilterEditProc, (LPARAM)cur) == IDCANCEL) { + mir_free(cur); + cur = nullptr; + } + else { + cur->next = connExceptionsTmp; + connExceptionsTmp = cur; + } + + fillExceptionsListView(hwndDlg); + ListView_SetItemState(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS), 0, LVNI_FOCUSED | LVIS_SELECTED, LVNI_FOCUSED | LVIS_SELECTED); + SetFocus(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS)); + } + break; + + case ID_DELETE: + { + int pos, pos1; + struct CONNECTION *cur = connExceptionsTmp, *pre = nullptr; + + pos = (int)ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS), -1, LVNI_FOCUSED); + if (pos == -1)break; + pos1 = pos; + while (pos--) { + pre = cur; + cur = cur->next; + } + if (pre == nullptr) + connExceptionsTmp = connExceptionsTmp->next; + else + (pre)->next = cur->next; + mir_free(cur); + fillExceptionsListView(hwndDlg); + ListView_SetItemState(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS), pos1, LVNI_FOCUSED | LVIS_SELECTED, LVNI_FOCUSED | LVIS_SELECTED); + SetFocus(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS)); + break; + } + case ID_UP: + { + int pos, pos1; + struct CONNECTION *cur = nullptr, *pre = nullptr, *prepre = nullptr; + + cur = connExceptionsTmp; + + pos = (int)ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS), -1, LVNI_FOCUSED); + if (pos == -1)break; + pos1 = pos; + while (pos--) { + prepre = pre; + pre = cur; + cur = cur->next; + } + if (prepre != nullptr) { + pre->next = cur->next; + cur->next = pre; + prepre->next = cur; + } + else if (pre != nullptr) { + pre->next = cur->next; + cur->next = pre; + connExceptionsTmp = cur; + } + fillExceptionsListView(hwndDlg); + ListView_SetItemState(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS), pos1 - 1, LVNI_FOCUSED | LVIS_SELECTED, LVNI_FOCUSED | LVIS_SELECTED); + SetFocus(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS)); + break; + } + case ID_DOWN: + { + int pos, pos1; + struct CONNECTION *cur = nullptr, *pre = nullptr; + + cur = connExceptionsTmp; + + pos = (int)ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS), -1, LVNI_FOCUSED); + if (pos == -1)break; + pos1 = pos; + while (pos--) { + pre = cur; + cur = cur->next; + } + if (cur == connExceptionsTmp&&cur->next != nullptr) { + connExceptionsTmp = cur->next; + cur->next = cur->next->next; + connExceptionsTmp->next = cur; + } + else if (cur->next != nullptr) { + struct CONNECTION *tmp = cur->next->next; + pre->next = cur->next; + cur->next->next = cur; + cur->next = tmp; + } + fillExceptionsListView(hwndDlg); + ListView_SetItemState(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS), pos1 + 1, LVNI_FOCUSED | LVIS_SELECTED, LVNI_FOCUSED | LVIS_SELECTED); + SetFocus(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS)); + break; + } + case IDC_SETCOLOURS: + { + HWND hwnd = GetDlgItem(hwndDlg, IDC_BGCOLOR); + settingSetColours = IsDlgButtonChecked(hwndDlg, IDC_SETCOLOURS); + EnableWindow(hwnd, settingSetColours); + hwnd = GetDlgItem(hwndDlg, IDC_FGCOLOR); + EnableWindow(hwnd, settingSetColours); + break; + } + case IDC_BGCOLOR: settingBgColor = (COLORREF)SendDlgItemMessage(hwndDlg, IDC_BGCOLOR, CPM_GETCOLOUR, 0, 0); break; + case IDC_FGCOLOR: settingFgColor = (COLORREF)SendDlgItemMessage(hwndDlg, IDC_FGCOLOR, CPM_GETCOLOUR, 0, 0); break; + + } + break; + + case WM_NOTIFY://apply changes so write it to db + switch (((LPNMHDR)lParam)->idFrom) { + case 0: + switch (((LPNMHDR)lParam)->code) { + case PSN_RESET: + LoadSettings(); + deleteConnectionsTable(connExceptionsTmp); + connExceptionsTmp = LoadSettingsConnections(); + return TRUE; + + case PSN_APPLY: + g_plugin.setDword("Interval", settingInterval); + g_plugin.setDword("PopupInterval", settingInterval1); + g_plugin.setByte("PopupSetColours", settingSetColours); + g_plugin.setDword("PopupBgColor", settingBgColor); + g_plugin.setDword("PopupFgColor", settingFgColor); + g_plugin.setByte("ResolveIp", settingResolveIp); + g_plugin.setByte("FilterDefaultAction", settingDefaultAction); + + for (int i = 0; i < STATUS_COUNT; i++) { + char buff[128]; + mir_snprintf(buff, "Status%d", i); + settingStatus[i] = (ListView_GetCheckState(GetDlgItem(hwndDlg, IDC_STATUS), i) ? TRUE : FALSE); + g_plugin.setByte(buff, settingStatus[i] ? 1 : 0); + } + if (WAIT_OBJECT_0 == WaitForSingleObject(hExceptionsMutex, 100)) { + deleteConnectionsTable(connExceptions); + saveSettingsConnections(connExceptionsTmp); + connExceptions = connExceptionsTmp; + connExceptionsTmp = LoadSettingsConnections(); + ReleaseMutex(hExceptionsMutex); + } + return TRUE; + } + break; + } + + if (GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS) == ((LPNMHDR)lParam)->hwndFrom) { + switch (((LPNMHDR)lParam)->code) { + case NM_DBLCLK: + { + int pos, pos1; + struct CONNECTION *cur = nullptr; + + cur = connExceptionsTmp; + + pos = (int)ListView_GetNextItem(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS), -1, LVNI_FOCUSED); + if (pos == -1)break; + pos1 = pos; + while (pos--) { + cur = cur->next; + } + DialogBoxParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILTER_DIALOG), hwndDlg, FilterEditProc, (LPARAM)cur); + fillExceptionsListView(hwndDlg); + ListView_SetItemState(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS), pos1, LVNI_FOCUSED | LVIS_SELECTED, LVNI_FOCUSED | LVIS_SELECTED); + SetFocus(GetDlgItem(hwndDlg, IDC_LIST_EXCEPTIONS)); + break; + } + } + } + + if (GetDlgItem(hwndDlg, IDC_STATUS) == ((LPNMHDR)lParam)->hwndFrom) { + switch (((LPNMHDR)lParam)->code) { + case LVN_ITEMCHANGED: + NMLISTVIEW *nmlv = (NMLISTVIEW *)lParam; + if ((nmlv->uNewState ^ nmlv->uOldState) & LVIS_STATEIMAGEMASK) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + } + break; + + case WM_DESTROY: + bOptionsOpen = FALSE; + deleteConnectionsTable(connExceptionsTmp); + connExceptionsTmp = nullptr; + return TRUE; + } + return 0; +} + +//options page on miranda called +int ConnectionNotifyOptInit(WPARAM wParam, LPARAM) +{ + OPTIONSDIALOGPAGE odp = {}; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_DIALOG); + odp.szTitle.w = _A2W(PLUGINNAME); + odp.szGroup.w = LPGENW("Plugins"); + odp.flags = ODPF_BOLDGROUPS | ODPF_UNICODE; + odp.pfnDlgProc = DlgProcConnectionNotifyOpts;//callback function name + g_plugin.addOptions(wParam, &odp); + return 0; +} + +//gives protocol avainable statuses +INT_PTR GetCaps(WPARAM wParam, LPARAM) +{ + if (wParam == PFLAGNUM_1) + return 0; + if (wParam == PFLAGNUM_2) + return PF2_ONLINE; // add the possible statuses here. + if (wParam == PFLAGNUM_3) + return 0; + return 0; +} + +//gives name to protocol module +INT_PTR GetName(WPARAM wParam, LPARAM lParam) +{ + mir_strncpy((char*)lParam, PLUGINNAME, wParam); + return 0; +} + +//gives icon for proto module +INT_PTR TMLoadIcon(WPARAM wParam, LPARAM) +{ + UINT id; + + switch (wParam & 0xFFFF) { + case PLI_PROTOCOL: + id = IDI_ICON1; + break; // IDI_TM is the main icon for the protocol + default: + return 0; + } + return (INT_PTR)LoadImage(g_plugin.getInst(), MAKEINTRESOURCE(id), IMAGE_ICON, GetSystemMetrics(wParam&PLIF_SMALL ? SM_CXSMICON : SM_CXICON), GetSystemMetrics(wParam&PLIF_SMALL ? SM_CYSMICON : SM_CYICON), 0); +} +//======================================================= +//SetStatus +//======================================================= +INT_PTR SetStatus(WPARAM wParam, LPARAM lParam) +{ + if (wParam == ID_STATUS_OFFLINE) { + diffstat = 0; + //PostThreadMessage(ConnectionCheckThreadId,WM_QUIT ,0, 0); + SetEvent(killCheckThreadEvent); + + } + else if (wParam == ID_STATUS_ONLINE) { + diffstat = 0; + ResetEvent(killCheckThreadEvent); + if (!hConnectionCheckThread) + hConnectionCheckThread = (HANDLE)mir_forkthreadex(checkthread, nullptr, (unsigned int*)&ConnectionCheckThreadId); + } + else { + int retv = 0; + + if (settingStatus[wParam - ID_STATUS_ONLINE]) + retv = SetStatus(ID_STATUS_OFFLINE, lParam); + else + retv = SetStatus(ID_STATUS_ONLINE, lParam); + //LNEnableMenuItem(hMenuHandle ,TRUE); + diffstat = wParam; + return retv; + + // the status has been changed to unknown (maybe run some more code) + } + //broadcast the message + + //oldStatus = currentStatus; + if (currentStatus != (int)wParam) + ProtoBroadcastAck(PLUGINNAME, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)currentStatus, wParam); + currentStatus = wParam; + return 0; + +} +//======================================================= +//GetStatus +//======================================================= +INT_PTR GetStatus(WPARAM, LPARAM) +{ + return currentStatus; +} + +//thread function with connections check loop +static unsigned __stdcall checkthread(void *) +{ + + #ifdef _DEBUG + _OutputDebugString(L"check thread started"); + #endif + while (1) { + struct CONNECTION* conn = nullptr, *connOld = first, *cur = nullptr; + #ifdef _DEBUG + _OutputDebugString(L"checking connections table..."); + #endif + if (WAIT_OBJECT_0 == WaitForSingleObject(killCheckThreadEvent, 100)) { + hConnectionCheckThread = nullptr; + return 0; + } + + conn = GetConnectionsTable(); + cur = conn; + while (cur != nullptr) { + if (searchConnection(first, cur->strIntIp, cur->strExtIp, cur->intIntPort, cur->intExtPort, cur->state) == nullptr && (settingStatusMask & (1 << (cur->state - 1)))) { + + #ifdef _DEBUG + wchar_t msg[1024]; + mir_snwprintf(msg, L"%s:%d\n%s:%d", cur->strIntIp, cur->intIntPort, cur->strExtIp, cur->intExtPort); + _OutputDebugString(L"New connection: %s", msg); + #endif + pid2name(cur->Pid, cur->PName, _countof(cur->PName)); + if (WAIT_OBJECT_0 == WaitForSingleObject(hExceptionsMutex, 100)) { + if (checkFilter(connExceptions, cur)) { + showMsg(cur->PName, cur->Pid, cur->strIntIp, cur->strExtIp, cur->intIntPort, cur->intExtPort, cur->state); + Skin_PlaySound(PLUGINNAME_NEWSOUND); + } + ReleaseMutex(hExceptionsMutex); + } + } + cur = cur->next; + } + + first = conn; + deleteConnectionsTable(connOld); + Sleep(settingInterval); + } + hConnectionCheckThread = nullptr; + return 1; +} + +//popup reactions +static LRESULT CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) { + case WM_COMMAND: + if (HIWORD(wParam) == STN_CLICKED)//client clicked on popup with left mouse button + { + struct CONNECTION *conn = (struct CONNECTION*)mir_alloc(sizeof(struct CONNECTION)); + struct CONNECTION *mpd = (struct CONNECTION*) PUGetPluginData(hWnd); + + memcpy(conn, mpd, sizeof(struct CONNECTION)); + PUDeletePopup(hWnd); + PostThreadMessage(FilterOptionsThreadId, WM_ADD_FILTER, 0, (LPARAM)conn); + } + break; + + case WM_RBUTTONUP: + PUDeletePopup(hWnd); + break; + + case UM_INITPOPUP: + //struct CONNECTON *conn=NULL; + //conn = (struct CONNECTION*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)conn); + //MessageBox(NULL,conn->extIp); + //PUDeletePopUp(hWnd); + break; + + case UM_FREEPLUGINDATA: + struct CONNECTION *mpd = (struct CONNECTION*)PUGetPluginData(hWnd); + if (mpd > 0) mir_free(mpd); + return TRUE; //TRUE or FALSE is the same, it gets ignored. + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + + +//show popup +void showMsg(wchar_t *pName, DWORD pid, wchar_t *intIp, wchar_t *extIp, int intPort, int extPort, int state) +{ + + POPUPDATAW ppd; + //hContact = A_VALID_HANDLE_YOU_GOT_FROM_SOMEWHERE; + //hIcon = A_VALID_HANDLE_YOU_GOT_SOMEWHERE; + //char * lpzContactName = (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)lhContact,0); + //99% of the times you'll just copy this line. + //1% of the times you may wish to change the contact's name. I don't know why you should, but you can. + //char * lpzText; + //The text for the second line. You could even make something like: char lpzText[128]; mir_wstrcpy(lpzText, "Hello world!"); It's your choice. + + struct CONNECTION *mpd = (struct CONNECTION*)mir_alloc(sizeof(struct CONNECTION)); + //MessageBox(NULL,"aaa","aaa",1); + memset(&ppd, 0, sizeof(ppd)); //This is always a good thing to do. + ppd.lchContact = NULL;//(HANDLE)hContact; //Be sure to use a GOOD handle, since this will not be checked. + ppd.lchIcon = LoadIcon(g_plugin.getInst(), MAKEINTRESOURCE(IDI_ICON1)); + if (settingResolveIp) { + wchar_t hostName[128]; + getDnsName(extIp, hostName, _countof(hostName)); + mir_snwprintf(ppd.lpwzText, L"%s:%d\n%s:%d", hostName, extPort, intIp, intPort); + } + else mir_snwprintf(ppd.lpwzText, L"%s:%d\n%s:%d", extIp, extPort, intIp, intPort); + + mir_snwprintf(ppd.lpwzContactName, L"%s (%s)", pName, tcpStates[state - 1]); + + if (settingSetColours) { + ppd.colorBack = settingBgColor; + ppd.colorText = settingFgColor; + } + ppd.PluginWindowProc = PopupDlgProc; + + ppd.iSeconds = settingInterval1; + //Now the "additional" data. + wcsncpy_s(mpd->strIntIp, intIp, _TRUNCATE); + wcsncpy_s(mpd->strExtIp, extIp, _TRUNCATE); + wcsncpy_s(mpd->PName, pName, _TRUNCATE); + mpd->intIntPort = intPort; + mpd->intExtPort = extPort; + mpd->Pid = pid; + + //Now that the plugin data has been filled, we add it to the PopUpData. + ppd.PluginData = mpd; + + //Now that every field has been filled, we want to see the popup. + PUAddPopupW(&ppd); +} + +//called after all plugins loaded. +//all Connection staff will be called, that will not hang miranda on startup +static int modulesloaded(WPARAM, LPARAM) +{ + + #ifdef _DEBUG + _OutputDebugString(L"Modules loaded, lets start TN..."); + #endif + // hConnectionCheckThread = (HANDLE)mir_forkthreadex(checkthread, 0, 0, ConnectionCheckThreadId); + + //#ifdef _DEBUG + // _OutputDebugString("started check thread %d",hConnectionCheckThread); + //#endif + killCheckThreadEvent = CreateEvent(nullptr, FALSE, FALSE, L"killCheckThreadEvent"); + hFilterOptionsThread = startFilterThread(); + //updaterRegister(); + + return 0; +} +//function hooks before unload +static int preshutdown(WPARAM, LPARAM) +{ + deleteConnectionsTable(first); + deleteConnectionsTable(connExceptions); + deleteConnectionsTable(connExceptionsTmp); + + PostThreadMessage(ConnectionCheckThreadId, WM_QUIT, 0, 0); + PostThreadMessage(FilterOptionsThreadId, WM_QUIT, 0, 0); + + return 0; +} + +int CMPlugin::Load() +{ + #ifdef _DEBUG + _OutputDebugString(L"Entering Load dll"); + #endif + + hExceptionsMutex = CreateMutex(nullptr, FALSE, L"ExceptionsMutex"); + + LoadSettings(); + connExceptions = LoadSettingsConnections(); + + // set all contacts to offline + for (auto &hContact : Contacts(PLUGINNAME)) + g_plugin.setWord(hContact, "status", ID_STATUS_OFFLINE); + + CreateProtoServiceFunction(PLUGINNAME, PS_GETCAPS, GetCaps); + CreateProtoServiceFunction(PLUGINNAME, PS_GETNAME, GetName); + CreateProtoServiceFunction(PLUGINNAME, PS_LOADICON, TMLoadIcon); + CreateProtoServiceFunction(PLUGINNAME, PS_SETSTATUS, SetStatus); + CreateProtoServiceFunction(PLUGINNAME, PS_GETSTATUS, GetStatus); + + g_plugin.addSound(PLUGINNAME_NEWSOUND, _A2W(PLUGINNAME), LPGENW("New Connection Notification")); + + HookEvent(ME_OPT_INITIALISE, ConnectionNotifyOptInit); // register service to hook option call + HookEvent(ME_SYSTEM_MODULESLOADED, modulesloaded); // hook event that all plugins are loaded + HookEvent(ME_SYSTEM_PRESHUTDOWN, preshutdown); + return 0; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +int CMPlugin::Unload() +{ + WaitForSingleObjectEx(hConnectionCheckThread, INFINITE, FALSE); + + if (hConnectionCheckThread) CloseHandle(hConnectionCheckThread); + if (hCheckEvent) DestroyHookableEvent(hCheckEvent); + if (hCheckHook) UnhookEvent(hCheckHook); + if (killCheckThreadEvent) CloseHandle(killCheckThreadEvent); + if (hExceptionsMutex) CloseHandle(hExceptionsMutex); + + #ifdef _DEBUG + _OutputDebugString(L"Unloaded"); + #endif + return 0; +} diff --git a/protocols/ConnectionNotify/src/debug.cpp b/protocols/ConnectionNotify/src/debug.cpp new file mode 100644 index 0000000000..8abe549a22 --- /dev/null +++ b/protocols/ConnectionNotify/src/debug.cpp @@ -0,0 +1,13 @@ +#include "stdafx.h" + +void _OutputDebugString(wchar_t* lpOutputString, ...) +{ + CMStringW format; + va_list args; + va_start(args, lpOutputString); + format.FormatV(lpOutputString, args); + va_end(args); + + format.AppendChar('\n'); + OutputDebugString(format); +} diff --git a/protocols/ConnectionNotify/src/debug.h b/protocols/ConnectionNotify/src/debug.h new file mode 100644 index 0000000000..044e81fe9f --- /dev/null +++ b/protocols/ConnectionNotify/src/debug.h @@ -0,0 +1,9 @@ +#pragma once +#ifndef _INC_DEBUG +#define _INC_DEBUG + +#include <windows.h> +#include <stdio.h> + +void _OutputDebugString(wchar_t* lpOutputString, ...); +#endif
\ No newline at end of file diff --git a/protocols/ConnectionNotify/src/filter.cpp b/protocols/ConnectionNotify/src/filter.cpp new file mode 100644 index 0000000000..e5cc01e98e --- /dev/null +++ b/protocols/ConnectionNotify/src/filter.cpp @@ -0,0 +1,141 @@ +#include "stdafx.h" + +HWND filterAddDlg = nullptr; +extern struct CONNECTION *connExceptions; +extern HANDLE hFilterOptionsThread; +extern DWORD FilterOptionsThreadId; +extern struct CONNECTION *connCurrentEdit; +extern BOOL settingDefaultAction; +extern HANDLE hExceptionsMutex; +extern BOOL bOptionsOpen; +static unsigned __stdcall filterQueue(void *dummy); +static INT_PTR CALLBACK ConnectionFilterEditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + +HANDLE startFilterThread() +{ + return (HANDLE)mir_forkthreadex(filterQueue, nullptr, (unsigned int*)&FilterOptionsThreadId); +} + +static unsigned __stdcall filterQueue(void *) +{ + BOOL bRet; + MSG msg; + //while(1) + while ((bRet = GetMessage(&msg, nullptr, 0, 0)) != 0) + { + if (msg.message == WM_ADD_FILTER) + { + struct CONNECTION *conn = (struct CONNECTION *)msg.lParam; + filterAddDlg = CreateDialogParam(g_plugin.getInst(), MAKEINTRESOURCE(IDD_FILTER_DIALOG), nullptr, ConnectionFilterEditProc, (LPARAM)conn); + ShowWindow(filterAddDlg, SW_SHOW); + + } + if (nullptr == filterAddDlg || !IsDialogMessage(filterAddDlg, &msg)) { /* Wine fix. */ + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + hFilterOptionsThread = nullptr; + return TRUE; +} + +static INT_PTR CALLBACK ConnectionFilterEditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_INITDIALOG: + { + struct CONNECTION *conn = (struct CONNECTION*)lParam; + TranslateDialogDefault(hWnd); + + SetDlgItemText(hWnd, ID_TEXT_NAME, conn->PName); + SetDlgItemText(hWnd, ID_TXT_LOCAL_IP, conn->strIntIp); + SetDlgItemText(hWnd, ID_TXT_REMOTE_IP, conn->strExtIp); + SetDlgItemInt(hWnd, ID_TXT_LOCAL_PORT, conn->intIntPort, FALSE); + SetDlgItemInt(hWnd, ID_TXT_REMOTE_PORT, conn->intExtPort, FALSE); + SendDlgItemMessage(hWnd, ID_CBO_ACTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("Always show popup")); + SendDlgItemMessage(hWnd, ID_CBO_ACTION, CB_ADDSTRING, 0, (LPARAM)TranslateT("Never show popup")); + SendDlgItemMessage(hWnd, ID_CBO_ACTION, CB_SETCURSEL, 0, 0); + mir_free(conn); + return TRUE; + } + case WM_ACTIVATE: + if (0 == wParam) // becoming inactive + filterAddDlg = nullptr; + else // becoming active + filterAddDlg = hWnd; + return FALSE; + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case ID_OK: + { + wchar_t tmpPort[6]; + if (bOptionsOpen) + { + MessageBox(hWnd, TranslateT("First close options window"), L"ConnectionNotify", MB_OK | MB_ICONSTOP); + break; + } + if (WAIT_OBJECT_0 == WaitForSingleObject(hExceptionsMutex, 100)) + { + if (connCurrentEdit == nullptr) + { + connCurrentEdit = (struct CONNECTION*)mir_alloc(sizeof(struct CONNECTION)); + connCurrentEdit->next = connExceptions; + connExceptions = connCurrentEdit; + } + GetDlgItemText(hWnd, ID_TXT_LOCAL_PORT, tmpPort, _countof(tmpPort)); + if (tmpPort[0] == '*') + connCurrentEdit->intIntPort = -1; + else + connCurrentEdit->intIntPort = GetDlgItemInt(hWnd, ID_TXT_LOCAL_PORT, nullptr, FALSE); + GetDlgItemText(hWnd, ID_TXT_REMOTE_PORT, tmpPort, _countof(tmpPort)); + if (tmpPort[0] == '*') + connCurrentEdit->intExtPort = -1; + else + connCurrentEdit->intExtPort = GetDlgItemInt(hWnd, ID_TXT_REMOTE_PORT, nullptr, FALSE); + + GetDlgItemText(hWnd, ID_TXT_LOCAL_IP, connCurrentEdit->strIntIp, _countof(connCurrentEdit->strIntIp)); + GetDlgItemText(hWnd, ID_TXT_REMOTE_IP, connCurrentEdit->strExtIp, _countof(connCurrentEdit->strExtIp)); + GetDlgItemText(hWnd, ID_TEXT_NAME, connCurrentEdit->PName, _countof(connCurrentEdit->PName)); + + connCurrentEdit->Pid = !(BOOL)SendDlgItemMessage(hWnd, ID_CBO_ACTION, CB_GETCURSEL, 0, 0); + connCurrentEdit = nullptr; + saveSettingsConnections(connExceptions); + ReleaseMutex(hExceptionsMutex); + } + //EndDialog(hWnd,IDOK); + DestroyWindow(hWnd); + return TRUE; + } + case ID_CANCEL: + connCurrentEdit = nullptr; + DestroyWindow(hWnd); + //EndDialog(hWnd,IDCANCEL); + return TRUE; + } + return FALSE; + + break; + case WM_CLOSE: + DestroyWindow(hWnd); + case WM_DESTROY: + filterAddDlg = nullptr; + connCurrentEdit = nullptr; + //DestroyWindow(hWnd); + //PostQuitMessage(0); + break; + } + return FALSE; +} + +BOOL checkFilter(struct CONNECTION *head, struct CONNECTION *conn) +{ + for (struct CONNECTION *cur = head; cur != nullptr; cur = cur->next) + if (wildcmpw(conn->PName, cur->PName) && wildcmpw(conn->strIntIp, cur->strIntIp) && wildcmpw(conn->strExtIp, cur->strExtIp) + && (cur->intIntPort == -1 || cur->intIntPort == conn->intIntPort) && (cur->intExtPort == -1 || cur->intExtPort == conn->intExtPort)) + return cur->Pid; + + return settingDefaultAction; +} + diff --git a/protocols/ConnectionNotify/src/filter.h b/protocols/ConnectionNotify/src/filter.h new file mode 100644 index 0000000000..f21ba7c95a --- /dev/null +++ b/protocols/ConnectionNotify/src/filter.h @@ -0,0 +1,9 @@ +#pragma once +#ifndef _INC_FILTER +#define _INC_FILTER + +HANDLE startFilterThread(); +BOOL checkFilter(struct CONNECTION *head, struct CONNECTION *conn); + +#define WM_ADD_FILTER (WM_APP + 1) +#endif diff --git a/protocols/ConnectionNotify/src/netstat.cpp b/protocols/ConnectionNotify/src/netstat.cpp new file mode 100644 index 0000000000..93d906cc4f --- /dev/null +++ b/protocols/ConnectionNotify/src/netstat.cpp @@ -0,0 +1,148 @@ +#include "stdafx.h" + +struct CONNECTION *GetConnectionsTable() +{ + // Declare and initialize variables + MIB_TCPTABLE_OWNER_PID *pTcpTable = (MIB_TCPTABLE_OWNER_PID *)MALLOC(sizeof(MIB_TCPTABLE_OWNER_PID)); + if (pTcpTable == nullptr) { + //printf("Error allocating memory!\n"); + return nullptr; + } + + DWORD dwSize = sizeof(MIB_TCPTABLE_OWNER_PID); + // Make an initial call to GetTcpTable to + // get the necessary size into the dwSize variable + DWORD dwRetVal = GetExtendedTcpTable(pTcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0); + if (dwRetVal == ERROR_INSUFFICIENT_BUFFER) { + FREE(pTcpTable); + pTcpTable = (MIB_TCPTABLE_OWNER_PID *)MALLOC(dwSize); + if (pTcpTable == nullptr) { + //printf("Error allocating memory\n"); + return nullptr; + } + } + + // Make a second call to GetTcpTable to get + // the actual data we require + if ((dwRetVal = GetExtendedTcpTable(pTcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) != NO_ERROR) { + //printf("\tGetTcpTable() failed with return value %d\n", dwRetVal); + FREE(pTcpTable); + return nullptr; + } + //printf("\tLocal Addr\tLocal Port\tRemote Addr\tRemote Port\n"); + //printf("Number of entries: %d\n", (int) pTcpTable->dwNumEntries); + struct in_addr IpAddr; + struct CONNECTION *connHead = nullptr; + for (DWORD i = 0; i < pTcpTable->dwNumEntries; i++) { + struct CONNECTION *newConn = (struct CONNECTION*)mir_alloc(sizeof(struct CONNECTION)); + memset(newConn, 0, sizeof(struct CONNECTION)); + //pid2name(pTcpTable->table[i].dwOwningPid,&newConn->Pname); + + if (pTcpTable->table[i].dwLocalAddr) { + IpAddr.S_un.S_addr = (ULONG)pTcpTable->table[i].dwLocalAddr; + //_snprintf(newConn->strIntIp,_countof(newConn->strIntIp),"%d.%d.%d.%d",IpAddr.S_un.S_un_b.s_b1,IpAddr.S_un.S_un_b.s_b2,IpAddr.S_un.S_un_b.s_b3,IpAddr.S_un.S_un_b.s_b4); + wchar_t *strIntIp = mir_a2u(inet_ntoa(IpAddr)); + wcsncpy(newConn->strIntIp, strIntIp, _countof(newConn->strIntIp) - 1); + mir_free(strIntIp); + } + + if (pTcpTable->table[i].dwRemoteAddr) { + IpAddr.S_un.S_addr = (u_long)pTcpTable->table[i].dwRemoteAddr; + wchar_t *strExtIp = mir_a2u(inet_ntoa(IpAddr)); + wcsncpy(newConn->strExtIp, strExtIp, _countof(newConn->strExtIp) - 1); + mir_free(strExtIp); + } + newConn->state = pTcpTable->table[i].dwState; + newConn->intIntPort = ntohs((u_short)pTcpTable->table[i].dwLocalPort); + newConn->intExtPort = ntohs((u_short)pTcpTable->table[i].dwRemotePort); + newConn->Pid = pTcpTable->table[i].dwOwningPid; + switch (pTcpTable->table[i].dwState) { + case MIB_TCP_STATE_CLOSED: + //printf("CLOSED\n"); + break; + case MIB_TCP_STATE_LISTEN: + //printf("LISTEN\n"); + break; + case MIB_TCP_STATE_SYN_SENT: + //printf("SYN-SENT\n"); + break; + case MIB_TCP_STATE_SYN_RCVD: + //printf("SYN-RECEIVED\n"); + break; + case MIB_TCP_STATE_ESTAB: + //printf("ESTABLISHED\n"); + break; + case MIB_TCP_STATE_FIN_WAIT1: + //printf("FIN-WAIT-1\n"); + break; + case MIB_TCP_STATE_FIN_WAIT2: + //printf("FIN-WAIT-2 \n"); + break; + case MIB_TCP_STATE_CLOSE_WAIT: + //printf("CLOSE-WAIT\n"); + break; + case MIB_TCP_STATE_CLOSING: + //printf("CLOSING\n"); + break; + case MIB_TCP_STATE_LAST_ACK: + //printf("LAST-ACK\n"); + break; + case MIB_TCP_STATE_TIME_WAIT: + //printf("TIME-WAIT\n"); + break; + case MIB_TCP_STATE_DELETE_TCB: + //printf("DELETE-TCB\n"); + break; + default: + //printf("UNKNOWN dwState value\n"); + break; + } + newConn->next = connHead; + connHead = newConn; + //printf("TCP[%d]:%s%15d%20s%15d\n", i, szLocalAddr,ntohs((u_short)pTcpTable->table[i].dwLocalPort), szRemoteAddr,ntohs((u_short)pTcpTable->table[i].dwRemotePort)); + //printf("\tTCP[%d] Local Addr: %s\n", i, szLocalAddr); + // printf("\tTCP[%d] Local Port: %d \n", i, ntohs((u_short)pTcpTable->table[i].dwLocalPort)); + //printf("\tTCP[%d] Remote Addr: %s\n", i, szRemoteAddr); + //printf("\tTCP[%d] Remote Port: %d\n", i, ntohs((u_short)pTcpTable->table[i].dwRemotePort)); + } + FREE(pTcpTable); + + return connHead; +} + +void deleteConnectionsTable(struct CONNECTION *head) +{ + struct CONNECTION *cur = head, *del; + + while (cur != nullptr) { + del = cur; + cur = cur->next; + mir_free(del); + head = cur; + } + head = nullptr; +} + +struct CONNECTION *searchConnection(struct CONNECTION *head, wchar_t *intIp, wchar_t *extIp, int intPort, int extPort, int state) +{ + for (struct CONNECTION *cur = head; cur != nullptr; cur = cur->next) { + if (mir_wstrcmp(cur->strIntIp, intIp) == 0 && + mir_wstrcmp(cur->strExtIp, extIp) == 0 && + cur->intExtPort == extPort && + cur->intIntPort == intPort && + cur->state == state) + return cur; + } + return nullptr; +} + +void getDnsName(wchar_t *strIp, wchar_t *strHostName, size_t len) +{ + in_addr iaHost; + + char *szStrIP = mir_u2a(strIp); + iaHost.s_addr = inet_addr(szStrIP); + mir_free(szStrIP); + hostent *h = gethostbyaddr((char *)&iaHost, sizeof(struct in_addr), AF_INET); + wcsncpy_s(strHostName, len, (h == nullptr) ? strIp : _A2T(h->h_name), _TRUNCATE); +} diff --git a/protocols/ConnectionNotify/src/netstat.h b/protocols/ConnectionNotify/src/netstat.h new file mode 100644 index 0000000000..e4d1631775 --- /dev/null +++ b/protocols/ConnectionNotify/src/netstat.h @@ -0,0 +1,18 @@ +#pragma once + +struct CONNECTION +{ + wchar_t strIntIp[16]; + wchar_t strExtIp[16]; + int intIntPort; + int intExtPort; + int state; + DWORD Pid; + wchar_t PName[260]; + struct CONNECTION *next; +}; + +struct CONNECTION* GetConnectionsTable(); +void deleteConnectionsTable(struct CONNECTION* head); +struct CONNECTION* searchConnection(struct CONNECTION* head, wchar_t *intIp, wchar_t *extIp, int intPort, int extPort, int state); +void getDnsName(wchar_t *strIp, wchar_t *strHostName, size_t len); diff --git a/protocols/ConnectionNotify/src/pid2name.cpp b/protocols/ConnectionNotify/src/pid2name.cpp new file mode 100644 index 0000000000..f5c10ca9e6 --- /dev/null +++ b/protocols/ConnectionNotify/src/pid2name.cpp @@ -0,0 +1,21 @@ +#include "stdafx.h" + +void pid2name(DWORD procid, wchar_t *buffer, size_t bufLen) +{ + PROCESSENTRY32 ProcessStruct; + ProcessStruct.dwSize = sizeof(PROCESSENTRY32); + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnap == INVALID_HANDLE_VALUE) + return; + if (Process32First(hSnap, &ProcessStruct) == FALSE) + return; + + do { + if (ProcessStruct.th32ProcessID == procid) { + wcsncpy_s(buffer, bufLen, ProcessStruct.szExeFile, _TRUNCATE); + break; + } + } while (Process32Next(hSnap, &ProcessStruct)); + + CloseHandle(hSnap); +} diff --git a/protocols/ConnectionNotify/src/pid2name.h b/protocols/ConnectionNotify/src/pid2name.h new file mode 100644 index 0000000000..96338a14b1 --- /dev/null +++ b/protocols/ConnectionNotify/src/pid2name.h @@ -0,0 +1,8 @@ +#pragma once + +#ifndef _INC_PID2NAME +#define _INC_PID2NAME + +void pid2name(DWORD, wchar_t*, size_t); +#endif + diff --git a/protocols/ConnectionNotify/src/resource.h b/protocols/ConnectionNotify/src/resource.h new file mode 100644 index 0000000000..0215e70270 --- /dev/null +++ b/protocols/ConnectionNotify/src/resource.h @@ -0,0 +1,34 @@ +#ifndef IDC_STATIC +#define IDC_STATIC (-1) +#endif + +#define IDI_ICON1 101 +#define IDD_OPT_DIALOG 102 +#define IDI_ICON2 103 +#define IDD_FILTER_DIALOG 105 +#define IDI_ICON3 110 +#define IDI_ICON4 111 +#define IDI_ICON5 114 +#define IDI_ICON6 115 +#define ID_TEXT_NAME 1000 +#define IDC_RESOLVEIP 1001 +#define IDC_LIST_EXCEPTIONS 1002 +#define IDC_INTERVAL 1003 +#define ID_CHK_DEFAULTACTION 1004 +#define ID_DELETE 1005 +#define ID_DOWN 1006 +#define ID_ADD 1007 +#define ID_UP 1008 +#define IDC_SETCOLOURS 1009 +#define IDC_INTERVAL1 1010 +#define IDC_BGCOLOR 1011 +#define IDC_FGCOLOR 1012 +#define IDC_STATUS 1016 +#define IDC_VERSION 1017 +#define ID_TXT_LOCAL_IP 1070 +#define ID_TXT_REMOTE_IP 1071 +#define ID_CBO_ACTION 1074 +#define ID_TXT_REMOTE_PORT 1075 +#define ID_TXT_LOCAL_PORT 1076 +#define ID_CANCEL 1077 +#define ID_OK 1078 diff --git a/protocols/ConnectionNotify/src/stdafx.cxx b/protocols/ConnectionNotify/src/stdafx.cxx new file mode 100644 index 0000000000..1b563fc866 --- /dev/null +++ b/protocols/ConnectionNotify/src/stdafx.cxx @@ -0,0 +1,18 @@ +/* +Copyright (C) 2012-19 Miranda NG team (https://miranda-ng.org) + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation version 2 +of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "stdafx.h"
\ No newline at end of file diff --git a/protocols/ConnectionNotify/src/stdafx.h b/protocols/ConnectionNotify/src/stdafx.h new file mode 100644 index 0000000000..98123939fd --- /dev/null +++ b/protocols/ConnectionNotify/src/stdafx.h @@ -0,0 +1,51 @@ +#pragma once + +#include <windows.h> +#include <Commctrl.h> +#include <assert.h> +#include <iphlpapi.h> +#include <Tlhelp32.h> + +#include <newpluginapi.h> +#include <m_core.h> +#include <m_clistint.h> +#include <m_skin.h> +#include <m_langpack.h> +#include <m_options.h> +#include <m_popup.h> +#include <m_utils.h> +#include <m_protosvc.h> +#include <m_system.h> + +#ifdef _DEBUG +#include "debug.h" +#endif +#include "resource.h" +#include "netstat.h" +#include "filter.h" +#include "version.h" +#include "pid2name.h" + +#define MAX_SETTING_STR 512 +#define MAX_LENGTH 512 +#define STATUS_COUNT 9 + +// Note: could also use malloc() and free() +#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) +#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) + +#define PLUGINNAME "ConnectionNotify" +#define PLUGINNAME_NEWSOUND PLUGINNAME "_new_sound" + +struct CMPlugin : public PLUGIN<CMPlugin> +{ + CMPlugin(); + + int Load() override; + int Unload() override; +}; + +void showMsg(wchar_t *pName,DWORD pid,wchar_t *intIp,wchar_t *extIp,int intPort,int extPort,int state); +static unsigned __stdcall checkthread(void *dummy); +struct CONNECTION * LoadSettingsConnections(); +void saveSettingsConnections(struct CONNECTION *connHead); diff --git a/protocols/ConnectionNotify/src/version.h b/protocols/ConnectionNotify/src/version.h new file mode 100644 index 0000000000..6ca2e3eb6f --- /dev/null +++ b/protocols/ConnectionNotify/src/version.h @@ -0,0 +1,38 @@ +/* +Exchange notifier plugin for Miranda IM + +Copyright © 2006 Cristian Libotean, Attila Vajda + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#ifndef M_NONNECTIONNOTIFY_VERSION_H +#define M_NONNECTIONNOTIFY_VERSION_H + +#define __MAJOR_VERSION 0 +#define __MINOR_VERSION 1 +#define __RELEASE_NUM 0 +#define __BUILD_NUM 5 + +#include <stdver.h> + +#define __PLUGIN_NAME "Connection Notify" +#define __FILENAME "ConnectionNotify.dll" +#define __DESCRIPTION "Notify with popup if some connection established" +#define __AUTHOR "MaKaR" +#define __COPYRIGHT "© 2011-13 MaKaRSoFT" +#define __AUTHORWEB "https://miranda-ng.org/p/ConnectionNotify/" + +#endif //M_EXCHANGE_VERSION_H |