From 67010ebc31ce45e6c42d2c31d983f3988bb320e1 Mon Sep 17 00:00:00 2001 From: Kirill Volinsky Date: Wed, 20 Mar 2013 13:04:46 +0000 Subject: added some old plugins git-svn-id: http://svn.miranda-ng.org/main/trunk@4123 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/!NotAdopted/WinPopup/add_dialog.cpp | 74 ++ plugins/!NotAdopted/WinPopup/add_dialog.h | 25 + plugins/!NotAdopted/WinPopup/chat.cpp | 337 ++++++ plugins/!NotAdopted/WinPopup/chat.h | 44 + plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h | 338 ++++++ plugins/!NotAdopted/WinPopup/icons/add.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/away.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/bad_name.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/bad_names.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/computer.ico | Bin 0 -> 1406 bytes .../!NotAdopted/WinPopup/icons/computer_error.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/dnd.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/explore.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/freechat.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/good_name.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/good_names.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/invisible.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/lana.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/na.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/occupied.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/offline.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/online.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/onthephone.ico | Bin 0 -> 2550 bytes plugins/!NotAdopted/WinPopup/icons/other_name.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/other_names.ico | Bin 0 -> 1406 bytes plugins/!NotAdopted/WinPopup/icons/outtolunch.ico | Bin 0 -> 2550 bytes .../!NotAdopted/WinPopup/icons/overlay/away.ico | Bin 0 -> 1150 bytes plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico | Bin 0 -> 1150 bytes .../WinPopup/icons/overlay/freechat.ico | Bin 0 -> 1150 bytes .../WinPopup/icons/overlay/invisible.ico | Bin 0 -> 1150 bytes plugins/!NotAdopted/WinPopup/icons/overlay/na.ico | Bin 0 -> 1150 bytes .../WinPopup/icons/overlay/occupied.ico | Bin 0 -> 1150 bytes .../!NotAdopted/WinPopup/icons/overlay/onphone.ico | Bin 0 -> 1150 bytes .../WinPopup/icons/overlay/outtolunch.ico | Bin 0 -> 1150 bytes .../!NotAdopted/WinPopup/icons/winpopup_proto.ico | Bin 0 -> 9062 bytes plugins/!NotAdopted/WinPopup/m_uninstaller.h | 703 +++++++++++ plugins/!NotAdopted/WinPopup/m_updater.h | 117 ++ plugins/!NotAdopted/WinPopup/mailslot.cpp | 313 +++++ plugins/!NotAdopted/WinPopup/mailslot.h | 48 + plugins/!NotAdopted/WinPopup/md5.h | 222 ++++ plugins/!NotAdopted/WinPopup/messagebox.cpp | 232 ++++ plugins/!NotAdopted/WinPopup/messagebox.h | 29 + plugins/!NotAdopted/WinPopup/messenger.cpp | 469 ++++++++ plugins/!NotAdopted/WinPopup/messenger.h | 54 + plugins/!NotAdopted/WinPopup/netbios.cpp | 1065 +++++++++++++++++ plugins/!NotAdopted/WinPopup/netbios.h | 134 +++ plugins/!NotAdopted/WinPopup/netbios_name.cpp | 640 ++++++++++ plugins/!NotAdopted/WinPopup/netbios_name.h | 157 +++ plugins/!NotAdopted/WinPopup/network.cpp | 88 ++ plugins/!NotAdopted/WinPopup/network.h | 31 + plugins/!NotAdopted/WinPopup/options.cpp | 392 +++++++ plugins/!NotAdopted/WinPopup/options.h | 24 + plugins/!NotAdopted/WinPopup/processapi.cpp | 578 ++++++++++ plugins/!NotAdopted/WinPopup/processapi.h | 264 +++++ plugins/!NotAdopted/WinPopup/resource.h | 66 ++ plugins/!NotAdopted/WinPopup/scanner.cpp | 218 ++++ plugins/!NotAdopted/WinPopup/scanner.h | 49 + plugins/!NotAdopted/WinPopup/sdk/m_avatars.h | 359 ++++++ plugins/!NotAdopted/WinPopup/sdk/m_chat.h | 685 +++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_clist.h | 637 ++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_database.h | 1199 +++++++++++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_langpack.h | 114 ++ plugins/!NotAdopted/WinPopup/sdk/m_netlib.h | 832 +++++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_options.h | 138 +++ plugins/!NotAdopted/WinPopup/sdk/m_plugins.h | 85 ++ plugins/!NotAdopted/WinPopup/sdk/m_popup.h | 424 +++++++ plugins/!NotAdopted/WinPopup/sdk/m_protocols.h | 487 ++++++++ plugins/!NotAdopted/WinPopup/sdk/m_protomod.h | 136 +++ plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h | 775 +++++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_system.h | 631 ++++++++++ plugins/!NotAdopted/WinPopup/sdk/m_userinfo.h | 76 ++ plugins/!NotAdopted/WinPopup/sdk/m_utils.h | 573 +++++++++ plugins/!NotAdopted/WinPopup/sdk/newpluginapi.h | 291 +++++ plugins/!NotAdopted/WinPopup/sdk/statusmodes.h | 52 + plugins/!NotAdopted/WinPopup/search.cpp | 330 ++++++ plugins/!NotAdopted/WinPopup/search.h | 60 + plugins/!NotAdopted/WinPopup/services.cpp | 1003 ++++++++++++++++ plugins/!NotAdopted/WinPopup/services.h | 36 + plugins/!NotAdopted/WinPopup/smbconst.h | 108 ++ plugins/!NotAdopted/WinPopup/stdafx.cpp | 22 + plugins/!NotAdopted/WinPopup/stdafx.h | 136 +++ plugins/!NotAdopted/WinPopup/user_info.cpp | 334 ++++++ plugins/!NotAdopted/WinPopup/user_info.h | 24 + plugins/!NotAdopted/WinPopup/winpopup_proto.cpp | 1217 ++++++++++++++++++++ plugins/!NotAdopted/WinPopup/winpopup_proto.def | 27 + plugins/!NotAdopted/WinPopup/winpopup_proto.h | 322 ++++++ plugins/!NotAdopted/WinPopup/winpopup_proto.rc | 251 ++++ plugins/!NotAdopted/WinPopup/winpopup_proto_7.sln | 21 + .../!NotAdopted/WinPopup/winpopup_proto_7.vcproj | 406 +++++++ .../!NotAdopted/WinPopup/winpopup_proto_9.icproj | 37 + plugins/!NotAdopted/WinPopup/winpopup_proto_9.sln | 28 + .../!NotAdopted/WinPopup/winpopup_proto_9.vcproj | 773 +++++++++++++ .../!NotAdopted/WinPopup/winpopup_proto_pack.cmd | 6 + .../!NotAdopted/WinPopup/winpopup_proto_readme.txt | 245 ++++ .../!NotAdopted/WinPopup/winpopup_proto_todo.txt | 9 + .../WinPopup/winpopup_proto_translation.txt | 43 + 96 files changed, 19643 insertions(+) create mode 100644 plugins/!NotAdopted/WinPopup/add_dialog.cpp create mode 100644 plugins/!NotAdopted/WinPopup/add_dialog.h create mode 100644 plugins/!NotAdopted/WinPopup/chat.cpp create mode 100644 plugins/!NotAdopted/WinPopup/chat.h create mode 100644 plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h create mode 100644 plugins/!NotAdopted/WinPopup/icons/add.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/away.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/bad_name.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/bad_names.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/computer.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/computer_error.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/dnd.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/explore.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/freechat.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/good_name.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/good_names.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/invisible.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/lana.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/na.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/occupied.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/offline.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/online.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/onthephone.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/other_name.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/other_names.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/outtolunch.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/away.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/freechat.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/invisible.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/na.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/occupied.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/onphone.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/overlay/outtolunch.ico create mode 100644 plugins/!NotAdopted/WinPopup/icons/winpopup_proto.ico create mode 100644 plugins/!NotAdopted/WinPopup/m_uninstaller.h create mode 100644 plugins/!NotAdopted/WinPopup/m_updater.h create mode 100644 plugins/!NotAdopted/WinPopup/mailslot.cpp create mode 100644 plugins/!NotAdopted/WinPopup/mailslot.h create mode 100644 plugins/!NotAdopted/WinPopup/md5.h create mode 100644 plugins/!NotAdopted/WinPopup/messagebox.cpp create mode 100644 plugins/!NotAdopted/WinPopup/messagebox.h create mode 100644 plugins/!NotAdopted/WinPopup/messenger.cpp create mode 100644 plugins/!NotAdopted/WinPopup/messenger.h create mode 100644 plugins/!NotAdopted/WinPopup/netbios.cpp create mode 100644 plugins/!NotAdopted/WinPopup/netbios.h create mode 100644 plugins/!NotAdopted/WinPopup/netbios_name.cpp create mode 100644 plugins/!NotAdopted/WinPopup/netbios_name.h create mode 100644 plugins/!NotAdopted/WinPopup/network.cpp create mode 100644 plugins/!NotAdopted/WinPopup/network.h create mode 100644 plugins/!NotAdopted/WinPopup/options.cpp create mode 100644 plugins/!NotAdopted/WinPopup/options.h create mode 100644 plugins/!NotAdopted/WinPopup/processapi.cpp create mode 100644 plugins/!NotAdopted/WinPopup/processapi.h create mode 100644 plugins/!NotAdopted/WinPopup/resource.h create mode 100644 plugins/!NotAdopted/WinPopup/scanner.cpp create mode 100644 plugins/!NotAdopted/WinPopup/scanner.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_avatars.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_chat.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_clist.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_database.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_langpack.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_netlib.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_options.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_plugins.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_popup.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_protocols.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_protomod.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_system.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_userinfo.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/m_utils.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/newpluginapi.h create mode 100644 plugins/!NotAdopted/WinPopup/sdk/statusmodes.h create mode 100644 plugins/!NotAdopted/WinPopup/search.cpp create mode 100644 plugins/!NotAdopted/WinPopup/search.h create mode 100644 plugins/!NotAdopted/WinPopup/services.cpp create mode 100644 plugins/!NotAdopted/WinPopup/services.h create mode 100644 plugins/!NotAdopted/WinPopup/smbconst.h create mode 100644 plugins/!NotAdopted/WinPopup/stdafx.cpp create mode 100644 plugins/!NotAdopted/WinPopup/stdafx.h create mode 100644 plugins/!NotAdopted/WinPopup/user_info.cpp create mode 100644 plugins/!NotAdopted/WinPopup/user_info.h create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto.cpp create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto.def create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto.h create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto.rc create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_7.sln create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_7.vcproj create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_9.icproj create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_9.sln create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_9.vcproj create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_pack.cmd create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_readme.txt create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_todo.txt create mode 100644 plugins/!NotAdopted/WinPopup/winpopup_proto_translation.txt (limited to 'plugins/!NotAdopted/WinPopup') diff --git a/plugins/!NotAdopted/WinPopup/add_dialog.cpp b/plugins/!NotAdopted/WinPopup/add_dialog.cpp new file mode 100644 index 0000000000..3312c73385 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/add_dialog.cpp @@ -0,0 +1,74 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "add_dialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +static INT_PTR CALLBACK DlgProcAddContact(HWND hwndDlg, UINT Msg, + WPARAM wParam, LPARAM /*lParam*/) +{ + switch ( Msg ) + { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + return TRUE; + + case WM_COMMAND: + switch ( LOWORD( wParam ) ) + { + case IDOK: + { + bool bGroup = IsDlgButtonChecked( hwndDlg, IDC_GROUP ) == BST_CHECKED; + CString sName; + GetDlgItemText( hwndDlg, IDC_NAME, sName.GetBuffer( 128 ), 127 ); + sName.ReleaseBuffer(); + sName.Trim(); + if ( ! sName.IsEmpty() ) + { + HCURSOR hCurrent = SetCursor( LoadCursor( NULL, IDC_WAIT ) ); + HANDLE hContact = AddToListByName( sName, 0, NULL, true, bGroup ); + SetCursor( hCurrent ); + if ( hContact ) + EndDialog( hwndDlg, IDOK ); + } + } + return TRUE; + + case IDCANCEL: + EndDialog( hwndDlg, IDCANCEL ); + return TRUE; + } + break; + } + return FALSE; +} + +void AddDialog(HWND hParentWnd) +{ + DialogBox( pluginModule, MAKEINTRESOURCE( IDD_ADD ), hParentWnd, DlgProcAddContact ); +} diff --git a/plugins/!NotAdopted/WinPopup/add_dialog.h b/plugins/!NotAdopted/WinPopup/add_dialog.h new file mode 100644 index 0000000000..16f0245eb8 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/add_dialog.h @@ -0,0 +1,25 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2009 Nikolay Raspopov + +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. +*/ + +#pragma once + +// Показывает диалог для ручного добавления контакта по имени/адресу +void AddDialog(HWND hParentWnd); diff --git a/plugins/!NotAdopted/WinPopup/chat.cpp b/plugins/!NotAdopted/WinPopup/chat.cpp new file mode 100644 index 0000000000..4572bb10ac --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/chat.cpp @@ -0,0 +1,337 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2008-2010 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "chat.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#ifdef CHAT_ENABLED + +HANDLE plugin_CHAT_EVENT = NULL; + +static int __cdecl CHAT_EVENT(WPARAM /* wParam */, LPARAM lParam) +{ + GCHOOK* pgch = (GCHOOK*)lParam; + switch ( pgch->pDest->iType ) + { + case GC_USER_MESSAGE: + { + // Дублирование в чат + ChatMessage( pgch->pDest->ptszID, pgch->ptszText ); + + // Отправка сообщения + DWORD dwLastError = 0; + SendMessage( pgch->pDest->ptszID, pgch->ptszText, dwLastError ); + } + break; + } + + return 0; +} + +bool ChatRegister() +{ + GCREGISTER gcr = + { + sizeof( GCREGISTER ), + 0, + modname, + modname, + 0, + 0, + NULL + }; + int result = CallServiceSync( MS_GC_REGISTER, 0, (LPARAM)&gcr ); + if ( result != 0 ) + return false; + + _ASSERT (plugin_CHAT_EVENT == NULL); + plugin_CHAT_EVENT = HookEvent (ME_GC_EVENT, CHAT_EVENT); + _ASSERT (plugin_CHAT_EVENT != NULL); + + return true; +} + +void ChatUnregister() +{ + if (plugin_CHAT_EVENT) + { + UnhookEvent (plugin_CHAT_EVENT); + plugin_CHAT_EVENT = NULL; + } +} + +bool ChatNewSession(LPCTSTR szSession) +{ + GCSESSION gcr = + { + sizeof( GCSESSION ), + GCW_CHATROOM, + modname, + (LPCSTR)szSession, + (LPCSTR)szSession, + NULL, + 0, + 0 + }; + return ( CallServiceSync( MS_GC_NEWSESSION, 0, (LPARAM)&gcr ) == 0 ); +} + +bool ChatAddGroup(LPCTSTR szSession, LPCTSTR szGroup) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_ADDGROUP + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + NULL, + NULL, + (LPCSTR)szGroup, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +bool ChatJoinMe(LPCTSTR szSession, LPCTSTR szGroup) +{ + CString sMe; + + CString sMyNick = GetNick( NULL ); + if ( ! sMyNick.IsEmpty() ) + sMe = sMyNick; + else + sMe = pluginMachineName; + + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_JOIN + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + (LPCSTR)(LPCTSTR)sMe, + (LPCSTR)(LPCTSTR)sMe, + (LPCSTR)szGroup, + NULL, + TRUE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +bool ChatJoinUser(LPCTSTR szSession, LPCTSTR szUser, LPCTSTR szGroup) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_JOIN + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + (LPCSTR)szUser, + (LPCSTR)szUser, + (LPCSTR)szGroup, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +bool ChatInitDone(LPCTSTR szSession) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_CONTROL + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + NULL, + NULL, + NULL, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, SESSION_INITDONE, (LPARAM)&gce ) == 0 ); +} + +bool ChatOnline(LPCTSTR szSession) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_CONTROL + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + NULL, + NULL, + NULL, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, SESSION_ONLINE, (LPARAM)&gce ) == 0 ); +} + +bool ChatOffline(LPCTSTR szSession) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_CONTROL + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + NULL, + NULL, + NULL, + NULL, + NULL, + FALSE, + 0, + 0, + NULL + }; + return ( CallServiceSync( MS_GC_EVENT, SESSION_OFFLINE, (LPARAM)&gce ) == 0 ); +} + +bool ChatMessage(LPCTSTR szSession, LPCTSTR szFrom, LPCTSTR szMessage) +{ + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_MESSAGE + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + (LPCSTR)szMessage, + (LPCSTR)szFrom, + (LPCSTR)szFrom, + NULL, + NULL, + FALSE, + 0, + 0, + time() + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +bool ChatMessage(LPCTSTR szSession, LPCTSTR szMessage) +{ + CString sMe; + + CString sMyNick = GetNick( NULL ); + if ( ! sMyNick.IsEmpty() ) + sMe = sMyNick; + else + sMe = pluginMachineName; + + GCDEST gcdest = + { + modname, + (LPSTR)szSession, + GC_EVENT_MESSAGE + }; + GCEVENT gce = + { + sizeof( GCEVENT ), + &gcdest, + (LPCSTR)szMessage, + (LPCSTR)(LPCTSTR)sMe, + (LPCSTR)(LPCTSTR)sMe, + NULL, + NULL, + TRUE, + 0, + 0, + time() + }; + return ( CallServiceSync( MS_GC_EVENT, 0, (LPARAM)&gce ) == 0 ); +} + +CString GetChatSession(HANDLE hContact) +{ + CString sContact; + DBVARIANT dbv = {}; + if ( ! DBGetContactSettingTString( hContact, modname, "ChatRoomID", &dbv ) ) + { + sContact = dbv.pszVal; + DBFreeVariant( &dbv ); + } + return sContact; +} + +bool IsChatRoom(HANDLE hContact) +{ + return ( DBGetContactSettingByte( hContact, modname, "ChatRoom", 0 ) != 0 ); +} + +#endif // CHAT_ENABLED diff --git a/plugins/!NotAdopted/WinPopup/chat.h b/plugins/!NotAdopted/WinPopup/chat.h new file mode 100644 index 0000000000..6351ea3042 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/chat.h @@ -0,0 +1,44 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2008-2009 Nikolay Raspopov + +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. +*/ + +#pragma once + +#ifdef CHAT_ENABLED + +bool ChatRegister(); +void ChatUnregister(); +bool ChatNewSession(LPCTSTR szSession); +bool ChatAddGroup(LPCTSTR szSession, LPCTSTR szGroup); +bool ChatJoinMe(LPCTSTR szSession, LPCTSTR szGroup); +bool ChatJoinUser(LPCTSTR szSession, LPCTSTR szUser, LPCTSTR szGroup); +bool ChatInitDone(LPCTSTR szSession); +bool ChatOnline(LPCTSTR szSession); +bool ChatOffline(LPCTSTR szSession); +bool ChatMessage(LPCTSTR szSession, LPCTSTR szFrom, LPCTSTR szMessage); +bool ChatMessage(LPCTSTR szSession, LPCTSTR szMessage); + +// Получение идентификатора чата (обычно имя рабочей группы) +CString GetChatSession(HANDLE hContact); + +// Проверка что контакт - это чат +bool IsChatRoom(HANDLE hContact); + +#endif // CHAT_ENABLED diff --git a/plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h b/plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h new file mode 100644 index 0000000000..218a5a114c --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/dllLoaderMinimal.h @@ -0,0 +1,338 @@ +/* + * This software is the original work of DKLT. + * Copyright (c) 2002 DKLT. All rights reserved. + * email: dtung@eng.monash.edu.au + * + */ +/* + * Permission to make digital or hard copies of all or part of this work for personal + * or classroom use is granted without fee provided that copies are not distributed + * for profit or commercial advantage. + */ + +#ifndef LOADDLL_H +#define LOADDLL_H + +/// proof of concept code follows +/////// +/////// class DllLoader and class DllFunctor<...> +/////// +/////// Two classes are designed to provide the functionality to load a function, +/////// using the "function name" as an identifier, from a Win32 .dll file. +/////// Sample code are attached at the end of this file. +/////// +/////// -04Oct2003 11.52pm +/////// reworked article and sample code to be posted on codeproject.com +/////// better defined behaviours with refined logics idealistic goals yet to be completed +/////// +/////// -29Mar2003 1.47pm +/////// Polishing code for public release. minimizing code size, removing redundent +/////// comments, eliminating deprecated funcs. +/////// +/////// -29Mar2003 12.47am +/////// Revising the src tree. Using redundent code to achieve src level compatibility +/////// (ie: same set of calls for both funcs attached with apps or reside in dlls) +/////// +/////// -12Nov2002 1.35am +/////// My first attempt to tidy the code for another public release. +/////// +/////// -14Oct2002 1.40am +/////// created and tested briefly inside \DKLT TestApp\ +/////// +/////// +/////// + +//template + +/// +/// No error message for you +/// +#ifndef ERRORMSG +#define DEBUGMSG(aMesg) ; +#define ERRORMSG(aMesg) ; +#endif + +/// +/// protos +/// +class DllLoader; +template class DllFunctor; + + +/* +//++++++++++++++++++++++++++++++++++++++++++++++++++++ +// For Current release, you write code like these +//++++++++++++++++++++++++++++++++++++++++++++++++++++ + /// + /// u can load a dll function in two differnt ways + /// + DllLoader dll("testDll.dll", false); + DllFunctor fAdd("Add"); + fAdd.SetDll(dll); + + int b; + b = fSub()(b,1); // with delay load, but not src level compatible + + OR + + + DllLoader dll("testDll.dll"); + FuncPtrType( int(*)(int,int) ) Add; + dll.LoadFunc(Add,"Add"); + int a=90; + a = Add(a,1); // src level compatible, but no delay load + + + +//++++++++++++++++++++++++++++++++++++++++++++++++++++ +// For previous release, you write code like these +//++++++++++++++++++++++++++++++++++++++++++++++++++++ + + // + // sample code for demonstrating class DllLoader {...}; and DllFunctor<...> {...}; + // + FuncPtrType( int(*)(int) ) a; // define a new variable "a" of type "int(*)(int)" + + DllLoader Dlldshow("dlls.dll"); // expect a dll name "dlls.dll" + Dllshow.LoadFunc( a, "test"); // load func named "test" from dll file + int i =a(10); + +//++++++++++++++++++++++++++++++++++++++++++++++++++++ +// For initial release, you write code like these +//++++++++++++++++++++++++++++++++++++++++++++++++++++ + This version enables a delay-load behaviour. Note the double ()() call on last line. + + // + // sample code for demonstrating class DllLoader {...}; and DllFunctor<...> {...}; + // + + DllLoader Dlldshow("dlls.dll"); + DllFunctor update("UpdatePoint"); + + Dlldshow.find(update); + + update() (&pt); + + +*/ + +/* + A little comment here + + My previous attempts to use operator()(...) and operator FuncPtrType () with MSVC + failed, where FuncPtrType is a function pointer typedef. That technique, enables + more control over a functor object. ie: can implement delay load among many exciting + features. That technique, however, works with g++ line of compilers. + + This current implementation is design for use with MSVC line of compilers only. + + It seems, from the MSVC compiler error message, that "operator FuncPtrType ()" is + never a candidate function, not to mention viability. I guess this is how they + design and implemented MSVC6. ".net" version doesnt "evaluate" + "operator FuncPtrType()" properly as well. + + - DKLT March 2003 +*/ + + +////// +//////++++++++++++++++++++++++++++++++++++++++++++++++++ +////// This marco is for performing the following task... GoodJob! creative man!! +//////++++++++++++++++++++++++++++++++++++++++++++++++++ +////// normally, u define a function pointer variable this way +////// +////// int (*c) (int) = test; // c pointing to "int test(int) {...}" +////// +////// This marco enables u define a function pointer this way +////// +////// FuncPtrType( int(*)(int) ) c =test; +////// +////// +////// took me a while to come up with this one. +////// +////// - DKLT 2003 March + +template +struct TypeOnlyStruct { +typedef FuncTypeTTT FuncType; +}; + +#define FuncPtrType(funcType) \ + TypeOnlyStruct::FuncType + +////// +////// potential problems +////// - an instantiation for every differnt type on the template class +////// thus bloated executable? need to fully test it out. not sure about +////// behaviour at this stage. +////// - DKLT March 2003 + + +////// +////// class DllLoader {...} +////// -init a dll file with LoadLibrary() so that its mapped into dll memory +////// space. this class is designed to use with class DllFunctor<...>. +////// +////// +///////////////////////////////////////////////////////// +class DllLoader +{ +///////////////////////////////////////////////////////// + +private: + TCHAR dllName[ MAX_PATH ]; + +public: + HINSTANCE dll; + + DllLoader (LPCTSTR n, bool loadNow = true) : + dll(0) + { + lstrcpy( dllName, n ); + if (loadNow) + LoadLibrary(); + } + ~DllLoader () + { + FreeLibrary(); + } + + // test to see if dll is loaded already + operator bool () const + { + return (dll != 0); + } + +// FuncTypePtr(int(*)(int)) a; +// Dllshow.LoadFunc( a, "test") ; +// int i =a(10); + + /// This is my latest implementation + ///---------------------------------------------------------- + /// public: + /// template + /// DllLoader::LoadFunc(FuncTTT& c, string fNameStr) + ///---------------------------------------------------------- + /// This function loads a function named "fNameStr" from a DllLoader object + /// and put the address of that function into c. + /// + /// - template type is derived(deduced) from 1st param. + /// + ///note: bloated executable is possible + template + //-------------------------- + FuncTTT LoadFunc(FuncTTT& c, LPCSTR fNameStr) { + //-------------------------- + FuncTTT fPtr; + + // existing lib loaded? + if (!dll) + if (!this->LoadLibrary()) + return (FuncTTT) NULL; + + // load func from dll + fPtr =(FuncTTT)GetProcAddress ( + dll, // handle to DLL module + fNameStr // name of function + ); + if (!fPtr) { + /// return a pointer to a base generic function would be good. ie: ERROR prompt + return (FuncTTT) NULL; + } + c = fPtr; + return fPtr; + } + +public: + /// + /// decrement dll ref count via win32 ::FreeLibrary(...) + /// + //-------------------------- + void FreeLibrary() { + //-------------------------- + if (dll) { + ::FreeLibrary(dll); + dll=0; + } + } + +public: + /// + /// find the dll file and attempt to load it + /// + //------------------------ + bool LoadLibrary (HINSTANCE hInstance = NULL) { + //------------------------ + + // existing lib loaded? + if (dll !=0 ) + this->FreeLibrary(); + + // load from: + // 1. The directory from which the application loaded. + // 2. The current directory. + // 3. The Windows system directory. + // 4. The Windows directory. + // 5. The directories that are listed in the PATH environment variable. + dll = ::LoadLibrary( dllName ); + if ( ! dll ) + { + // 6. The module directory (if dll). + if ( hInstance ) + { + TCHAR self[ MAX_PATH ]; + GetModuleFileName( hInstance, self, MAX_PATH ); + lstrcpy( lstrnrchr( self, _T('\\'), lstrlen( self )) + 1, dllName ); + dll = ::LoadLibrary( self ); + } + if ( ! dll ) + { + return false; + } + } + return true; + } + + ////// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ////// All class functions below are for backward compatibility.... + ////// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + ////// U may delete all of them if u dont need them + ////// + /// + /// find() is deprecated. Do not use it anymore. + /// locate the functor inside a dll. let a DllFunctor object to do the job + /// instead... double dispatch?? + /// +public:template + bool find(DllFunctor& functor) { + return functor.LoadFromDll(this); + } + +}; + +/// +/// DllFunctor<> is templated on the function type +/// +template +class DllFunctor { + FuncPtrType fp; // pointer to dll function + DllLoader* dll; // which dllLoader to load from + CString fname; // name of function as char array + +public: + DllFunctor(FuncPtrType f, DllLoader* d=0): fp(f), dll(d) {;} + DllFunctor(LPCTSTR n): fname(n),fp(0), dll(0) {;} + FuncPtrType operator()() { + if (!*dll) { + if (!dll->LoadLibrary()) + return (FuncPtrType) NULL; + } + if (fp == 0) { + dll->LoadFunc (fp, fname.c_str()); + } + return fp; + } + void SetDll(DllLoader& d) { dll=&d; } +}; + +#endif diff --git a/plugins/!NotAdopted/WinPopup/icons/add.ico b/plugins/!NotAdopted/WinPopup/icons/add.ico new file mode 100644 index 0000000000..2b407bd899 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/add.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/away.ico b/plugins/!NotAdopted/WinPopup/icons/away.ico new file mode 100644 index 0000000000..fd4fc06d27 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/away.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/bad_name.ico b/plugins/!NotAdopted/WinPopup/icons/bad_name.ico new file mode 100644 index 0000000000..d90e82cf30 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/bad_name.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/bad_names.ico b/plugins/!NotAdopted/WinPopup/icons/bad_names.ico new file mode 100644 index 0000000000..939dcffcb1 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/bad_names.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/computer.ico b/plugins/!NotAdopted/WinPopup/icons/computer.ico new file mode 100644 index 0000000000..70e0c09112 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/computer.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/computer_error.ico b/plugins/!NotAdopted/WinPopup/icons/computer_error.ico new file mode 100644 index 0000000000..380ed3d9f1 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/computer_error.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/dnd.ico b/plugins/!NotAdopted/WinPopup/icons/dnd.ico new file mode 100644 index 0000000000..3cc44e4a98 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/dnd.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/explore.ico b/plugins/!NotAdopted/WinPopup/icons/explore.ico new file mode 100644 index 0000000000..0e26c97f10 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/explore.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/freechat.ico b/plugins/!NotAdopted/WinPopup/icons/freechat.ico new file mode 100644 index 0000000000..730bbe436a Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/freechat.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/good_name.ico b/plugins/!NotAdopted/WinPopup/icons/good_name.ico new file mode 100644 index 0000000000..86aaef9d46 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/good_name.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/good_names.ico b/plugins/!NotAdopted/WinPopup/icons/good_names.ico new file mode 100644 index 0000000000..37fc97841f Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/good_names.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/invisible.ico b/plugins/!NotAdopted/WinPopup/icons/invisible.ico new file mode 100644 index 0000000000..2c5378e70c Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/invisible.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/lana.ico b/plugins/!NotAdopted/WinPopup/icons/lana.ico new file mode 100644 index 0000000000..d753509117 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/lana.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/na.ico b/plugins/!NotAdopted/WinPopup/icons/na.ico new file mode 100644 index 0000000000..e9cffaf26f Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/na.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/occupied.ico b/plugins/!NotAdopted/WinPopup/icons/occupied.ico new file mode 100644 index 0000000000..2abca3db31 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/occupied.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/offline.ico b/plugins/!NotAdopted/WinPopup/icons/offline.ico new file mode 100644 index 0000000000..a94a20319a Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/offline.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/online.ico b/plugins/!NotAdopted/WinPopup/icons/online.ico new file mode 100644 index 0000000000..8bd53fe6f7 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/online.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/onthephone.ico b/plugins/!NotAdopted/WinPopup/icons/onthephone.ico new file mode 100644 index 0000000000..5f88fdbc48 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/onthephone.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/other_name.ico b/plugins/!NotAdopted/WinPopup/icons/other_name.ico new file mode 100644 index 0000000000..b46b632318 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/other_name.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/other_names.ico b/plugins/!NotAdopted/WinPopup/icons/other_names.ico new file mode 100644 index 0000000000..c5eb01ad5c Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/other_names.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/outtolunch.ico b/plugins/!NotAdopted/WinPopup/icons/outtolunch.ico new file mode 100644 index 0000000000..9b144d1eea Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/outtolunch.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/away.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/away.ico new file mode 100644 index 0000000000..4c6928082d Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/away.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico new file mode 100644 index 0000000000..778689c234 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/dnd.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/freechat.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/freechat.ico new file mode 100644 index 0000000000..58a04c226e Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/freechat.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/invisible.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/invisible.ico new file mode 100644 index 0000000000..9775d6deea Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/invisible.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/na.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/na.ico new file mode 100644 index 0000000000..8ffa02a346 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/na.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/occupied.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/occupied.ico new file mode 100644 index 0000000000..290f2b4ef7 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/occupied.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/onphone.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/onphone.ico new file mode 100644 index 0000000000..9dda2ec2ae Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/onphone.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/overlay/outtolunch.ico b/plugins/!NotAdopted/WinPopup/icons/overlay/outtolunch.ico new file mode 100644 index 0000000000..d357c23da1 Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/overlay/outtolunch.ico differ diff --git a/plugins/!NotAdopted/WinPopup/icons/winpopup_proto.ico b/plugins/!NotAdopted/WinPopup/icons/winpopup_proto.ico new file mode 100644 index 0000000000..6ee65927cf Binary files /dev/null and b/plugins/!NotAdopted/WinPopup/icons/winpopup_proto.ico differ diff --git a/plugins/!NotAdopted/WinPopup/m_uninstaller.h b/plugins/!NotAdopted/WinPopup/m_uninstaller.h new file mode 100644 index 0000000000..695330c4c5 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/m_uninstaller.h @@ -0,0 +1,703 @@ +/* + + PluginUninstaller 1.1.2.1 for Miranda IM 0.3.3a and + + ------------------------------------------------------------------------ + Developers - C/C++ Header File + + Plugin Info: ---------------------------- + | Version: 1.1.2.1 + | Filename: uninstaller.dll + | Author: H. Herkenrath (hrathh@users.sourceforge.net) + | Description: Extends the plugin options and offers the possibility + | to directly remove plugins and delete all associated + | settings and files. + + Contents: ------------------------------- + | > General Info: + | - Uninstall Example/Template + | - Changing displayed icon + | - Changing displayed docs + | - Message boxes on uninstall + | - Service Accesibility + | - Including this file + | + | > Structs: + | - Uninstall Params (PLUGINUNINSTALLPARAMS) + | + | > Helpers: + | - Macro: Run service while uninstalling (PUICallService) + | - Function: Remove some files in directory (PUIRemoveFilesInDirectory) + | + | > Events: + | - Allow to uninstall a plugin (ME_PLUGINUNINSTALLER_OKTOUNINSTALL) + | - Plugin gets uninstalled (ME_PLUGINUNINSTALLER_UNINSTALL) + | + | > Services: + | - Remove database module (MS_PLUGINUNINSTALLER_REMOVEDBMODULE) + | - Remove a setting globally (MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY) + | - Remove skinned sound (MS_PLUGINUNINSTALLER_REMOVESKINSOUND) + | - Uninstall a plugin (MS_PLUGINUNISTALLER_UNISTALLPLUGIN) + | - Getting handles (MS_PLUGINUNINSTALLER_GETHANDLE) + | + + + This file is only thought for plugin developers. + If you only want to use "PluginUninstaller" and don't want to develop a plugin + or something with it you don't need this file. + + If there are any problems or bugs with or in this file or something else + please mail me. My e-mail address is: hrathh@users.sourceforge.net + For more documentation you can use this address, too. :-) + + If you have any whishes on some plugin uninstalling for your + plugin you can mail me, too. :-) + +*/ +#ifndef M_UNINSTALLER_H +#define M_UNINSTALLER_H + +#ifndef CallService + #pragma message("Mistake Alert!: "m_uninstaller.h" needs to be included after "newpluginapi.h"!\n The following errors are resulting of this mistake.\n") +#endif + + +// | General Info +// ----------------------------- + +// Uninstall Example/Template +// --------------------------- +// Making your plugin uninstallable is very easy. +// Just add the following "Uninstall" function near the "Unload" function +// in your plugin. +// A template plugin is available in the source code package. + +// Old: +// int __declspec(dllexport) Uninstall(BOOL bIsMirandaRunning, BOOL bDoDeleteSettings, char* pszPluginPath); + +// New: +//int __declspec(dllexport) UninstallEx(PLUGINUNINSTALLPARAMS* ppup) +//{ + // Available Variables: + // ----------------------------- + // ppup->bIsMirandaRunning: + // Contains if Miranda is running + // (Currently this is always TRUE). + + // ppup->bDoDeleteSettings: + // Contains if the users selected + // that he wants all settings be deleted. + + // ppup->pszPluginsPath: + // Contains the plugins directory name. + + + // Notes: + // ----------------------------- + + // Run before "Unload" function: + // -> IMPORTANT: Be careful not to write to the database or to files in "Unload" again!!! + // -> Perhaps create a global BOOL variable which is set to TRUE when your plugin gets uninstalled + // or check of a database setting "IsInstalled" in Unload() or sth. like that + + // All Miranda is still loaded + + // Here you can do: + // - Delete settings group in database + // - Delete registry items + // - Delete ini-files and other settings files + // - Delete other files + + // Your plugin dll gets automatically deleted + + // Services to remove are offered: + // MS_PLUGINUNINSTALLER_REMOVEDBMODULE + // MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY + // MS_PLUGINUNINSTALLER_REMOVESKINSOUND + + + // Getting other useful paths: + // ----------------------------- + + // System directory: + + //char szSysPath[MAX_PATH]; + //GetSystemDirectory(szSysPath, MAX_PATH); + + + // Windows directory: + + //char szWinPath[MAX_PATH]; + //GetWindowsDirectory(szWinPath, MAX_PATH); + + + // Other directories: + + // char szPath[MAX_PATH]; + // SHGetSpecialFolderPath(NULL, szPath, CSIDL_* , FALSE); + + // Some available dirs: + // CSIDL_APPDATA CSIDL_SENDTO CSIDL_FAVORITES + // CSIDL_STARTUP CSIDL_PROFILE CSIDL_DESKTOPDIRECTORY + + + // Delete Files + //const char* apszFiles[] = {"MyPlugin_Readme.txt", "MyPlugin_License.txt", "MyPlugin_Developer.txt", "MyPlugin_Translation.txt"}; + //PUIRemoveFilesInPath(ppup->pszPluginsPath, apszFiles); + + // Delete Settings + //if(ppup->bDoDeleteSettings == TRUE) + //{ + //if (ppup->bIsMirandaRunning == TRUE) // Check if it is possible to access services + //{ + // Remove plugin's module + //PUIRemoveDbModule("MyPlugin"); + + // Remove plugin's sounds + //PUIRemoveSkinSound("MySoundSetting1"); + //PUIRemoveSkinSound("MySoundSetting2"); + //} + //} + + // Remember: + // Do not forget to remove your (eventually) created registry items here, too. + + + // The plugin's dll file gets deleted after returning. + + // Remember: + // If your DLL file is additionally in use by another application (eg. Windows) + // you need to free the DLL *here* completely. Otherwise it can't be deleted. + +// return 0; +//} + + + +// Changing displayed icon +// --------------------------- +// The icon that gets displayed on the options page is always the "first" +// icon in your DLL file. +// An icon in your DLL file is the first icon when it has the lowest recource ID. +// If you would like to have an other icon shown in the options please change your +// icon resource IDs so that the icon you would like to have has the lowest one. +// For example if you use MS Visual C++, open "resource.h" and change the resource define +// of your prefered icon to the lowest icon number. + + +// Changing displayed docs +// --------------------------- +// The items "License" and "More Information" on the plugin details page +// are created when the a license and/or a readme file for the plugin exists. +// The files get detected automatically and need a special name +// so that they get detected. +// The text files need to be either placed in the "Plugins" directory or +// in the "Docs" directory. Whereof the last one is the better one :-) +// +// For the license file the following file name formatings are possible: +// PluginName-License.txt (I personally think that this is the best naming solution... :-) ) +// PluginName_License.txt, +// +// For the readme file the following ones are possible: +// PluginName-Readme.txt (Again...I like this one :-D ), +// PluginName_Readme.txt, + +// Message boxes on uninstall +// --------------------------- +// If you would like to ask the user for something to remove/uninstall +// please hook the event ME_PLUGINUNINSTALLER_UNINSTALL and show your +// message box there. Save the action the user chose in a +// global BOOL variable and do the chosen action in "UninstallEx". +// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE. + + +// Service Accessibility +// --------------------------- +// Remember that you only can use these functions after the event ME_SYSTEM_MODULESLOADED +// or later because "PluginUninstaller" needs to be loaded first. +// Normally you only use them in your "UninstallEx" function. +// +// IMPORTANT!: +// Please make sure that you always use the macro PUICallService +// in the "UninstallEx" function instead of the CallService function. + + +// Including this file +// --------------------------- +// To use some of the uninstalling functionality you have to include this file +// into your project. +// +// IMPORTANT!: +// Please make sure that you include the file "newpluginapi.h" before this one. +// If this isn't the case there may some compile errors come up. + + // -> Example: + // If your plugin is in the directory "Plugins/MyPlugin/" and + // this include file is in the directory "Plugins/PluginUninstaller" + // you can use the following: + + //#include "../PluginUninstaller/m_uninstaller.h" + + // If your plugin is in an directory that is different to that one just + // change the include path to the one you want. + + + + + +// | Structs +// ----------------------------- + +// --------------------------------------------- +// -- Struct: Uninstall Params ----------------- +// --------------------------------------------- + +// Struct: PLUGINUNINSTALLPARAMS +// (Gets passed to "UninstallEx" function) + +typedef int (*HELPERPROC)(const char*, WPARAM, LPARAM); // Used internally (for pHelperProcAddress) + +typedef struct { + BOOL bIsMirandaRunning; // Is TRUE when Miranda is loaded and services are available (Please use PUICallService instead of CallService) + BOOL bDoDeleteSettings; // Is TRUE when user wants to delete settings (If this is FALSE, please only delete your files) + char* pszPluginsPath; // Contains the plugin directory path + char* pszDocsPath; // Contains the document directory for plugins documentation (Added in version 1.1.1.0) + char* pszIconsPath; // Contains the icon directory for icon dlls (Added in version 1.1.2.0) + HELPERPROC pHelperProcAddress; // Used internally (Contains proc address for PUICallService) +} PLUGINUNINSTALLPARAMS; + + + + + +// | Helper +// ----------------------------- + + +// --------------------------------------------- +// -- Macro: Run service while uninstalling ---- +// --------------------------------------------- + +// Macro: PUICallService + +#define PUICallService(service, wParam, lParam) (ppup->pHelperProcAddress) (service, wParam, lParam); + +// Description: +// ------------- +// This service provides the possibility to call a Miranda +// service in the "UninstallEx" function. +// Important!: Use this macro always instead of "CallService", +// because else a crash occurs when the plugin was decativated +// and gets uninstalled + +// Parameters: +// ------------- +// Same parameters as CallService of Miranda Core. + +// Return Values: +// -------------- +// Return values are the same as the CallService function of Miranda Core. +// Additionaly returns CALLSERVICE_NOTFOUND if Miranda is not loaded +// which means the services are not accessable. + + + // Example: + // ---------------------------------- + + //if ( (bIsMirandaRunning == TRUE) && (bDoDeleteSettings == TRUE) ) + //{ + // Remove plugin's module + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)"MyPlugin", 0); + //} + + + + +// --------------------------------------------- +// -- Function: Remove some files in directory - +// --------------------------------------------- + +// Function: PUIRemoveFilesInDirectory + +static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[]); + +// Description: +// ------------- +// This helper provides the possibility to easily +// remove specified files in a specified directory. + +// Note: The last version of this helper (PUIRemoveFilesInPath) +// did not work correctly. +// Please do now always append a NULL slot to the end of your array. + +// Parameters: +// ------------- +// char* pszPath = Path to the files in array +// const LPCSTR apszFiles[] = NULL-terminated array of files to be deleted. + +// Return Values: +// -------------- +// Returns TRUE if the files could be deleted. +// FALSE if the files could not be deleted or did not exist. + + +static BOOL __inline PUIRemoveFilesInDirectory(char* pszPath, const char* apszFiles[]) +{ + char szFile[MAX_PATH]; + BOOL bReturn = FALSE; + unsigned iFile = 0; + unsigned cbPath = (unsigned)lstrlenA(pszPath); + + for (; apszFiles[iFile] != NULL; ++iFile) + { + if(cbPath + lstrlenA(apszFiles[iFile]) < sizeof(szFile) / sizeof(szFile[0])) + { + lstrcpyA(szFile, pszPath); + lstrcatA(szFile, apszFiles[iFile]); + + if (DeleteFileA(szFile)) bReturn = TRUE; + } + } + + return bReturn; +} + + // Example: + // ---------------------------------- + + //const char* apszFiles[] = {"File1.txt", "File2.txt", "File3.txt", NULL}; + //PUIRemoveFilesInDirectory(ppup->pszPluginsPath, apszFiles); + + + + +// | Events +// ----------------------------- + + +// --------------------------------------------- +// -- Event: Allow to uninstall a plugin ------- +// --------------------------------------------- + +// Event: ME_PLUGINUNINSTALLER_OKTOUNINSTALL + +#define ME_PLUGINUNINSTALLER_OKTOUNINSTALL "PluginUninstaller/OkToUninstall" + +// Submitted Values: +// ----------------- +// wParam = pszPluginName (String containing the translated plugin name) +// lParam = pszPluginFile (String containing the plugin dll file name in lower case) + +// Return Values: +// ----------------- +// Returning 1 on this event causes the "Remove Plugin" button to be disabled. + + + +// --------------------------------------------- +// -- Event: Plugin gets uninstalled ----------- +// --------------------------------------------- + +// Event: ME_PLUGINUNINSTALLER_UNINSTALL + +#define ME_PLUGINUNINSTALLER_UNINSTALL "PluginUninstaller/Uninstall" + +// Submitted Values: +// ----------------- +// wParam = pszPluginName (String containing the translated plugin name) +// lParam = pszPluginFile (String containing the plugin dll file name in lower case) + +// Return Values: +// ----------------- +// Returning 1 on this event causes the uninstall process to be canceled. + +// Notice: +// Hook this event if you would like to ask the user for something to remove/uninstall +// and show your message box on this event. Save the action the user chose in a +// global BOOL variable and do the chosen action in "UninstallEx". +// You can get the plugins options window handle with MS_PLUGINUNINSTALLER_GETHANDLE. + +// Other plugins can use this event to be noticed that another plugin isn't installed anylonger. + + + + +// | Services +// ----------------------------- + + +// --------------------------------------------- +// -- Service: Remove database module ---------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_REMOVEDBMODULE + +#define MS_PLUGINUNINSTALLER_REMOVEDBMODULE "PluginUninstaller/RemoveDbModule" + +// Description: +// ------------- +// This service provides the possibility to delete all database modules +// associated to your plugin. +// The specified database module will be removed in all contacts +// including the NULL contact. +// Remember to call it always with PUICallService in "UninstallEx" function. + +// Parameters: +// ------------- +// wParam = (char*)pszModule // Pointer to a string containd module name. Can't be NULL +// lParam = (const char*)apszIgnoreSettings // NULL terminated array of strings. Can be 0 if no settings should be ignored. + // See example 3 for more details + +// Return Values: +// -------------- +// Returns 0 on success. +// Nonzero if the module was not present in database. + + +#ifndef UNINSTALLER_NOHELPERS + +// Can only be used in "UninstallEx" function +#define PUIRemoveDbModule(pszModule) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)pszModule, 0); + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIRemoveDbModule("MyPlugin"); + + + // Example 2: + // ---------------------------------- + + //char szModule[] = "MyModule"; + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, 0); + + + // Example 3: + // ---------------------------------- + + // This deletes all settings in the specified module exept + // the specified settings: "Setting1",..."Setting4" + + // char szModule[] = "MyModule"; + // const char* apszIgnoreSettings[] = {"Setting1", "Setting2", "Setting3", "Setting4", NULL}; + // PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szModule, (LPARAM)&apszIgnoreSettings); + + + +// --------------------------------------------- +// -- Service: Remove a setting globally ------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY + +#define MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY "PluginUninstaller/RemoveDbSettingGlobally" + +// Description: +// ------------- +// This service provides the possibility to delete a specific +// setting in database in all contacts including the NULL contact. +// Remember to call it always with PUICallService in "UninstallEx" function. + +// Parameters: +// ------------- +// wParam = (char*)pszModule +// lParam = (char*)pszSetting + +// Return Values: +// -------------- +// Returns 0 on success. +// Nonzero if the setting was not present in database. + + +#ifndef UNINSTALLER_NOHELPERS + +// Can only be used in "UninstallEx" function +#define PUIRemoveDbSettingGlobally(pszModule, pszSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)pszModule, (LPARAM)pszSetting); + + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIRemoveDbSettingGlobally("MyPlugin", "MySetting"); + + + // Example 2: + // ---------------------------------- + + //szModule[] = "MyPlugin"; + //szSetting[] = "MySetting"; + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBSETTINGGLOBALLY, (WPARAM)szModule, (LPARAM)szSetting); + + + + + + +// --------------------------------------------- +// -- Service: Remove skinned sound ------------ +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_REMOVESKINSOUND + +#define MS_PLUGINUNINSTALLER_REMOVESKINSOUND "PluginUninstaller/RemoveSkinSound" + +// Description: +// ------------- +// This service provides the possibility to delete all your sound settings +// associated to your plugin. +// The specified sound will be be removed. +// Remember to call it always with PUICallService in "UninstallEx" function. + +// Parameters: +// ------------- +// wParam = (char*)pszSoundSetting +// lParam = 0 + +// Return Values: +// -------------- +// Returns 0 on success. +// Nonzero if the sound was not present in database. + + +#ifndef UNINSTALLER_NOHELPERS + +// Can only be used in "UninstallEx" function +#define PUIRemoveSkinSound(pszSoundSetting) PUICallService(MS_PLUGINUNINSTALLER_REMOVESKINSOUND, (WPARAM)pszSoundSetting, 0); + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIRemoveSkinSound("MySoundSetting"); + + + // Example 2: + // ---------------------------------- + + //szSoundModule[] = "MySoundSetting"; + //PUICallService(MS_PLUGINUNINSTALLER_REMOVEDBMODULE, (WPARAM)szSoundSetting, 0); + + + + + +// --------------------------------------------- +// -- Service: Uninstall a plugin -------------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN + +#define MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN "PluginUninstaller/UninstallPlugin" + +// Description: +// ------------- +// This service marks a plugin to be uninstalled at next restart of Miranda IM. +// It uses the default value for "Delete all settings". +// You can use this service for example when you want that your sub-plugin gets +// also removed when your main-plugin is uninstalled. +// Note: This service is not needed for the normal uninstalling functionality. + +// Parameters: +// ------------- +// wParam = (char*)pszPluginName // do not translate this! +// lParam = (char*)pszPluginFile // without path, only file name! + +// Return Values: +// -------------- +// Returns always 0. + + +#ifndef UNINSTALLER_NOHELPERS + +int __inline PUIUninstallPlugin(char* pszPluginName, char* pszPluginFile) +{ + return CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)pszPluginName, (LPARAM)pszPluginFile); +} + +#endif + + + // Example 1: + // ---------------------------------- + + //PUIUninstallPlugin("PluginName", "plugin.dll"); + + + // Example 2: + // ---------------------------------- + + // hInst => Handle of a specific (your?) plugin + // char szPluginName[] = "YourPluginName"; + + //char* pFileName; + //char szPath[MAX_PATH]; + + //GetModuleFileName(hInst, szPath, sizeof(szPath)); + //pFileName = strrchr(szPath, '\\'); + //pFileName = pFileName+1; // Pointer arithmetic + + //CallService(MS_PLUGINUNINSTALLER_UNINSTALLPLUGIN, (WPARAM)szPluginName, (LPARAM)pFileName); + + + + +// --------------------------------------------- +// -- Service: Getting handles ----------------- +// --------------------------------------------- + +// Service: MS_PLUGINUNINSTALLER_GETHANDLE + +#define MS_PLUGINUNINSTALLER_GETHANDLE "PluginUninstaller/GetHandle" + +// Description: +// ------------- +// This service gets a specified window/instance handle. + +// Note: This service must not be used in "UninstallEx" function. +// It is mainly thought for being used in ME_PLUGINUNINSTALLER_UNINSTALL event +// to give out a MessageBox or something like that. + +// Parameters: +// ------------- +// wParam = UINT uHandleType; +// lParam = 0 + +// Possible values for wParam: +#define PUIHT_HINST_PLUGIN_INSTANCE 0 // HINSTANCE of the PluginUninstaller plugin +#define PUIHT_HWND_PLUGIN_OPTIONS 1 // HWND of the plugin options dialog (if it is loaded; else NULL) + +// Return Values: +// -------------- +// Returns the specified handle value. +// If no handle type is specified it returns NULL. +// The handle doesn't need to be destroyed. + + +#ifndef UNINSTALLER_NOHELPERS + +HANDLE __inline PUIGetHandle(UINT uHandleType) +{ + return (HANDLE)CallService(MS_PLUGINUNINSTALLER_GETHANDLE, uHandleType, 0); +} + +#endif + + + // Example + // ---------------------------------- + + //HWND hwndDlg; + //hwndDlg = (HWND)PUIGetHandle(PUIHT_HWND_PLUGIN_OPTIONS); + + + + + +#endif // M_UNINSTALLER_H diff --git a/plugins/!NotAdopted/WinPopup/m_updater.h b/plugins/!NotAdopted/WinPopup/m_updater.h new file mode 100644 index 0000000000..c83b8a4600 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/m_updater.h @@ -0,0 +1,117 @@ +#ifndef _M_UPDATER_H +#define _M_UPDATER_H + +// if you set Update::szUpdateURL to the following value when registering, as well as setting your beta site and version data, +// updater will ignore szVersionURL and pbVersionPrefix, and attempt to find the file listing URL's from the backend XML data. +// for this to work, the plugin name in pluginInfo.shortName must match the file listing exactly (except for case) +#define UPDATER_AUTOREGISTER "UpdaterAUTOREGISTER" + +typedef struct Update_tag { + int cbSize; + char *szComponentName; // component name as it will appear in the UI (will be translated before displaying) + + char *szVersionURL; // URL where the current version can be found (NULL to disable) + BYTE *pbVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data + // (not that this URL could point at a binary file - dunno why, but it could :) + int cpbVersionPrefix; // number of bytes pionted to by pbVersionPrefix + char *szUpdateURL; // URL where dll/zip is located + // set to UPDATER_AUTOREGISTER if you want updater to find the file listing URLs (ensure plugin shortName matches file listing!) + + char *szBetaVersionURL; // URL where the beta version can be found (NULL to disable betas) + BYTE *pbBetaVersionPrefix; // bytes occuring in VersionURL before the version, used to locate the version information within the URL data + int cpbBetaVersionPrefix; // number of bytes pionted to by pbVersionPrefix + char *szBetaUpdateURL; // URL where dll/zip is located + + BYTE *pbVersion; // bytes of current version, used for comparison with those in VersionURL + int cpbVersion; // number of bytes pionted to by pbVersion + + char *szBetaChangelogURL; // url for displaying changelog for beta versions +} Update; + +// register a comonent with the updater +// +// wparam = 0 +// lparam = (LPARAM)&Update +#define MS_UPDATE_REGISTER "Update/Register" + +// utility functions to create a version string from a DWORD or from pluginInfo +// point buf at a buffer at least 16 chars wide - but note the version string returned may be shorter +// +__inline static char *CreateVersionString(DWORD version, char *buf) { + mir_snprintf(buf, 16, "%d.%d.%d.%d", (version >> 24) & 0xFF, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF); + return buf; +} + +__inline static char *CreateVersionStringPlugin(PLUGININFO *pluginInfo, char *buf) { + return CreateVersionString(pluginInfo->version, buf); +} + + +// register the 'easy' way - use this method if you have no beta URL and the plugin is on the miranda file listing +// NOTE: the plugin 'short name' in pluginInfo must match the name of the plugin on the file listing, exactly (not including case) +// AND the plugin version string on the file listing must be the string version of the version in pluginInfo (i.e. 0.0.0.1, +// so no letters, brackets, etc.) +// +// wParam = (int)fileID - this is the file ID from the file listing (i.e. the number at the end of the download link) +// lParam = (PLUGININFO*)&pluginInfo +#define MS_UPDATE_REGISTERFL "Update/RegisterFL" + +// this event is fired when the startup process is complete, but NOT if a restart is imminent +// it is designed for status managment plugins to use as a trigger for beggining their own startup process +// wParam = lParam = 0 (unused) +// (added in version 0.1.6.0) +#define ME_UPDATE_STARTUPDONE "Update/StartupDone" + +// this service can be used to enable/disable Updater's global status control +// it can be called from the StartupDone event handler +// wParam = (BOOL)enable +// lParam = 0 +// (added in version 0.1.6.0) +#define MS_UPDATE_ENABLESTATUSCONTROL "Update/EnableStatusControl" + +// An description of usage of the above service and event: +// Say you are a status control plugin that normally sets protocol or global statuses in your ModulesLoaded event handler. +// In order to make yourself 'updater compatible', you would move the status control code from ModulesLoaded to another function, +// say DoStartup. Then, in ModulesLoaded you would check for the existence of the MS_UPDATE_ENABLESTATUSCONTROL service. +// If it does not exist, call DoStartup. If it does exist, hook the ME_UPDATE_STARTUPDONE event and call DoStartup from there. You may +// also wish to call MS_UPDATE_ENABLESTATUSCONTROL with wParam == FALSE at this time, to disable Updater's own status control feature. + +#endif + + +/////////////// Usage Example /////////////// + +#ifdef EXAMPLE_CODE + +// you need to #include "m_updater.h" and HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded) in your Load function... + +int OnModulesLoaded(WPARAM wParam, LPARAM lParam) { + + Update update = {0}; // for c you'd use memset or ZeroMemory... + char szVersion[16]; + + update.cbSize = sizeof(Update); + + update.szComponentName = pluginInfo.shortName; + update.pbVersion = (BYTE *)CreateVersionString(&pluginInfo, szVersion); + update.cpbVersion = strlen((char *)update.pbVersion); + + // these are the three lines that matter - the archive, the page containing the version string, and the text (or data) + // before the version that we use to locate it on the page + // (note that if the update URL and the version URL point to standard file listing entries, the backend xml + // data will be used to check for updates rather than the actual web page - this is not true for beta urls) + update.szUpdateURL = "http://scottellis.com.au:81/test/updater.zip"; + update.szVersionURL = "http://scottellis.com.au:81/test/updater_test.html"; + update.pbVersionPrefix = (BYTE *)"Updater version "; + + update.cpbVersionPrefix = strlen((char *)update.pbVersionPrefix); + + CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update); + + // Alternatively, to register a plugin with e.g. file ID 2254 on the file listing... + // CallService(MS_UPDATE_REGISTERFL, (WPARAM)2254, (LPARAM)&pluginInfo); + + return 0; +} + +#endif diff --git a/plugins/!NotAdopted/WinPopup/mailslot.cpp b/plugins/!NotAdopted/WinPopup/mailslot.cpp new file mode 100644 index 0000000000..5774cfa2a9 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/mailslot.cpp @@ -0,0 +1,313 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "mailslot.h" +#include "messagebox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define MAX_MESSAGE_SIZE 424 // Размер пакета данных (байт) посылаемых/принимаемых + // через мейлслот + +mailslot pluginMailslot; // Мейлслот для приема сообщений + +/*const struct { // Список конфликтующих процессов + LPCTSTR name; +} blacklist [] = { + _T("winpopup"), + _T("vikpopup"), + _T("netter"), + _T("realpopup"), + NULL +};*/ + +//////////////////////////////////////////////////////////////////////// +// Class mailslot + +mailslot::mailslot () : + m_hMailslot (INVALID_HANDLE_VALUE), + m_MonitorTerm (NULL), + m_Monitor (NULL) +{ +} + +mailslot::~mailslot () +{ + Destroy (); +} + +bool mailslot::Create (LPCTSTR Name) +{ + CLock oLock( m_cs ); + + m_sName = Name; + + bool ret = true; + if ( ! IsValid() ) + { + // Открытие мейлслота + CString sAddr; + sAddr.Format( _T("\\\\.\\mailslot\\%s"), (LPCTSTR)m_sName ); + + m_hMailslot = CreateMailslot( sAddr, 0, 2000, NULL ); + if ( ! IsValid() ) + { + ret = false; + DWORD err = GetLastError (); + if (err == ERROR_ALREADY_EXISTS) + WarningBox (NULL, 0, _T("%s\r\n%s"), T_CREATE_ERROR, + TranslateT ("Please shutdown any other IM applications and/or Messenger service")); + else + WarningBox (NULL, err, T_CREATE_ERROR); + } + } + if (ret) + { + if (m_MonitorTerm) + ResetEvent (m_MonitorTerm); + else + m_MonitorTerm = CreateEvent (NULL, TRUE, FALSE, NULL); + m_Monitor = (HANDLE)mir_forkthread( MonitorThread, this ); + } + + return ret; +} + +void mailslot::AskForDestroy() +{ + if (m_MonitorTerm) + SetEvent (m_MonitorTerm); +} + +void mailslot::Destroy () +{ + CLock oLock( m_cs ); + + // Запрос останова мониторинга мейлслота + AskForDestroy(); + + // Закрытие мейлслота + if ( IsValid() ) + { + CloseHandle (m_hMailslot); + m_hMailslot = INVALID_HANDLE_VALUE; + } + + // Ожидание останова мониторинга + if (m_Monitor) + { + if (WaitForSingleObject (m_Monitor, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate mailslot monitor!"); + TerminateThread (m_Monitor, 0); + } + m_Monitor = NULL; + } + if (m_MonitorTerm) + { + CloseHandle (m_MonitorTerm); + m_MonitorTerm = NULL; + } +} + +bool mailslot::IsValid() const +{ + return ( m_hMailslot != INVALID_HANDLE_VALUE ); +} + +bool mailslot::SendMailslotMessage(HANDLE hContact, LPCTSTR msg, DWORD& err) +{ + // Получение адресата + CString sTo = GetNick( hContact ); + if ( sTo.IsEmpty() ) + { + err = ERROR_BAD_NETPATH; + return false; + } + + // Получение своего имени + CString sFrom = GetNick( NULL ); + if ( sFrom.IsEmpty() ) + { + err = ERROR_BAD_NETPATH; + return false; + } + + // Нет разницы группа это или компьютер + // bool bGroup = IsGroup( hContact ); + + // Сборка пакета сообщения: FROM<00>TO<00>MESSAGE<00> + COemString sOemMessage = msg; + COemString sOemTo = (LPCTSTR)sTo; + COemString sOemFrom = (LPCTSTR)sFrom; + + // Размер заголовка пакета + int fixed_size = sOemFrom.GetLength() + 1 + sOemTo.GetLength() + 1 + 1; + if ( fixed_size >= MAX_MESSAGE_SIZE ) + { + err = ERROR_BAD_LENGTH; + return false; + } + + // Создание мейлслота для отправки сообщения + CString sAddr; + sAddr.Format( _T("\\\\%s\\mailslot\\%s"), sTo, (LPCTSTR)m_sName ); + HANDLE hFile = CreateFile( sAddr, GENERIC_WRITE, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + if ( hFile == INVALID_HANDLE_VALUE ) + { + err = GetLastError(); + return false; + } + + int max_message_size = MAX_MESSAGE_SIZE - fixed_size; + char buf[ MAX_MESSAGE_SIZE ] = {}; + lstrcpynA( buf, sOemFrom, sOemFrom.GetLength() + 1 ); + lstrcpynA( buf + sOemFrom.GetLength() + 1, sOemTo, sOemTo.GetLength() + 1 ); + do + { + int message_size = ( sOemMessage.GetLength() < max_message_size ) ? + sOemMessage.GetLength() : max_message_size; + lstrcpynA( buf + fixed_size - 1, sOemMessage, message_size + 1 ); + + // Отсылка пакета + DWORD written = 0; + if ( ! WriteFile( hFile, buf, (DWORD)fixed_size + message_size, &written, NULL ) || + ( written < (DWORD)fixed_size ) ) + { + err = GetLastError(); + CloseHandle( hFile ); + return false; + } + Sleep( 100 ); + + // Укорачивание на отосланный пакет + sOemMessage.CutFromStart( message_size ); + } + while ( sOemMessage.GetLength() ); + + err = ERROR_SUCCESS; + CloseHandle( hFile ); + return true; +} + +bool mailslot::Receive(unsigned char* buf /* OEM */, DWORD size) +{ + // Разборка сообщения <00><00><00> (последний <00> необязателен) + if (size) + { + char* from = (char*) buf; + char* to = lstrnchr (from, 0, (int)size); + if (to) + { + DWORD from_len = (DWORD)( to - from + 1 ); + if ( from_len < size ) + { + to++; + size -= from_len; + char* msg = lstrnchr (to, 0, (int)size); + if (msg) + { + DWORD to_len = (DWORD)( msg - to + 1 ); + if (to_len < size) + { + msg++; + size -= to_len; + char* eof = lstrnchr (msg, 0, (int)size); + DWORD msg_len = eof ? (DWORD)( eof - msg + 1 ) : size; + if (msg_len == size) + { + CAnsiString sFrom (from); + CAnsiString sTo (to); + CAnsiString sMessage (msg); + ReceiveContactMessage(sFrom, sTo, sMessage, sMessage.GetLength ()); + return true; + } + } + } + } + } + } + return false; +} + +void mailslot::MonitorThread(void* param) +{ + if ( mailslot* pMailslot = (mailslot*)param ) + { + pMailslot->Monitor(); + pMailslot->m_Monitor = NULL; + } +} + +void mailslot::Monitor () +{ + // Ожидание прерывания 500 мс при закрытом майлслоте, иначе 50 мс + while ( WaitForSingleObject( m_MonitorTerm, IsValid() ? 50u : 500u ) == WAIT_TIMEOUT ) + { + // Проверка входящих сообщений + LPSTR buf = NULL; + for ( DWORD buf_size = MAX_MESSAGE_SIZE; IsValid(); buf_size += 1024 ) + { + if ( WaitForSingleObject( m_MonitorTerm, 0 ) != WAIT_TIMEOUT ) + break; + + if ( buf ) mir_free( buf ); + buf = (LPSTR)mir_alloc( buf_size ); + + DWORD readed = 0; + DWORD err = ReadFile (m_hMailslot, buf, buf_size, + &readed, NULL) ? ERROR_SUCCESS : GetLastError (); + if (err == ERROR_ACCESS_DENIED || err == ERROR_SEM_TIMEOUT) + { + // Тайм-аут мейлслота + break; + } + else if (err == ERROR_SUCCESS) + { + // Данные приняты + if (readed) + if (!Receive((LPBYTE)buf, readed)) + LOG("Receive error (bad format?)"); + break; + } + else if (err == ERROR_INSUFFICIENT_BUFFER) + { + // Нехватка размера буфера + continue; + } + else + { + // Другие ошибки + // ERROR_HANDLE_EOF - хендл мейлслота закрыт + LOG("ReadFile form mailslot error: %d", err); + break; + } + } + if ( buf ) mir_free( buf ); + } +} diff --git a/plugins/!NotAdopted/WinPopup/mailslot.h b/plugins/!NotAdopted/WinPopup/mailslot.h new file mode 100644 index 0000000000..921127ae6e --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/mailslot.h @@ -0,0 +1,48 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +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. +*/ + +#pragma once + +class mailslot +{ +public: + mailslot(); + ~mailslot(); + + bool Create(LPCTSTR Name); + void AskForDestroy(); // Для ускорения + void Destroy(); + bool IsValid() const; + bool SendMailslotMessage(HANDLE hContact, LPCTSTR msg, DWORD& err); + +protected: + CString m_sName; // Имя мейлслота + HANDLE m_hMailslot; // Хэндлер мейлслота + CComAutoCriticalSection m_cs; // Защита данных + HANDLE m_MonitorTerm; // Событие для остановки Monitor + HANDLE m_Monitor; // Прием/отправка сообщений через мейлслот + + bool Receive(unsigned char* buf /* OEM */, DWORD size); + static void MonitorThread(void* param); + void Monitor(); +}; + +extern mailslot pluginMailslot; // Мейлслот для приема сообщений diff --git a/plugins/!NotAdopted/WinPopup/md5.h b/plugins/!NotAdopted/WinPopup/md5.h new file mode 100644 index 0000000000..dc5284ed35 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/md5.h @@ -0,0 +1,222 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +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. +*/ + +#pragma once + +typedef unsigned long uint32; + +struct MD5Context { + uint32 buf[4]; + uint32 bits[2]; + unsigned char in[64]; +}; + +// Start MD5 accumulation. Set bit count to 0 and buffer to mysterious +// initialization constants. +inline void md5init (struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +// The four core functions - F1 is optimized somewhat +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +// This is the central step in the MD5 algorithm. +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +// The core of the MD5 algorithm, this alters an existing MD5 hash to +// reflect the addition of 16 longwords of new data. MD5Update blocks +// the data and converts bytes into longwords for this routine. +inline void md5transform (uint32 buf[4], uint32 in[16]) +{ + register uint32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +// Update context to reflect the concatenation of another buffer full of bytes. +inline void md5update (struct MD5Context *ctx, const unsigned char *buf, unsigned len) +{ + uint32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((uint32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + CopyMemory (p, buf, len); + return; + } + CopyMemory (p, buf, t); + md5transform(ctx->buf, (uint32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + CopyMemory (ctx->in, buf, 64); + md5transform(ctx->buf, (uint32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + CopyMemory (ctx->in, buf, len); +} + +// Final wrapup - pad to 64-byte boundary with the bit pattern +// 1 0* (64-bit count of bits processed, MSB-first) +inline void md5final (unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + ZeroMemory (p, count); + md5transform(ctx->buf, (uint32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + ZeroMemory (ctx->in, 56); + } else { + /* Pad block to 56 bytes */ + ZeroMemory (p, count - 8); + } + + /* Append length in bits and transform */ + ((uint32 *) ctx->in)[14] = ctx->bits[0]; + ((uint32 *) ctx->in)[15] = ctx->bits[1]; + + md5transform(ctx->buf, (uint32 *) ctx->in); + CopyMemory (digest, ctx->buf, 16); + ZeroMemory (ctx, sizeof(ctx)); /* In case it's sensitive */ +} diff --git a/plugins/!NotAdopted/WinPopup/messagebox.cpp b/plugins/!NotAdopted/WinPopup/messagebox.cpp new file mode 100644 index 0000000000..008110c269 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/messagebox.cpp @@ -0,0 +1,232 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "messagebox.h" +#include "netbios.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +class messagebox +{ +public: + messagebox () : + m_hwndOwner (NULL), + m_hwndMessageBox (NULL), + m_Timeout (0), + m_MonitorTerm (NULL) + { + } + + int WINAPI DoModal (const LPMSGBOXPARAMS lpMsgBoxParams, DWORD dwTimeout) + { + int ret = 0; + m_hwndOwner = lpMsgBoxParams->hwndOwner; + m_Timeout = dwTimeout; + m_hwndMessageBox = NULL; + m_MonitorTerm = CreateEvent (NULL, TRUE, FALSE, NULL); + if (m_MonitorTerm) { + HANDLE hThread = (HANDLE)mir_forkthread( MsgBox, this ); + if (hThread) { + + ret = MessageBoxIndirect (lpMsgBoxParams); + + // Ожидание завершения + SetEvent (m_MonitorTerm); + WaitForSingleObject (hThread, INFINITE); + } + CloseHandle (m_MonitorTerm); + } + return ret; + } + +protected: + static BOOL CALLBACK EnumWindowsProc (HWND hWnd, LPARAM lParam) + { + messagebox* self = reinterpret_cast (lParam); + + DWORD dwProcessId; + GetWindowThreadProcessId (hWnd, &dwProcessId); + const LONG req_style = WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU; + HWND hButton; + TCHAR ClassName[ 8 ]; + if ( GetCurrentProcessId () != dwProcessId || + ( GetWindowLongPtr(hWnd, GWL_STYLE) & req_style ) != req_style || + GetParent( hWnd ) != NULL || + GetWindow( hWnd, GW_OWNER ) != self->m_hwndOwner || + ( hButton = GetWindow( hWnd, GW_CHILD ) ) == NULL || + GetClassName( hButton, ClassName, _countof( ClassName ) ) == 0 || + lstrcmpi( _T("button"), ClassName ) != 0 ) + return TRUE; + + self->m_hwndMessageBox = hWnd; + + return FALSE; + } + + static void MsgBox (LPVOID param) + { + messagebox* self = reinterpret_cast (param); + + // Ловим диалог 10 секунд + DWORD i = 0; + while (WaitForSingleObject (self->m_MonitorTerm, 250) == WAIT_TIMEOUT && + EnumWindows (messagebox::EnumWindowsProc, reinterpret_cast (self)) && + i++ < 10 * 4); + if (!self->m_hwndMessageBox) + // Так и не поймали + return; + + HWND hButton = GetWindow (self->m_hwndMessageBox, GW_CHILD); + + // Отсчёт времени + while (self->m_Timeout-- && + WaitForSingleObject (self->m_MonitorTerm, 1000) == WAIT_TIMEOUT && + IsWindow (self->m_hwndMessageBox) && IsWindow (hButton)) { + CString buf, msg; + int buf_size = GetWindowTextLength (hButton); + if (buf_size) { + GetWindowText (hButton, buf.GetBuffer (buf_size + 1), buf_size + 1); + buf.ReleaseBuffer (); + } + int n = buf.ReverseFind (_T('=')); + msg.Format (_T(" = %u"), self->m_Timeout); + SetWindowText (hButton, ((n < 1) ? buf : buf.Left (n - 1)) + msg); + } + + // Закрытие окна + if (IsWindow (self->m_hwndMessageBox) && IsWindow (hButton)) { + DWORD_PTR res; + SendMessageTimeout (self->m_hwndMessageBox, WM_COMMAND, + (WPARAM) GetDlgCtrlID (hButton), + (LPARAM) hButton, SMTO_ABORTIFHUNG | SMTO_NORMAL, 10000, &res); + } + + return; + } + + volatile HWND m_hwndOwner; + volatile HWND m_hwndMessageBox; + volatile DWORD m_Timeout; + HANDLE m_MonitorTerm; +}; + +static int WINAPI MessageBoxIndirectTimeout (const LPMSGBOXPARAMS lpMsgBoxParams, DWORD dwTimeout) +{ + messagebox mb; + return mb.DoModal (lpMsgBoxParams, dwTimeout); +} + +LPCTSTR const szModules [] = { + _T("netapi32.dll"), + _T("netmsg.dll"), + _T("wininet.dll"), + _T("ntdll.dll"), + _T("ntdsbmsg.dll"), + NULL +}; + +void GetErrorMessage (DWORD dwLastError, CString &msg) +{ + CString buf; + if ( HRESULT_FACILITY( dwLastError ) == FACILITY_NETBIOS ) + { + CString sMessage = (LPCTSTR)CA2T( GetNetbiosError( HRESULT_CODE ( dwLastError ) ) ); + if ( ! sMessage.IsEmpty() ) + msg.Format( _T("%s\r\nNetBIOS %s: %u"), sMessage, T_ERROR, HRESULT_CODE( dwLastError ) ); + else + msg.Format( _T("NetBIOS %s: %u"), T_ERROR, HRESULT_CODE( dwLastError ) ); + } + else + { + HMODULE hModule = NULL; + for (int i = 0; szModules [i]; i++) + { + hModule = LoadLibraryEx (szModules [i], NULL, LOAD_LIBRARY_AS_DATAFILE); + LPTSTR MessageBuffer = NULL; + if (FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM | + (hModule ? FORMAT_MESSAGE_FROM_HMODULE : 0u), + hModule, dwLastError, 0u, (LPTSTR) &MessageBuffer, 0u, NULL)) + { + buf = MessageBuffer; + buf.Trim (_T(" \t\r\n")); + LocalFree (MessageBuffer); + if (hModule) + FreeLibrary (hModule); + break; + } + if (hModule) + FreeLibrary (hModule); + } + if ( ! buf.IsEmpty() ) + msg.Format( _T("%s\r\n%s: %u"), (LPCTSTR)buf, T_ERROR, dwLastError ); + else + msg.Format( _T("%s: %u"), T_ERROR, dwLastError ); + } +} + +static void PopupOrMessageBox (LPPOPUPDATAT ppdp) +{ + if (CALLSERVICE_NOTFOUND == PUAddPopUpT (ppdp)) + { + MSGBOXPARAMS mbp = { 0 }; + mbp.cbSize = sizeof (MSGBOXPARAMS); + mbp.lpszText = ppdp->lptzText; + mbp.lpszCaption = ppdp->lptzContactName; + mbp.dwStyle = MB_OK | MB_ICONEXCLAMATION | MB_SYSTEMMODAL; + MessageBoxIndirectTimeout (&mbp, (DWORD)ppdp->iSeconds); + } +} + +void WarningBox (HANDLE hContact /* = NULL */, DWORD dwLastError /* = 0 */, LPCTSTR format, ...) +{ + if (!pluginInstalled) + return; + + POPUPDATAT pdp = { 0 }; + pdp.lchContact = hContact; + pdp.lchIcon = (HICON) LoadImage( pluginModule, MAKEINTRESOURCE (IDI_WINPOPUP), + IMAGE_ICON, 16, 16, LR_SHARED ); + lstrcpy (pdp.lptzContactName, modtitle_t); + va_list marker; + va_start (marker, format); + wvsprintf( pdp.lptzText, format, marker ); + va_end (marker); + pdp.iSeconds = 10; + + if (dwLastError) { + CString msg; + GetErrorMessage (dwLastError, msg); + int len = lstrlen (pdp.lptzText); + pdp.lptzText [len] = _T('\r'); + pdp.lptzText [len + 1] = _T('\n'); + lstrcpy (pdp.lptzText + len + 2, msg); + } + + PopupOrMessageBox (&pdp); +} diff --git a/plugins/!NotAdopted/WinPopup/messagebox.h b/plugins/!NotAdopted/WinPopup/messagebox.h new file mode 100644 index 0000000000..bde25887f4 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/messagebox.h @@ -0,0 +1,29 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +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. +*/ + +#pragma once + +// Отображение пояснительного текста ошибки в виде высплывающей подсказки если +// установлен Popup Plugin, иначе в виде диалога с автозакрытием +void WarningBox (HANDLE hContact /* = NULL */, DWORD dwLastError /* = 0 */, LPCTSTR format, ...); + +// Получение описания WinAPI или NetBIOS ошибки по её номеру +void GetErrorMessage (DWORD dwLastError, CString &msg); diff --git a/plugins/!NotAdopted/WinPopup/messenger.cpp b/plugins/!NotAdopted/WinPopup/messenger.cpp new file mode 100644 index 0000000000..b73bd4b23a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/messenger.cpp @@ -0,0 +1,469 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "services.h" +#include "messenger.h" +#include "processapi.h" +#include "messagebox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +static bool IsMessengerRunning() +{ + bool found = false; + HANDLE h = CreateMailslot (_T("\\\\.\\mailslot\\") MESSENGER_MAIL, 0, 0, NULL); + if (h == INVALID_HANDLE_VALUE) { + if (GetLastError () == ERROR_ALREADY_EXISTS) + found = true; + else + LOG ("IsMessengerRunning() error 0x%08x", GetLastError ()); + } else + CloseHandle (h); + return found; +} + +messenger pluginMessenger; // Прием/отправка сообщений через Messenger + +messenger::messenger () : + m_MonitorTerm (NULL), + m_Monitor (NULL), + m_ID (0), + m_bMSMessengerStopped (false) +{ +} + +messenger::~messenger () +{ + Destroy (); +} + +bool messenger::Create(BOOL start) +{ + if ( pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT ) + return false; + + // Косвенная проверка, что Messenger запущен + bool messngr = IsMessengerRunning(); + if ( start ) + { + if ( ! messngr ) + Start (); + } + else + { + if ( messngr ) + Stop (); + } + + m_ID = GetProcessId (_T("csrss.exe")); + LOG ( ( m_ID ? "Messenger host process CSRSS.EXE found : PID %u(%08x)" : + "Messenger host process CSRSS.EXE not found" ), m_ID, m_ID ); + + // Запуск сканера контактов + if (m_MonitorTerm) + ResetEvent (m_MonitorTerm); + else + m_MonitorTerm = CreateEvent (NULL, TRUE, FALSE, NULL); + + if (!m_Monitor) + m_Monitor = (HANDLE)mir_forkthread( MonitorThread, this ); + + return (m_Monitor != NULL); +} + +void messenger::AskForDestroy() +{ + if (m_MonitorTerm) + SetEvent (m_MonitorTerm); +} + +void messenger::Destroy () +{ + if (pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT) + return; + + AskForDestroy(); + + if (m_Monitor) + { + if (WaitForSingleObject (m_Monitor, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate Messenger monitor!"); + TerminateThread (m_Monitor, 0); + } + m_Monitor = NULL; + } + + if (m_MonitorTerm) + { + CloseHandle (m_MonitorTerm); + m_MonitorTerm = NULL; + } + + // Запуск "Службы Сообщений", если ее останавливали + if (m_bMSMessengerStopped) + Start (); +} + +messenger::operator bool () const +{ + return (m_Monitor != NULL); +} + +BOOL CALLBACK messenger::EnumWindowsProc (HWND hWnd, LPARAM lParam) +{ + DWORD dwTargetId = reinterpret_cast (lParam)->m_ID; + DWORD dwProcessId = 0; + GetWindowThreadProcessId (hWnd, &dwProcessId); + if (dwTargetId && dwTargetId != dwProcessId) + return TRUE; + + const LONG req_style = WS_VISIBLE | WS_POPUP | WS_CAPTION | WS_SYSMENU; + const LONG req_style_ex = WS_EX_TOPMOST; + HWND hButton, hText; + TCHAR ClassName[ 8 ] = {}; + if ((GetWindowLongPtr(hWnd, GWL_STYLE) & req_style) != req_style || + (GetWindowLongPtr(hWnd, GWL_EXSTYLE) & req_style_ex) != req_style_ex || + GetParent (hWnd) != NULL || + GetWindow (hWnd, GW_OWNER) != NULL || + // child 1 = Button, child 2 = STATIC, child 3 = NULL + (hButton = GetWindow (hWnd, GW_CHILD)) == NULL || + GetClassName( hButton, ClassName, _countof( ClassName ) ) == 0 || + lstrcmpi (_T("button"), ClassName) != 0 || + (hText = GetNextWindow (hButton, GW_HWNDNEXT)) == NULL || + GetClassName( hText, ClassName, _countof( ClassName ) ) == 0 || + lstrcmpi( _T("static"), ClassName ) != 0 || + GetNextWindow (hText, GW_HWNDNEXT) != NULL) + // Чужое окно + return TRUE; + + CString buf; + int buf_size = GetWindowTextLength (hText); + if (buf_size) { + GetWindowText (hText, buf.GetBuffer (buf_size + 1), buf_size + 1); + buf.ReleaseBuffer (); + } + + if (!buf.IsEmpty ()) { + CString tok, from, to, msg; + int curPos = 0; + for (int i = 0; (tok = buf.Tokenize( _T(" "), curPos)), !tok.IsEmpty (); i++) { + switch (i) { + case 2: + from = tok; + break; + case 4: + to = tok; + break; + } + } + int n = buf.Find ( _T("\n") ); + msg = buf.Mid (n + 3); + if (!from.IsEmpty () && !to.IsEmpty () && !msg.IsEmpty ()) { + // Закрытие окна + DWORD_PTR res = 0; + SendMessageTimeout (hWnd, WM_COMMAND, (WPARAM) GetDlgCtrlID (hButton), + (LPARAM) hButton, SMTO_ABORTIFHUNG | SMTO_NORMAL, 10000, &res); + + // Ок + ReceiveContactMessage(from, to, msg, msg.GetLength ()); + } + } + + return FALSE; +} + +void messenger::Monitor () +{ + while (WaitForSingleObject (m_MonitorTerm, 250) == WAIT_TIMEOUT) + { + EnumWindows (EnumWindowsProc, reinterpret_cast (this)); + } + m_Monitor = NULL; +} + +void messenger::MonitorThread(LPVOID lpParameter) +{ + reinterpret_cast< messenger* >( lpParameter )->Monitor(); +} + +// Запуск "Службы Сообщений" +bool messenger::Start () +{ + if (pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT) + return false; + + bool ret = m_bMSMessengerStopped = false; + + // Открытие менеджера сервисов + SC_HANDLE manager = fnOpenSCManager (NULL, NULL, + STANDARD_RIGHTS_READ | SC_MANAGER_CONNECT); + if (manager) { + // Открытие сервиса + SC_HANDLE service = fnOpenService (manager, MESSENGER, + SERVICE_START | SERVICE_QUERY_STATUS); + if (service) { + for(;;) + { + // Проверка состояния сервиса + SERVICE_STATUS ss = { 0 }; + if (fnQueryServiceStatus (service, &ss)) { + if (ss.dwCurrentState == SERVICE_RUNNING) { + // Уже работает + LOG ("Messenger service already running"); + ret = true; + } else { + // Запуск сервиса + if (fnStartService (service, 0, NULL)) + // Ожидание запуска сервиса + ret = WaitForService (T_START_ERROR, service, SERVICE_START_PENDING, SERVICE_RUNNING); + else { + DWORD err = GetLastError (); + if ( err == ERROR_SERVICE_DISABLED ) + { + // Попытка разрешения сервиса + if ( Enable() ) + // Повтор + continue; + } else + WarningBox (NULL, err, T_START_ERROR); + } + } + } else + WarningBox (NULL, GetLastError (), T_START_ERROR); + break; + } + fnCloseServiceHandle (service); + } else + WarningBox (NULL, GetLastError (), T_START_ERROR); + fnCloseServiceHandle (manager); + } else + WarningBox (NULL, GetLastError (), T_START_ERROR); + return ret; +} + +// Останов "Службы Сообщений" +bool messenger::Stop () +{ + if (pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT) + return false; + + bool ret = m_bMSMessengerStopped = false; + + // Открытие менеджера сервисов + SC_HANDLE manager = fnOpenSCManager (NULL, NULL, + STANDARD_RIGHTS_READ | SC_MANAGER_CONNECT); + if (manager) + { + // Открытие сервиса + SC_HANDLE service = fnOpenService (manager, MESSENGER, + SERVICE_STOP | SERVICE_QUERY_STATUS); + if (service) + { + // Проверка состояния сервиса + SERVICE_STATUS ss = {}; + if (fnQueryServiceStatus (service, &ss)) + { + if (ss.dwCurrentState == SERVICE_STOPPED) + { + // Уже остановлен + LOG ("Messenger service already stopped"); + ret = true; // m_bMSMessengerStopped = false + } + else + { + // Останов сервиса + ZeroMemory (&ss, sizeof (SERVICE_STATUS)); + if (fnControlService (service, SERVICE_CONTROL_STOP, &ss)) + { + // Ожидание останова + ret = m_bMSMessengerStopped = WaitForService ( + T_STOP_ERROR, service, + SERVICE_STOP_PENDING, SERVICE_STOPPED); + } + else + { + if (GetLastError () == ERROR_SERVICE_NOT_ACTIVE) + // Уже остановлен + ret = true; // m_bMSMessengerStopped = false + else + WarningBox (NULL, GetLastError (), T_STOP_ERROR); + } + } + } + else + WarningBox (NULL, GetLastError (), T_STOP_ERROR); + fnCloseServiceHandle (service); + } + else + { + if (GetLastError () == ERROR_SERVICE_DOES_NOT_EXIST) + // Такого сервиса нет - ок + ret = true; // m_bMSMessengerStopped = false + else + WarningBox (NULL, GetLastError (), T_STOP_ERROR); + } + fnCloseServiceHandle (manager); + } + else + WarningBox (NULL, GetLastError (), T_STOP_ERROR); + + return ret; +} + +// Разрешение запуска "Службы Сообщений" +bool messenger::Enable () +{ + bool ret = false; + + // Открытие менеджера сервисов + SC_HANDLE manager = fnOpenSCManager (NULL, NULL, + STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG | + SC_MANAGER_CONNECT | SC_MANAGER_LOCK); + if (manager) + { + // Блокировка менеджера + SC_LOCK lock = fnLockServiceDatabase( manager ); + if (lock) + { + // Открытие сервиса + SC_HANDLE service = fnOpenService ( manager, MESSENGER, + SERVICE_CHANGE_CONFIG ); + if (service) + { + // Установка автозапуска сервиса + if ( fnChangeServiceConfig( service, SERVICE_NO_CHANGE, + SERVICE_AUTO_START, SERVICE_NO_CHANGE, + NULL, NULL, NULL, NULL, NULL, NULL, NULL ) ) + ret = true; + else + WarningBox (NULL, GetLastError (), T_ENABLE_ERROR); + + fnCloseServiceHandle (service); + } + else + WarningBox (NULL, GetLastError (), T_ENABLE_ERROR); + + fnUnlockServiceDatabase( lock ); + } + else + WarningBox (NULL, GetLastError (), T_ENABLE_ERROR); + + fnCloseServiceHandle ( manager ); + } + else + WarningBox (NULL, GetLastError (), T_ENABLE_ERROR); + return ret; +} + +bool messenger::WaitForService (LPCTSTR reason, SC_HANDLE service, DWORD process, DWORD end) +{ + SERVICE_STATUS ss = { 0 }; + if (fnQueryServiceStatus (service, &ss)) + { + DWORD dwStartTickCount = GetTickCount(); + DWORD dwOldCheckPoint = ss.dwCheckPoint; + while (ss.dwCurrentState == process) { + // Do not wait longer than the wait hint. A good interval is + // one tenth the wait hint, but no less than 1 second and no + // more than 10 seconds. + DWORD dwWaitTime = ss.dwWaitHint / 10; + if (dwWaitTime < 1000) + dwWaitTime = 1000; + else + if (dwWaitTime > 10000) + dwWaitTime = 10000; + Sleep (dwWaitTime); + // Check the status again. + if (!fnQueryServiceStatus (service, &ss)) + { + WarningBox (NULL, GetLastError (), reason); + return false; + } + if (ss.dwCurrentState == end) + break; + if (ss.dwCheckPoint > dwOldCheckPoint) + { + // The service is making progress. + dwStartTickCount = GetTickCount(); + dwOldCheckPoint = ss.dwCheckPoint; + } else + { + if (GetTickCount() - dwStartTickCount > ss.dwWaitHint) + { + WarningBox (NULL, 0, _T("%s\r\n%s"), TranslateT ("No progress"), reason); + return false; + } + } + } + if (ss.dwCurrentState == end) + return true; + WarningBox (NULL, 0, _T("%s\r\n%s"), TranslateT ("Unexpected service status change"), reason); + } + else + WarningBox (NULL, GetLastError (), reason); + return false; +} + +bool messenger::SendMessengerMessage(HANDLE hContact, LPCTSTR msg, DWORD& err) +{ + if ( pluginOS.dwPlatformId != VER_PLATFORM_WIN32_NT || ! fnNetMessageBufferSend ) + { + err = ERROR_NOT_SUPPORTED; + return false; + } + + // Получение адресата + CString sTo = GetNick( hContact ); + if ( sTo.IsEmpty() ) + { + err = NERR_NameNotFound; + return false; + } + + // Получение своего имени + CString sFrom = GetNick( NULL ); + if ( sFrom.IsEmpty() ) + { + err = NERR_NameNotFound; + return false; + } + + // Нет разницы группа это или компьютер + // bool bGroup = IsGroup( hContact ); + + LPWSTR wto = mir_t2u( sTo ); + LPWSTR wfrom = mir_t2u( sFrom ); + LPWSTR wmsg = mir_t2u( msg ); + err = fnNetMessageBufferSend( NULL, wto, wfrom, (LPBYTE)wmsg, + lstrlen( msg ) * sizeof( WCHAR ) ); + mir_free( wto ); + mir_free( wfrom ); + mir_free( wmsg ); + + return ( err == NERR_Success ); +} diff --git a/plugins/!NotAdopted/WinPopup/messenger.h b/plugins/!NotAdopted/WinPopup/messenger.h new file mode 100644 index 0000000000..582b4d554c --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/messenger.h @@ -0,0 +1,54 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +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. +*/ + +#pragma once + +class messenger +{ +public: + messenger (); + ~messenger (); + + bool Create (BOOL start); + void AskForDestroy(); // Для ускорения + void Destroy (); + operator bool () const; + + bool Start (); // Запуск "Службы Сообщений" + bool Stop (); // Останов "Службы Сообщений" + bool Enable (); // Разрешение запуска "Службы Сообщений" + + bool SendMessengerMessage(HANDLE hContact, LPCTSTR msg, DWORD& err); + +protected: + HANDLE m_MonitorTerm; // Событие для остановки + HANDLE m_Monitor; // Периодическая проверка + DWORD m_ID; // ID процесса CSRSS.EXE + bool m_bMSMessengerStopped; // Флаг показывающий был ли остановлен + // MS Messenger с помощью функции Stop() + + void Monitor (); + static BOOL CALLBACK EnumWindowsProc (HWND hwnd, LPARAM lParam); + static void MonitorThread (LPVOID lpParameter); + static bool WaitForService (LPCTSTR reason, SC_HANDLE service, DWORD process, DWORD end); +}; + +extern messenger pluginMessenger; // Прием/отправка сообщений через Messenger diff --git a/plugins/!NotAdopted/WinPopup/netbios.cpp b/plugins/!NotAdopted/WinPopup/netbios.cpp new file mode 100644 index 0000000000..21a0cfd3c4 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/netbios.cpp @@ -0,0 +1,1065 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "netbios.h" +#include "smbconst.h" +#include "messagebox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +netbios pluginNetBIOS; // Прием/отправка сообщений через NetBIOS + +// Макрос печати NetBIOS-имени +#define NETBIOS_NAME_TRACE(bb,mm,nn) mir_snprintf((bb),(mm),"%s #%d %02x %c %s", \ + (nn.GetANSIFullName()), (nn.name_num), (nn.name_flags), \ + (((nn.name_flags & GROUP_NAME) == GROUP_NAME) ? 'G' : 'U'), \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == REGISTERING) ? "REGISTERING" : \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == REGISTERED) ? "REGISTERED" : \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == DEREGISTERED) ? "DEREGISTERED" : \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == DUPLICATE) ? "DUPLICATE" : \ + (((nn.name_flags & (NAME_FLAGS_MASK & ~GROUP_NAME)) == DUPLICATE_DEREG) ? "DUPLICATE_DEREG" : \ + "UNKNOWN")))))); + +// NetBIOS commands +static const struct +{ + UCHAR code; // NetBIOS command code + LPCSTR name; // NetBIOS command description +} +NCBCommands[] = +{ + { NCBCALL, "CALL" }, + { NCBLISTEN, "LISTEN" }, + { NCBHANGUP, "HANG UP" }, + { NCBSEND, "SEND" }, + { NCBRECV, "RECEIVE" }, + { NCBRECVANY, "RECEIVE ANY" }, + { NCBCHAINSEND, "CHAIN SEND" }, + { NCBDGSEND, "SEND DATAGRAM" }, + { NCBDGRECV, "RECEIVE DATAGRAM" }, + { NCBDGSENDBC, "SEND BROADCAST DATAGRAM" }, + { NCBDGRECVBC, "RECEIVE BROADCAST DATAGRAM" }, + { NCBADDNAME, "ADD NAME" }, + { NCBDELNAME, "DELETE NAME" }, + { NCBRESET, "RESET" }, + { NCBASTAT, "ADAPTER STATUS" }, + { NCBSSTAT, "SESSION STATUS" }, + { NCBCANCEL, "CANCEL" }, + { NCBADDGRNAME, "ADD GROUP NAME" }, + { NCBENUM, "ENUMERATE LANA NUMBERS" }, + { NCBUNLINK, "UNLINK" }, + { NCBSENDNA, "SEND NO ACK" }, + { NCBCHAINSENDNA, "CHAIN SEND NO ACK" }, + { NCBLANSTALERT, "LAN STATUS ALERT" }, + { NCBACTION, "ACTION" }, + { NCBFINDNAME, "FIND NAME" }, + { NCBTRACE, "TRACE" }, + { 0, NULL } +}; + +// NetBIOS errors +static const struct +{ + UCHAR error; // NetBIOS error code + LPCSTR message; // NetBIOS error message +} +NRCErrors [] = +{ + { NRC_GOODRET, "The operation succeeded." }, + { NRC_BUFLEN, "An illegal buffer length was supplied." }, + { NRC_ILLCMD, "An illegal command was supplied." }, + { NRC_CMDTMO, "The command was timed out." }, + { NRC_INCOMP, "The message was incomplete. The application is to issue another command." }, + { NRC_BADDR, "The buffer address was illegal." }, + { NRC_SNUMOUT, "The session number was out of range." }, + { NRC_NORES, "No resource was available." }, + { NRC_SCLOSED, "The session was closed." }, + { NRC_CMDCAN, "The command was canceled." }, + { NRC_DUPNAME, "A duplicate name existed in the local name table." }, + { NRC_NAMTFUL, "The name table was full." }, + { NRC_ACTSES, "The command finished; the name has active sessions and is no longer registered." }, + { NRC_LOCTFUL, "The local session table was full." }, + { NRC_REMTFUL, "The remote session table was full. The request to open a session was rejected." }, + { NRC_ILLNN, "An illegal name number was specified." }, + { NRC_NOCALL, "The system did not find the name that was called." }, + { NRC_NOWILD, "Wildcards are not permitted in the ncb_name member." }, + { NRC_INUSE, "The name was already in use on the remote adapter." }, + { NRC_NAMERR, "The name was deleted." }, + { NRC_SABORT, "The session ended abnormally." }, + { NRC_NAMCONF, "A name conflict was detected." }, + { NRC_IFBUSY, "The interface was busy." }, + { NRC_TOOMANY, "Too many commands were outstanding; the application can retry the command later." }, + { NRC_BRIDGE, "The ncb_lana_num member did not specify a valid network number." }, + { NRC_CANOCCR, "The command finished while a cancel operation was occurring." }, + { NRC_CANCEL, "The NCBCANCEL command was not valid; the command was not canceled." }, + { NRC_DUPENV, "The name was defined by another local process." }, + { NRC_ENVNOTDEF, "The environment was not defined." }, + { NRC_OSRESNOTAV, "Operating system resources were exhausted. The application can retry the command later." }, + { NRC_MAXAPPS, "The maximum number of applications was exceeded." }, + { NRC_NOSAPS, "No service access points (SAPs) were available for NetBIOS." }, + { NRC_NORESOURCES, "The requested resources were not available." }, + { NRC_INVADDRESS, "The NCB address was not valid." }, + { NRC_INVDDID, "The NCB DDID was invalid." }, + { NRC_LOCKFAIL, "The attempt to lock the user area failed." }, + { NRC_OPENERR, "An error occurred during an open operation being performed by the device driver." }, + { NRC_SYSTEM, "A system error occurred." }, + { NRC_PENDING, "An asynchronous operation is not yet finished." }, + { 0, NULL } +}; + +LPCSTR GetNetbiosCommand(UCHAR command) +{ + command &= 0x7f; // strip ASYNCH bit + for ( int i = 0; NCBCommands[ i ].name; ++i ) + if ( NCBCommands[ i ].code == command ) + return NCBCommands[ i ].name; + return "UNKNOWN"; +} + +LPCSTR GetNetbiosError(UCHAR err) +{ + for ( int i = 0; NRCErrors [ i ].message; ++i ) + if ( NRCErrors [ i ].error == err ) + return NRCErrors [ i ].message; + return "Unknown error."; +} + +UCHAR NetbiosEx(NCB* pNCB) +{ + UCHAR command = pNCB->ncb_command; + UCHAR ret = Netbios( pNCB ); + //if ( ret != NRC_GOODRET ) + if ( ret == pNCB->ncb_retcode ) + { + LOG( "NetBIOS call 0x%02x \"%s\" result: 0x%02x \"%s\"", + command, GetNetbiosCommand( command ), + ret, GetNetbiosError( ret ) ); + } + else + { + LOG( "NetBIOS call 0x%02x \"%s\" result: 0x%02x \"%s\", return: 0x%02x \"%s\"", + command, GetNetbiosCommand( command ), + ret, GetNetbiosError( ret ), + pNCB->ncb_retcode, GetNetbiosError( pNCB->ncb_retcode ) ); + } + return ret; +} + +// Определение NCB не на стеке +// KB317437: "NetBIOS Listen May Return a Damaged NCB Structure" +// The _NCB structure that is returned when a NetBIOS Listen call completes may have a changed server name offset. +class CNCB +{ +public: + CNCB() : + m_buf( VirtualAlloc( NULL, 4096, MEM_COMMIT, PAGE_READWRITE ) ) + { + } + + ~CNCB() + { + if ( m_buf ) + { + VirtualFree( m_buf, 0, MEM_RELEASE ); + } + } + + inline operator bool() const + { + return ( m_buf != NULL ); + } + + inline operator NCB*() const + { + return (NCB*)m_buf; + } + + inline NCB* operator->() const + { + return (NCB*)m_buf; + } + +protected: + void* m_buf; +}; + +//////////////////////////////////////////////////////////////////////// +// Class netbios + +netbios::netbios () : + m_initialized( false ) +{ + ZeroMemory (&m_le, sizeof (m_le)); +} + +netbios::~netbios () +{ + Destroy (); +} + +bool netbios::Create (BOOL registration) +{ + CLock oLock( m_csData ); + + if ( ! m_initialized ) + { + // Перечисление адаптеров + if ( EnumLanas( m_le ) == NRC_GOODRET ) + { + // Сброс адаптеров + for ( UCHAR i = 0; i < m_le.length; i++ ) + { + ResetLana( m_le.lana [i] ); + } + + // Регистрация имён, если нужна + if ( registration ) + { + Register (); + } + } + + m_initialized = true; + } + + return m_initialized; +} + +void netbios::AskForDestroy() +{ + CLock oLock( m_csData ); + + // Запрос на дерегистрацию имён + for ( size_t i = 0; i < m_names.GetCount (); ++i ) + m_names [i]->AskForDestroy(); +} + +void netbios::Destroy () +{ + CLock oLock( m_csData ); + + if ( m_initialized ) + { + Deregister(); + m_initialized = false; + } +} + +unsigned char* netbios::SetSMBHeaderCommand (unsigned char* szHeader, BYTE iCommandCode, size_t iBufferLen) +{ + ZeroMemory (szHeader, iBufferLen); + *(DWORD*)szHeader = SMB_MAGIC; + szHeader [4] = iCommandCode; + return (szHeader + SMB_HEADER_SIZE); +} + +netbios::operator bool() const +{ + return m_initialized; +} + +bool netbios::SendNetBIOSMessage(HANDLE hContact, LPCTSTR msg, DWORD& err) +{ + // Created by Ilja Razinkov (also known as IPv6), 2002, IPv6Intendo@yandex.ru + // Keep this comment if you redistribute this file + + //Схема отправки большого NB-сообщения: + //1) Шлется D5. Текст сообщения: + //- 00, длина остатка A (1 байт), 00 (3 байта) + //- остаток A. 04, строка КТО, 00, 04, строка КОМУ, 00 + //в ответ приходит КОД СООБЩЕНИЯ (2 байта) и 00,00,00 (всего 5 байт), с D5 в заголовке + // + //2) Шлется D7. Текст сообщения: + //- КОД СООБЩЕНИЯ (2 байта), 00, длина остатка (A+B) (1 байт), 00 (всего 5 байт) + //- остаток A. 01, длина остатка B, 00 (3 байта) + //- остаток B. очередной кусок посланного СООБЩЕНИЯ + //в ответ приходит пустое сообщение (с 3мя 0-лями), с D7 в заголовке + // + //3) Пункт 2 повторяется пока не будет отослано все СООБЩЕНИЕ + // + //4) Шлется D6.Текст сообщения: + //- КОД СООБЩЕНИЯ (2 байта), 00, 00, 00 (всего 5 байт) + //в ответ приходит пустое сообщение (с 3мя 0-лями), с D6 в заголовке + + // Получение адресата + CString sTo = GetNick( hContact ); + if ( sTo.IsEmpty() ) + { + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, NRC_NOCALL ); + return false; + } + + // Получение своего имени + CString sFrom = GetNick( NULL ); + if ( sFrom.IsEmpty() ) + { + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, NRC_NOCALL ); + return false; + } + + bool bGroup = IsGroup( hContact ); + + // Подготовка данных + CStringA sMessage( msg ); + sMessage.AnsiToOem(); + sMessage.Replace( "\r\n", "\x14" ); // -> <14> + sMessage.Replace( "\r", "\x14" ); // -> <14> + sMessage.Replace( "\n", "\x14" ); // -> <14> + netbios_name nname_To( sTo, 3, bGroup ); + netbios_name nname_From( sFrom, 3 ); + + // Поиск адаптера + UCHAR lana = 0; + if ( ! FindNameLana( nname_To, lana ) ) + { + LOG ("SendNetBIOSMessage : Unknown name"); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, NRC_NOCALL ); + return false; + } + + // Коннект к клиенту + UCHAR lsn = 0; + err = Call (lana, nname_From, nname_To, lsn); + if (err != NRC_GOODRET) + { + LOG ("SendNetBIOSMessage : Cannot connect" ); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + + UCHAR SMBBlock [168] = { 0 }; + UCHAR* szSMBData = NULL; + UCHAR iFromLen = (UCHAR)nname_From.GetLength (); + UCHAR iToLen = (UCHAR)nname_To.GetLength (); + UCHAR iHiMsgCode = 0, iLoMsgCode = 0; + + // 1. Шлем заголовок + LOG ( "SendNetBIOSMessage : Send start of multi-block message" ); + szSMBData = SetSMBHeaderCommand (SMBBlock, SMBsendstrt, sizeof (SMBBlock)); + UCHAR dwD5ALength = (UCHAR)( 1 + iFromLen + 2 + iToLen + 1 ); + szSMBData[1] = dwD5ALength; + szSMBData[3] = 4; + szSMBData[4+iFromLen+1] = 4; + CopyMemory ( szSMBData + 4, nname_From.netbiosed.name, iFromLen ); + CopyMemory ( szSMBData + 4 + iFromLen + 2, nname_To.netbiosed.name, iToLen ); + UCHAR dwD5Length = (UCHAR)( 3 + dwD5ALength ); + err = Send (lana, lsn, SMBBlock, (WORD) (SMB_HEADER_SIZE + dwD5Length)); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : Can`t start session" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + + // Ждем подтверждения + WORD length = sizeof (SMBBlock); + err = Recv (lana, lsn, SMBBlock, length); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : No reply (start session)" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + iHiMsgCode=SMBBlock[SMB_HEADER_SIZE]; + iLoMsgCode=SMBBlock[SMB_HEADER_SIZE+1]; + + // 2. Шлем сообщение (кусочками) + UCHAR dwD7BLength = 0; + for (int iSendedBytes = 0; iSendedBytes < sMessage.GetLength (); iSendedBytes += dwD7BLength) + { + dwD7BLength = sizeof (SMBBlock) - (5 + 3 + SMB_HEADER_SIZE); + szSMBData = SetSMBHeaderCommand (SMBBlock, SMBsendtxt, sizeof (SMBBlock)); + if (iSendedBytes + dwD7BLength > sMessage.GetLength ()) + dwD7BLength = (UCHAR)( sMessage.GetLength () - iSendedBytes ); + szSMBData[0]=iHiMsgCode; + szSMBData[1]=iLoMsgCode; + szSMBData[3]=(UCHAR)( dwD7BLength + 3 ); + szSMBData[5]=1; + szSMBData[6]=dwD7BLength; + CopyMemory (szSMBData + 5 + 3, (LPCSTR) sMessage + iSendedBytes, dwD7BLength); + LOG( "SendNetBIOSMessage : Send text (%u-%u bytes) of multi-block message" , iSendedBytes, iSendedBytes + dwD7BLength - 1); + err = Send (lana, lsn, SMBBlock, (WORD) (SMB_HEADER_SIZE + 5 + 3 + dwD7BLength)); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : Can`t use session" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + // Ждем подтверждения + length = sizeof (SMBBlock); + err = Recv (lana, lsn, SMBBlock, length); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : No reply (use session)" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + } + + // 3. Шлем извещение что все отослано + LOG ( "SendNetBIOSMessage : Send and of multi-block message" ); + szSMBData = SetSMBHeaderCommand (SMBBlock, SMBsendend, sizeof (SMBBlock)); + DWORD dwD6Length=5; + szSMBData[0]=iHiMsgCode; + szSMBData[1]=iLoMsgCode; + err = Send (lana, lsn, SMBBlock, (WORD) (SMB_HEADER_SIZE + dwD6Length)); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : Can`t close session" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + + // Ждем подтверждения + length = sizeof (SMBBlock); + err = Recv (lana, lsn, SMBBlock, length); + if (err != NRC_GOODRET) + { + LOG ( "SendNetBIOSMessage : No reply (close session)" ); + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 0, FACILITY_NETBIOS, err ); + return false; + } + + // Закрываем сессию + Hangup (lana, lsn); + err = (DWORD)MAKE_HRESULT( 1, FACILITY_NETBIOS, NRC_GOODRET ); + return true; +} + +ip netbios::FindNameIP (LPCTSTR szName, UCHAR type) +{ + // Поиск имени + netbios_name nname( szName, type ); + ip addr = INADDR_NONE; + FIND_NAME_BLOCK fn = { 0 }; + for (UCHAR i = 0; i < m_le.length; i++) { + UINT uReturn = FindName (nname, m_le.lana [i], fn); + if (uReturn == NRC_GOODRET) { + LOG( "Found %s at %u boxes. LAN #%u IP: %u.%u.%u.%u", nname.GetANSIFullName(), + fn.fnb_header.node_count, m_le.lana [i], + fn.fnb_Names [0].source_addr[2], + fn.fnb_Names [0].source_addr[3], + fn.fnb_Names [0].source_addr[4], + fn.fnb_Names [0].source_addr[5]); + addr = ((ip)fn.fnb_Names [0].source_addr[5]) | + ((ip)fn.fnb_Names [0].source_addr[4] << 8) | + ((ip)fn.fnb_Names [0].source_addr[3] << 16) | + ((ip)fn.fnb_Names [0].source_addr[2] << 24); + break; + } + } + return addr; +} + +void netbios::GetRegisteredNames (netbios_name_list& names) +{ + CLock oLock( m_csData ); + + for (size_t i = 0; i < m_names.GetCount (); ++i) + names.AddTail (*m_names [i]); +} + +bool netbios::GetNames(netbios_name_list& names, LPCTSTR name, bool bGroup) +{ + // Получение имен + ADAPTER_STATUS_BLOCK astat = { 0 }; + netbios_name nname( name, 0, bGroup ); + UINT uReturn = NRC_GOODRET; + for (UCHAR i = 0; i < m_le.length; i++) + { + uReturn = GetAdapterStatus (nname, m_le.lana [i], astat); + if (uReturn == NRC_GOODRET) + { + for (int j = 0; j < astat.asb_header.name_count; ++j) + { + names.AddTail (netbios_name (astat.asb_Names [j], m_le.lana [i])); + } + } + } + return (uReturn == NRC_GOODRET); +} + +netbios_name* netbios::GetName (const netbios_name& nname) +{ + CLock oLock( m_csData ); + + netbios_name* ret = NULL; + for (size_t i = 0; i < m_names.GetCount (); ++i) + { + if ( nname == *(m_names [i]) ) + { + // Похожее имя обнаружено + ret = m_names [i]; + break; + } + } + + return ret; +} + +bool netbios::FindNameLana(const netbios_name& nname, UCHAR& lana) +{ + // Получение имен + ADAPTER_STATUS_BLOCK astat = {}; + for (UCHAR i = 0; i < m_le.length; i++) + { + UINT uReturn = GetAdapterStatus (nname, m_le.lana [i], astat); + if ( uReturn == NRC_GOODRET ) + { + for ( int j = 0; j < astat.asb_header.name_count; ++j ) + { + if (nname == astat.asb_Names [j]) + { + // Имя обнаружено + LOG ( "FindNameLana : Name \"%s\" found at #%d", nname.GetANSIFullName(), m_le.lana [i]); + lana = m_le.lana [i]; + return true; + } + } + } + LOG( "FindNameLana : Name \"%s\" not found", nname.GetANSIFullName()); + } + + return false; +} + +bool netbios::GetMAC (UCHAR lana, CString& mac) +{ + ADAPTER_STATUS_BLOCK astat = { 0 }; + netbios_name nname; + UINT uReturn = GetAdapterStatus (nname, lana, astat); + if (uReturn == NRC_GOODRET) { + mac.Format (_T("%02x:%02x:%02x:%02x:%02x:%02x"), + astat.asb_header.adapter_address[0], + astat.asb_header.adapter_address[1], + astat.asb_header.adapter_address[2], + astat.asb_header.adapter_address[3], + astat.asb_header.adapter_address[4], + astat.asb_header.adapter_address[5]); + } else + mac.Empty (); + return true; +} + +UCHAR netbios::FindName (const netbios_name& nname, UCHAR lana, FIND_NAME_BLOCK& fn) +{ + ZeroMemory (&fn, sizeof (FIND_NAME_BLOCK)); + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBFINDNAME; + ncb->ncb_lana_num = lana; + CopyMemory( ncb->ncb_callname, nname.netbiosed.name, NCBNAMSZ ); + ncb->ncb_buffer = reinterpret_cast (&fn); + ncb->ncb_length = sizeof (FIND_NAME_BLOCK); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::GetAdapterStatus (const netbios_name& nname, UCHAR lana, ADAPTER_STATUS_BLOCK& astat) +{ + ZeroMemory (&astat, sizeof (ADAPTER_STATUS_BLOCK)); + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBASTAT; + ncb->ncb_lana_num = lana; + CopyMemory( ncb->ncb_callname, nname.netbiosed.name, NCBNAMSZ ); + ncb->ncb_buffer = reinterpret_cast (&astat); + ncb->ncb_length = sizeof (ADAPTER_STATUS_BLOCK); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::EnumLanas (LANA_ENUM& le) +{ + // Перечисление адаптеров + ZeroMemory (&le, sizeof (LANA_ENUM)); + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBENUM; + ncb->ncb_buffer = (PUCHAR) ≤ + ncb->ncb_length = sizeof (LANA_ENUM); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::ResetLana (UCHAR lana) +{ + // Сброс адаптера + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBRESET; + ncb->ncb_lana_num = lana; + ncb->ncb_callname [0] = 20; // maximum sessions + ncb->ncb_callname [2] = 30; // maximum names + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::Hangup (UCHAR lana, UCHAR lsn) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBHANGUP; + ncb->ncb_lana_num = lana; + ncb->ncb_lsn = lsn; + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::Send (UCHAR lana, UCHAR lsn, unsigned char* data, WORD length) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_lana_num = lana; + ncb->ncb_command = NCBSEND; + ncb->ncb_lsn = lsn; + ncb->ncb_length = length; + ncb->ncb_buffer = data; + ncb->ncb_rto = ncb->ncb_sto = (UCHAR) 10; // 10 * 500 ms = 5 s + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::Recv (UCHAR lana, UCHAR lsn, unsigned char* data, WORD& length) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBRECV; + ncb->ncb_lana_num = lana; + ncb->ncb_lsn = lsn; + ncb->ncb_length = length; + ncb->ncb_buffer = data; + ncb->ncb_rto = ncb->ncb_sto = (UCHAR) 10; // 10 * 500 ms = 5 s + NetbiosEx (ncb); + length = ncb->ncb_length; + return ncb->ncb_retcode; +} + +UCHAR netbios::Stat (const netbios_name& nname, SESSION_INFO_BLOCK* psibSession) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBSSTAT; + ncb->ncb_lana_num = nname.GetLana(); + ncb->ncb_buffer = (unsigned char*)psibSession; + ncb->ncb_length = sizeof (SESSION_INFO_BLOCK); + CopyMemory (ncb->ncb_name, nname.netbiosed.name, NCBNAMSZ); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::Listen (const netbios_name& nname, UCHAR& lsn) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + CopyMemory (ncb->ncb_name, nname.netbiosed.name, NCBNAMSZ); + CopyMemory (ncb->ncb_callname, SMB_ANY_NAME, NCBNAMSZ); + ncb->ncb_command = NCBLISTEN; + ncb->ncb_num = nname.netbiosed.name_num; + ncb->ncb_lana_num = nname.GetLana(); + ncb->ncb_rto = ncb->ncb_sto = (UCHAR) 2; // 2 * 500 ms = 1 s + NetbiosEx (ncb); + lsn = ncb->ncb_lsn; + return ncb->ncb_retcode; +} + +UCHAR netbios::AddName (netbios_name& nname) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = (UCHAR)( nname.IsGroupName() ? NCBADDGRNAME : NCBADDNAME ); + ncb->ncb_lana_num = nname.GetLana(); + CopyMemory (ncb->ncb_name, nname.netbiosed.name, NCBNAMSZ); + NetbiosEx (ncb); + nname.netbiosed.name_num = ncb->ncb_num; + return ncb->ncb_retcode; +} + +UCHAR netbios::DeleteName (const netbios_name& nname) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + ncb->ncb_command = NCBDELNAME; + ncb->ncb_lana_num = nname.GetLana(); + ncb->ncb_num = nname.netbiosed.name_num; + CopyMemory (ncb->ncb_name, nname.netbiosed.name, NCBNAMSZ); + NetbiosEx (ncb); + return ncb->ncb_retcode; +} + +UCHAR netbios::SendDatagram (const netbios_name& nname_from, const netbios_name& nname_to, unsigned char* data, WORD length) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + CopyMemory( ncb->ncb_name, nname_from.netbiosed.name, NCBNAMSZ ); + CopyMemory( ncb->ncb_callname, nname_to.netbiosed.name, NCBNAMSZ ); + ncb->ncb_command = NCBDGSEND; + ncb->ncb_num = nname_from.netbiosed.name_num; + ncb->ncb_lana_num = nname_from.GetLana(); + ncb->ncb_buffer = data; + ncb->ncb_length = length; + + CLock oLock( m_csNetBIOS ); + Sleep( 100 ); + + NetbiosEx (ncb); + + return ncb->ncb_retcode; +} + +UCHAR netbios::RecvDatagram (netbios_name& nname_from, const netbios_name& nname_to, unsigned char* data, WORD& length) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + CopyMemory (ncb->ncb_name, nname_to.netbiosed.name, NCBNAMSZ); + ncb->ncb_command = NCBDGRECV; + ncb->ncb_num = nname_to.netbiosed.name_num; + ncb->ncb_lana_num = nname_to.GetLana(); + ncb->ncb_buffer = data; + ncb->ncb_length = length; + NetbiosEx (ncb); + nname_from = ncb->ncb_callname; + length = ncb->ncb_length; + return ncb->ncb_retcode; +} + +UCHAR netbios::Call (UCHAR lana, const netbios_name& nname_from, const netbios_name& nname_to, UCHAR& lsn) +{ + CNCB ncb; + if ( ! ncb ) return NRC_SYSTEM; + CopyMemory( ncb->ncb_name, nname_from.netbiosed.name, NCBNAMSZ ); + CopyMemory( ncb->ncb_callname, nname_to.netbiosed.name, NCBNAMSZ ); + ncb->ncb_lana_num = lana; + ncb->ncb_rto = ncb->ncb_sto = 10; // 5 секунд + ncb->ncb_command = NCBCALL; + NetbiosEx (ncb); + lsn = ncb->ncb_lsn; + return ncb->ncb_retcode; +} + +bool netbios::AskAway(const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + // Сборка пакета + const WORD packet_size = sizeof( WORD ) + 1; + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet[ 2 ] = SM_GETAWAYMESSAGE; + + for (UCHAR i = 0; i < m_le.length; i++) + { + if ( netbios_name* nname = GetName( netbios_name( + pluginMachineName, 0x03, false, m_le.lana [i] ) ) ) + { + LOG( "Send \"Ask Away\" request to \"%s\"", nname_to.GetANSIFullName() ); + + if ( SendDatagram( *nname, nname_to, packet, packet_size ) == NRC_GOODRET ) + { + ret = true; + } + } + } + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::SendAway(netbios_name& nname_from, const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + CString sAwayT; + pluginStatusMessage.Lookup( pluginCurrentStatus, sAwayT ); + CT2A sAwayA( sAwayT ); + WORD len = (WORD)min( lstrlenA( sAwayA ), 250 ); + + // Сборка пакета + WORD packet_size = (WORD)( 2 + 1 + 4 + len ); + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet [ 2 ] = SM_SENDAWAYMESSAGE; + *(__int32*)( packet + 2 + 1 ) = 0; + CopyMemory( packet + 2 + 1 + 4, sAwayA, len ); + + LOG( "Send \"Away\" answer from \"%s\" to \"%s\" : \"%s\"", nname_from.GetANSIFullName(), nname_to.GetANSIFullName(), (LPCSTR)sAwayA ); + + ret = ( SendDatagram( nname_from, nname_to, packet, packet_size ) == NRC_GOODRET ); + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::AskStatus(const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + // Сборка пакета + const WORD packet_size = 2 + 1; + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet[ 2 ] = SM_GETSTATUS; + + for (UCHAR i = 0; i < m_le.length; i++) + { + if ( netbios_name* nname = GetName( netbios_name( + pluginMachineName, 0x03, false, m_le.lana [i] ) ) ) + { + LOG( "Send \"Ask Status\" request to \"%s\"", nname_to.GetANSIFullName() ); + + if ( SendDatagram( *nname, nname_to, packet, packet_size ) == NRC_GOODRET ) + { + ret = true; + } + } + } + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::SendStatus(netbios_name& nname_from, const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + // Сборка пакета + const WORD packet_size = 2 + 1 + 4; + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet [ 2 ] = SM_SENDSTATUS; + *(__int32*)( packet + 2 + 1 ) = (__int32)pluginCurrentStatus; + + LOG( "Send \"Status\" answer from \"%s\" to \"%s\" : \"%s\"", nname_from.GetANSIFullName(), nname_to.GetANSIFullName(), STATUS2TEXT(pluginCurrentStatus) ); + + ret = ( SendDatagram( nname_from, nname_to, packet, packet_size ) == NRC_GOODRET ); + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::BroadcastStatus() +{ + bool ret = false; + if ( m_initialized ) + { + for (UCHAR i = 0; i < m_le.length; i++) + { + netbios_name nname_to( MNS_STATUS, 0xab, true, m_le.lana [i] ); + netbios_name* nname = GetName( + netbios_name ( pluginMachineName, 0x03, false, m_le.lana [i] ) ); + if ( nname ) + ret = SendStatus( *nname, nname_to ) || ret; + } + } + return ret; +} + +bool netbios::AskAvatar(const netbios_name& nname_to) +{ + bool ret = false; + if ( m_initialized ) + { + // Сборка пакета + const WORD packet_size = 2 + 1; + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet[ 2 ] = SM_GETAVATAR; + + for (UCHAR i = 0; i < m_le.length; i++) + { + if ( netbios_name* nname = GetName( netbios_name( + pluginMachineName, 0x03, false, m_le.lana [i] ) ) ) + { + LOG( "Send \"Ask Avatar\" request to \"%s\"", nname_to.GetANSIFullName() ); + + if ( SendDatagram( *nname, nname_to, packet, packet_size ) == NRC_GOODRET ) + { + ret = true; + } + } + } + + mir_free( packet ); + } + } + return ret; +} + +bool netbios::SendAvatar(netbios_name& nname_from, const netbios_name& nname_to) +{ + if ( ! m_initialized ) + return false; + + if ( ! ServiceExists( MS_AV_GETMYAVATAR ) ) + // Нет аватарского плагина + return false; + + // Запрос аватара протокола + AVATARCACHEENTRY* pAvatar = (AVATARCACHEENTRY*)CallService( + MS_AV_GETMYAVATAR, 0, (LPARAM)modname ); + if ( ! pAvatar ) + // Запрос общего аватара + pAvatar = (AVATARCACHEENTRY*)CallService( MS_AV_GETMYAVATAR, 0, (LPARAM)"" ); + if ( ! pAvatar || pAvatar->cbSize < sizeof( AVATARCACHEENTRY ) ) + // Нет аватара + return false; + + CString sFilename = (LPCTSTR)CA2T( pAvatar->szFilename ); + + CAtlFile oAvatarFile; + if ( FAILED( oAvatarFile.Create( sFilename, GENERIC_READ, + FILE_SHARE_READ, OPEN_EXISTING ) ) ) + // Файл не найден + return false; + + ULONGLONG avatar_size = 0; + if ( FAILED( oAvatarFile.GetSize( avatar_size ) ) || + avatar_size < 16 || avatar_size > MAX_AVATAR_SIZE ) + // Слишком маленький или слишком большой файл + return false; + + bool ret = false; + + // Сборка статусного пакета + WORD packet_size = (WORD)( 2 + 1 + avatar_size ); + if ( UCHAR* packet = (UCHAR*)mir_alloc( packet_size ) ) + { + *(WORD*)packet = SM_MAGIC; + packet[ 2 ] = SM_SENDAVATAR; + + // Чтение аватара из файла + if ( SUCCEEDED( oAvatarFile.Read( packet + 2 + 1, avatar_size ) ) ) + { + LOG( "Send \"Avatar\" answer from \"%s\" to \"%s\"", nname_from.GetANSIFullName(), nname_to.GetANSIFullName() ); + + ret = ( SendDatagram( nname_from, nname_to, packet, packet_size ) == NRC_GOODRET ); + } + + mir_free( packet ); + } + + return ret; +} + +bool netbios::Register () +{ + CLock oLock( m_csData ); + + bool ret = false; + + // Удаление имён, если они есть + for (size_t i = 0; i < m_names.GetCount (); ++i) + delete m_names [i]; + m_names.RemoveAll (); + + // Добавление имен на каждом адаптере + for (UCHAR i = 0; i < m_le.length; i++) + { + // COMPUTER <01> U + netbios_name *pnn1 = + DBGetContactSettingByte (NULL, modname, "RegisterNick", TRUE) ? + new netbios_name ( pluginMachineName, 0x01, false, m_le.lana [i]) : NULL; + if (pnn1) + m_names.Add (pnn1); + + // COMPUTER <03> U + netbios_name *pnn2 = + DBGetContactSettingByte (NULL, modname, "RegisterNick", TRUE) ? + new netbios_name ( pluginMachineName, 0x03, false, m_le.lana [i]) : NULL; + if (pnn2) + m_names.Add (pnn2); + + // USER <03> U + netbios_name *pnn3 = + DBGetContactSettingByte (NULL, modname, "RegisterUser", TRUE) ? + new netbios_name ( pluginUserName, 0x03, false, m_le.lana [i]) : NULL; + if (pnn3) { + // Проверка на совпадение имени пользователя и имени компьютера + if (pnn2 && *pnn3 == *pnn2) + // Имена совпадают + delete pnn3; + else + m_names.Add (pnn3); + } + + // MNS_STATUS G + netbios_name *pnn4 = + DBGetContactSettingByte (NULL, modname, "RegisterStatus", TRUE) ? + new netbios_name (MNS_STATUS, 0xab, true, m_le.lana [i]) : NULL; + if ( pnn4 ) + m_names.Add( pnn4 ); + } + + // Регистрация имен + for ( size_t i = 0; i < m_names.GetCount (); ++i ) + { + if ( m_names [i]->Register() ) + { + ret = true; + } + } + + return ret; +} + +// Дерегистрация NetBIOS-имен +void netbios::Deregister () +{ + CLock oLock( m_csData ); + + // Дерегистрация имён + for (size_t i = 0; i < m_names.GetCount (); ++i) + m_names [i]->Destroy(); + + // Удаление имён + for (size_t i = 0; i < m_names.GetCount (); ++i) + delete m_names [i]; + m_names.RemoveAll (); +} diff --git a/plugins/!NotAdopted/WinPopup/netbios.h b/plugins/!NotAdopted/WinPopup/netbios.h new file mode 100644 index 0000000000..a56294cb14 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/netbios.h @@ -0,0 +1,134 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +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. +*/ + +#pragma once + +#include "netbios_name.h" + +const DWORD SMB_MAGIC = 0x424d53ff; // 0xff 'S' 'M' 'B' +const WORD SM_MAGIC = 0x4d53; // 'S' 'M' + +// NetBIOS datagrams: +// (obsolete) +const UCHAR SM_CHANGESTATUS = 0x01; +// Status request: 'S' 'M' 0x02 +const UCHAR SM_GETSTATUS = 0x02; +// Status answer: 'S' 'M' 0x03 status(i32) +const UCHAR SM_SENDSTATUS = 0x03; +// Away message request: 'S' 'M' 0x04 +const UCHAR SM_GETAWAYMESSAGE = 0x04; +// Away message answer: 'S' 'M' 0x05 0x00(i32) message(ASCII) +const UCHAR SM_SENDAWAYMESSAGE = 0x05; +// Avatar request: 'S' 'M' 0x06 +const UCHAR SM_GETAVATAR = 0x06; +// Avatar answer: 'S' 'M' 0x07 avatar +const UCHAR SM_SENDAVATAR = 0x07; + +const LPCTSTR MNS_STATUS = _T("MNS_STATUS"); + +#define MAX_AVATAR_SIZE 65000 // Максимальный размер файла аватара (байт) + +#pragma pack (push, 1) + +typedef struct _FIND_NAME_BLOCK +{ + FIND_NAME_HEADER fnb_header; + FIND_NAME_BUFFER fnb_Names [256]; +} FIND_NAME_BLOCK, *PFIND_NAME_BLOCK; + +typedef struct _ADAPTER_STATUS_BLOCK +{ + ADAPTER_STATUS asb_header; + NAME_BUFFER asb_Names [NCBNAMSZ]; +} ADAPTER_STATUS_BLOCK, *PADAPTER_STATUS_BLOCK; + +#pragma pack (pop) + +class netbios +{ +public: + netbios(); + ~netbios(); + + bool Create (BOOL registration); + void AskForDestroy(); // Для ускорения + void Destroy (); + operator bool() const; + + bool SendNetBIOSMessage (HANDLE hContact, LPCTSTR msg /* ANSI */, DWORD& err); + ip FindNameIP (LPCTSTR szName /* ANSI */, UCHAR type = 3); + void GetRegisteredNames (netbios_name_list& names); + bool GetNames (netbios_name_list& names, LPCTSTR name /* ANSI */, bool bGroup); + + // Получение имени из списка по указанному имени + netbios_name* GetName (const netbios_name& nname); + + // Поиск номера адаптера через который можно достучаться до указанного имени + bool FindNameLana (const netbios_name& nname, UCHAR& lana); + + bool GetMAC (UCHAR lana, CString& mac); + UCHAR FindName (const netbios_name& nname, UCHAR lana, FIND_NAME_BLOCK& fn); + UCHAR GetAdapterStatus (const netbios_name& nname, UCHAR lana, ADAPTER_STATUS_BLOCK& astat); + UCHAR EnumLanas (LANA_ENUM& le); + UCHAR ResetLana (UCHAR lana); + UCHAR Hangup (UCHAR lana, UCHAR lsn); + UCHAR Send (UCHAR lana, UCHAR lsn, unsigned char* data, WORD length); + UCHAR Recv (UCHAR lana, UCHAR lsn, unsigned char* data, WORD& length); + UCHAR Stat (const netbios_name& nname, SESSION_INFO_BLOCK* psibSession); + UCHAR Listen (const netbios_name& nname, UCHAR& lsn); + UCHAR AddName (netbios_name& nname); + UCHAR DeleteName (const netbios_name& nname); + UCHAR SendDatagram (const netbios_name& nname_from, const netbios_name& nname_to, unsigned char* data, WORD length); + UCHAR RecvDatagram (netbios_name& nname_from, const netbios_name& nname_to, unsigned char* data, WORD& length); + UCHAR Call (UCHAR lana, const netbios_name& nname_from, const netbios_name& nname_to, UCHAR& lsn); + unsigned char* SetSMBHeaderCommand (unsigned char* szHeader, BYTE iCommandCode, size_t iBufferLen); + + // Запрос эвей-сообщения + bool AskAway(const netbios_name& nname_to); + // Отправка эвей-сообщения + bool SendAway(netbios_name& nname_from, const netbios_name& nname_to); + // Запрос статуса + bool AskStatus(const netbios_name& nname_to); + // Отправка статуса + bool SendStatus(netbios_name& nname_from, const netbios_name& nname_to); + // Отправка статуса на всех адаптерах (от COMPUTER<03> U на MNS_STATUS G) + bool BroadcastStatus(); + // Запрос аватара + bool AskAvatar(const netbios_name& nname_to); + // Отправка аватара + bool SendAvatar(netbios_name& nname_from, const netbios_name& nname_to); + +protected: + bool m_initialized; // Флаг инициализации подсистемы NetBIOS + netbios_name_array m_names; // Все регистрируемые NetBIOS-имена для слушателя + LANA_ENUM m_le; // Список адаптеров + CComAutoCriticalSection m_csData; // Защита данных + CComAutoCriticalSection m_csNetBIOS; // Синхронизация NetBIOS + + bool Register (); // Регистрация всех NetBIOS-имен + void Deregister (); // Дерегистрация всех NetBIOS-имен +}; + +extern netbios pluginNetBIOS; // Прием/отправка сообщений через NetBIOS + +LPCSTR GetNetbiosCommand(UCHAR command); +LPCSTR GetNetbiosError(UCHAR err); +UCHAR NetbiosEx(NCB* pNCB); diff --git a/plugins/!NotAdopted/WinPopup/netbios_name.cpp b/plugins/!NotAdopted/WinPopup/netbios_name.cpp new file mode 100644 index 0000000000..ce3ad86ce7 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/netbios_name.cpp @@ -0,0 +1,640 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "netbios.h" +#include "smbconst.h" +#include "messagebox.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//////////////////////////////////////////////////////////////////////// +// Class netbios_name + +netbios_name::netbios_name(LPCTSTR n, UCHAR type, bool group, UCHAR lana) : + m_managed (false), + m_registered (false), + m_duplicated (false), + m_error (false), + m_lana (lana), + m_listener (NULL), + m_dgreceiver (NULL), + m_term (NULL) +{ + // Преобразование имени в NetBIOS-имя + int len = NCBNAMSZ - 1; + CT2A nA( n ); + LPCSTR src = (LPCSTR)nA; + LPSTR dst = (LPSTR)netbiosed.name; + for ( ; len && *src; --len, ++dst, ++src ) + *dst = *src; + for ( ; len; --len ) + *dst++ = ' '; + *dst = (CHAR)type; + CharUpperBuffA( (LPSTR)netbiosed.name, NCBNAMSZ - 1 ); + CharToOemBuffA( (LPSTR)netbiosed.name, (LPSTR)netbiosed.name, NCBNAMSZ - 1 ); + netbiosed.name_num = 0; + netbiosed.name_flags = (UCHAR)( group ? GROUP_NAME : UNIQUE_NAME ); + + original = GetANSIName(); +} + +netbios_name::netbios_name(const NAME_BUFFER& n, UCHAR lana) : + m_managed (false), + m_registered (false), + m_duplicated (false), + m_error (false), + m_lana (lana), + m_listener (NULL), + m_dgreceiver (NULL), + m_term (NULL) +{ + CopyMemory (&netbiosed, &n, sizeof (NAME_BUFFER)); + original = GetANSIName(); +} + +netbios_name& netbios_name::operator=(const netbios_name& n) +{ + _ASSERTE (m_managed == false); + m_managed = n.m_managed; + _ASSERTE (m_registered == false); + m_registered = n.m_registered; + _ASSERTE (m_duplicated == false); + m_duplicated = n.m_duplicated; + _ASSERTE (m_error == false); + m_error = n.m_error; + m_lana = n.m_lana; + _ASSERTE( m_listener == NULL ); + m_listener = NULL; + _ASSERTE( m_dgreceiver == NULL ); + m_dgreceiver = NULL; + _ASSERTE( m_term == NULL ); + m_term = NULL; + CopyMemory (&netbiosed, &n.netbiosed, sizeof( NAME_BUFFER )); + original = n.original; + return *this; +} + +netbios_name& netbios_name::operator= (const UCHAR* n) +{ + _ASSERTE (m_managed == false); + m_managed = false; + _ASSERTE (m_registered == false); + m_registered = false; + _ASSERTE (m_duplicated == false); + m_duplicated = false; + _ASSERTE (m_error == false); + m_error = false; + m_lana = 0; + _ASSERTE( m_listener == NULL ); + m_listener = NULL; + _ASSERTE( m_dgreceiver == NULL ); + m_dgreceiver = NULL; + _ASSERTE( m_term == NULL ); + m_term = NULL; + CopyMemory (netbiosed.name, n, NCBNAMSZ); + netbiosed.name_num = 0; + netbiosed.name_flags = UNIQUE_NAME; + original = GetANSIName(); + + return *this; +} + +bool netbios_name::operator== (const NAME_BUFFER& n) const +{ + return ( netbiosed.name [NCBNAMSZ - 1] == n.name [NCBNAMSZ - 1] ) && + ( ( netbiosed.name_flags & GROUP_NAME ) == ( n.name_flags & GROUP_NAME ) ) && + ( memcmp( netbiosed.name, n.name, NCBNAMSZ - 1 ) == 0 ); +} + +bool netbios_name::operator!= (const NAME_BUFFER& n) const +{ + return ! operator==( n ); +} + +bool netbios_name::operator== (const netbios_name& n) const +{ + return ( m_lana == n.m_lana ) && operator==( n.netbiosed ); +} + +bool netbios_name::operator!= (const netbios_name& n) const +{ + return ( m_lana != n.m_lana ) || operator!=( n.netbiosed ); +} + +bool netbios_name::Register() +{ + m_managed = true; + + UCHAR ret = AddName (); + LOG("Register NetBIOS name \"%s\" on lana %d num=%d : 0x%02x \"%s\"", GetANSIFullName(), m_lana, netbiosed.name_num, ret, GetNetbiosError( ret ) ); + m_registered = (ret == NRC_GOODRET); + m_duplicated = (ret == NRC_DUPNAME); + if ( ret != NRC_GOODRET && ret != NRC_DUPNAME ) + { + WarningBox (NULL, (DWORD)MAKE_HRESULT (0, FACILITY_NETBIOS, ret), + _T("%s: %s"), TranslateT ("Cannot register NetBIOS name"), (LPCTSTR)CA2T( GetANSIFullName() ) ); + } + + if (!m_term) + m_term = CreateEvent (NULL, TRUE, FALSE, NULL); + else + ResetEvent (m_term); + + if ( m_term && !m_listener ) + m_listener = (HANDLE)mir_forkthread( ListenerThread, this ); + + if ( m_term && !m_dgreceiver && + // NOTE: Под Win9x нельзя запускать ожидание датаграмм для имён-дубликатов + // т.к. потом невозможно выбить управление из функции Netbios() даже если + // разрегистрировать имя + !m_duplicated ) + { + m_dgreceiver = (HANDLE)mir_forkthread( DatagramReceiverThread, this ); + } + + return m_registered; +} + +void netbios_name::AskForDestroy() +{ + if (m_term) + SetEvent (m_term); +} + +void netbios_name::Destroy() +{ + // Запрос останова рабочего потока-слушателя + if ( m_term ) SetEvent( m_term ); + + // Удаление имени (если не удалить, то слушатель не завершиться) + UCHAR ret = DeleteName (); + LOG("Unregister NetBIOS name \"%s\" on lana %d num=%d : 0x%02x \"%s\"", GetANSIFullName(), m_lana, netbiosed.name_num, ret, GetNetbiosError( ret ) ); + m_registered = !(ret == NRC_GOODRET); + if ( m_duplicated ) + { + // Восстановление имени + m_duplicated = false; + + // NOTE: Восстанавливать не надо - проблем больше + // uReturn = AddName (); + // LOG("Restore NetBIOS name \"%s\" on lana %d : 0x%02x", GetANSIFullName(), m_lana, uReturn); + } + + // Ожидание, а затем принудительный останов + if ( m_listener ) + { + if ( m_term ) SetEvent( m_term ); + if (WaitForSingleObject (m_listener, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate NetBIOS listener!"); + TerminateThread (m_listener, 0); + } + m_listener = NULL; + } + + if ( m_dgreceiver ) + { + if ( m_term ) SetEvent( m_term ); + if (WaitForSingleObject (m_dgreceiver, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate NetBIOS datagram receiver!"); + TerminateThread (m_dgreceiver, 0); + } + m_dgreceiver = NULL; + } + + if ( m_term ) + { + CloseHandle (m_term); + m_term = NULL; + } +} + +CStringA netbios_name::GetANSIName() const +{ + CStringA sName; + LPSTR szName = sName.GetBuffer( NCBNAMSZ ); + CopyMemory( szName, (LPCSTR)netbiosed.name, NCBNAMSZ - 1 ); + szName[ NCBNAMSZ - 1 ] = 0; + sName.ReleaseBuffer(); + sName.Trim(); + sName.OemToAnsi(); + return sName; +} + +CStringA netbios_name::GetANSIFullName() const +{ + CStringA sType; + sType.Format( " <%02X>", GetType() ); + return original + sType; +} + +UCHAR netbios_name::GetType () const +{ + return netbiosed.name [NCBNAMSZ - 1]; +} + +bool netbios_name::IsGroupName () const +{ + return ((netbiosed.name_flags & GROUP_NAME) == GROUP_NAME); +} + +bool netbios_name::IsRegistered () const +{ + return m_registered; +} + +bool netbios_name::IsDuplicated () const +{ + return m_duplicated; +} + +bool netbios_name::IsError () const +{ + return m_error; +} + +bool netbios_name::IsOwnName () const +{ + return m_managed; +} + +UCHAR netbios_name::GetLana () const +{ + return m_lana; +} + +bool netbios_name::GetRealSender (UCHAR lsn, CStringA& sRealFrom) const +{ + sRealFrom.Empty (); + + SESSION_INFO_BLOCK sibSession = {}; + UCHAR dwInfoRes = pluginNetBIOS.Stat( *this, &sibSession ); + if ( dwInfoRes == NRC_GOODRET ) + { + for ( int i = 0; i < sibSession.sib_header.num_sess; i++ ) + { + if ( sibSession.sib_Names [i].lsn == lsn ) + { + // Наша сессия + const char* n = (const char*)sibSession.sib_Names [i].remote_name; + BYTE j = NCBNAMSZ - 2; + for ( ; j && ( n [ j ] == ' ' ); --j ); + sRealFrom.Append( n, j + 1 ); + sRealFrom.OemToAnsi(); + return true; + } + } + } + return false; +} + +size_t netbios_name::GetLength() const +{ + return (size_t)original.GetLength(); +} + +UCHAR netbios_name::AddName() +{ + return pluginNetBIOS.AddName( *this ); +} + +UCHAR netbios_name::DeleteName() +{ + return pluginNetBIOS.DeleteName( *this ); +} + +typedef struct _ReceiverData +{ + netbios_name* self; + UCHAR lsn; +} ReceiverData; + +void netbios_name::Listener() +{ + m_error = false; + while ( WaitForSingleObject( m_term, 50 ) == WAIT_TIMEOUT ) + { + UCHAR lsn = 0; + UCHAR ret = pluginNetBIOS.Listen( *this, lsn ); + if ( ret != NRC_GOODRET ) + { + LOG( "Listener : Closing \"%s\"", GetANSIFullName() ); + m_error = true; + break; + } + + LOG( "Listener : Got packet for \"%s\"", GetANSIFullName() ); + if ( ReceiverData* data = (ReceiverData*)mir_alloc( sizeof( ReceiverData ) ) ) + { + data->self = this; + data->lsn = lsn; + mir_forkthread( ReceiverThread, data ); + } + } +} + +void netbios_name::ListenerThread(LPVOID param) +{ + if ( netbios_name* pName = (netbios_name*)param ) + { + pName->Listener(); + pName->m_listener = NULL; + } +} + +void netbios_name::DatagramReceiver() +{ + UCHAR* SMBBlock = (UCHAR*)mir_alloc( 65536 ); + if ( ! SMBBlock ) + { + m_error = true; + return; + } + + m_error = false; + while ( WaitForSingleObject ( m_term, 50 ) == WAIT_TIMEOUT ) + { + ZeroMemory( SMBBlock, 65536 ); + + WORD iReadedBytes = 65535; + netbios_name nname_from; + UCHAR ret = pluginNetBIOS.RecvDatagram( nname_from, *this, SMBBlock, iReadedBytes ); + if ( ret != NRC_GOODRET ) + { + // Ошибка - выход + m_error = true; + break; + } + + nname_from.m_lana = m_lana; + + LOG( "Got datagram from \"%s\" to \"%s\"", nname_from.GetANSIFullName(), GetANSIFullName() ); + + // Свое собственное сообщение? + if ( IsItMe ( CA2T( nname_from.original ) ) ) + { + LOG( "DatagramReceiver : Ignoring my datagram" ); + continue; + } + + // Обработка датаграмм + if ( iReadedBytes > 2 && *(WORD*)SMBBlock == SM_MAGIC ) + { + UCHAR iMsgType = SMBBlock[ 2 ]; + switch ( iMsgType ) + { + case SM_GETSTATUS: + // Отвечаем своим статусом + LOG( "DatagramReceiver : It's status request" ); + pluginNetBIOS.SendStatus( *this, nname_from ); + break; + + case SM_SENDSTATUS: + // Находим контакт и ставим его статус + if ( iReadedBytes == 2 + 1 + 4 ) + { + HANDLE hContact = GetContact( CA2T( nname_from.original ) ); + if ( hContact ) + { + LOG( "DatagramReceiver : It's status answer" ); + SetContactStatus( hContact, *(__int32*)(SMBBlock + 2 + 1), false ); + } + else + LOG( "DatagramReceiver : Unknown contact" ); + } + else + LOG( "DatagramReceiver : Invalid format" ); + break; + + case SM_GETAWAYMESSAGE: + // Отвечаем своим эвей-сообщением + LOG( "DatagramReceiver : It's away request" ); + pluginNetBIOS.SendAway( *this, nname_from ); + break; + + case SM_SENDAWAYMESSAGE: + // Находим контакт и ставим его эвей-сообщение + if ( iReadedBytes >= 2 + 1 + 4 ) + { + if ( HANDLE hContact = GetContact( CA2T( nname_from.original ) ) ) + { + LPCSTR szAway = (LPCSTR)( SMBBlock + 2 + 1 + 4 ); + SMBBlock[ iReadedBytes ] = 0; // ASCII -> ASCIIZ + + LOG( "DatagramReceiver : It's away answer \"%s\"", szAway ); + SetContactAway( hContact, szAway ); + } + else + LOG( "DatagramReceiver : Unknown contact" ); + } + else + LOG( "DatagramReceiver : Invalid format" ); + break; + + case SM_GETAVATAR: + // Отвечаем своим аватаром + LOG( "DatagramReceiver : It's avatar request." ); + pluginNetBIOS.SendAvatar( *this, nname_from ); + break; + + case SM_SENDAVATAR: + // Находим контакт и ставим его аватар + if ( iReadedBytes >= 2 + 1 && iReadedBytes < MAX_AVATAR_SIZE + 3 ) + { + if ( HANDLE hContact = GetContact( CA2T( nname_from.original ) ) ) + { + LOG( "DatagramReceiver : It's avatar answer" ); + SetContactAvatar( hContact, SMBBlock + 2 + 1, (DWORD)iReadedBytes - 3 ); + } + else + LOG( "DatagramReceiver : Unknown contact" ); + } + else + LOG( "DatagramReceiver : Invalid format or too big avatar" ); + break; + + default: + LOG( "DatagramReceiver : Unsupported message type 0x%02x", iMsgType ); + } + } + else + LOG( "DatagramReceiver : Unsupported data 0x%04x", *(WORD*)SMBBlock ); + } + + mir_free( SMBBlock ); +} + +void netbios_name::DatagramReceiverThread(LPVOID param) +{ + if ( netbios_name* pName = (netbios_name*)param ) + { + pName->DatagramReceiver(); + pName->m_dgreceiver = NULL; + } +} + +void netbios_name::Receiver(UCHAR lsn) +{ + // Created by Ilja Razinkov (also known as IPv6), 2002, IPv6Intendo@yandex.ru + // Keep this comment if you redistribute this file + + UCHAR* SMBBlock = (UCHAR*)mir_alloc( 65536 ); + if ( ! SMBBlock ) + return; + + CStringA sTo, sFrom, sMessage; + UCHAR nRes; + for (;;) + { + ZeroMemory( SMBBlock, 65536 ); + + // Получение очередного блока данных + WORD iReadedBytes = 65535; + nRes = pluginNetBIOS.Recv (m_lana, lsn, SMBBlock, iReadedBytes); + if (nRes != NRC_GOODRET) + { + LOG( "Receiver : Error while receiving data block" ); + break; + } + + // Смотрим что к нам пришло - сообщение или что-то неизвестное + if ( iReadedBytes < 4 || *(DWORD*)SMBBlock != SMB_MAGIC ) + { + LOG( "Receiver : Unsupported data 0x%08x", *(DWORD*)SMBBlock ); + break; + } + + UCHAR iMsgType = SMBBlock [4]; + if (iMsgType != SMBsends && + iMsgType != SMBsendstrt && + iMsgType != SMBsendend && + iMsgType != SMBsendtxt) + { + LOG( "Receiver : Unsupported message type 0x%02x", iMsgType ); + break; + } + + // Шлём подтверждение + UCHAR szReply [SMB_HEADER_SIZE + 5]; + UCHAR* szReplyData = + pluginNetBIOS.SetSMBHeaderCommand (szReply, iMsgType, sizeof (szReply)); + if (iMsgType == SMBsendstrt) + { + // Код сообщения + static UCHAR rnd = 1; + szReplyData [0] = 1; // Номер сообщения + szReplyData [1] = rnd++; // + if ( rnd > 5 ) + rnd = 1; + } + nRes = pluginNetBIOS.Send (m_lana, lsn, szReply, + (WORD)( (iMsgType == SMBsendstrt) ? (SMB_HEADER_SIZE + 5) : (SMB_HEADER_SIZE + 3) ) ); + if ( nRes != NRC_GOODRET ) + { + // Нефатальная ошибка + LOG( "Receiver : Error while sending ack" ); + } + + // Действия в зависимости от типа сообщения + if (iMsgType == SMBsends) + { + LOG( "Receiver : Got single-block message" ); + // Короткое сообщение, вытаскиваем данные и выходим... + sFrom = (const char*) SMBBlock + SMB_HEADER_SIZE + 4; + int iFromOffset = sFrom.GetLength (); + sTo = (const char*) SMBBlock + SMB_HEADER_SIZE + 4 + iFromOffset + 2; + int iToOffset = sTo.GetLength (); + sMessage = (const char*) SMBBlock + SMB_HEADER_SIZE + 4 + iFromOffset + 2 + + iToOffset + 4; + break; + } + else if (iMsgType == SMBsendstrt) + { + LOG( "Receiver : Got start of multi-block message" ); + // Кусочковое сообщение, начало, смотрим от кого и кому + sFrom = (const char*) SMBBlock + SMB_HEADER_SIZE + 4; + int iFromOffset = sFrom.GetLength (); + sTo = (const char*) SMBBlock + SMB_HEADER_SIZE + iFromOffset + 4 + 2; + } + else if (iMsgType == SMBsendtxt) + { + // Кусочковое сообщение, блок с данными, конкатенируем... + int iConcatSize = iReadedBytes - SMB_HEADER_SIZE - 8; + LOG( "Receiver : Got text (%d-%d bytes) of multi-block message", sMessage.GetLength(), sMessage.GetLength() + iConcatSize - 1 ); + sMessage.Append ((const char*) (SMBBlock + SMB_HEADER_SIZE + 8), iConcatSize); + } + else if (iMsgType == SMBsendend) + { + LOG( "Receiver : Got end of multi-block message" ); + // Кусочковое сообщение, конец, все получено, выходим + break; + } + } + + sMessage.Replace( "\x14", "\r\n" ); // <14> -> + + sTo.OemToAnsi(); + sFrom.OemToAnsi(); + sMessage.OemToAnsi(); + + // Смотрим информацию о сессии + CStringA sRealFrom; + if (GetRealSender (lsn, sRealFrom)) + { + LOG( "Receiver : Message from \"%s\" (real \"%s\") to \"%s\"", (LPCSTR)sFrom, (LPCSTR)sRealFrom, (LPCSTR)sTo); + sFrom = sRealFrom; + } + else + { + LOG( "Receiver : Message from \"%s\" (real sender unknown) to \"%s\"", (LPCSTR)sFrom, (LPCSTR)sTo); + } + + // Скажем до свиданья... + pluginNetBIOS.Hangup (m_lana, lsn); + + // Открываем сообщение (пустое игнорируем) + if ( ! sMessage.IsEmpty() ) + { + ReceiveContactMessage( CA2T( sFrom ), CA2T( sTo ), CA2T( sMessage ), sMessage.GetLength ()); + } + else + { + LOG( "Receiver : Ignoring empty message" ); + } + + mir_free( SMBBlock ); +} + +void netbios_name::ReceiverThread(LPVOID param) +{ + if ( ReceiverData* data = (ReceiverData*)param ) + { + data->self->Receiver( data->lsn ); + mir_free( data ); + } +} diff --git a/plugins/!NotAdopted/WinPopup/netbios_name.h b/plugins/!NotAdopted/WinPopup/netbios_name.h new file mode 100644 index 0000000000..2d35531b33 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/netbios_name.h @@ -0,0 +1,157 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +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. +*/ + +#pragma once + +#define SMB_ANY_NAME _T("* ") +#define FACILITY_NETBIOS (0x0f0f) +#define SMB_HEADER_SIZE (32) + +#pragma pack (push, 1) + +typedef struct SESSION_INFO_BLOCK +{ + SESSION_HEADER sib_header; + SESSION_BUFFER sib_Names[ NCBNAMSZ ]; +} SESSION_INFO_BLOCK, *PSESSION_INFO_BLOCK; + +#pragma pack (pop) + +class netbios_name +{ +public: + netbios_name(LPCTSTR n = SMB_ANY_NAME /* ANSI */, UCHAR type = 0, bool group = false, UCHAR lana = 0); + netbios_name(const NAME_BUFFER& n, UCHAR lana); + netbios_name& operator=(const netbios_name& n); + netbios_name& operator=(const UCHAR* n); + // Сравнение (производиться только по имени, номеру имени, типу имени) + bool operator==(const NAME_BUFFER& n) const; + // Сравнение (производиться только по имени, номеру имени, типу имени) + bool operator!=(const NAME_BUFFER& n) const; + // Сравнение (производиться только по имени, номеру имени, типу имени, адаптеру) + bool operator==(const netbios_name& n) const; + // Сравнение (производиться только по имени, номеру имени, типу имени, адаптеру) + bool operator!=(const netbios_name& n) const; + // Регистрация имени + bool Register(); + // Для ускорения + void AskForDestroy(); + // Дерегистрация имени + void Destroy(); + // Обратное преобразование NetBIOS-имени из OEM в ANSI в виде: NAME + CStringA GetANSIFullName() const; + + CStringA original; // Полное имя (в ANSI кодировке) + NAME_BUFFER netbiosed; // NetBIOS имя (в OEM кодировке): + // typedef struct _NAME_BUFFER { + // UCHAR name[NCBNAMSZ]; + // UCHAR name_num; + // UCHAR name_flags; + // } NAME_BUFFER, *PNAME_BUFFER; + + // Получение атрибутов имени: + + UCHAR GetType() const; + bool IsGroupName() const; + bool IsRegistered() const; + bool IsDuplicated() const; + bool IsError() const; + bool IsOwnName() const; + UCHAR GetLana() const; + size_t GetLength() const; // Длина имени NetBIOS + +protected: + bool m_managed; // Флаг управляемого имени + bool m_registered; // Флаг успешной регистрации имени + bool m_duplicated; // Флаг существования имени до регистрации + bool m_error; // Флаг ошибки прослушивания имени + UCHAR m_lana; // Номер адаптера + HANDLE m_listener; // Хэндлер рабочего потока-слушателя сессий + HANDLE m_dgreceiver; // Хэндлер рабочего потока-слушателя датаграмм + HANDLE m_term; // Хэндлер события останова рабочего потока-слушателя + + // Обратное преобразование NetBIOS-имени из OEM в ANSI + CStringA GetANSIName() const; + + bool GetRealSender(UCHAR lsn, CStringA& sRealFrom) const; + UCHAR AddName(); + UCHAR DeleteName(); + + // Ожидание начала сессии + void Listener(); + static void ListenerThread(LPVOID param); + + // Ожидание датаграммы + void DatagramReceiver(); + static void DatagramReceiverThread(LPVOID param); + + // Обработка сессии (из Listener) + void Receiver(UCHAR lsn); + static void ReceiverThread(LPVOID param); +}; + +typedef CAtlArray netbios_name_array; +typedef CAtlList netbios_name_list; + +/* +Name Number(h) Type Usage +-------------------------------------------------------------------------- + 00 U Workstation Service + 01 U Messenger Service +<\\--__MSBROWSE__> 01 G Master Browser + 03 U Messenger Service + 06 U RAS Server Service + 1F U NetDDE Service + 20 U File Server Service + 21 U RAS Client Service + 22 U Microsoft Exchange Interchange(MSMail +Connector) + 23 U Microsoft Exchange Store + 24 U Microsoft Exchange Directory + 30 U Modem Sharing Server Service + 31 U Modem Sharing Client Service + 43 U SMS Clients Remote Control + 44 U SMS Administrators Remote Control +Tool + 45 U SMS Clients Remote Chat + 46 U SMS Clients Remote Transfer + 4C U DEC Pathworks TCPIP service on +Windows NT + 42 U mccaffee anti-virus + 52 U DEC Pathworks TCPIP service on +Windows NT + 87 U Microsoft Exchange MTA + 6A U Microsoft Exchange IMC + BE U Network Monitor Agent + BF U Network Monitor Application + 03 U Messenger Service + 00 G Domain Name + 1B U Domain Master Browser + 1C G Domain Controllers + 1D U Master Browser + 1E G Browser Service Elections + 1C G IIS + 00 U IIS + [2B] U Lotus Notes Server Service +IRISMULTICAST [2F] G Lotus Notes +IRISNAMESERVER [33] G Lotus Notes +Forte_$ND800ZA [20] U DCA IrmaLan Gateway Server Service +*/ diff --git a/plugins/!NotAdopted/WinPopup/network.cpp b/plugins/!NotAdopted/WinPopup/network.cpp new file mode 100644 index 0000000000..4f51318e08 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/network.cpp @@ -0,0 +1,88 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "network.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// Проверка, что строка похожа на IPv4-адрес в формате xx.xx.xx.xx +bool IsValidIP (LPCTSTR name) +{ + int dots = 0; + bool digit = false; + for ( ; *name; name++ ) + { + if ( *name == _T('.') ) + { + if ( ! digit ) + // Две точки подряд + return false; + + dots++; + digit = false; + } + else if ( *name < _T('0') || *name > _T('9') ) + { + // Это не цифра + return false; + } + else + { + digit = true; + } + } + return dots == 3 && digit; +} + +// Получение IP по имени хоста и получение короткого имени хоста +ip ResolveToIP (CString& name) +{ + // Получение имени из IP-адреса + ip addr = IsValidIP (name) ? ::inet_addr ( CT2A( name ) ) : INADDR_NONE; + if (addr != INADDR_NONE) { + struct hostent *hp = ::gethostbyaddr ((const char*) &addr, sizeof (addr), AF_INET); + if (hp) { + // Укорачиваем имя + name = hp->h_name; + int n = name.Find ('.'); + if (n != -1) + name = name.Left (n); + } + } + // Получение IP-адреса из имени + if (addr == INADDR_NONE) { + struct hostent *hp = ::gethostbyname ( CT2A( name ) ); + if (hp) { + addr = ((struct in_addr*)hp->h_addr)->s_addr; + // Укорачиваем имя + name = hp->h_name; + int n = name.Find ('.'); + if (n != -1) + name = name.Left (n); + } + } + return ntohl (addr); +} diff --git a/plugins/!NotAdopted/WinPopup/network.h b/plugins/!NotAdopted/WinPopup/network.h new file mode 100644 index 0000000000..541c764fbc --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/network.h @@ -0,0 +1,31 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2009 Nikolay Raspopov + +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. +*/ + +#pragma once + +// Адрес IPv4 +typedef unsigned long ip; + +// Проверка, что строка похожа на IP-адрес в формате xx.xx.xx.xx +bool IsValidIP (LPCTSTR name); + +// Получение IP по имени хоста и получение короткого имени хоста +ip ResolveToIP (CString& name); diff --git a/plugins/!NotAdopted/WinPopup/options.cpp b/plugins/!NotAdopted/WinPopup/options.cpp new file mode 100644 index 0000000000..bfc227402a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/options.cpp @@ -0,0 +1,392 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "services.h" +#include "options.h" +#include "netbios.h" +#include "add_dialog.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#define WM_FILLTREE (WM_USER+75) + +static netbios_name_list nns; +static HWND hTree = NULL; + +typedef struct _DlgDataOptions +{ + HMODULE hContact; + HIMAGELIST hTreeImages; + bool need_restart; +} DlgDataOptions; + +static void FillTreeThread (LPVOID param) +{ + // Ожидание инициализации NetBIOS (20 секунд) + for ( int i = 0; i < 20 && ! pluginNetBIOS && IsWindow( hTree ); i++ ) + Sleep( 1000 ); + + if ( IsWindow( hTree ) ) + { + // ...вначале своими именами + pluginNetBIOS.GetRegisteredNames( nns ); + // ...потом остальными именами + pluginNetBIOS.GetNames( nns, pluginMachineName, false ); + // ...и уведомление о готовности данных + PostMessage( reinterpret_cast (param), WM_FILLTREE, 0, 0 ); + } +} + +static void Refresh (HWND hwndDlg, HWND hwndTree) +{ + bool bOnline = ( pluginCurrentStatus != ID_STATUS_OFFLINE ); + + nns.RemoveAll (); + + // Заполнение дерева имён... + TreeView_DeleteAllItems (hwndTree); + TVINSERTSTRUCT tvis = { TVI_ROOT, TVI_LAST }; + tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE; + tvis.item.iImage = tvis.item.iSelectedImage = bOnline ? 0 : 8; + tvis.item.pszText = bOnline ? TranslateT("Retrieving...") : TranslateT("Offline"); + TreeView_InsertItem (hwndTree, &tvis); + + if ( bOnline ) + { + // Запуск опроса хоста + mir_forkthread( FillTreeThread, hwndDlg ); + } +} + +static INT_PTR CALLBACK DlgProcOptions (HWND hwndDlg, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + static bool bLastOnline = false; + DlgDataOptions* data = reinterpret_cast (GetWindowLongPtr (hwndDlg, DWLP_USER)); + + switch ( Msg ) + { + case WM_INITDIALOG: + { + TranslateDialogDefault (hwndDlg); + + data = (DlgDataOptions*)mir_alloc( sizeof( DlgDataOptions ) ); + if ( ! data ) + return FALSE; + + SetWindowLongPtr (hwndDlg, DWLP_USER, reinterpret_cast (data)); + data->need_restart = false; + data->hTreeImages = ImageList_Create (16, 16, ILC_COLOR8 | ILC_MASK, 8, 0); + + hTree = GetDlgItem (hwndDlg, IDC_TREE); + + ImageList_AddIcon (data->hTreeImages, reinterpret_cast (LoadImage ( // 0 + pluginModule, MAKEINTRESOURCE (IDI_COMPUTER), IMAGE_ICON, 16, 16, LR_SHARED ))); + + ImageList_AddIcon (data->hTreeImages, reinterpret_cast (LoadImage ( // 1 + pluginModule, MAKEINTRESOURCE (IDI_LANA), IMAGE_ICON, 16, 16, LR_SHARED ))); + + HICON hIcon; + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_GOOD_NAME), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 2 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_1, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_BAD_NAME), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 3 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_2, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_OTHER_NAME), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 4 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_3, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_GOOD_NAMES), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 5 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_4, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_BAD_NAMES), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 6 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_5, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_OTHER_NAMES), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 7 + SendDlgItemMessage (hwndDlg, IDC_LEGEND_6, STM_SETICON, + reinterpret_cast (hIcon), 0); + + hIcon = reinterpret_cast (LoadImage ( + pluginModule, MAKEINTRESOURCE (IDI_COMPUTER_ERROR), IMAGE_ICON, 16, 16, LR_SHARED )); + ImageList_AddIcon (data->hTreeImages, hIcon); // 8 + + TreeView_SetImageList (hTree, data->hTreeImages, TVSIL_NORMAL); + + BOOL b = DBGetContactSettingByte (NULL, modname, "RegisterNick", TRUE); + CheckDlgButton (hwndDlg, IDC_CHECK_NICK, (UINT)( b ? BST_CHECKED : BST_UNCHECKED )); + EnableWindow (GetDlgItem (hwndDlg, IDC_NICK1), b); + EnableWindow (GetDlgItem (hwndDlg, IDC_NICK2), b); + + b = DBGetContactSettingByte (NULL, modname, "RegisterUser", TRUE); + CheckDlgButton (hwndDlg, IDC_CHECK_USER, (UINT)( b ? BST_CHECKED : BST_UNCHECKED )); + EnableWindow (GetDlgItem (hwndDlg, IDC_USER), b); + + CheckDlgButton (hwndDlg, IDC_AUTOANSWER, + (UINT)( DBGetContactSettingByte (NULL, modname, "Auto-answer", FALSE) ? + BST_CHECKED : BST_UNCHECKED ) ); + CheckDlgButton (hwndDlg, IDC_DUPS, + (UINT)( DBGetContactSettingByte (NULL, modname, "Filter-dups", TRUE) ? + BST_CHECKED : BST_UNCHECKED ) ); + CheckDlgButton (hwndDlg, IDC_ALWAYSCHECK00FORONLINE, + (UINT)( IsLegacyOnline( NULL ) ? BST_CHECKED : BST_UNCHECKED ) ); + + BYTE method = (BYTE) DBGetContactSettingByte (NULL, modname, "SendMethod", 0); + CheckRadioButton (hwndDlg, IDC_USE_MAILSLOT, IDC_USE_NETSEND, + IDC_USE_MAILSLOT + method); + EnableWindow (GetDlgItem (hwndDlg, IDC_USE_NETSEND), (fnNetMessageBufferSend != NULL)); + + CString sMyNick = GetNick( NULL ); + if ( ! sMyNick.IsEmpty() ) + { + netbios_name nname (sMyNick, 3); + SetDlgItemText (hwndDlg, IDC_NICK1, CA2T( nname.GetANSIFullName() ) ); + } + + if ( ! sMyNick.IsEmpty() ) + { + netbios_name nname (sMyNick, 1); + SetDlgItemText (hwndDlg, IDC_NICK2, CA2T( nname.GetANSIFullName() ) ); + } + + DBVARIANT dbv = {}; + if ( ! DBGetContactSettingTString( NULL, modname, "User", &dbv ) ) + { + netbios_name nname (dbv.ptszVal, 3); + SetDlgItemText (hwndDlg, IDC_USER, CA2T( nname.GetANSIFullName() ) ); + DBFreeVariant (&dbv); + } + + bLastOnline = ! ( pluginCurrentStatus != ID_STATUS_OFFLINE ); + + SetTimer( hwndDlg, 55, 500, NULL ); + + return TRUE; + } + + case WM_TIMER: + if ( bLastOnline != ( pluginCurrentStatus != ID_STATUS_OFFLINE ) ) + { + bLastOnline = ( pluginCurrentStatus != ID_STATUS_OFFLINE ); + Refresh( hwndDlg, hTree ); + } + return TRUE; + + case WM_DESTROY: + { + nns.RemoveAll(); + SetWindowLongPtr( hwndDlg, DWLP_USER, NULL ); + if ( data ) + { + ImageList_Destroy( data->hTreeImages ); + mir_free( data ); + } + hTree = NULL; + break; + } + + case WM_FILLTREE: + { + // Заполнение дерева имён + TreeView_DeleteAllItems (hTree); + TVINSERTSTRUCT tvis = { TVI_ROOT, TVI_LAST }; + tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; + tvis.item.pszText = (LPTSTR)(LPCTSTR)pluginMachineName; + tvis.item.iImage = tvis.item.iSelectedImage = nns.GetCount() ? 0 : 8; + HTREEITEM hRoot = TreeView_InsertItem (hTree, &tvis); + if ( nns.GetCount() ) + { + TVITEM item = { 0 }; + for (POSITION pos = nns.GetHeadPosition (); pos;) + { + netbios_name nname (nns.GetNext (pos)); + tvis.item.lParam = nname.GetLana(); + + // Поиск ланы в дереве по номеру + item.hItem = TreeView_GetChild (hTree, hRoot); + while (item.hItem) + { + item.mask = TVIF_HANDLE | TVIF_PARAM; + if (TreeView_GetItem (hTree, &item) && + item.lParam == nname.GetLana ()) + // найден + break; + item.hItem = TreeView_GetNextSibling (hTree, item.hItem); + } + if (item.hItem) + // Лана уже есть + tvis.hParent = item.hItem; + else + { + // Ланы ещё нет + tvis.hParent = hRoot; + tvis.item.iImage = tvis.item.iSelectedImage = 1; + CString tmp; + tmp.Format ( _T("%s #%d"), TranslateT ("LAN adapter"), nname.GetLana ()); + tvis.item.pszText = (LPTSTR) (LPCTSTR) tmp; + tvis.hParent = TreeView_InsertItem (hTree, &tvis); + + pluginNetBIOS.GetMAC (nname.GetLana (), tmp); + tmp.Insert (0, _T("MAC: ")); + tvis.item.pszText = (LPTSTR) (LPCTSTR) tmp; + TreeView_InsertItem (hTree, &tvis); + } + + CA2T textT( nname.GetANSIFullName() ); + tvis.item.pszText = (LPTSTR)(LPCTSTR)textT; + tvis.item.iImage = tvis.item.iSelectedImage = + (nname.IsOwnName () ? (nname.IsError () ? 1 : 0) : 2) + + (nname.IsGroupName () ? 5 : 2); + + // Поиск имени в лане по имени + item.hItem = TreeView_GetChild (hTree, tvis.hParent); + while (item.hItem) + { + item.mask = TVIF_HANDLE | TVIF_TEXT; + item.cchTextMax = 64; + CString tmp; + item.pszText = tmp.GetBuffer (item.cchTextMax); + BOOL ret = TreeView_GetItem (hTree, &item); + tmp.ReleaseBuffer (); + if (ret && tmp == textT ) + // найден + break; + item.hItem = TreeView_GetNextSibling (hTree, item.hItem); + } + if (!item.hItem) + // Имени ещё нет + TreeView_InsertItem (hTree, &tvis); + } + } + TreeView_Expand (hTree, hRoot, TVE_EXPAND); + + nns.RemoveAll (); + return TRUE; + } + + case WM_NOTIFY: + { + LPPSHNOTIFY lpHdr = reinterpret_cast (lParam); + if (lpHdr->hdr.idFrom == 0) { + data->hContact = reinterpret_cast (lpHdr->lParam); + switch (lpHdr->hdr.code) { + case PSN_KILLACTIVE: + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); + return TRUE; + + case PSN_APPLY: + DBWriteContactSettingByte (NULL, modname, "RegisterNick", + (BYTE)( (IsDlgButtonChecked (hwndDlg, IDC_CHECK_NICK) == BST_CHECKED ? TRUE : FALSE ) )); + DBWriteContactSettingByte (NULL, modname, "RegisterUser", + (BYTE)( (IsDlgButtonChecked (hwndDlg, IDC_CHECK_USER) == BST_CHECKED ? TRUE : FALSE ) )); + DBWriteContactSettingByte (NULL, modname, "Auto-answer", + (BYTE)( (IsDlgButtonChecked (hwndDlg, IDC_AUTOANSWER) == BST_CHECKED ? TRUE : FALSE ) )); + DBWriteContactSettingByte (NULL, modname, "Filter-dups", + (BYTE)( (IsDlgButtonChecked (hwndDlg, IDC_DUPS) == BST_CHECKED ? TRUE : FALSE ) )); + DBWriteContactSettingByte (NULL, modname, "SendMethod", + (BYTE)( (((IsDlgButtonChecked (hwndDlg, IDC_USE_MAILSLOT) == BST_CHECKED) ? 0 : + ((IsDlgButtonChecked (hwndDlg, IDC_USE_NETBIOS) == BST_CHECKED) ? 1 : + ((IsDlgButtonChecked (hwndDlg, IDC_USE_NETSEND) == BST_CHECKED) ? 2 : + 0 ) ))))); + SetLegacyOnline( NULL, ( IsDlgButtonChecked( hwndDlg, + IDC_ALWAYSCHECK00FORONLINE ) == BST_CHECKED ) ); + SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); + if (data->need_restart) { + data->need_restart = false; + GotoOffline (); + Sleep (2000); + Refresh (hwndDlg, hTree); + } + return TRUE; + } + } + break; + } + + case WM_COMMAND: + { + switch (LOWORD(wParam)) { + case IDC_CHECK_NICK: + case IDC_CHECK_USER: + EnableWindow (GetDlgItem (hwndDlg, IDC_NICK1), + IsDlgButtonChecked (hwndDlg, IDC_CHECK_NICK) == BST_CHECKED); + EnableWindow (GetDlgItem (hwndDlg, IDC_NICK2), + IsDlgButtonChecked (hwndDlg, IDC_CHECK_NICK) == BST_CHECKED); + EnableWindow (GetDlgItem (hwndDlg, IDC_USER), + IsDlgButtonChecked (hwndDlg, IDC_CHECK_USER) == BST_CHECKED); + + case IDC_USE_MAILSLOT: + case IDC_USE_NETBIOS: + case IDC_USE_NETSEND: + data->need_restart = true; + + case IDC_AUTOANSWER: + case IDC_ALWAYSCHECK00FORONLINE: + case IDC_DUPS: + PropSheet_Changed (GetParent (hwndDlg), hwndDlg); + break; + + case IDC_ADD: + AddDialog( hwndDlg ); + break; + } + break; + } + } + return FALSE; +} + +int __cdecl OPT_INITIALISE (WPARAM wParam, LPARAM /* lParam */) +{ + OPTIONSDIALOGPAGE odp = {}; + odp.cbSize = sizeof ( OPTIONSDIALOGPAGE ); + odp.pszGroup = "Network"; + odp.position = odp.pszGroup [0]; + odp.hInstance = pluginModule; + odp.pszTemplate = MAKEINTRESOURCEA (IDD_OPTIONS); + odp.pszTitle = modtitle; + odp.pfnDlgProc = DlgProcOptions; + odp.flags = ODPF_BOLDGROUPS; + CallService (MS_OPT_ADDPAGE, wParam, (LPARAM) &odp); + + return 0; +} diff --git a/plugins/!NotAdopted/WinPopup/options.h b/plugins/!NotAdopted/WinPopup/options.h new file mode 100644 index 0000000000..8b7d8b8bec --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/options.h @@ -0,0 +1,24 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +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. +*/ + +#pragma once + +int __cdecl OPT_INITIALISE (WPARAM wParam, LPARAM lParam); diff --git a/plugins/!NotAdopted/WinPopup/processapi.cpp b/plugins/!NotAdopted/WinPopup/processapi.cpp new file mode 100644 index 0000000000..d37578aed1 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/processapi.cpp @@ -0,0 +1,578 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2010 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "processapi.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +DWORD GetProcessId (LPCTSTR name) +{ + DWORD id = 0; + int name_len = lstrlen (name); + CProcessApi papi; + if (papi.Init (true)) { + DWORD pl = papi.ProcessesGetList(); + if (pl) { + CProcessApi::tProcessInfo pi = {0}; + while (papi.ProcessesWalk (pl, &pi)) { + int len = lstrlen (pi.FileName); + if (len >= name_len && + lstrcmpi (pi.FileName + (len - name_len), name) == 0) { + id = pi.pid; + break; + } + } + } + papi.ProcessesFreeList(pl); + } + return id; +} + +/* ----------------------------------------------------------------------------- + * Copyright (c) 2003 Elias Bachaalany + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ----------------------------------------------------------------------------- + */ + +#ifdef _UNICODE + #define Modifier "W" +#else + #define Modifier "A" +#endif + +// custom macro to allow me to load functions dynamically +#define DynamicGetProcAddress(lib, prefix, mod_name, Mod) \ + { \ + PVOID p = GetProcAddress(lib, #mod_name Mod); \ + if (!p) { \ + FreeLibrary(lib); \ + return (LastError = paeNoEntryPoint, false); \ + } \ + ##prefix##mod_name = (t_##prefix##mod_name)p; \ + } + +//-------------------------------------------------------------------------------------------- +// The constructor only initializes some internal variables +CProcessApi::CProcessApi() : + m_hPsApi (NULL), + m_hTlHlp (NULL), + m_hNtApi (NULL), + m_bPsApi (false), + m_bToolHelp (false), + m_bNtApi (false), + LastError (paeSuccess) +{ +} + +//-------------------------------------------------------------------------------------------- +// This is the destructor. It frees any process helper api that has been used +CProcessApi::~CProcessApi() +{ + if (m_hPsApi) + FreeLibrary(m_hPsApi); + if (m_hTlHlp) + FreeLibrary(m_hTlHlp); + if (m_hNtApi) + FreeLibrary(m_hNtApi); +} + +//-------------------------------------------------------------------------------------------- +// Used to initialize the CProcessApi class +bool CProcessApi::Init (bool bNtApiFirst) +{ + bool loaded = m_bPsApi || m_bToolHelp || m_bNtApi; + + if (bNtApiFirst && !loaded) { + loaded = Load_NtApi(); + } + + if (!loaded) { + loaded = Load_PsApi(); + } + + if (!loaded) { + loaded = Load_TlHlp(); + } + + if (!bNtApiFirst && !loaded) { + loaded = Load_NtApi(); + } + + return (loaded ? (LastError = paeSuccess, true) : (LastError = paeNoApi, false)); +} + +//-------------------------------------------------------------------------------------------- +// This function returns a list id (list id) that can be used w/ Walking functions +// in order to navigate through the process list +// This function decides what to use from the helper apis +DWORD CProcessApi::ModulesGetList(DWORD pid) +{ + tModulesData *md = new tModulesData; + if ( ! md ) + return (LastError = paeNoMem, 0u); + + // create the list + md->ml = new tModulesList; + if ( ! md->ml ) + { + delete md; + return (LastError = paeNoMem, 0u); + } + + // decide what to use + if (m_bPsApi) + LastError = ModulesPopulatePsApi(pid, md); + else if (m_bToolHelp) + LastError = ModulesPopulateToolHelp(pid, md); + else if (m_bNtApi) + LastError = ModulesPopulateNtApi(pid, md); + + return (DWORD) md; +} + +//-------------------------------------------------------------------------------------------- +// Populates the modules of a process using ToolHelp api +DWORD CProcessApi::ModulesPopulateToolHelp(DWORD pid, tModulesData *md) +{ + MODULEENTRY32 me32 = {sizeof(MODULEENTRY32), 0}; + tModuleInfo mi = {0}; + + // Take a snapshot of all modules in the specified process. + HANDLE hModuleSnap = tlhlp_CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid); + + if (hModuleSnap == INVALID_HANDLE_VALUE) + return paeNoSnap; + + // Start walking + BOOL bMore = tlhlp_Module32First(hModuleSnap, &me32); + do + { + lstrcpy (mi.FileName, me32.szExePath); + mi.ImageBase = me32.modBaseAddr; + mi.ImageSize = me32.modBaseSize; + + // save item + md->ml->Add (mi); + + // search next + bMore = tlhlp_Module32Next(hModuleSnap, &me32); + } while (bMore); + + CloseHandle (hModuleSnap); + md->Pos = 0; + return paeSuccess; +} + +//-------------------------------------------------------------------------------------------- +// Populates the modules of a process using PsApi api +DWORD CProcessApi::ModulesPopulatePsApi(DWORD pid, tModulesData *md) +{ + DWORD nModules, nCount = 4096; + HANDLE hProcess; + + // allocate memory for modules + HMODULE *modules = new HMODULE[nCount]; + + // open process for querying only + hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (!hProcess) + return paeNoSnap; + + // now try to enum all modules + if (!psapi_EnumProcessModules(hProcess, modules, nCount * sizeof(DWORD), &nModules)) + { + CloseHandle(hProcess); + return paeNoSnap; + } + + // because nModules returned from EnumProcessModules() is in bytes, I divid by 4 to return n DWORDs + nModules /= 4; + + tModuleInfo mi = {0}; + MODULEINFO psapiMi = {0}; + + for (DWORD i=0; i < nModules; i++) + { + // get module name + psapi_GetModuleFileNameEx(hProcess, modules[i], mi.FileName, sizeof(mi.FileName)); + + // get module information + psapi_GetModuleInformation(hProcess, modules[i], &psapiMi, sizeof(MODULEINFO)); + + // get relevant data + mi.ImageBase = psapiMi.lpBaseOfDll; + mi.ImageSize = psapiMi.SizeOfImage; + + // save item + md->ml->Add (mi); + } + + md->Pos = 0; + CloseHandle(hProcess); + delete [] modules; + + return paeSuccess; +} + +//-------------------------------------------------------------------------------------------- +// It frees a modules list by its ID +void CProcessApi::ModulesFreeList(DWORD_PTR lid) +{ + tModulesData *md = reinterpret_cast(lid); + delete md->ml; + delete md; +} + +//-------------------------------------------------------------------------------------------- +// This function allows you to retrieve information about a certain module in a process +// You can either use this function using the Pos parameter controlled by the ModulesCount() +// Or you can keep calling it till it returns false +bool CProcessApi::ModulesWalk(DWORD_PTR lid, tModuleInfo *mi, DWORD Pos) +{ + tModulesData *md = reinterpret_cast(lid); + + // auto position ? + if (Pos == -1) + Pos = md->Pos; + + // out of bounds? + if (Pos > md->ml->GetCount()) + return (LastError = paeOutOfBounds, false); + + // end reached ? + else if (Pos == md->ml->GetCount()) + return (LastError = paeNoMore, false); + + // copy information to user buffer + *mi = md->ml->GetAt (Pos); + + // advance position to next item + md->Pos++; + + return (LastError = paeSuccess, true); +} + + +//-------------------------------------------------------------------------------------------- +// This function allows you to retrieve information about a certain process in the list +// You can either use this function using the Pos parameter controlled by the ProcessesCount() +// Or you can keep calling it till it returns false +bool CProcessApi::ProcessesWalk(DWORD_PTR lid, tProcessInfo *pi, DWORD Pos) +{ + tProcessesData *pd = reinterpret_cast(lid); + + // auto position ? + if (Pos == -1) + Pos = pd->Pos; + + // out of bounds? + if (Pos > pd->pl->GetCount()) + return (LastError = paeOutOfBounds, false); + // end reached ? + else if (Pos == pd->pl->GetCount()) + return (LastError = paeNoMore, false); + + // copy information to user buffer + *pi = pd->pl->GetAt (Pos); + + // advance position to next item + pd->Pos++; + return (LastError = paeSuccess, true); +} + + +//-------------------------------------------------------------------------------------------- +// This function returns a list id (list id) that can be used w/ Walking functions +// in order to navigate through the process list +// This function decides what to use from the helper apis +DWORD CProcessApi::ProcessesGetList() +{ + tProcessesData *pd = new tProcessesData; + if (!pd) + return (LastError = paeNoMem, 0u); + + // create the list + pd->pl = new tProcessesList; + if (!pd->pl) + { + delete pd; + return (LastError = paeNoMem, 0u); + } + + // decide what to use + if (m_bPsApi) + LastError = ProcessesPopulatePsApi(pd); + else if (m_bToolHelp) + LastError = ProcessesPopulateToolHelp(pd); + else if (m_bNtApi) + LastError = ProcessesPopulateNtApi(pd); + + return (DWORD) pd; +} + +//-------------------------------------------------------------------------------------------- +// It frees a process list by its ID +void CProcessApi::ProcessesFreeList(DWORD_PTR lid) +{ + tProcessesData *pd = reinterpret_cast(lid); + delete pd->pl; + delete pd; +} + +//-------------------------------------------------------------------------------------------- +// Dynamically loads the PsApi functions +bool CProcessApi::Load_PsApi() +{ + if (m_bPsApi) + return true; + if (!m_hPsApi) + m_hPsApi = LoadLibrary (_T("psapi.dll")); + if (!m_hPsApi) + return false; + + DynamicGetProcAddress(m_hPsApi, psapi_, GetModuleFileNameEx, Modifier); + DynamicGetProcAddress(m_hPsApi, psapi_, EnumProcessModules, ""); + DynamicGetProcAddress(m_hPsApi, psapi_, EnumProcesses, ""); + DynamicGetProcAddress(m_hPsApi, psapi_, GetModuleInformation, ""); + + m_bPsApi = true; + return true; +} + + +//-------------------------------------------------------------------------------------------- +// Dynamically loads the ToolHelp functions +bool CProcessApi::Load_TlHlp() +{ + if (m_bToolHelp) + return true; + if (!m_hTlHlp) + m_hTlHlp = LoadLibrary (_T("kernel32.dll")); + if (!m_hTlHlp) + return false; + + DynamicGetProcAddress(m_hTlHlp, tlhlp_, CreateToolhelp32Snapshot, ""); + DynamicGetProcAddress(m_hTlHlp, tlhlp_, Process32First, ""); + DynamicGetProcAddress(m_hTlHlp, tlhlp_, Process32Next, ""); + DynamicGetProcAddress(m_hTlHlp, tlhlp_, Module32First, ""); + DynamicGetProcAddress(m_hTlHlp, tlhlp_, Module32Next, ""); + + m_bToolHelp = true; + return true; +} + +bool CProcessApi::Load_NtApi() +{ + if (m_bNtApi) + return true; + if (!m_hNtApi) + m_hNtApi = LoadLibrary (_T("ntdll.dll")); + if (!m_hNtApi) + return false; + + DynamicGetProcAddress(m_hNtApi, ntapi_, ZwQuerySystemInformation, ""); + + m_bNtApi = true; + return true; +} + +//-------------------------------------------------------------------------------------------- +// Populates a tProcessesList with the help of ToolHelp API +// Returns an error code paeXXXX +DWORD CProcessApi::ProcessesPopulateToolHelp(tProcessesData *pd) +{ + // create a process snapshot + HANDLE hSnap = tlhlp_CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnap == INVALID_HANDLE_VALUE) + return paeNoSnap; + + BOOL bMore; + tProcessInfo pi = {0}; + + PROCESSENTRY32 pe32 = {sizeof(PROCESSENTRY32), 0}; + + // clear the list + pd->pl->RemoveAll (); + + // initialize position + pd->Pos = 0; + + bMore = tlhlp_Process32First(hSnap, &pe32); + while (bMore) + { + // convert from PROCESSENTRY32 to my unified tProcessInfo struct + pi.pid = pe32.th32ProcessID; + lstrcpy (pi.FileName, pe32.szExeFile); + + pd->pl->Add(pi); + bMore = tlhlp_Process32Next(hSnap, &pe32); + } + + CloseHandle(hSnap); + return paeSuccess; +} + + +//-------------------------------------------------------------------------------------------- +// Populates the list using PsApi functions +DWORD CProcessApi::ProcessesPopulatePsApi(tProcessesData *pd) +{ + DWORD nProcess, // number of processes returned + nCount(4096); // maximum number of processes (defined by me) + + // Dynamic array for storing returned processes IDs + DWORD *processes = new DWORD[nCount]; + + // enum all processes + if (!psapi_EnumProcesses(processes, nCount * sizeof(DWORD), &nProcess)) + { + delete [] processes; + return paeNoSnap; + } + + // convert fron bytes count to items count + nProcess /= 4; + + // walk in process list + for (DWORD i = 0; i < nProcess; i++) { + + if (processes[i] == 0) + // Idle + continue; + + // open process for querying only + HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processes[i]); + if (!hProcess) + continue; + + // get the process's image name by getting first module + DWORD nmod; + HMODULE mod1; + + tProcessInfo pi = {0}; + pi.pid = processes [i]; + if (!psapi_EnumProcessModules (hProcess, &mod1, sizeof(mod1), &nmod)) + lstrcpy (pi.FileName, _T("-")); + else + psapi_GetModuleFileNameEx (hProcess, mod1, pi.FileName, sizeof(pi.FileName)); + pd->pl->Add (pi); + + CloseHandle(hProcess); + } + + // reposition list to 0 + pd->Pos = 0; + delete [] processes; + + return paeSuccess; +} + +DWORD CProcessApi::ProcessesPopulateNtApi (tProcessesData *pd) +{ + ULONG cbBuffer = 0x10000; + char* pBuffer; + NTSTATUS Status; + do { + pBuffer = new char [cbBuffer]; + if (pBuffer == NULL) + return paeNoMem; + Status = ntapi_ZwQuerySystemInformation (SystemProcessesAndThreadsInformation, + pBuffer, cbBuffer, NULL); + if (Status == STATUS_INFO_LENGTH_MISMATCH) { + delete [] pBuffer; + cbBuffer *= 2; + } else + if (!NT_SUCCESS(Status)) { + delete [] pBuffer; + return paeNoSnap; + } + } while (Status == STATUS_INFO_LENGTH_MISMATCH); + + PSYSTEM_PROCESSES pProcesses = (PSYSTEM_PROCESSES) pBuffer; + for (;;) { + if (pProcesses->ProcessName.Buffer != NULL) { + tProcessInfo pi; + pi.pid = pProcesses->ProcessId; +#ifdef UNICODE + lstrcpy (pi.FileName, pProcesses->ProcessName.Buffer); +#else + WideCharToMultiByte (CP_ACP, 0, pProcesses->ProcessName.Buffer, -1, + pi.FileName, MAX_PATH, NULL, NULL); +#endif + pd->pl->Add (pi); + } // else + // Idle + + if (pProcesses->NextEntryDelta == 0) + break; + + // find the address of the next process structure + pProcesses = (PSYSTEM_PROCESSES)(((LPBYTE)pProcesses) + pProcesses->NextEntryDelta); + } + pd->Pos = 0; + delete [] pBuffer; + return paeSuccess; +} + +DWORD CProcessApi::ModulesPopulateNtApi(DWORD /* pid */, tModulesData* /* md */) +{ + return paeSuccess; +} + +//-------------------------------------------------------------------------------------------- +// Returns the count in the processes list +DWORD CProcessApi::ProcessesCount(DWORD_PTR lid) const +{ + return (DWORD)(reinterpret_cast(lid))->pl->GetCount(); +} + +//-------------------------------------------------------------------------------------------- +// Returns the count in the modules list +DWORD CProcessApi::ModulesCount(DWORD_PTR lid) const +{ + return (DWORD)(reinterpret_cast(lid))->ml->GetCount(); +} diff --git a/plugins/!NotAdopted/WinPopup/processapi.h b/plugins/!NotAdopted/WinPopup/processapi.h new file mode 100644 index 0000000000..b1875751ea --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/processapi.h @@ -0,0 +1,264 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +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. +*/ + +#pragma once + +#pragma pack (push, 1) + +typedef LONG NTSTATUS; +typedef LONG KPRIORITY; +typedef LONG SYSTEM_INFORMATION_CLASS; + +#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) +#define SystemProcessesAndThreadsInformation 5 + +typedef struct _CLIENT_ID { + DWORD UniqueProcess; + DWORD UniqueThread; +} CLIENT_ID; + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING; + +typedef struct _VM_COUNTERS { + SIZE_T PeakVirtualSize; + SIZE_T VirtualSize; + ULONG PageFaultCount; + SIZE_T PeakWorkingSetSize; + SIZE_T WorkingSetSize; + SIZE_T QuotaPeakPagedPoolUsage; + SIZE_T QuotaPagedPoolUsage; + SIZE_T QuotaPeakNonPagedPoolUsage; + SIZE_T QuotaNonPagedPoolUsage; + SIZE_T PagefileUsage; + SIZE_T PeakPagefileUsage; +} VM_COUNTERS; + +typedef struct _SYSTEM_THREADS { + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER CreateTime; + ULONG WaitTime; + PVOID StartAddress; + CLIENT_ID ClientId; + KPRIORITY Priority; + KPRIORITY BasePriority; + ULONG ContextSwitchCount; + LONG State; + LONG WaitReason; +} SYSTEM_THREADS, * PSYSTEM_THREADS; + +typedef struct _SYSTEM_PROCESSES { + ULONG NextEntryDelta; + ULONG ThreadCount; + ULONG Reserved1[6]; + LARGE_INTEGER CreateTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER KernelTime; + UNICODE_STRING ProcessName; + KPRIORITY BasePriority; + ULONG ProcessId; + ULONG InheritedFromProcessId; + ULONG HandleCount; + ULONG Reserved2[2]; + VM_COUNTERS VmCounters; +#if _WIN32_WINNT >= 0x500 + IO_COUNTERS IoCounters; +#endif + SYSTEM_THREADS Threads[1]; +} SYSTEM_PROCESSES, * PSYSTEM_PROCESSES; + +#pragma pack (pop) + +//-------------------------------------------------------------------------------------------- +// CProcessApi class - written by Elias Bachaalany. +// Check the implementation file for more information +// + +class CProcessApi +{ +public: + typedef struct tProcessInfo + { + DWORD pid; + TCHAR FileName[MAX_PATH]; + }; + + typedef struct tModuleInfo + { + LPVOID ImageBase; + DWORD ImageSize; + TCHAR FileName[MAX_PATH]; + }; + +private: + typedef CAtlArray tProcessesList; + typedef CAtlArray tModulesList; + + typedef struct tProcessesData + { + DWORD Pos; + tProcessesList *pl; + }; + + typedef struct tModulesData + { + DWORD Pos; + tModulesList *ml; + }; + + // PSAPI.DLL functions prototype + typedef BOOL (WINAPI *t_psapi_EnumProcesses)( + DWORD *lpidProcess, // array of process identifiers + DWORD cb, // size of array + DWORD *cbNeeded // number of bytes returned + ); + + typedef BOOL (WINAPI *t_psapi_EnumProcessModules)( + HANDLE hProcess, // handle to process + HMODULE *lphModule, // array of module handles + DWORD cb, // size of array + LPDWORD lpcbNeeded // number of bytes required + ); + + typedef DWORD (WINAPI *t_psapi_GetModuleFileNameEx)( + HANDLE hProcess, // handle to process + HMODULE hModule, // handle to module + LPTSTR lpFilename, // path buffer + DWORD nSize // maximum characters to retrieve + ); + + typedef BOOL (WINAPI *t_psapi_GetModuleInformation)( + HANDLE hProcess, + HMODULE hModule, + LPMODULEINFO lpmodinfo, + DWORD cb + ); + + // functions instances + t_psapi_GetModuleFileNameEx psapi_GetModuleFileNameEx; + t_psapi_EnumProcessModules psapi_EnumProcessModules; + t_psapi_EnumProcesses psapi_EnumProcesses; + t_psapi_GetModuleInformation psapi_GetModuleInformation; + + // TOOLHELP functions prototype + typedef HANDLE (WINAPI *t_tlhlp_CreateToolhelp32Snapshot)( + DWORD dwFlags, + DWORD th32ProcessID + ); + + typedef BOOL (WINAPI *t_tlhlp_Process32First)( + HANDLE hSnapshot, + LPPROCESSENTRY32 lppe + ); + + typedef BOOL (WINAPI *t_tlhlp_Process32Next)( + HANDLE hSnapshot, + LPPROCESSENTRY32 lppe + ); + + typedef BOOL (WINAPI *t_tlhlp_Module32First)( + HANDLE hSnapshot, + LPMODULEENTRY32 lpme + ); + + typedef BOOL (WINAPI *t_tlhlp_Module32Next)( + HANDLE hSnapshot, + LPMODULEENTRY32 lpme + ); + + // functions instances + t_tlhlp_CreateToolhelp32Snapshot tlhlp_CreateToolhelp32Snapshot; + t_tlhlp_Process32First tlhlp_Process32First; + t_tlhlp_Process32Next tlhlp_Process32Next; + t_tlhlp_Module32First tlhlp_Module32First; + t_tlhlp_Module32Next tlhlp_Module32Next; + + // NTDLL.DLL functions prototype + typedef NTSTATUS (NTAPI *t_ntapi_ZwQuerySystemInformation)( + SYSTEM_INFORMATION_CLASS SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength + ); + + // functions instances + t_ntapi_ZwQuerySystemInformation ntapi_ZwQuerySystemInformation; + + // Private member variables + HMODULE m_hPsApi; + HMODULE m_hTlHlp; + HMODULE m_hNtApi; + + bool m_bPsApi; + bool m_bToolHelp; + bool m_bNtApi; + + bool Load_PsApi(); + bool Load_TlHlp(); + bool Load_NtApi(); + + DWORD ProcessesPopulatePsApi(tProcessesData *pd); + DWORD ProcessesPopulateToolHelp(tProcessesData *pd); + DWORD ProcessesPopulateNtApi(tProcessesData *pd); + + DWORD ModulesPopulatePsApi(DWORD pid, tModulesData *md); + DWORD ModulesPopulateToolHelp(DWORD pid, tModulesData *md); + DWORD ModulesPopulateNtApi(DWORD pid, tModulesData *md); + +public: + // CProcessApi error enum + enum + { + paeSuccess = 0, // No error + paeNoApi, // No process API helper dll found + paeNoEntryPoint, // One needed entrypoint not found in helper dll + paeNoMem, // Not enough memory + paeNoSnap, // Could not get a snapshot + paeNoMore, // List contains no more items + paeOutOfBounds, // Tried to access list w/ an invalid index + paeYYY + }; + + DWORD LastError; // Holds the last error + + CProcessApi(); + ~CProcessApi(); + + bool Init (bool bNtApiFirst = false); + + DWORD ProcessesGetList(); + bool ProcessesWalk(DWORD_PTR lid, tProcessInfo *pi, DWORD Pos = -1); + DWORD ProcessesCount(DWORD_PTR lid) const; + void ProcessesFreeList(DWORD_PTR lid); + + DWORD ModulesGetList(DWORD ProcessID); + bool ModulesWalk(DWORD_PTR lid, tModuleInfo *mi, DWORD Pos = -1); + DWORD ModulesCount(DWORD_PTR lid) const; + void ModulesFreeList(DWORD_PTR lid); +}; + +// Получение PID запущенного процесса по имени его выполнимого модуля +DWORD GetProcessId (LPCTSTR name); diff --git a/plugins/!NotAdopted/WinPopup/resource.h b/plugins/!NotAdopted/WinPopup/resource.h new file mode 100644 index 0000000000..be40ff446c --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/resource.h @@ -0,0 +1,66 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by winpopup_proto.rc +// +#define IDI_WINPOPUP 102 +#define IDI_ONLINE 104 +#define IDI_OFFLINE 105 +#define IDD_OPTIONS 106 +#define IDI_AWAY 128 +#define IDI_FREECHAT 129 +#define IDI_INVISIBLE 130 +#define IDI_NA 131 +#define IDI_DND 158 +#define IDI_OCCUPIED 159 +#define IDC_AUTOANSWER 1001 +#define IDI_ONTHEPHONE 1002 +#define IDC_NICK1 1002 +#define IDI_OUTTOLUNCH 1003 +#define IDC_USER 1003 +#define IDC_NICK2 1004 +#define IDC_ADD 1005 +#define IDC_NAME 1006 +#define IDC_DUPS 1006 +#define IDC_TREE 1007 +#define IDC_LEGEND_1 1008 +#define IDC_LEGEND_2 1009 +#define IDC_LEGEND_3 1010 +#define IDC_LEGEND_4 1011 +#define IDC_LEGEND_5 1012 +#define IDC_LEGEND_6 1013 +#define IDC_USE_MAILSLOT 1014 +#define IDC_USE_NETBIOS 1015 +#define IDC_USE_NETSEND 1016 +#define IDC_CHECK_USER 1017 +#define IDC_CHECK_NICK 1018 +#define IDC_ABOUT 1019 +#define IDC_ONLINE_CHECK 1020 +#define IDC_ALWAYSCHECK00FORONLINE 1021 +#define IDC_CHECK00FORONLINE 1022 +#define IDC_CHECK1 1023 +#define IDC_GROUP 1023 +#define IDD_ADD 2000 +#define IDI_LANA 2001 +#define IDI_COMPUTER 2002 +#define IDI_GOOD_NAME 2003 +#define IDI_BAD_NAME 2004 +#define IDI_OTHER_NAME 2005 +#define IDI_OTHER_NAMES 2006 +#define IDI_BAD_NAMES 2007 +#define IDI_GOOD_NAMES 2008 +#define IDD_USERINFO 2009 +#define IDI_EXPLORE 2011 +#define IDI_COMPUTER_ERROR 2013 +#define IDI_ADD_COMPUTER 2014 +#define IDD_CREATE 2015 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 2016 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1024 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/plugins/!NotAdopted/WinPopup/scanner.cpp b/plugins/!NotAdopted/WinPopup/scanner.cpp new file mode 100644 index 0000000000..a6956ff51a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/scanner.cpp @@ -0,0 +1,218 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2011 Nikolay Raspopov + +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. +*/ + +#include "stdafx.h" +#include "winpopup_proto.h" +#include "scanner.h" +#include "netbios.h" +#include "chat.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +contact_scanner pluginScanner; + +contact_scanner::contact_scanner () : + m_ScannerTerm (NULL), + m_Scanner (NULL) +{ +} + +contact_scanner::~contact_scanner () +{ + Destroy (); +} + +bool contact_scanner::Create () +{ + // Запуск сканера контактов + if (m_ScannerTerm) + ResetEvent (m_ScannerTerm); + else + m_ScannerTerm = CreateEvent (NULL, TRUE, FALSE, NULL); + + if ( ! m_Scanner ) + m_Scanner = (HANDLE)mir_forkthread( ScannerThread, this ); + + return ( m_Scanner != NULL ); +} + +void contact_scanner::AskForDestroy() +{ + if (m_ScannerTerm) + SetEvent (m_ScannerTerm); +} + +void contact_scanner::Destroy () +{ + AskForDestroy(); + + if (m_Scanner) + { + if (WaitForSingleObject (m_Scanner, ALMOST_INFINITE) == WAIT_TIMEOUT) + { + LOG("Terminate scanner!"); + TerminateThread (m_Scanner, 0); + } + m_Scanner = NULL; + } + + if (m_ScannerTerm) { + CloseHandle (m_ScannerTerm); + m_ScannerTerm = NULL; + } +} + +contact_scanner::operator bool () const +{ + return ( m_Scanner != NULL ); +} + +// First, Next, ... Next, NULL, First, Next... +HANDLE contact_scanner::GetNextScannableContact() +{ + static HANDLE hContact = NULL; + if (!hContact) + hContact = (HANDLE) CallService (MS_DB_CONTACT_FINDFIRST, 0, 0); + + // Циклический перебор контактов + while( hContact ) + { + // Проверка на совпадение протокола контакта + if ( IsMyContact( hContact ) && + !DBGetContactSettingByte (hContact, "CList", "NotOnList", 0) && + !DBGetContactSettingByte (hContact, "CList", "Hidden", 0) ) + { + // Вычисление сколько секунд прошло со времени последнего + // обновления статуса контакта. Нужна проверка? + DWORD elapsed = GetElapsed (hContact, "LastSeen"); + if ( elapsed >= MIN_PING_INTERVAL ) + break; + } + hContact = (HANDLE) CallService (MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + return hContact; +} + +int contact_scanner::ScanContact(HANDLE hContact) +{ + if ( ! pluginInstalled ) + return ID_STATUS_OFFLINE; + +#ifdef CHAT_ENABLED + if ( IsChatRoom( hContact ) ) + { + CString sSession = GetChatSession( hContact ); + if ( pluginChatEnabled && ! sSession.IsEmpty() ) + { + CAtlList< CString > lst; + EnumWorkgroups( lst ); + for ( POSITION pos = lst.GetHeadPosition(); pos; ) + { + if ( lst.GetNext( pos ) == sSession ) + return ID_STATUS_ONLINE; + } + } + return ID_STATUS_OFFLINE; + } + else +#endif // CHAT_ENABLED + { + int status = ID_STATUS_OFFLINE; + + // Получение статуса "Always Online" + if ( DBGetContactSettingByte( hContact, modname, "AlwaysOnline", FALSE ) ) + status = ID_STATUS_ONLINE; + + // Получение имени контакта + CString sNick = GetNick( hContact ); + if ( ! sNick.IsEmpty() ) + { + if ( IsGroup( hContact ) ) + { + // Имя "ВСЕ" вегда онлайн + if ( sNick == _T("*") ) + return ID_STATUS_ONLINE; + + // Перечисление групп и сличение с нашей + CAtlList< CString > lst; + EnumWorkgroups( lst ); + for ( POSITION pos = lst.GetHeadPosition(); pos; ) + { + if ( lst.GetNext( pos ).CompareNoCase( sNick ) == 0 ) + return ID_STATUS_ONLINE; + } + } + else if ( IsLegacyOnline( NULL ) || IsLegacyOnline( hContact ) ) + { + // Синхронный опрос хоста на наличие NetBIOS-имени "Nick <00> U" + netbios_name nname( sNick, 0x00, false ); + UCHAR foo; + if ( pluginNetBIOS.FindNameLana( nname, foo ) ) + { + status = ID_STATUS_ONLINE; + + // Асинхронный опрос контакта "Nick <00> U" + pluginNetBIOS.AskStatus( nname ); + } + } + else + { + // Синхронный опрос хоста на наличие NetBIOS-имени "Nick <03> U" + netbios_name nname( sNick, 0x03, false ); + UCHAR foo; + if ( pluginNetBIOS.FindNameLana( nname, foo ) ) + { + status = ID_STATUS_ONLINE; + + // Асинхронный опрос контакта "Nick <03> U" + pluginNetBIOS.AskStatus( nname ); + } + } + } + return status; + } +} + +void contact_scanner::Scanner () +{ + while (WaitForSingleObject (m_ScannerTerm, 1000) == WAIT_TIMEOUT) + { + // Выборка следующего кандидата на проверку + if ( HANDLE hContact = GetNextScannableContact() ) + { + // Проверка контакта + SetContactStatus( hContact, ScanContact( hContact ), true ); + } + } +} + +void contact_scanner::ScannerThread (LPVOID lpParameter) +{ + if ( contact_scanner* pScanner = (contact_scanner*)lpParameter ) + { + pScanner->Scanner(); + pScanner->m_Scanner = NULL; + } +} diff --git a/plugins/!NotAdopted/WinPopup/scanner.h b/plugins/!NotAdopted/WinPopup/scanner.h new file mode 100644 index 0000000000..f2a5c87402 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/scanner.h @@ -0,0 +1,49 @@ +/* + +WinPopup Protocol plugin for Miranda IM. + +Copyright (C) 2004-2006 Nikolay Raspopov + +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. +*/ + +#pragma once + +class contact_scanner +{ +public: + contact_scanner (); + ~contact_scanner (); + + bool Create (); + void AskForDestroy(); // Для ускорения + void Destroy (); + operator bool () const; + + // Проверка статуса контакта (асинхронная и синхронная) + static int ScanContact(HANDLE hContact); + +protected: + HANDLE m_ScannerTerm; // Событие для остановки + HANDLE m_Scanner; // Хэндлер нити периодической проверки контактов + + // Получить следующий контакт нуждающийся в проверке + static HANDLE GetNextScannableContact (); + // Рабочая нить цикла периодической проверки контактов + void Scanner (); + static void ScannerThread (LPVOID lpParameter); +}; + +extern contact_scanner pluginScanner; diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_avatars.h b/plugins/!NotAdopted/WinPopup/sdk/m_avatars.h new file mode 100644 index 0000000000..9df013446f --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_avatars.h @@ -0,0 +1,359 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2004 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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. + +Avatar service + +- load and maintain a cache of contact avatars. +- draw avatars to a given target device context +- maintain per protocol fallback images + +The avatar service builds on top of Mirandas core bitmap loading service (MS_UTILS_LOADBITMAP). +However, if imgdecoder.dll is installed in mirandas main or Plugins directory, it can be used +to support PNG images. The avatar service loads 32bit PNG images and peforms alpha channel +premultiplication so that these images can be rendered by using the Win32 AlphaBlend() API. + +The cache grows on demand only, that is, no avatars are PREloaded. An avatar is only loaded +if a plugin requests this by using the MS_AV_GETAVATAR service. Since avatars may update +asynchronously, the avatar iamge may not be ready when a plugin calls the service. In that +case, an event (ME_AV_AVATARCHANGED) is fired when a contacts avatar changes. This event +is also fired, when a contact avatar changes automatically. + +The service takes care about protocol capabilites (does not actively fetch avatars for +protocols which do not report avatar capabilities via PF4_AVATARS or for protocols which +have been disabled in the option dialog). It also does not actively fetch avatars for +protocols which are in invisible status mode (may cause privacy issues and some protocols +like MSN don't allow any outbound client communication when in invisible status mode) +unless AF_FETCHALWAYS is set. + +- TODO +- maintain recent avatars (store the last hashes to avoid re-fetching) +- cache expiration, based on least recently used algorithm. + +(c) 2005 by Nightwish, silvercircle@gmail.com + +*/ + +#ifndef _M_AVATARS_H +#define _M_AVATARS_H + +#define AVS_BITMAP_VALID 1 +#define AVS_BITMAP_EXPIRED 2 // the bitmap has been expired from the cache. (unused, currently. +#define AVS_HIDEONCLIST 4 +#define AVS_PREMULTIPLIED 8 // set in the dwFlags member of the struct avatarCacheEntry for 32 bit transparent + // images when loaded with imgdecoder. These images can be rendered transparently + // using the AlphaBlend() API with AC_SRC_ALPHA +#define AVS_PROTOPIC 16 // picture is a protocol picture +#define AVS_CUSTOMTRANSPBKG 32 // Bitmap was changed to set the background color transparent +#define AVS_HASTRANSPARENCY 64 // Bitmap has at least one pixel transparent +#define AVS_OWNAVATAR 128 // is own avatar entry +#define AVS_NOTREADY 4096 + +struct avatarCacheEntry { + DWORD cbSize; // set to sizeof(struct) + HANDLE hContact; // contacts handle, 0, if it is a protocol avatar + HBITMAP hbmPic; // bitmap handle of the picutre itself + DWORD dwFlags; // see above for flag values + LONG bmHeight, bmWidth; // bitmap dimensions + DWORD t_lastAccess; // last access time (currently unused, but plugins should still + // use it whenever they access the avatar. may be used in the future + // to implement cache expiration + LPVOID lpDIBSection; // unused field + char szFilename[MAX_PATH]; // filename of the avatar (absolute path) +}; + +typedef struct avatarCacheEntry AVATARCACHEENTRY; + +struct CacheNode { + struct CacheNode *pNextNode; + struct avatarCacheEntry ace; + //CRITICAL_SECTION cs; + BOOL loaded; + int mustLoad; + DWORD dwFlags; + int pa_format; +}; + +#define AVDRQ_FALLBACKPROTO 0x0001 // use the protocol picture as fallback (currently not used) +#define AVDRQ_FAILIFNOTCACHED 0x0002 // don't create a cache entry if it doesn't already exist. (currently not working) +#define AVDRQ_ROUNDEDCORNER 0x0004 // draw with rounded corners +#define AVDRQ_DRAWBORDER 0x0008 // draw a border around the picture +#define AVDRQ_PROTOPICT 0x0010 // draw a protocol picture (if available). +#define AVDRQ_HIDEBORDERONTRANSPARENCY 0x0020 // hide border if bitmap has transparency +#define AVDRQ_OWNPIC 0x0040 // draw own avatar (szProto is valid - use "" for global avatar) +#define AVDRQ_RESPECTHIDDEN 0x0080 // don't draw images marked as hidden +#define AVDRQ_DONTRESIZEIFSMALLER 0x0100 // don't resize images that are smaller then the draw area +#define AVDRQ_FORCEFASTALPHA 0x0200 // force rendering with simple AlphaBlend (will use FI_Resample otherwise) +#define AVDRQ_FORCEALPHA 0x0400 // force with simple AlphaBlend (may use StretchBlt otherwise) +#define AVDRQ_AERO 0x0800 // draw on aero surface + +// request to draw a contacts picture. See MS_AV_DRAWAVATAR service description + +typedef struct _avatarDrawRequest { + DWORD cbSize; // set this to sizeof(AVATARDRAWREQUEST) - mandatory, service will return failure code if + // cbSize is wrong + HANDLE hContact; // the contact for which the avatar should be drawn. set it to 0 to draw a protocol picture + HDC hTargetDC; // target device context + RECT rcDraw; // target rectangle. The avatar will be centered within the rectangle and scaled to fit. + DWORD dwFlags; // flags (see above for valid bitflags) + DWORD dwReserved; // for future use + DWORD dwInternal; // don't use it + COLORREF clrBorder; // color for the border (used with AVDRQ_DRAWBORDER) + UCHAR radius; // radius (used with AVDRQ_ROUNDEDCORNER) + UCHAR alpha; // alpha value for semi-transparent avatars (valid values form 1 to 255, if it is set to 0 + // the avatar won't be transparent. + char *szProto; // only used when AVDRQ_PROTOPICT or AVDRQ_OWNPIC is set +} AVATARDRAWREQUEST; + +#define CACHE_BLOCKSIZE 20 + +#define AVS_MODULE "AVS_Settings" // db settings module path +#define PPICT_MODULE "AVS_ProtoPics" // protocol pictures are saved here + +// obtain the bitmap handle of the avatar for the given contact +// wParam = (HANDLE)hContact +// lParam = 0; +// returns: pointer to a struct avatarCacheEntry *, NULL on failure +// if it returns a failure, the avatar may be ready later and the caller may receive +// a notification via ME_AV_AVATARCHANGED +// DONT modify the contents of the returned data structure + +#define MS_AV_GETAVATARBITMAP "SV_Avatars/GetAvatar" + +// obtain a avatar cache entry for one of my own avatars +// wParam = 0 +// lParam = (char *)szProto (protocol for which we need to obtain the own avatar information). Use "" to global +// returns: pointer to a struct avatarCacheEntry *, NULL on failure +// DONT modify the contents of the returned data structure + +#define MS_AV_GETMYAVATAR "SV_Avatars/GetMyAvatar" + +// protect the current contact picture from being overwritten by automatic +// avatar updates. Actually, it only backups the contact picture filename +// and will used the backuped version until the contact picture gets unlocked +// again. So this service does not disable avatar updates, but it "fakes" +// a locked contact picture to the users of the GetAvatar service. +// +// wParam = (HANDLE)hContact +// lParam = 1 -> lock the avatar, lParam = 0 -> unlock + +#define MS_AV_PROTECTAVATAR "SV_Avatars/ProtectAvatar" + +// set (and optionally protect) a local contact picture for the given hContact +// +// wParam = (HANDLE)hContact +// lParam = either a full picture filename or NULL. If lParam == NULL, the service +// will open a file selection dialog. + +#define MS_AV_SETAVATAR "SV_Avatars/SetAvatar" + +// set a local picture for the given protocol +// +// wParam = (char *) protocol name or NULL for all protocols +// lParam = either a full picture filename or NULL. If lParam == NULL, the service +// will open a file selection dialog. If lParam == "" the avatar will be removed + +#define MS_AV_SETMYAVATAR "SV_Avatars/SetMyAvatar" + +// see if is possible to set the avatar for the expecified protocol +// +// wParam = (char *) protocol name +// lParam = 0 +// return = 1 if can set, 0 if can't + +#define MS_AV_CANSETMYAVATAR "SV_Avatars/CanSetMyAvatar" + +// Call avatar option dialog for contact +// +// wParam = (HANDLE)hContact + +#define MS_AV_CONTACTOPTIONS "SV_Avatars/ContactOptions" + +// draw an avatar picture +// +// wParam = 0 (not used) +// lParam = AVATARDRAWREQUEST *avdr +// draw a contact picture to a destination device context. see description of +// the AVATARDRAWREQUEST structure for more information on how to use this +// service. +// return value: 0 -> failure, avatar probably not available, or not ready. The drawing +// service DOES schedule an avatar update so your plugin will be notified by the ME_AV_AVATARCHANGED +// event when the requested avatar is ready for use. +// 1 -> success. avatar was found and drawing should be ok. +// -1 -> global avatar is incosistent + +#define MS_AV_DRAWAVATAR "SV_Avatars/Draw" + +// fired when a contacts avatar cached by avs changes +// it includes changes made by the user +// wParam = hContact +// lParam = struct avatarCacheEntry *cacheEntry +// the event CAN pass a NULL pointer in lParam which means that the avatar has changed, +// but is no longer valid (happens, when a contact removes his avatar, for example). +// DONT DESTROY the bitmap handle passed in the struct avatarCacheEntry * +// +// It is also possible that this event passes 0 as wParam (hContact), in which case, +// a protocol picture (pseudo - avatar) has been changed. + +#define ME_AV_AVATARCHANGED "SV_Avatars/AvatarChanged" + + +typedef struct _contactAvatarChangedNotification { + int cbSize; // sizeof() + HANDLE hContact; // this might have to be set by the caller too + int format; // PA_FORMAT_* + char filename[MAX_PATH]; // full path to filename which contains the avatar + char hash[128]; // avatar hash +} CONTACTAVATARCHANGEDNOTIFICATION; + +// fired when the contacts avatar is changed by the contact +// wParam = hContact +// lParam = struct CONTACTAVATARCHANGENOTIFICATION *cacn +// the event CAN pass a NULL pointer in lParam which means that the contact deleted its avatar + +#define ME_AV_CONTACTAVATARCHANGED "SV_Avatars/ContactAvatarChanged" + +// fired when one of our own avatars was changed +// wParam = (char *)szProto (protocol for which a new avatar was set) +// lParam = AVATARCACHEENTRY *ace (new cache entry, NULL if the new avatar is not valid) + +#define ME_AV_MYAVATARCHANGED "SV_Avatars/MyAvatarChanged" + +// Service to be called by protocols to report an avatar has changed. Some avatar changes +// can be detected automatically, but some not (by now only Skype ones) +// wParam = (char *)szProto (protocol for which a new avatar was set) +// lParam = 0 + +#define MS_AV_REPORTMYAVATARCHANGED "SV_Avatars/ReportMyAvatarChanged" + + + +// Bitmap services ////////////////////////////////////////////////////////////////////// + +// Load an image +// wParam = NULL +// lParam = filename +#define MS_AV_LOADBITMAP32 "SV_Avatars/LoadBitmap32" + +// Save an HBITMAP to an image +// wParam = HBITMAP +// lParam = full path of filename +#define MS_AV_SAVEBITMAP "SV_Avatars/SaveBitmap" +#define MS_AV_SAVEBITMAPW "SV_Avatars/SaveBitmapW" + +#if defined(UNICODE) + #define MS_AV_SAVEBITMAPT MS_AV_SAVEBITMAPW +#else + #define MS_AV_SAVEBITMAPT MS_AV_SAVEBITMAP +#endif + +// Returns != 0 if can save that type of image, = 0 if cant +// wParam = 0 +// lParam = PA_FORMAT_* // image format +#define MS_AV_CANSAVEBITMAP "SV_Avatars/CanSaveBitmap" + +// Returns a copy of the bitmap with the size especified or the original bitmap if nothing has to be changed +// wParam = ResizeBitmap * +// lParam = NULL +#define MS_AV_RESIZEBITMAP "SV_Avatars/ResizeBitmap" + +/* + * flags for internal use ONLY + */ + +#define MC_ISMASTERCONTACT 0x01 +#define MC_ISSUBCONTACT 0x02 +#define AVH_MUSTNOTIFY 0x04 // node->dwFlags (loader thread must notify avatar history about change/delete event) +#define AVS_DELETENODEFOREVER 0x08 + + + +// Protocol services ////////////////////////////////////////////////////////////////////// + +/* +wParam=0 +lParam=(const char *)Avatar file name or NULL to remove the avatar +return=0 for sucess +*/ +#define PS_SETMYAVATAR "/SetMyAvatar" + +/* +wParam=(char *)Buffer to file name +lParam=(int)Buffer size +return=0 for sucess +*/ +#define PS_GETMYAVATAR "/GetMyAvatar" + + +#define PIP_NONE 0 +#define PIP_SQUARE 1 + +// Avatar image max size +// lParam = (POINT*) maxSize (use -1 for no max) +// return 0 for success +#define AF_MAXSIZE 1 + +// Avatar image proportion +// lParam = 0 +// return or of PIP_* +#define AF_PROPORTION 2 + +// Avatar format supported when setting avatars +// lParam = PA_FORMAT_* +// return = 1 (supported) or 0 (not supported) +#define AF_FORMATSUPPORTED 3 + +// Avatars are enabled for protocol? +// lParam = 0 +// return = 1 (avatars ready) or 0 (disabled) +#define AF_ENABLED 4 + +// This protocol don't need delays for fetching contact avatars +// lParam = 0 +// return = 1 (don't need) or 0 (need) +#define AF_DONTNEEDDELAYS 5 + +// Avatar file max size +// return size in bytes (0 for no limit) +#define AF_MAXFILESIZE 6 + +// The amount of time avs should wait after a download avatar failed for a contact +// lParam = 0 +// return = the time, in ms +#define AF_DELAYAFTERFAIL 7 + +// Fetching avatars is always possible and allowed +// lParam = 0 +// return = 1 (always) or 0 (depending on our or contacts status mode) +#define AF_FETCHALWAYS 8 + + +/* +Query avatar caps for a protocol +wParam = One of AF_* +lParam = See descr of each AF_* +return = See descr of each AF_*. Return 0 by default +*/ +#define PS_GETAVATARCAPS "/GetAvatarCaps" + + + +#endif diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_chat.h b/plugins/!NotAdopted/WinPopup/sdk/m_chat.h new file mode 100644 index 0000000000..e3cd416c6d --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_chat.h @@ -0,0 +1,685 @@ +/* +Chat module plugin for Miranda IM + +Copyright (C) 2003 JГ¶rgen Persson + +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. +*/ + + + +/* + This plugin provides event driven chat rooms for protocols that wish to use it. + It is built for IRC, which I also develop and is naturally biased towards IRC, + but it should work very well with other protocols too. I will try to explain as + careful as possible in this document how to use chat.dll + + -- General guidelines -- + + There is ONE rule a protocol MUST follow to use this: + + 1. Do NOT touch hContacts that has a byte "ChatRoom" set to ANYTHING other than 0! (Could be 1, 2, 3, ...) + This is because chat.dll adds contacts to the clist using the protocol name + supplied by the protocol. But this will naturally not work well if the + protocol also tampers with the contacts. The value of the BYTE indicates which type of + window/contact it is (see the GCW_* flags below). There is two exceptions to this rule: + + * You should continue to handle the right click menu items of these + contacts as usual, by hooking the menu prebuild hook etc. Chat.dll can not + handle this in an efficient manner! + + * You should also handle when the user deletes the contact/room from the + contact list, as the protocol will then most likely have to send some message + to the server that the user has left the room. + + NOTE. Chat keeps its own copies of strings passed. + + + * * Example of implementing this rule * *: + * * This is a code snippet that is common in protocols * *: + + + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) + { + szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto != NULL && !lstrcmpi(szProto, PROTONAME)) + { + ... do something with the hContact here; + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + + + + * * You should do this instead * *: + + + + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0); + while (hContact) + { + szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto != NULL && !lstrcmpi(szProto, PROTONAME)) + { + if (DBGetContactSettingByte(hContact, PROTONAME, "ChatRoom", 0) == 0) + { + ... do something with the hContact here; + } + } + hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0); + } + + + There is not more to it than that! To recapitulate: do NOT touch contacts where the + BYTE "ChatRoom" is set to anything other than 0, + + + + + + + OK, enough of the precautions, HOW DO YOU USE CHAT? In short you need to do FOUR things: + + 1. REGISTER your protocol with Chat + Only registered protocols can use Chat + + 2. CREATE SESSIONS when your protocol are joining a group chat room. (One per room joined) + These sessions will be put on the contact-list and are managed totally by chat. + This is the reason you must obey to the "precautions" I mentioned above. + Do not tamper directly with Chat's hContacts. Use Services provided by Chat instead. + + 3. SEND EVENTS to the sessions created in #3. + These events reflect users joining/leaving/speaking etc. + + 4. DESTROY SESSIONS when the user leaves the room (ie the session is not needed anymore). + + These four points are implemented in three services: MS_GC_REGISTER, MS_GC_NEWSESSION + and MS_GC_EVENT. +*/ + + +//------------------------- SERVICES ------------------------ +/* + Step 1. -- REGISTER with Chat -- + + The first thing that a protocol need to do is register with Chat. This is best done + when ALL modules has loaded (ME_SYSTEM_MODULESLOADED). The registration is + needed to make sure that the protocol obey rule 1 mentioned above, but also to + set protocol specific preferences. + + * Use MS_GC_REGISTER like this: CallService(MS_GC_REGISTER, 0, (LPARAM)(GCREGISTER *) &gcr; + + * returns 0 on success or error code on failure. +*/ + +// Flags +#define GC_BOLD 0x0001 //enable the 'bold' button +#define GC_ITALICS 0x0002 //enable the 'italics' button +#define GC_UNDERLINE 0x0004 //enable the 'underline' button +#define GC_COLOR 0x0008 //enable the 'foreground color' button +#define GC_BKGCOLOR 0x0010 //enable the 'background color' button +#define GC_ACKMSG 0x0020 //the protocol must acknowlege messages sent +#define GC_TYPNOTIF 0x0040 //NOT SUPPORTED YET! Enable typing notifications. +#define GC_CHANMGR 0x0080 //enable the 'channel settings' button +#define GC_SINGLEFORMAT 0x0100 //the protocol supports only 1 formatting per message +#define GC_FONTSIZE 0x0200 //enable font size selection + +#define GC_UNICODE 0x01000 //NOT SUPPORTED YET! Enable unicode (if chat supports it), + //Pass UNICODE instead of ASCII. Note that + //registration will fail if the unicode version of chat is not installed +#if defined( _UNICODE ) + #define GC_TCHAR GC_UNICODE +#else + #define GC_TCHAR 0 +#endif + +// Error messages +#define GC_REGISTER_WRONGVER 1 //You appear to be using the wrong version of this API. Registration failed. +#define GC_REGISTER_ERROR 2 //An internal error occurred. Registration failed. +#define GC_REGISTER_NOUNICODE 3 //MS_GC_REGISTER returns this error if the Unicode version of chat + //is not installed and GC_UNICODE is set. Registration failed + +// GCREGISTER struct +typedef struct { + int cbSize; //Set to sizeof(GCREGISTER); + DWORD dwFlags; //Use GC_* flags above to indicate features supported + const char* pszModule; //This MUST be the protocol name as registered with Miranda IM + union { + const char* pszModuleDispName; //This is the protocol's real name as it will be displayed to the user + const TCHAR* ptszModuleDispName; // used if GC_TCHAR flag is passed + }; + int iMaxText; //Max message length the protocol supports. Will limit the typing area input. 0 = no limit + int nColors; //Number of colors in the colorchooser menu for the color buttons. Max = 100 + COLORREF* pColors; //pointer to the first item in a static COLORREF array containing the colors + //that should be showed in the colorchooser menu. + //ie: COLORREF crCols[nColors]; + // pColors = &crCols[0]; +} + GCREGISTER; + +#define MS_GC_REGISTER "GChat/Register" + +/* + Step 2. -- CREATE a new SESSION -- + + Create a new session (chat room) and set various settings related to it. + The chat room will not be shown to the user until the 'set up' phase is + completed and SESSION_INITDONE is sent. See the MS_GC_EVENT for that. + + * Use MS_GC_NEWSESSION like this: CallService(MS_GC_NEWSESSION, 0, (LPARAM)(GCSESSION *) &gcr; + + * returns 0 on success or error code on failure +*/ + + +// Session type +#define GCW_CHATROOM 1 // the session is a dedicated multi user chat room. ex "IRC channels". + // A hContact will be added for the session +#define GCW_SERVER 2 // the session is used as a network console. ex "IRC server window" + // A hContact will be added for the session, but it will default to being hidden (on the CList) +#define GCW_PRIVMESS 3 // NOT SUPPORTED YET! the session is a 1 to 1 session, but with additional + // support for adding more users etc. ex "MSN session". + + + +// Error messages +#define GC_NEWSESSION_WRONGVER 1 //You appear to be using the wrong version of this API. +#define GC_NEWSESSION_ERROR 2 //An internal error occurred. + + +// GCREGISTER structure +typedef struct { + int cbSize; //Set to sizeof(GCSESSION); + int iType; //Use one of the GCW_* flags above to set the type of session + const char *pszModule; //The name of the protocol owning the session (the same as pszModule when you register) + union { + const char* pszName; //The name of the session as it will be displayed to the user + const TCHAR* ptszName; + }; + union { + const char* pszID; //The unique identifier for the session. + const TCHAR* ptszID; + }; + union { + const char* pszStatusbarText; //Optional text to set in the statusbar of the chat room window, or NULL. + const TCHAR* ptszStatusbarText; + }; + DWORD dwFlags; + DWORD dwItemData; //Set user defined data for this session. Retrieve it by using the GC_EVENT_GETITEMDATA event + } GCSESSION; +#define MS_GC_NEWSESSION "GChat/NewChat" + + + + + + +/* + Step 3 -- SEND an EVENT -- + + Events is what drives Chat! After having created the session in Step 2 + it is time to make it work for real. Follow these guidelines: + + 1. Start off by telling Chat what possible statuses a user can have (in the nicklist) + by sending GC_EVENT_ADDGROUP as many times as needed. Also supply an icon + to go with this status. Ex "Voice status" on IRC + + 2.Then send "JOIN" events (GC_EVENT_JOIN) to populate the user list. + You will need to send one event per user that should be added. As long as + SESSION_INITDONE has not been sent these events will not show up in the log. + + 3.When you are done with filling the user list it is a good time to end + the set up phase and make the window visible by calling GC_EVENT_CONTROL event + with wParam = SESSION_INITDONE. + + 4.You will also want to send a GC_EVENT_CONTROL with wParam = SESSION_ONLINE to + make the statusbar and the CList item go to "online" status + + You have now set up the session and made it active. A CList hContact has been added + to the contact list and a chat room window is associated to the session. Send EVENTS to + Chat users speaking, users joining and so on. See below for full + list of what events are possible. + + IMPORTANT: For sending events you'll use the GCEVENT and GCDEST structures. A GCDEST + structure pointer is passed inside GCEVENT and it tells Chat what event type it is + and what session it is related to. The GCDEST structure and its members are ALWAYS + used (but the members can be NULL in some occasions). Depending on what type of event + you are sending, the members of GCEVENT have different usage. Each event and how to + use the members are discussed below. The "bAddToLog" and "time" members are always valid + and always mean the same. bAddToLog = TRUE means that the event is added to the disk log + (at least when this makes sense). This can be used by Jabber for instance, when + it needs to add channel history to the window, but without logging to disk. + The "time" member is the timestamp of the event.(Tip. use the function time(NULL) + to set the current time) + + NOTE. It is possible to send formatted text (bold, italics, underlined, foreground color + and background color) to Chat by using the following identifiers in the text (pszText): + + %cXX - set the foreground color ( XX is the zero based decimal index of the color registered in MS_GC_REGISTER.. Always use two digits ) + %C - reset foreground color to default + %fXX - set the background color ( XX is the zero based decimal index of the color registered in MS_GC_REGISTER.. Always use two digits ) + %F - reset the background color to default + %b - enable bold + %B - disable bold + %u - enable underlined + %U - disable underlined + %i - enable italics + %I - disable italics + %r - reset all to default + %% - escape the formatting. Translates to % + + IMPORTANT. If you have specified GC_COLOR or GC_BKGCOLOR when you registered you can expect to + get these identifiers in the text you receive from Chat as well. Make sure % is ALWAYS + translated to %% in text you send to Chat to avoid accidental formatting. + NOTE. You will not get %cRRRGGGBBB back, instead you will get the index of the colour as + registered with GC_REGISTER. Eg %c3 (the fourth colour of your index) + + * Use MS_GC_EVENT like this: CallService(MS_GC_EVENT, 0, (LPARAM)(GCEVENT *) &gce; + + * returns 0 on success or error code on failure + +*/ + +// * List of possible events to send to Chat. Unlisted members are not valid * +// * for the event. Listed members are mandatory unless otherwise specified * + + +// GC_EVENT_JOIN - " has joined" (A user is joining the session) +// pszNick - Display name +// pszUID - Unique identifier of the user +// pszStatus - Which status does the user have. Should be a status previously +// registered with GC_EVENT_ADDGROUP. Ex "Voice" in IRC +// bIsMe - Set to TRUE if it is the Miranda user +// Chat needs to know which user in the userlist that is "self" +// It cannot highlight a message containing the "own" nick without this info +// NOTE. if time == NULL, then the event will not be shown in the message log +#define GC_EVENT_JOIN 0x0001 + +// GC_EVENT_PART - " has left: " (A user left the session) +// pszNick - Display name +// pszUID - Unique identifier +// pszText - Optional part message, can be NULL +#define GC_EVENT_PART 0x0002 + +// GC_EVENT_QUIT - " disconnected: pszText" (A user disconnected from the network) +// pszID(in GCDEST) - Should be NULL as a disconnect event is global. +// pszNick - Display name +// pszUID - Unique identifier +// pszText - Optional disconnect message, can be NULL +#define GC_EVENT_QUIT 0x0004 + +// GC_EVENT_KICK - " kicked : " (A user is kicking another user from the room) +// pszNick - Display name of the one being being kicked +// pszUID - Unique identifier of the one being kicked +// pszStatus - Name of user who is doing the kicking +// pszText - Optional kick message, can be NULL +#define GC_EVENT_KICK 0x0008 + +// GC_EVENT_NICK - " is now known as " (A user changed his name) +// NOTE, see GC_EVENT_CHUID also +// pszID(in GCDEST) - Should be NULL as a nick change event is global. +// pszNick - Old display name +// pszUID - Unique identifier +// pszText - New display name of the user. Color codes are not valid +#define GC_EVENT_NICK 0x0010 + +// GC_EVENT_NOTICE - "Notice from : " (An IRC type notice) +// pszID(in GCDEST) - Should be NULL to send to the active window +// pszNick - Display name +// pszUID - Unique identifier +// pszText - Notice text +#define GC_EVENT_NOTICE 0x0020 + +// GC_EVENT_MESSAGE - ": (A user is speaking) +// pszNick - Display name +// pszUID - Unique identifier +// bIsMe - Set to TRUE if it is the Miranda user +// pszText - Message text. +#define GC_EVENT_MESSAGE 0x0040 + +// GC_EVENT_TOPIC - "Topic is (Set by: " (The room topic was changed/set) +// pszNick - Optional display name of who set the topic, can be NULL +// pszUID - Optional unique identifier of who set the topic, can be NULL +// pszText - Topic text +#define GC_EVENT_TOPIC 0x0080 + +// GC_EVENT_INFORMATION (Informational text) Ex a server response to a /WHO command in IRC +// pszID(in GCDEST) - NULL to send to the active window +// pszText - Information text +#define GC_EVENT_INFORMATION 0x0100 + +// GC_EVENT_ACTION - " " (An IRC Style action event) +// pszNick - Display name +// pszUID - Unique identifier +// bIsMe - Set to TRUE if it is the Miranda user +// pszText - Message text. +#define GC_EVENT_ACTION 0x0200 + +// GC_EVENT_ADDSTATUS - " enables '' for " (A status change has occured for a user) +// NOTE. Status changes are cumulative. The user will show in the nicklist with the highest status received. +// Ex, IRC users can have "Op" and "Voice" statuses simultaneously but s/he will be displayed as "Op" +// pszNick - Display name of the one who receives a new status +// pszUID - Unique identifier of the one who receives a new status +// pszText - The display name of the one who is setting the status. Color codes are not valid +// pszStatus - The status. Should be a status previously +// registered with GC_EVENT_ADDGROUP. Ex "Voice" in IRC +#define GC_EVENT_ADDSTATUS 0x0400 + +// GC_EVENT_REMOVESTATUS - " disables '' for " (A status change has occured for a user) +// NOTE. Status changes are cumulative. The user will show in the nicklist with the highest status received. +// Ex, IRC users can have "Op" and "Voice" statuses simultaneously but s/he will be displayed as "Op" +// pszNick - Display name of the one who got a status mode disabled +// pszUID - Unique identifier of the one who got a status mode disabled +// pszText - The display name of the one disabling the status. Color codes are not valid +// pszStatus - The status. Should be a status previously +// registered with GC_EVENT_ADDGROUP. Ex "Voice" in IRC +#define GC_EVENT_REMOVESTATUS 0x0800 + +// GC_EVENT_CHUID - not shown in the log (Change the unique identifier of a contact) +// pszID(in GCDEST) - Should be NULL as a unique id's are global. +// pszUID - The current unique identifier +// pszText - The new unique identifier. Color codes are not valid +#define GC_EVENT_CHUID 0x1000 + +// GC_EVENT_CHANGESESSIONAME - not shown in the log (Change the display name of a session) +// pszText - The new name. Color codes are not valid +#define GC_EVENT_CHANGESESSIONAME 0x1001 + +// GC_EVENT_ADDGROUP - not shown in the log (Add a possible status mode to the nicklist, ex IRC uses "Op", "Voice", "Normal" etc ) +// NOTE. When adding several statuses, start with the highest status +// pszStatus - The new group name +// dwItemData - Optional HICON handle to a 10x10 icon. Set to NULL to use the built in icons. +#define GC_EVENT_ADDGROUP 0x1002 + +// GC_EVENT_SETITEMDATA & GC_EVENT_SETITEMDATA - not shown in the log (Get/Set the user defined data of a session) +// dwItemData - The itemdata to set or get +#define GC_EVENT_SETITEMDATA 0x1003 +#define GC_EVENT_GETITEMDATA 0x1004 + +// GC_EVENT_SETSBTEXT - not shown in the log (Set the text of the statusbar for a chat room window) +// pszText - Statusbar text. Color codes are not valid +#define GC_EVENT_SETSBTEXT 0x1006 + +// GC_EVENT_ACK - not shown in the log (Acknowledge a outgoing message, when GC_ACKMSG is set +#define GC_EVENT_ACK 0x1007 + +// GC_EVENT_SENDMESSAGE - not shown in the log ("Fake" a message from a chat room as if the user had typed it). Used by IRC to broadcast /AME and /AMSG messages +// pszText - The text +#define GC_EVENT_SENDMESSAGE 0x1008 + +// GC_EVENT_SETSTATUSEX - not shown in the log (Space or tab delimited list of pszUID's to indicate as away). +// Used by IRC to mark users as away in the nicklist. If UIDs can contain spaces, use tabs +// pszText - Space or tab delimited list of pszUID's + +#define GC_SSE_ONLYLISTED 0x0001 // processes only listed contacts, resets all contacts otherwise +#define GC_SSE_ONLINE 0x0002 // displays a contact online, otherwise away +#define GC_SSE_TABDELIMITED 0x0004 // use tabs as delimiters + +#define GC_EVENT_SETSTATUSEX 0x1009 + +// GC_EVENT_SETCONTACTSTATUS - sets status icon for contact +// pszUID - Unique identifier of the one who receives a new status +// dwItemData - (DWORD)ID_STATUS_* or zero to remove status icon +#define GC_EVENT_SETCONTACTSTATUS 0x100A + +// GC_EVENT_CONTROL - not shown in the log (Control window associated to a session and the session itself) +// NOTE 1: No members of GCEVENT are used, send one of the below flags in wParam instead, +// Ex CallService(GC_EVENT_CONTROL, SESSION_INITDONE, (LPARAM)&gce); +// NOTE 2: The first four control events are the only ones you should use most likely! +// The ones below them are used by IRC to join channels hidden or maximized and show the server window from the system menu. +// The SESSION_VISIBLE, SESSION_HIDDEN, SESSION_MAXIMIZE and SESSION_MINIMIZE events CAN replace SESSION_INITDONE but I urge you not to +// do that as it will override any settings the user has made in the Chat options +// NOTE 3: If pszID (of GCDEST) = NULL then this message will be broadcasted to all sessions, which can be usefule for terminating +// all sessions when the protocol was disconnected +#define SESSION_INITDONE 1 //send this when the session is fully set up (all users have ben added to the nicklist) +#define SESSION_TERMINATE 7 //send to terminate a session and close the window associated with it +#define SESSION_OFFLINE 8 //send to set the session as "online" (hContact is set to Online etc) +#define SESSION_ONLINE 9 //send to set the session as "offline" (hContact is set to Offline etc) +//------------ +#define WINDOW_VISIBLE 2 //make the room window visible +#define WINDOW_HIDDEN 3 //close the room window. Session is not terminated. +#define WINDOW_MAXIMIZE 4 //make the room window maximized +#define WINDOW_MINIMIZE 5 //make the room window minimized +#define WINDOW_CLEARLOG 6 //clear the log of the room window + +#define GC_EVENT_CONTROL 0x1005 + +// Error messages +#define GC_EVENT_WRONGVER 1 //You appear to be using the wrong version of this API. +#define GC_EVENT_ERROR 2 //An internal error occurred. + +// The GCDEST structure. It is passed to Chat inside GCEVENT. +typedef struct { + char* pszModule; //Name of the protocol (same as you registered with) + union { + char* pszID; //Unique identifier of the session, or NULL to broadcast to all sessions as specified above + TCHAR* ptszID; + }; + int iType; //Use GC_EVENT_* as defined above. Only one event per service call. +} GCDEST; + + +// The GCEVENT structure +typedef struct { + int cbSize; // Set to sizeof(GCEVENT); + GCDEST* pDest; // pointer to a GCDEST structure which specifies the session to receive the event + union { + const char *pszText; // usage depends on type of event, max 2048 characters + const TCHAR *ptszText; + }; + union { + const char* pszNick; // usage depends on type of event + const TCHAR* ptszNick; + }; + union { + const char* pszUID; // usage depends on type of event, Do NOT use spaces for unique user identifiers. + const TCHAR* ptszUID; + }; + union { + const char* pszStatus; // usage depends on type of event + const TCHAR* ptszStatus; + }; + union { + const char* pszUserInfo; // Additional user information that is displayed after the nickname. + const TCHAR* ptszUserInfo; + }; + // IRC use it to display a hostmask for JOIN, PART (and more) events. + BOOL bIsMe; // Is this event from the Miranda user? + DWORD dwFlags; // event flags: GCEF_ADDTOLOG, GC_UNICODE + + // FALSE any other time than when initializing the window (before sending SESSION_INITDONE) + DWORD_PTR dwItemData; // User specified data. + DWORD time; // Timestamp of the event +} + GCEVENT; + +#define MS_GC_EVENT "GChat/NewEvent" + +#define GCEF_ADDTOLOG 0x0001 + +// OK! That was about everything that you need to know about for operating Chat in a basic way. +// There are however some more things you will need to know about. Some you may use and some you may not need, + +/* + -- GETTING info about a SESSION or session data -- + + Use this service to get information on different aspects of the sessions that are registered with Chat. + + * Use MS_GC_GETINFO like this: CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)(char *) pszModule); + + * returns -1 on failure and the sessioncount on success +*/ + +#define MS_GC_GETSESSIONCOUNT "GChat/GetCount" + +/* + -- GETTING info about a SESSION or session data -- + + Use this service to get information on different aspects of the sessions that are registered with Chat. + + * Use MS_GC_GETINFO like this: CallService(MS_GC_GETINFO, 0, (LPARAM)(GC_INFO *) &gci; + + * returns 0 on success or error code on failure +*/ + +// Flags +#define BYINDEX 0x0001 // iItem is valid and should contain the index of the session to get +#define BYID 0x0002 // pszID is valid and should contain the ID of the session to get. This is the default if no +#define HCONTACT 0x0004 // hContact is valid +#define DATA 0x0008 // wItemData is valid +#define ID 0x0010 // pszID is valid. +#define NAME 0x0020 // pszName is valid +#define TYPE 0x0040 // iType is valid +#define COUNT 0x0080 // iCount is valid +#define USERS 0x0100 // pszUsers is valid + + +// The GC_INFO structure +typedef struct { + DWORD Flags; // use a combination of the above flags + int iItem; // session type (GCW_*) + int iType; // session type (GCW_*) + char* pszModule; // the module name as registered in MS_GC_REGISTER + TCHAR* pszID; // unique ID of the session + TCHAR* pszName; // display name of the session + DWORD_PTR dwItemData; // user specified data. + int iCount; // count of users in the nicklist + char* pszUsers; // space separated string containing the UID's of the users in the user list. + // NOTE. Use Mirandas mmi_free() on the returned string. + HANDLE hContact; // hContact for the session (can be NULL) +} + GC_INFO; + +#define MS_GC_GETINFO "GChat/GetInfo" + +//------------------------- HOOKS ------------------------ +/* + -- user interaction -- + Hook this to receive notifications about when user take actions in a chat room window. + Check for the below flags to find out what type of user interaction it is. See the + to find out which members of GCHOOK that are valid. + + * wParam=0 + * lParam=(LPARAM)(GCEVENT *)pgch + + * Returning nonzero from your hook will stop other hooks from being called. +*/ +#define GC_USER_MESSAGE 1 // user sent a message, with \n delimiting lines, pszText contains the text. +#define GC_USER_CHANMGR 2 // user clicked the settings button in a chat room +#define GC_USER_LOGMENU 3 // user has selected a message log menu item, dwData is valid. See ME_GC_BUILDMENU +#define GC_USER_NICKLISTMENU 4 // user has selected a userlist menu item, valid members: dwData. See ME_GC_BUILDMENU +#define GC_USER_TYPNOTIFY 5 // NOT IMPLEMENTED YET! user is typing +#define GC_USER_PRIVMESS 6 // user requests to send a private message to a user. pszUID is valid +#define GC_USER_LEAVE 8 // user requests to leave the session +#define GC_USER_CLOSEWND 9 // user closed the window (this is usually not an indication that the protocol + // should take action, but MSN may want to terminate the session here) +#define GC_SESSION_TERMINATE 7 // the session is about to be terminated, the "user defined data" is passed in dwData, which can be good free'ing any allocated memory. +#define ME_GC_EVENT "GChat/OutgoingEvent" + +typedef struct { + GCDEST* pDest; // pointer to a GCDEST structure which specifies from which session the hook was triggered + union { + char* pszText; // usage depends on type of event + TCHAR* ptszText; + }; + union { + char* pszUID; // unique identifier, usage depends on type of event + TCHAR* ptszUID; + }; + DWORD_PTR dwData; // user defined data, usage depends on type of event +} + GCHOOK; + +/* + -- Build the pop up menus -- + The user wants to show a right click (popup) menu and your protocol should tell what + items should be added to the menu. You should create a static array of struct gc_item's. + When you get this notification you should set "nItems" to the number of gc_item's + you want to show on the user's popup menu and then set the "Item" member to point to that array. + + * wParam=0 + * lParam=(LPARAM)(GCMENUITEM *)gcmi + + Returning nonzero from your hook will stop other hooks from being called. + +*/ + +// type of item to add to the popup menu +#define MENU_NEWPOPUP 1 // add submenu +#define MENU_POPUPITEM 2 // add item to current submenu +#define MENU_POPUPSEPARATOR 3 // add separator to current submenu +#define MENU_SEPARATOR 4 // add separator to menu +#define MENU_ITEM 5 // add item + +// Added in Miranda IM 0.8.0.6+ +#define MENU_POPUPCHECK 6 // add checked item to current submenu +#define MENU_CHECK 7 // add checked item +#define MENU_POPUPHMENU 8 // add custom submenu to current submenu, use dwID to specify HMENU +#define MENU_HMENU 9 // add custom submenu, use dwID to specify HMENU + +// type of menu that is being requested +#define MENU_ON_LOG 1 // pop up menu on the message log +#define MENU_ON_NICKLIST 2 // pop up menu on the user list + +// contains info on a menuitem to be added +struct gc_item { + TCHAR* pszDesc; // Textual description of the menu item to add + DWORD dwID; // when/if the user selects this menu item this + // value will be returned via the above hook, GC_USER_LOGMENU + // or GC_USER_NICKLISTMENU. Must not be 0 and must be unique. + int uType; // What kind of menu item is it? Use MENU_* flags above + BOOL bDisabled; // should the menu item be shown as disabled +}; + +typedef struct { + char * pszModule; // Contains the protocol name, do NOT change. + TCHAR* pszID; // The unique identifier of the session that triggered the hook, do NOT change. + TCHAR* pszUID; // Contains the unique identifier if Type = MENU_ON_NICKLIST. do NOT change. + int Type; // Type of menu. MENU_ON_* flags used. do NOT change. + int nItems; // Set this to the number of menu items you want to add + struct gc_item* Item; // pointer to the first in the array of gc_item's +} + GCMENUITEMS; + +#define ME_GC_BUILDMENU "GChat/BuildMenu" + +/* + * Example of how to add 2 items to the popup menu for the userlist * + + GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam; + if (gcmi->Type == MENU_ON_NICKLIST) + { + static struct gc_item Item[] = { + {Translate("User &details"), 1, MENU_ITEM, FALSE}, + {Translate("&Op"), 2, MENU_POPUPITEM, FALSE}, + }; + + gcmi->nItems = sizeof(Item)/sizeof(Item[0]); + gcmi->Item = &Item[0]; + gcmi->Item[gcmi->nItems-1].bDisabled = bFlag; + + return 0; + } +*/ + +////////////////////////////////////////////////////////////////////////// +// Get Chat ToolTip Text for buddy +// wParam = (WPARAM)(TCHAR*) roomID parentdat->ptszID +// lParam = (WPARAM)(TCHAR*) userID ui1->pszUID +// result (int)(TCHAR*)mir_tstrdup("tooltip text") +// returns pointer to text of tooltip and starts owns it +#define MS_GC_PROTO_GETTOOLTIPTEXT "/GetChatToolTipText" diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_clist.h b/plugins/!NotAdopted/WinPopup/sdk/m_clist.h new file mode 100644 index 0000000000..c0bbd3853a --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_clist.h @@ -0,0 +1,637 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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_CLIST_H__ +#define M_CLIST_H__ 1 + +#ifdef _MSC_VER + #pragma warning(disable:4201 4204) +#endif + +#include "statusmodes.h" + +#if defined _STATIC + typedef struct _tagIntMenuItem* HGENMENU; +#else + DECLARE_HANDLE(HGENMENU); +#endif + +//sent when the user asks to change their status +//wParam=new status, from statusmodes.h +//lParam=protocol name, NULL if for all protocols (added in v0.3.1alpha) +//also sent due to a ms_clist_setstatusmode call +#define ME_CLIST_STATUSMODECHANGE "CList/StatusModeChange" + +//force a change of status mode +//wParam=new status, from statusmodes.h +#define MS_CLIST_SETSTATUSMODE "CList/SetStatusMode" + +//get the current status mode +//wParam=lParam=0 +//returns the current status +//This is the status *as set by the user*, not any protocol-specific status +//All protocol modules will attempt to conform to this setting at all times +#define MS_CLIST_GETSTATUSMODE "CList/GetStatusMode" + +//gets a textual description of the given status mode (v0.1.0.1+) +//wParam=status mode, from statusmodes.h +//lParam=flags, below +//returns a static buffer of the description of the given status mode +//returns NULL if the status mode was unknown +#define GSMDF_PREFIXONLINE 1 //prefix "Online: " to all status modes that + //imply online, eg "Online: Away" +#define GCMDF_UNICODE 2 //will return TCHAR* instead of char* +#if defined( _UNICODE ) + #define GCMDF_TCHAR GCMDF_UNICODE //will return TCHAR* instead of char* +#else + #define GCMDF_TCHAR 0 //will return char*, as usual +#endif +#define GSMDF_UNTRANSLATED 4 +#define MS_CLIST_GETSTATUSMODEDESCRIPTION "CList/GetStatusModeDescription" + +//add a new item to the main menu +//wParam=0 +//lParam=(LPARAM)(CLISTMENUITEM*)&mi +//returns a handle to the new item, or NULL on failure +//the service that is called when the item is clicked is called with +//wParam=0, lParam=hwndContactList +//dividers are inserted every 100000 positions +//pszContactOwner is ignored for this service. +//there is a #define PUTPOSITIONSINMENU in clistmenus.c which, when set, will +//cause the position numbers to be placed in brackets after the menu items + +// WARNING: do not use Translate(TS) for p(t)szName or p(t)szPopupName as they +// are translated by the core, which may lead to double translation. +// Use LPGEN instead which are just dummy wrappers/markers for "lpgen.pl". +typedef struct { + int cbSize; //size in bytes of this structure + union { + char* pszName; //[TRANSLATED-BY-CORE] text of the menu item + TCHAR* ptszName; //Unicode text of the menu item + }; + DWORD flags; //set of CMIF_* flags + int position; //approx position on the menu. lower numbers go nearer the top + union { + HICON hIcon; //icon to put by the item. If this was not loaded from + //a resource, you can delete it straight after the call + HANDLE icolibItem; //set CMIF_ICONFROMICOLIB to pass this value + }; + char* pszService; //name of service to call when the item gets selected + union { + char* pszPopupName; //[TRANSLATED-BY-CORE] name of the popup menu that this item is on. If this + TCHAR* ptszPopupName; //is NULL the item is on the root of the menu + HGENMENU hParentMenu; // valid if CMIF_ROOTHANDLE is set. NULL or (HGENMENU)-1 means the root menu + }; + + int popupPosition; //position of the popup menu on the root menu. Ignored + //if pszPopupName is NULL or the popup menu already + //existed + DWORD hotKey; //keyboard accelerator, same as lParam of WM_HOTKEY,0 for none + char *pszContactOwner; //contact menus only. The protocol module that owns + //the contacts to which this menu item applies. NULL if it + //applies to all contacts. If it applies to multiple but not all + //protocols, add multiple menu items or use ME_CLIST_PREBUILDCONTACTMENU +} CLISTMENUITEM; + +#define HGENMENU_ROOT (( HGENMENU )-1) + +#define CMIF_GRAYED 1 +#define CMIF_CHECKED 2 +#define CMIF_HIDDEN 4 //only works on contact menus +#define CMIF_NOTOFFLINE 8 //item won't appear for contacts that are offline +#define CMIF_NOTONLINE 16 // " online +#define CMIF_NOTONLIST 32 //item won't appear on standard contacts +#define CMIF_NOTOFFLIST 64 //item won't appear on contacts that have the 'NotOnList' setting +#define CMIF_ROOTHANDLE 384 //means that hParentMenu member is set + +#define CMIF_UNICODE 512 //will return TCHAR* instead of char* +#if defined( _UNICODE ) + #define CMIF_TCHAR CMIF_UNICODE //will return TCHAR* instead of char* +#else + #define CMIF_TCHAR 0 //will return char*, as usual +#endif + +#define CMIF_KEEPUNTRANSLATED 1024 // don't translate a menu item +#define CMIF_ICONFROMICOLIB 2048 // use icolibName instead of hIcon +#define CMIF_DEFAULT 4096 // this menu item is the default one + +// for compatibility. since 0.8.0 they both mean nothing +#define CMIF_ROOTPOPUP 128 //root item for new popup(save return id for childs) +#define CMIF_CHILDPOPUP 256 //child for rootpopup menu + +#define MS_CLIST_ADDMAINMENUITEM "CList/AddMainMenuItem" + +//add a new item to the user contact menus +//identical to clist/addmainmenuitem except when item is selected the service +//gets called with wParam=(WPARAM)(HANDLE)hContact +//pszContactOwner is obeyed. +//popup menus are not supported. pszPopupName and popupPosition are ignored. +//If ctrl is held down when right clicking, the menu position numbers will be +//displayed in brackets after the menu item text. This only works in debug +//builds. +#define MS_CLIST_ADDCONTACTMENUITEM "CList/AddContactMenuItem" +#define MS_CLIST_ADDSTATUSMENUITEM "CList/AddStatusMenuItem" + +//modify an existing menu item v0.1.0.1+ +//wParam=(WPARAM)(HANDLE)hMenuItem +//lParam=(LPARAM)(CLISTMENUITEM*)&clmi +//returns 0 on success, nonzero on failure +//hMenuItem will have been returned by clist/add*menuItem +//clmi.flags should contain cmim_ constants below specifying which fields to +//update. Fields without a mask flag cannot be changed and will be ignored +#define CMIM_NAME 0x80000000 +#define CMIM_FLAGS 0x40000000 +#define CMIM_ICON 0x20000000 +#define CMIM_HOTKEY 0x10000000 +#define CMIM_ALL 0xF0000000 +#define MS_CLIST_MODIFYMENUITEM "CList/ModifyMenuItem" + +//the context menu for a contact is about to be built v0.1.0.1+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//modules should use this to change menu items that are specific to the +//contact that has them +#define ME_CLIST_PREBUILDCONTACTMENU "CList/PreBuildContactMenu" + +//sets the service to call when a contact is double-clicked +//wParam=0 +//lParam=(LPARAM)(CLISTDOUBLECLICKACTION*)&dca +//contactType is one or more of the constants below +//pszService is called with wParam=hContact, lParam=0 +//pszService will only be called if there is no outstanding event on the +//selected contact +//returns 0 on success, nonzero on failure +//in case of conflicts, the first module to have registered will get the +//double click, no others will. This service will return success even for +//duplicates. +/* + Note: During development of 0.3.0.0 (2003/02/15) this service was completely dropped + by default it always returns 1 to mark failure, see ME_CLIST_DOUBLECLICKED for + a better implementation as a hook. +*/ +typedef struct { + int cbSize; + char *pszContactOwner; //name of protocol owning contact, or NULL for all + DWORD flags; //any of the CMIF_NOT... flags above + char *pszService; //service to call on double click +} CLISTDOUBLECLICKACTION; +#define MS_CLIST_SETDOUBLECLICKACTION "CList/SetDoubleClickAction" + +/* +wParam=(WPARAM)hContact +lParam=0 + +Event is fired when there is a double click on a CList contact, +it is upto the caller to check for the protocol & status +of the HCONTACT, it's not done for you anymore since it didn't make +sense to store all this information in memory, etc. + +*/ +#define ME_CLIST_DOUBLECLICKED "CList/DoubleClicked" +//gets the string that the contact list will use to represent a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=flags +//returns a pointer to the name, will always succeed, even if it needs to +//return "(Unknown Contact)" +//this pointer is to a statically allocated buffer which will be overwritten +//on every call to this service. Callers should make sure that they copy the +//information before they call this service again. +#define GCDNF_NOMYHANDLE 1 //will never return the user's custom name +#define GCDNF_UNICODE 2 //will return TCHAR* instead of char* +#define GCDNF_NOCACHE 4 //will not use the cache + +#if defined( _UNICODE ) + #define GCDNF_TCHAR GCDNF_UNICODE //will return TCHAR* instead of char* +#else + #define GCDNF_TCHAR 0 //will return char*, as usual +#endif + + //even if it's the one that should be displayed. v0.1.2.0+ + //v0.3.0.0+ if using GCDNF_NOMYHANDLE you must free your string +#define MS_CLIST_GETCONTACTDISPLAYNAME "CList/GetContactDisplayName" + +// Invalidates the display name cache +//wParam=(WPARAM)(HANDLE)hContact +//lParam=not used +#define MS_CLIST_INVALIDATEDISPLAYNAME "CList/InvalidateDiplayName" + +//adds an event to the contact list's queue +//wParam=0 +//lParam=(LPARAM)(CLISTEVENT*)cle +//The contact list will flash hIcon next to the contact hContact (use NULL for +//a system message). szServiceName will be called when the user double clicks +//the icon, at which point the event will be removed from the contact list's +//queue automatically +//pszService is called with wParam=(WPARAM)(HWND)hwndContactList, +//lParam=(LPARAM)(CLISTEVENT*)cle. Its return value is ignored. cle is +//invalidated when your service returns, so take copies of any important +//information in it. +//hDbEvent should be unique since it and hContact are the identifiers used by +//clist/removeevent if, for example, your module implements a 'read next' that +//bypasses the double-click. +typedef struct { + int cbSize; //size in bytes of this structure + HANDLE hContact; //handle to the contact to put the icon by + HICON hIcon; //icon to flash + DWORD flags; //...of course + union + { + HANDLE hDbEvent; //caller defined but should be unique for hContact + char * lpszProtocol; + }; + LPARAM lParam; //caller defined + char *pszService; //name of the service to call on activation + union { + char *pszTooltip; //short description of the event to display as a + TCHAR *ptszTooltip; //tooltip on the system tray + }; +} CLISTEVENT; +#define CLEF_URGENT 1 //flashes the icon even if the user is occupied, + //and puts the event at the top of the queue +#define CLEF_ONLYAFEW 2 //the icon will not flash for ever, only a few + //times. This is for eg online alert +#define CLEF_UNICODE 4 //set pszTooltip as unicode + +#define CLEF_PROTOCOLGLOBAL 8 //set event globally for protocol, hContact has to be NULL, + //lpszProtocol the protocol ID name to be set + +#if defined( _UNICODE ) + #define CLEF_TCHAR CLEF_UNICODE //will use TCHAR* instead of char* +#else + #define CLEF_TCHAR 0 //will return char*, as usual +#endif + +#define MS_CLIST_ADDEVENT "CList/AddEvent" + +//removes an event from the contact list's queue +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(HANDLE)hDbEvent +//returns 0 if the event was successfully removed, or nonzero if the event +//was not found +#define MS_CLIST_REMOVEEVENT "Clist/RemoveEvent" + +//gets the details of an event in the queue v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=iEvent +//returns a CLISTEVENT* on success, NULL on failure +//Returns the iEvent-th event from the queue for hContact, so iEvent=0 will +//get the event that will be got when the user clicks on that contact. +//Use hContact=INVALID_HANDLE_VALUE to search over all contacts, so iEvent=0 +//will get the event that will be got if the user clicks the systray icon. +#define MS_CLIST_GETEVENT "CList/GetEvent" + +//process a WM_MEASUREITEM message for user context menus v0.1.1.0+ +//wParam, lParam, return value as for WM_MEASUREITEM +//This is for displaying the icons by the menu items. If you don't call this +//and clist/menudrawitem whne drawing a menu returned by one of the three menu +//services below then it'll work but you won't get any icons +#define MS_CLIST_MENUMEASUREITEM "CList/MenuMeasureItem" + +//process a WM_DRAWITEM message for user context menus v0.1.1.0+ +//wParam, lParam, return value as for WM_MEASUREITEM +//See comments for clist/menumeasureitem +#define MS_CLIST_MENUDRAWITEM "CList/MenuDrawItem" + +//builds the context menu for a specific contact v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//returns a HMENU identifying the menu. This should be DestroyMenu()ed when +//finished with. +#define MS_CLIST_MENUBUILDCONTACT "CList/MenuBuildContact" + +//gets the image list with all the useful icons in it v0.1.1.0+ +//wParam=lParam=0 +//returns a HIMAGELIST +//the members of this image list are opaque, and you should trust what you +//are given +#define MS_CLIST_GETICONSIMAGELIST "CList/GetIconsImageList" +#define IMAGE_GROUPOPEN 11 +#define IMAGE_GROUPSHUT 12 + +//get the icon that should be associated with a contact v0.1.2.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//returns an index into the contact list imagelist. See clist/geticonsimagelist +//If the contact is flashing an icon, this function will not return that +//flashing icon. Use me_clist_contacticonchanged to get info about that. +#define MS_CLIST_GETCONTACTICON "CList/GetContactIcon" + +//The icon of a contact in the contact list has changed v0.1.2.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=iconId +//iconId is an offset into the clist's imagelist. See clist/geticonsimagelist +#define ME_CLIST_CONTACTICONCHANGED "CList/ContactIconChanged" + +/******************************* CLUI only *********************************/ + +// Stuff below here is ideally for the use of a CList UI module only. + +//get a handle to the main Miranda menu v0.1.1.0+ +//wParam=lParam=0 +//returns a HMENU. This need not be freed since it's owned by clist +#define MS_CLIST_MENUGETMAIN "CList/MenuGetMain" + +//get a handle to the Miranda status menu v0.1.1.0+ +//wParam=lParam=0 +//returns a HMENU. This need not be freed since it's owned by clist +#define MS_CLIST_MENUGETSTATUS "CList/MenuGetStatus" + + + + +//processes a menu selection from a menu v0.1.1.0+ +//wParam=MAKEWPARAM(LOWORD(wParam from WM_COMMAND),flags) +//lParam=(LPARAM)(HANDLE)hContact +//returns TRUE if it processed the command, FALSE otherwise +//hContact is the currently selected contact. It it not used if this is a main +//menu command. If this is NULL and the command is a contact menu one, the +//command is ignored + +#define CLISTMENUIDMIN 0x4000 // reserved range for clist menu ids +#define CLISTMENUIDMAX 0x7fff +////////////////////////////////////////////////////////////////////////// +// NOTE: v0.7.0.26+ +// Due to it is generic practice to handle menu command via WM_COMMAND +// window message handle and practice to process it via calling service +// in form: CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(wParam), MPCF_CONTACTMENU), (LPARAM) hContact)) +// to ensure that WM_COMMAND was realy from clist menu not from other menu +// it is reserved range of menu ids from CLISTMENUIDMIN to CLISTMENUIDMAX +// the menu items with ids outside from such range will not be processed by service. +// Moreover if you process WM_COMMAND youself and your window contains self menu +// please be sure that you will not call service for non-clist menu items. +// The simplest way is to ensure that your menus are not use item ids from such range. +// Otherwise, you HAVE TO distinguish WM_COMMAND from clist menus and from youк internal menu and +// DO NOT call MS_CLIST_MENUPROCESSCOMMAND for non clist menus. + + +#define MPCF_CONTACTMENU 1 //test commands from a contact menu +#define MPCF_MAINMENU 2 //test commands from the main menu +#define MS_CLIST_MENUPROCESSCOMMAND "CList/MenuProcessCommand" + +//processes a menu hotkey v0.1.1.0+ +//wParam=virtual key code +//lParam=MPCF_ flags +//returns TRUE if it processed the command, FALSE otherwise +//this should be called in WM_KEYDOWN +#define MS_CLIST_MENUPROCESSHOTKEY "CList/MenuProcessHotkey" + +//process all the messages required for docking v0.1.1.0+ +//wParam=(WPARAM)(MSG*)&msg +//lParam=(LPARAM)(LRESULT*)&lResult +//returns TRUE if the message should not be processed further, FALSE otherwise +//only msg.hwnd, msg.message, msg.wParam and msg.lParam are used +//your wndproc should return lResult if and only if TRUE is returned +#define MS_CLIST_DOCKINGPROCESSMESSAGE "CList/DockingProcessMessage" + +//determines whether the contact list is docked v0.1.1.0+ +//wParam=lParam=0 +//returns nonzero if the contact list is docked, of 0 if it is not +#define MS_CLIST_DOCKINGISDOCKED "CList/DockingIsDocked" + +//process all the messages required for the tray icon v0.1.1.0+ +//wParam=(WPARAM)(MSG*)&msg +//lParam=(LPARAM)(LRESULT*)&lResult +//returns TRUE if the message should not be processed further, FALSE otherwise +//only msg.hwnd, msg.message, msg.wParam and msg.lParam are used +//your wndproc should return lResult if and only if TRUE is returned +#define MS_CLIST_TRAYICONPROCESSMESSAGE "CList/TrayIconProcessMessage" + +//process all the messages required for hotkeys v0.1.1.0+ +//wParam=(WPARAM)(MSG*)&msg +//lParam=(LPARAM)(LRESULT*)&lResult +//returns TRUE if the message should not be processed further, FALSE otherwise +//only msg.hwnd, msg.message, msg.wParam and msg.lParam are used +//your wndproc should return lResult if and only if TRUE is returned +#define MS_CLIST_HOTKEYSPROCESSMESSAGE "CList/HotkeysProcessMessage" + +//toggles the show/hide status of the contact list v0.1.1.0+ +//wParam=lParam=0 +//returns 0 on success, nonzero on failure +#define MS_CLIST_SHOWHIDE "CList/ShowHide" + +//temporarily disable the autohide feature v0.1.2.1+ +//wParam=lParam=0 +//returns 0 on success, nonzero on failure +//This service will restart the autohide timer, so if you need to keep the +//window visible you'll have to be getting user input regularly and calling +//this function each time +#define MS_CLIST_PAUSEAUTOHIDE "CList/PauseAutoHide" + +//sent when the group get modified (created, renamed or deleted) +//or contact is moving from group to group +//wParam=hContact - NULL if operation on group +//lParam=pointer to CLISTGROUPCHANGE +typedef struct { + int cbSize; //size in bytes of this structure + TCHAR* pszOldName; //old group name + TCHAR* pszNewName; //new group name +} CLISTGROUPCHANGE; + +#define ME_CLIST_GROUPCHANGE "CList/GroupChange" + +//creates a new group and calls CLUI to display it v0.1.1.0+ +//wParam=hParentGroup +//lParam=groupName +//returns a handle to the new group +//hParentGroup is NULL to create the new group at the root, or can be the +//handle of the group of which the new group should be a subgroup. +//groupName is a TCHAR* pointing to the group name to create or NULL for +//API to create unique name by itself +#define MS_CLIST_GROUPCREATE "CList/GroupCreate" + +//deletes a group and calls CLUI to display the change v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=0 +//returns 0 on success, nonzero on failure +#define MS_CLIST_GROUPDELETE "CList/GroupDelete" + +//change the expanded state flag for a group internally v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=newState +//returns 0 on success, nonzero on failure +//newState is nonzero if the group is expanded, 0 if it's collapsed +//CLUI is not called when this change is made +#define MS_CLIST_GROUPSETEXPANDED "CList/GroupSetExpanded" + +//changes the flags for a group v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=MAKELPARAM(flags,flagsMask) +//returns 0 on success, nonzero on failure +//Only the flags given in flagsMask are altered. +//CLUI is called on changes to GROUPF_HIDEOFFLINE. +#define MS_CLIST_GROUPSETFLAGS "CList/GroupSetFlags" + +//get the name of a group v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=(LPARAM)(int*)&isExpanded +//returns a static buffer pointing to the name of the group +//returns NULL if hGroup is invalid. +//this buffer is only valid until the next call to this service +//&isExpanded can be NULL if you don't want to know if the group is expanded +//or not. +#define MS_CLIST_GROUPGETNAME "CList/GroupGetName" + +//get the name of a group v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=(LPARAM)(DWORD*)&flags +//returns a static buffer pointing to the name of the group +//returns NULL if hGroup is invalid. +//this buffer is only valid until the next call to this service +//&flags can be NULL if you don't want any of that info. +#define GROUPF_EXPANDED 0x04 +#define GROUPF_HIDEOFFLINE 0x08 +#define MS_CLIST_GROUPGETNAME2 "CList/GroupGetName2" + +//move a group to directly before another group v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=(LPARAM)(HANDLE)hBeforeGroup +//returns the new handle of the group on success, NULL on failure +//The order is represented by the order in which MS_CLUI_GROUPADDED is called, +//however UIs are free to ignore this order and sort alphabetically if they +//wish. +#define MS_CLIST_GROUPMOVEBEFORE "CList/GroupMoveBefore" + +//rename a group internally v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hGroup +//lParam=(LPARAM)(char*)szNewName +//returns 0 on success, nonzero on failure +//this will fail if the group name is a duplicate of an existing name +//CLUI is not called when this change is made +#define MS_CLIST_GROUPRENAME "CList/GroupRename" + +//build a menu of the group tree v0.1.2.1+ +//wParam=0 +//lParam=0 +//returns a HMENU on success, or NULL on failure +//The return value must be DestroyMenu()ed when you're done with it. +//NULL will be returned if the user doesn't have any groups +//The dwItemData of every menu item is the handle to that group. +//Menu item IDs are assigned starting at 100, in no particular order. +#define MS_CLIST_GROUPBUILDMENU "CList/GroupBuildMenu" + +//changes the 'hide offline contacts' flag and call CLUI v0.1.1.0+ +//wParam=newValue +//lParam=0 +//returns 0 on success, nonzero on failure +//newValue is 0 to show all contacts, 1 to only show online contacts +//or -1 to toggle the value +#define MS_CLIST_SETHIDEOFFLINE "CList/SetHideOffline" + +//do the message processing associated with double clicking a contact v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//returns 0 on success, nonzero on failure +#define MS_CLIST_CONTACTDOUBLECLICKED "CList/ContactDoubleClicked" + +//do the processing for when some files are dropped on a contact v0.1.2.1+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(char**)ppFiles +//returns 0 on success, nonzero on failure +//ppFiles is an array of fully qualified filenames, ending with a NULL. +#define MS_CLIST_CONTACTFILESDROPPED "CList/ContactFilesDropped" + +//change the group a contact belongs to v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(HANDLE)hGroup +//returns 0 on success, nonzero on failure +//use hGroup=NULL to put the contact in no group +#define MS_CLIST_CONTACTCHANGEGROUP "CList/ContactChangeGroup" + +//determines the ordering of two contacts v0.1.1.0+ +//wParam=(WPARAM)(HANDLE)hContact1 +//lParam=(LPARAM)(HANDLE)hContact2 +//returns 0 if hContact1 is the same as hContact2 +//returns +1 if hContact2 should be displayed after hContact1 +//returns -1 if hContact1 should be displayed after hContact2 +#define MS_CLIST_CONTACTSCOMPARE "CList/ContactsCompare" + +/* + wParam=0 (not used) + lParam=(LPARAM) &MIRANDASYSTRAYNOTIFY + + Affects: Show a message in a ballon tip against a protocol icon (if installed) + Returns: 0 on success, non zero on failure + Notes : This service will not be created on systems that haven't got the Windows + support for ballontips, also note that it's upto Windows if it shows your + message and it keeps check of delays (don't be stupid about showing messages) + + Version: 0.3.1a +*/ +#define NIIF_INFO 0x00000001 +#define NIIF_WARNING 0x00000002 +#define NIIF_ERROR 0x00000003 +#define NIIF_ICON_MASK 0x0000000F +#define NIIF_NOSOUND 0x00000010 +#define NIIF_INTERN_UNICODE 0x00000100 + + +typedef struct { + int cbSize; // sizeof(MIRANDASYSTRAY) + char *szProto; // protocol to show under (may have no effect) + union { + char *szInfoTitle; // only 64chars of it will be used + TCHAR *tszInfoTitle; // used if NIIF_INTERN_UNICODE is specified + }; + union { + char *szInfo; // only 256chars of it will be used + TCHAR *tszInfo; // used if NIIF_INTERN_UNICODE is specified + }; + DWORD dwInfoFlags; // see NIIF_* stuff + UINT uTimeout; // how long to show the tip for +} MIRANDASYSTRAYNOTIFY; +#define MS_CLIST_SYSTRAY_NOTIFY "Miranda/Systray/Notify" + +#define SETTING_TOOLWINDOW_DEFAULT 1 +#define SETTING_SHOWMAINMENU_DEFAULT 1 +#define SETTING_SHOWCAPTION_DEFAULT 1 +#define SETTING_CLIENTDRAG_DEFAULT 1 +#define SETTING_ONTOP_DEFAULT 0 +#define SETTING_MIN2TRAY_DEFAULT 1 +#define SETTING_TRAY1CLICK_DEFAULT (IsWinVer7Plus()?1:0) +#define SETTING_HIDEOFFLINE_DEFAULT 0 +#define SETTING_HIDEEMPTYGROUPS_DEFAULT 0 +#define SETTING_USEGROUPS_DEFAULT 1 +#define SETTING_SORTBYSTATUS_DEFAULT 0 +#define SETTING_SORTBYPROTO_DEFAULT 0 +#define SETTING_TRANSPARENT_DEFAULT 0 +#define SETTING_ALPHA_DEFAULT 200 +#define SETTING_AUTOALPHA_DEFAULT 150 +#define SETTING_CONFIRMDELETE_DEFAULT 1 +#define SETTING_AUTOHIDE_DEFAULT 0 +#define SETTING_HIDETIME_DEFAULT 30 +#define SETTING_CYCLETIME_DEFAULT 4 +#define SETTING_TRAYICON_DEFAULT SETTING_TRAYICON_SINGLE +#define SETTING_ALWAYSSTATUS_DEFAULT 0 +#define SETTING_ALWAYSMULTI_DEFAULT 0 + +#define SETTING_TRAYICON_SINGLE 0 +#define SETTING_TRAYICON_CYCLE 1 +#define SETTING_TRAYICON_MULTI 2 + +#define SETTING_STATE_HIDDEN 0 +#define SETTING_STATE_MINIMIZED 1 +#define SETTING_STATE_NORMAL 2 + +#define SETTING_BRINGTOFRONT_DEFAULT 0 + +#endif // M_CLIST_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_database.h b/plugins/!NotAdopted/WinPopup/sdk/m_database.h new file mode 100644 index 0000000000..c1bf7dafd3 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_database.h @@ -0,0 +1,1199 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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_DATABASE_H__ +#define M_DATABASE_H__ 1 + +/******************* DATABASE MODULE ***************************/ + +/* Notes (as I think of them): +- The module is 100% thread-safe +- The database is the main routing point for the vast majority of Miranda. + Events are sent from the protocol module to here, and the send/recv message + module (for example) hooks the db/event/added event. Events like 'contact + online status changed' do not come through here - icqlib will send that one. +- contacts work much the same. the find/add users module calls db/contact/add + and db/contact/writesetting and the contact list will get db/contact/added + and db/contact/settingchanged events +- The user is just a special contact. A hcontact of NULL in most functions + means the user. Functions in which it cannot be used will be stated +- events attached to the user are things like system messages +- also in this module are crypt/decrypt functions for stuff that should be + obfuscated on the disk, and some time functions for dealing with timestamps + in events. +- the contactsettings system is designed for being read by many different + modules. eg lots of people will be interested in "ICQ"/"UIN", but the module + name passed to contact/writesetting should always be your own. The Mirabilis + ICQ database importer clearly has to be an exception to this rule, along with + a few other bits. +- the current database format means that geteventcontact is exceptionally slow. + It should be avoidable in most cases so I'm not too concerned, but if people + really need to use it a lot, I'll sort it out. +- handles do not need to be closed unless stated +- the database is loaded as a memory mapped file. This has various + disadvantages but a massive advantage in speed for random access. +- The database is optimised for reading. Write performance is fairly bad, + except for adding events which is the most common activity and pretty good. +- I'll work on caching to improve this later +- Deleted items are left as empty space and never reused. All new items are + put at the end. A count is kept of this slack space and at some point a + separate programme will need to be written to repack the database when the + slack gets too high. It's going to be a good few months of usage before this + can happen to anyone though, so no rush. +*/ + +/******************** GENERALLY USEFUL STUFF***********************/ + +#include + +#if !defined(M_SYSTEM_H__) + #include "m_system.h" +#endif + +#if !defined(M_UTILS_H__) + #include "m_utils.h" +#endif + +#ifdef _MSC_VER + #pragma warning(disable:4201 4204) +#endif + +//DBVARIANT: used by db/contact/getsetting and db/contact/writesetting +#define DBVT_DELETED 0 //this setting just got deleted, no other values are valid +#define DBVT_BYTE 1 //bVal and cVal are valid +#define DBVT_WORD 2 //wVal and sVal are valid +#define DBVT_DWORD 4 //dVal and lVal are valid +#define DBVT_ASCIIZ 255 //pszVal is valid +#define DBVT_BLOB 254 //cpbVal and pbVal are valid +#define DBVT_UTF8 253 //pszVal is valid +#define DBVT_WCHAR 252 //pszVal is valid +#if defined( _UNICODE ) + #define DBVT_TCHAR DBVT_WCHAR +#else + #define DBVT_TCHAR DBVT_ASCIIZ +#endif +#define DBVTF_VARIABLELENGTH 0x80 +#define DBVTF_DENYUNICODE 0x10000 +typedef struct { + BYTE type; + union { + BYTE bVal; char cVal; + WORD wVal; short sVal; + DWORD dVal; long lVal; + struct { + union { + char *pszVal; + TCHAR *ptszVal; + WCHAR *pwszVal; + }; + WORD cchVal; //only used for db/contact/getsettingstatic + }; + struct { + WORD cpbVal; + BYTE *pbVal; + }; + }; +} DBVARIANT; + +/******************************************************************/ +/************************* SERVICES *******************************/ +/******************************************************************/ + +/* DB/Contact/GetProfileName service +Gets the name of the profile currently being used by the database module. This +is the same as the filename of the database + wParam=(WPARAM)(UINT)cbName + lParam=(LPARAM)(char*)pszName +pszName is a pointer to the buffer that receives the name of the profile +cbName is the size in bytes of the pszName buffer +Returns 0 on success or nonzero otherwise +*/ +#define MS_DB_GETPROFILENAME "DB/GetProfileName" + +/* DB/Contact/GetProfilePath service +Gets the path of the profile currently being used by the database module. This +path does not include the last '\'. + wParam=(WPARAM)(UINT)cbName + lParam=(LPARAM)(char*)pszName +pszName is a pointer to the buffer that receives the path of the profile +cbName is the size in bytes of the pszName buffer +Returns 0 on success or nonzero otherwise +*/ +#define MS_DB_GETPROFILEPATH "DB/GetProfilePath" + +/************************* Contact ********************************/ + +/* DB/Contact/GetSetting service +Look up the value of a named setting for a specific contact in the database + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTGETSETTING*)&dbcgs +hContact should have been returned by find*contact or addcontact +Caller is responsible for free()ing dbcgs.pValue->pszVal and pbVal if they are +returned. This should be done with db/contact/freevariant if you have your own +heap (like DLLs do). +Note that DBCONTACTGETSETTING takes a pointer to a DBVARIANT, whereas +DBCONTACTWRITESETTING contains a DBVARIANT. +Returns 0 on success or nonzero if the setting name was not found or hContact +was invalid +Because this is such a common function there are some short helper function at +the bottom of this header that use it. + +(Added during 0.3.3+ development!!) + +If a setting is queried under for contact and it is deleted it will +not be returned as a successful attempt, prior to 0.3.3 a *deleted* +setting would be successfully read (which was a bug because the pValue +was often garbage and maybe not even NULL terminated) + +To test for existing but 'deleted' settings, the return value will +be 2, and pValue->type==DBVT_DELETED, at this point pValue is undefined. +*/ +typedef struct { + const char *szModule; // pointer to name of the module that wrote the + // setting to get + const char *szSetting; // pointer to name of the setting to get + DBVARIANT *pValue; // pointer to variant to receive the value +} DBCONTACTGETSETTING; +#define MS_DB_CONTACT_GETSETTING "DB/Contact/GetSetting" + +/* DB/Contact/GetSettingString service 0.4.3+ +Same as DB/Contact/GetSetting, but also gets the required string type inside +the dbcgs->type parameter +*/ +#define MS_DB_CONTACT_GETSETTING_STR "DB/Contact/GetSettingStr" + +/* DB/Contact/GetSettingStatic service +Look up the value of a named setting for a specific contact in the database + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTGETSETTING*)&dbcgs +hContact should have been returned by find*contact or addcontact +This service differs from db/contact/getsetting in that it won't malloc() +memory for the return value if it needs to do so. This introduces some extra +constraints: +Upon calling dbcgs.pValue->type should be initialised to the expected type of +the setting. If the setting is of an integral type it won't matter if it's +wrong and the service will correct it before returning, however if the setting +is a string or a blob the service needs to know where to put the data and will +fail if type is set wrongly. +If dbcgs.pValue->type is DBVT_ASCIIZ or DBVT_BLOB upon calling, the +corresponding data field (pszVal or pbVal) must point to a buffer allocated by +the caller and the length field (cchVal or cpbVal) must contain the size of +that buffer in bytes. +If the setting type is variable length (DBVT_ASCIIZ or DBVT_BLOB), on exit the +length field (cchVal or cpbVal) will be filled with the full length of the +setting's value (excluding the terminating nul if it's DBVT_ASCIIZ). +This service exists as well as db/contact/getsetting because malloc()/free() +can be too slow for frequently queried settings. +Returns 0 on success or nonzero if the setting name was not found or hContact +was invalid. +*/ +#define MS_DB_CONTACT_GETSETTINGSTATIC "DB/Contact/GetSettingStatic" + +/* DB/Contact/FreeVariant service +Free the memory in a DBVARIANT that is allocated by a call to +db/contact/getsetting + wParam=0 + lParam=(LPARAM)(DBVARIANT*)&dbv +Returns 0 on success, nonzero otherwise +This service is actually just a wrapper around a call to free() and a test to +check that it is a string or a blob in the variant. It exists because DLLs have +their own heap and cannot free the memory allocated in db/contact/getsetting. +Thus it need not be called if you know the variant contains some form of int, +and you will often see free() used instead in code written before I noticed +this problem. +Good style, of course, dictates that it should be present to match all calls to +db/contact/getsetting, but that's not going to happen of course. +There's a helper function for this at the bottom of this header too. +*/ +#define MS_DB_CONTACT_FREEVARIANT "DB/Contact/FreeVariant" + +/* DB/Contact/WriteSetting service +Change the value of, or create a new value with, a named setting for a specific +contact in the database to the given value + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTWRITESETTING*)&dbcws +hContact should have been returned by find*contact or addcontact +Returns 0 on success or nonzero if hContact was invalid +Note that DBCONTACTGETSETTING takes a pointer to a DBVARIANT, whereas +DBCONTACTWRITESETTING contains a DBVARIANT. +Because this is such a common function there are some short helper function at +the bottom of this header that use it. +Triggers a db/contact/settingchanged event just before it returns. +*/ +typedef struct { + const char *szModule; // pointer to name of the module that wrote the + // setting to get + const char *szSetting; // pointer to name of the setting to get + DBVARIANT value; // variant containing the value to set +} DBCONTACTWRITESETTING; +#define MS_DB_CONTACT_WRITESETTING "DB/Contact/WriteSetting" + +/* DB/Contact/DeleteSetting service +Removes a named setting for a specific contact from the database + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTGETSETTING*)&dbcgs +hContact should have been returned by find*contact or addcontact +pValue from dbcgs is not used. +Returns 0 on success or nonzero if the setting was not present or hContact was +invalid +Triggers a db/contact/settingchanged event before it deletes the setting. The +'new value' of the setting is set to type=0 and all the other fields are +undefined. +*/ +#define MS_DB_CONTACT_DELETESETTING "DB/Contact/DeleteSetting" + +/* db/contact/enumsettings v0.1.0.1+ +Lists all the settings a specific modules has stored in the database for a +specific contact. +wParam=(WPARAM)(HANDLE)hContact +lParam=(LPARAM)(DBCONTACTENUMSETTINGS*)&dbces +Returns the return value of the last call to pfnEnumProc, or -1 if there are +no settings for that module/contact pair +Writing to or deleting from the database while enumerating will have +unpredictable results for the enumeration, but the write will succeed. +Use db/modules/enum to get a complete list of module names +szSetting is only guaranteed to be valid for the duration of the callback. If +you want to keep it for longer you must allocation your own storage. +*/ +typedef int (*DBSETTINGENUMPROC)(const char *szSetting,LPARAM lParam); +typedef struct { + DBSETTINGENUMPROC pfnEnumProc; + LPARAM lParam; //passed direct to pfnEnumProc + const char *szModule; //name of the module to get settings for + DWORD ofsSettings; //filled by the function to contain the offset from + //the start of the database of the requested settings group. +} DBCONTACTENUMSETTINGS; +#define MS_DB_CONTACT_ENUMSETTINGS "DB/Contact/EnumSettings" + +/* DB/Contact/GetCount service +Gets the number of contacts in the database, which does not count the user + wParam=lParam=0 +Returns the number of contacts. They can be retrieved using contact/findfirst +and contact/findnext +*/ +#define MS_DB_CONTACT_GETCOUNT "DB/Contact/GetCount" + +/* DB/Contact/FindFirst service +Gets the handle of the first contact in the database. This handle can be used +with loads of functions. It does not need to be closed. + wParam=lParam=0 +Returns a handle to the first contact in the db on success, or NULL if there +are no contacts in the db. +*/ +#define MS_DB_CONTACT_FINDFIRST "DB/Contact/FindFirst" + +/* DB/Contact/FindNext service +Gets the handle of the next contact after hContact in the database. This handle +can be used with loads of functions. It does not need to be closed. + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns a handle to the contact after hContact in the db on success or NULL if +hContact was the last contact in the db or hContact was invalid. +*/ +#define MS_DB_CONTACT_FINDNEXT "DB/Contact/FindNext" + +/* DB/Contact/Delete +Deletes the contact hContact from the database and all events and settings +associated with it. + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns 0 on success or nonzero if hContact was invalid +Please don't try to delete the user contact (hContact=NULL) +Triggers a db/contact/deleted event just *before* it removes anything +Because all events are deleted, lots of people may end up with invalid event +handles from this operation, which they should be prepared for. +*/ +#define MS_DB_CONTACT_DELETE "DB/Contact/Delete" + +/* DB/Contact/Add +Adds a new contact to the database. New contacts initially have no settings +whatsoever, they must all be added with db/contacts/writesetting. + wParam=lParam=0 +Returns a handle to the newly created contact on success, or NULL otherwise. +Triggers a db/contact/added event just before it returns. +*/ +#define MS_DB_CONTACT_ADD "DB/Contact/Add" + +/* DB/Contact/Is +Checks if a given value is a valid contact handle, note that due +to the nature of multiple threading, a valid contact can still become +invalid after a call to this service. + wParam=(WPARAM)hContact + lParam=0 +Returns 1 if the contact is a contact, or 0 if the contact is not valid. +*/ +#define MS_DB_CONTACT_IS "DB/Contact/Is" + +/************************** Event *********************************/ + +/* DB/EventType/Register service (0.7+) +Registers the specified database event type, with module, id & description. +When someone needs to retrieve an event's text, a service named Module/GetEventText +will be called. For example, for module named 'foo' and event id 2000 a service +foo/GetEventText2000 should be defined to process this request. That handler should +decode a blob and return the event text in the required format, its prototype is identical +to a call of MS_DB_EVENT_GETTEXT (see below) + wParam=0 + lParam=(LPARAM)(DBEVENTTYPEDESCR*) +Always returns 0. +*/ + +#define DBEVENTTYPEDESCR_SIZE sizeof(DBEVENTTYPEDESCR) +#define DBEVENTTYPEDESCR_SIZE_V1 0x10 + +typedef struct +{ + int cbSize; // structure size in bytes + char* module; // event module name + int eventType; // event id, unique for this module + char* descr; // event type description (i.e. "File Transfer") + char* textService; // service name for MS_DB_EVENT_GETTEXT (0.8+, default Module+'/GetEventText'+EvtID) + char* iconService; // service name for MS_DB_EVENT_GETICON (0.8+, default Module+'/GetEventIcon'+EvtID) + HANDLE eventIcon; // icolib handle to eventicon (0.8+, default 'eventicon_'+Module+EvtID) + DWORD flags; // flags, combination of the DETF_* +} + DBEVENTTYPEDESCR; + +// constants for default event behaviour +#define DETF_HISTORY 1 // show event in history +#define DETF_MSGWINDOW 2 // show event in message window +#define DETF_NONOTIFY 4 // block event notify (e.g. Popups) + + +#define MS_DB_EVENT_REGISTERTYPE "DB/EventType/Register" + +/* DB/EventType/Get service (0.7+) +Retrieves the previously registered database event type, by module & id. + wParam=(WPARAM)(char*)szModule + lParam=(LPARAM)(int)eventType +Returns DBEVENTTYPEDESCR* or NULL, if an event isn't found. +*/ + +#define MS_DB_EVENT_GETTYPE "DB/EventType/Get" + +/* DB/Event/GetCount service +Gets the number of events in the chain belonging to a contact in the database. + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns the number of events in the chain owned by hContact or -1 if hContact +is invalid. They can be retrieved using the event/find* services. +*/ +#define MS_DB_EVENT_GETCOUNT "DB/Event/GetCount" + +/* DB/Event/Add +Adds a new event to a contact's event list + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBEVENTINFO*)&dbe +Returns a handle to the newly added event, or NULL on failure +Triggers a db/event/added event just before it returns. +Events are sorted chronologically as they are entered, so you cannot guarantee +that the new hEvent is the last event in the chain, however if a new event is +added that has a timestamp less than 90 seconds *before* the event that should +be after it, it will be added afterwards, to allow for protocols that only +store times to the nearest minute, and slight delays in transports. +There are a few predefined eventTypes below for easier compatibility, but +modules are free to define their own, beginning at 2000 +DBEVENTINFO.timestamp is in GMT, as returned by time(). There are services +db/time/x below with useful stuff for dealing with it. +*/ +#define DBEF_FIRST 1 //this is the first event in the chain; + //internal only: *do not* use this flag +#define DBEF_SENT 2 //this event was sent by the user. If not set this + //event was received. +#define DBEF_READ 4 //event has been read by the user. It does not need + //to be processed any more except for history. +#define DBEF_RTL 8 //event contains the right-to-left aligned text +#define DBEF_UTF 16 //event contains a text in utf-8 + +typedef struct { + int cbSize; //size of the structure in bytes + char *szModule; //pointer to name of the module that 'owns' this + //event, ie the one that is in control of the data format + DWORD timestamp; //seconds since 00:00, 01/01/1970. Gives us times until + //2106 unless you use the standard C library which is + //signed and can only do until 2038. In GMT. + DWORD flags; //the omnipresent flags + WORD eventType; //module-defined event type field + DWORD cbBlob; //size of pBlob in bytes + PBYTE pBlob; //pointer to buffer containing module-defined event data +} DBEVENTINFO; +#define EVENTTYPE_MESSAGE 0 +#define EVENTTYPE_URL 1 +#define EVENTTYPE_CONTACTS 2 //v0.1.2.2+ +#define EVENTTYPE_ADDED 1000 //v0.1.1.0+: these used to be module- +#define EVENTTYPE_AUTHREQUEST 1001 //specific codes, hence the module- +#define EVENTTYPE_FILE 1002 //specific limit has been raised to 2000 +#define MS_DB_EVENT_ADD "DB/Event/Add" + +/* DB/Event/Delete +Removes a single event from the database + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(HANDLE)hDbEvent +hDbEvent should have been returned by db/event/add or db/event/find*event +Returns 0 on success, or nonzero if hDbEvent was invalid +Triggers a db/event/deleted event just *before* the event is deleted +*/ +#define MS_DB_EVENT_DELETE "DB/Event/Delete" + +/* DB/Event/GetBlobSize +Retrieves the space in bytes required to store the blob in hDbEvent + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=0 +hDbEvent should have been returned by db/event/add or db/event/find*event +Returns the space required in bytes, or -1 if hDbEvent is invalid +*/ +#define MS_DB_EVENT_GETBLOBSIZE "DB/Event/GetBlobSize" + +/* DB/Event/Get +Retrieves all the information stored in hDbEvent + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=(LPARAM)(DBEVENTINFO*)&dbe +hDbEvent should have been returned by db/event/add or db/event/find*event +Returns 0 on success or nonzero if hDbEvent is invalid +Don't forget to set dbe.cbSize, dbe.pBlob and dbe.cbBlob before calling this +service +The correct value dbe.cbBlob can be got using db/event/getblobsize +If successful, all the fields of dbe are filled. dbe.cbBlob is set to the +actual number of bytes retrieved and put in dbe.pBlob +If dbe.cbBlob is too small, dbe.pBlob is filled up to the size of dbe.cbBlob +and then dbe.cbBlob is set to the required size of data to go in dbe.pBlob +On return, dbe.szModule is a pointer to the database module's own internal list +of modules. Look but don't touch. +*/ +#define MS_DB_EVENT_GET "DB/Event/Get" + +/* DB/Event/GetText (0.7.0+) +Retrieves the event's text + wParam=(WPARAM)0 (unused) + lParam=(LPARAM)(DBEVENTGETTEXT*)egt - pointer to structure with parameters + egt->dbei should be the valid database event read via MS_DB_EVENT_GET + egt->datatype = DBVT_WCHAR or DBVT_ASCIIZ or DBVT_TCHAR. If a caller wants to +suppress Unicode part of event in answer, add DBVTF_DENYUNICODE to this field. + egt->codepage is any valid codepage, CP_ACP by default. + +Function returns a pointer to a string in the required format. +This string should be freed by a call of mir_free +*/ +typedef struct { + DBEVENTINFO* dbei; + int datatype; + int codepage; +} DBEVENTGETTEXT; + +#define MS_DB_EVENT_GETTEXT "DB/Event/GetText" + +__inline static char* DbGetEventTextA( DBEVENTINFO* dbei, int codepage ) +{ DBEVENTGETTEXT temp = { dbei, DBVT_ASCIIZ, codepage }; + return (char*)CallService(MS_DB_EVENT_GETTEXT,0,(LPARAM)&temp); +} + +__inline static WCHAR* DbGetEventTextW( DBEVENTINFO* dbei, int codepage ) +{ DBEVENTGETTEXT temp = { dbei, DBVT_WCHAR, codepage }; + return (WCHAR*)CallService(MS_DB_EVENT_GETTEXT,0,(LPARAM)&temp); +} + +__inline static TCHAR* DbGetEventTextT( DBEVENTINFO* dbei, int codepage ) +{ DBEVENTGETTEXT temp = { dbei, DBVT_TCHAR, codepage }; + return (TCHAR*)CallService(MS_DB_EVENT_GETTEXT,0,(LPARAM)&temp); +} + +/* DB/Event/GetIcon (0.7.0.1+) +Retrieves the event's icon + wParam=(WPARAM)(int)flags - use LR_SHARED for shared HICON + lParam=(LPARAM)(DBEVENTINFO*)dbei +dbei should be a valid database event read via MS_DB_EVENT_GET + +Function returns HICON (use DestroyIcon to release resources if not LR_SHARED) + +A plugin can register the standard event icon in IcoLib named +'eventicon_'+Module+EvtID, like eventicon_ICQ2001. Otherwise, to declare an icon +with the non-standard name, you can declare the special service, Module/GetEventIcon, +which will retrieve the custom icon handle (HICON). This service function has the +same parameters MS_DB_EVENT_GETICON does. +*/ +#define MS_DB_EVENT_GETICON "DB/Event/GetIcon" + +/* DB/Event/GetString (0.9.0+) +Converts the event's string to TCHAR* depending on the event's format + wParam=(LPARAM)(DBEVENTINFO*)dbei + lParam=(WPARAM)(char*)str - string to be converted + returns TCHAR* - the converted string +Caller must free the result using mir_free +*/ + +#define MS_DB_EVENT_GETSTRINGT "DB/Event/GetStringT" + +__inline static TCHAR* DbGetEventStringT( DBEVENTINFO* dbei, const char* str ) +{ + return (TCHAR*)CallService( MS_DB_EVENT_GETSTRINGT, (WPARAM)dbei, (LPARAM)str ); +} + +/* DB/Event/MarkRead +Changes the flags for an event to mark it as read. + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(HANDLE)hDbEvent +hDbEvent should have been returned by db/event/add or db/event/find*event +Returns the entire flag DWORD for the event after the change, or -1 if hDbEvent +is invalid. +This is the one database write operation that does not trigger an event. +Modules should not save flags states for any length of time. +*/ +#define MS_DB_EVENT_MARKREAD "DB/Event/MarkRead" + +/* DB/Event/GetContact +Retrieves a handle to the contact that owns hDbEvent. + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=0 +hDbEvent should have been returned by db/event/add or db/event/find*event +NULL is a valid return value, meaning, as usual, the user. +Returns (HANDLE)(-1) if hDbEvent is invalid, or the handle to the contact on +success +This service is exceptionally slow. Use only when you have no other choice at +all. +*/ +#define MS_DB_EVENT_GETCONTACT "DB/Event/GetContact" + +/* DB/Event/FindFirst +Retrieves a handle to the first event in the chain for hContact + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns the handle, or NULL if hContact is invalid or has no events +Events in a chain are sorted chronologically automatically +*/ +#define MS_DB_EVENT_FINDFIRST "DB/Event/FindFirst" + +/* DB/Event/FindFirstUnread +Retrieves a handle to the first unread event in the chain for hContact + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns the handle, or NULL if hContact is invalid or all its events have been +read +Events in a chain are sorted chronologically automatically, but this does not +necessarily mean that all events after the first unread are unread too. They +should be checked individually with event/findnext and event/get +This service is designed for startup, reloading all the events that remained +unread from last time +*/ +#define MS_DB_EVENT_FINDFIRSTUNREAD "DB/Event/FindFirstUnread" + +/* DB/Event/FindLast +Retrieves a handle to the last event in the chain for hContact + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +Returns the handle, or NULL if hContact is invalid or has no events +Events in a chain are sorted chronologically automatically +*/ +#define MS_DB_EVENT_FINDLAST "DB/Event/FindLast" + +/* DB/Event/FindNext +Retrieves a handle to the next event in a chain after hDbEvent + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=0 +Returns the handle, or NULL if hDbEvent is invalid or is the last event +Events in a chain are sorted chronologically automatically +*/ +#define MS_DB_EVENT_FINDNEXT "DB/Event/FindNext" + +/* DB/Event/FindPrev +Retrieves a handle to the previous event in a chain before hDbEvent + wParam=(WPARAM)(HANDLE)hDbEvent + lParam=0 +Returns the handle, or NULL if hDbEvent is invalid or is the first event +Events in a chain are sorted chronologically automatically +*/ +#define MS_DB_EVENT_FINDPREV "DB/Event/FindPrev" + +/************************** Encryption ****************************/ + +/* DB/Crypt/EncodeString +Scrambles pszString in-place using a strange encryption algorithm + wParam=(WPARAM)(int)cbString + lParam=(LPARAM)(char*)pszString +cbString is the size of the buffer pointed to by pszString, *not* the length +of pszString. This service may be changed at a later date such that it +increases the length of pszString +Returns 0 always +*/ +#define MS_DB_CRYPT_ENCODESTRING "DB/Crypt/EncodeString" + +/* DB/Crypt/DecodeString +Descrambles pszString in-place using the strange encryption algorithm + wParam=(WPARAM)(int)cbString + lParam=(LPARAM)(char*)pszString +Reverses the operation done by crypt/encodestring +cbString is the size of the buffer pointed to by pszString, *not* the length +of pszString. +Returns 0 always +*/ +#define MS_DB_CRYPT_DECODESTRING "DB/Crypt/DecodeString" + +/**************************** Time ********************************/ + +/* DB/Time/TimestampToLocal +Converts a GMT timestamp into local time + wParam=(WPARAM)(DWORD)timestamp + lParam=0 +Returns the converted value +Timestamps have zero at midnight 1/1/1970 GMT, this service converts such a +value to be based at midnight 1/1/1970 local time. +This service does not use a simple conversion based on the current offset +between GMT and local. Rather, it figures out whether daylight savings time +would have been in place at the time of the stamp and gives the local time as +it would have been at the time and date the stamp contains. +This service isn't nearly as useful as db/time/TimestampToString below and I +recommend avoiding its use when possible so that you don't get your timezones +mixed up (like I did. Living at GMT makes things easier for me, but has certain +disadvantages :-) ). +*/ +#define MS_DB_TIME_TIMESTAMPTOLOCAL "DB/Time/TimestampToLocal" + +/* DB/Time/TimestampToString +Converts a GMT timestamp into a customisable local time string + wParam=(WPARAM)(DWORD)timestamp + lParam=(LPARAM)(DBTIMETOSTRING*)&tts +Returns 0 always +Uses db/time/timestamptolocal for the conversion so read that description to +see what's going on. +The string is formatted according to the current user's locale, language and +preferences. +szFormat can have the following special characters: + t Time without seconds, eg hh:mm + s Time with seconds, eg hh:mm:ss + m Time without minutes, eg hh + d Short date, eg dd/mm/yyyy + D Long date, eg d mmmm yyyy +All other characters are copied across to szDest as-is +*/ +typedef struct { + char *szFormat; // format string, as above + char *szDest; // place to put the output string + int cbDest; // maximum number of bytes to put in szDest +} DBTIMETOSTRING; +#define MS_DB_TIME_TIMESTAMPTOSTRING "DB/Time/TimestampToString" + +typedef struct { + TCHAR *szFormat; // format string, as above + TCHAR *szDest; // place to put the output string + int cbDest; // maximum number of bytes to put in szDest +} DBTIMETOSTRINGT; +#define MS_DB_TIME_TIMESTAMPTOSTRINGT "DB/Time/TimestampToStringT" + +/*************************** Random *******************************/ + +/* +Switches safety settings on or off +wParam=(WPARAM)(BOOL)newSetting +lParam=0 +returns 0 always +newSetting is TRUE initially. +Miranda's database is normally protected against corruption by agressively +flushing data to the disk on writes. If you're doing a lot of writes (eg in +an import plugin) it can sometimes be desirable to switch this feature off to +speed up the process. If you do switch it off, you must remember that crashes +are far more likely to be catastrophic, so switch it back on at the earliest +possible opportunity. +Note that if you're doing a lot of setting writes, the flush is already delayed +so you need not use this service for that purpose. +*/ +#define MS_DB_SETSAFETYMODE "DB/SetSafetyMode" + +/*************************** Modules ******************************/ + +/* db/modules/enum v0.1.0.1+ +Enumerates the names of all modules that have stored or requested information +from the database. +wParam=lParam +lParam=(WPARAM)(DBMODULEENUMPROC)dbmep +Returns the value returned by the last call to dbmep +This service is only really useful for debugging, in conjunction with +db/contact/enumsettings +lParam is passed directly to dbmep +dbmep should return 0 to continue enumeration, or nonzero to stop. +ofsModuleName is the offset of the module name from the start of the profile +database, and is only useful for really heavyweight debugging +Modules names will be enumerated in no particular order +Writing to the database while module names are being enumerated will cause +unpredictable results in the enumeration, but the write will work. +szModuleName is only guaranteed to be valid for the duration of the callback. +If you want to keep it for longer you must allocation your own storage. +**BUG**: Prior to 0.1.2.0 dbmep was called as (lParam)(szMod,ofsMod,lParam). + This means that the lParam parameter to dbmep was useless, and explains the + slightly odd 'wParam=lParam' in the definition. +*/ +typedef int (*DBMODULEENUMPROC)(const char *szModuleName,DWORD ofsModuleName,LPARAM lParam); +#define MS_DB_MODULES_ENUM "DB/Modules/Enum" + +/* DB/Module/Delete 0.8.0+ + +Removes all settings for the specified module. +wParam=0 (unused) +lParam=(LPARAM)(char*)szModuleName - the module name to be deleted +*/ + +#define MS_DB_MODULE_DELETE "DB/Module/Delete" + +/******************************************************************/ +/************************** EVENTS ********************************/ +/******************************************************************/ + +/* DB/Event/Added event +Called when a new event has been added to the event chain for a contact + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(HANDLE)hDbEvent +hDbEvent is a valid handle to the event. hContact is a valid handle to the +contact to which hDbEvent refers. +Since events are sorted chronologically, you cannot guarantee that hDbEvent is +at any particular position in the chain. +*/ +#define ME_DB_EVENT_ADDED "DB/Event/Added" + +/* DB/Event/FilterAdd (NOTE: Added during 0.3.3+ development!) +Called **before** a new event is made of a DBEVENTINFO structure, this +hook is not SAFE unless you know what you're doing with it, the arguments +are passed as-is (with errors, pointer problems, if any) from any arguments +passed to MS_DB_EVENT_ADD. + +The point of this hook is to stop any unwanted database events, to stop +an event being added, return 1, to allow the event to pass through return +0. + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)&DBEVENTINFO + +Any changed made to the said DBEVENTINFO are also passed along to the database, +therefore it is possible to shape the data, however DO NOT DO THIS. +*/ +#define ME_DB_EVENT_FILTER_ADD "DB/Event/FilterAdd" + +/* DB/Event/Deleted event +Called when an event is about to be deleted from the event chain for a contact + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(HANDLE)hDbEvent +hDbEvent is a valid handle to the event which is about to be deleted, but it +won't be once your hook has returned. +hContact is a valid handle to the contact to which hDbEvent refers, and will +remain valid. +Returning nonzero from your hook will not stop the deletion, but it will, as +usual, stop other hooks from being called. +*/ +#define ME_DB_EVENT_DELETED "DB/Event/Deleted" + +/* DB/Contact/Added event +Called when a new contact has been added to the database + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +hContact is a valid handle to the new contact. +Contacts are initially created without any settings, so if you hook this event +you will almost certainly also want to hook db/contact/settingchanged as well. +*/ +#define ME_DB_CONTACT_ADDED "DB/Contact/Added" + +/* DB/Contact/Deleted event +Called when an contact is about to be deleted + wParam=(WPARAM)(HANDLE)hContact + lParam=0 +hContact is a valid handle to the contact which is about to be deleted, but it +won't be once your hook has returned. +Returning nonzero from your hook will not stop the deletion, but it will, as +usual, stop other hooks from being called. +Deleting a contact invalidates all events in its chain. +*/ +#define ME_DB_CONTACT_DELETED "DB/Contact/Deleted" + +/* DB/Contact/SettingChanged event +Called when a contact has had one of its settings changed + wParam=(WPARAM)(HANDLE)hContact + lParam=(LPARAM)(DBCONTACTWRITESETTING*)&dbcws +hContact is a valid handle to the contact that has changed. +This event will be triggered many times rapidly when a whole bunch of values +are set. +Modules which hook this should be aware of this fact and quickly return if they +are not interested in the value that has been changed. +Careful not to get into infinite loops with this event. +The structure dbcws is the same one as is passed to the original service, so +don't change any of the members. +*/ +#define ME_DB_CONTACT_SETTINGCHANGED "DB/Contact/SettingChanged" + +/* DB/Contact/SetSettingResident service (0.6+) +Disables a setting saving to the database. + wParam=(WPARAM)(BOOL)bIsResident + lParam=(LPARAM)(char*)pszSettingName +*/ +#define MS_DB_SETSETTINGRESIDENT "DB/SetSettingResident" + +/******************************************************************/ +/********************* SETTINGS HELPER FUNCTIONS ******************/ +/******************************************************************/ + +#ifndef DB_NOHELPERFUNCTIONS + +#define db_byte_get(a,b,c,d) DBGetContactSettingByte(a,b,c,d) +#define db_word_get(a,b,c,d) DBGetContactSettingWord(a,b,c,d) +#define db_dword_get(a,b,c,d) DBGetContactSettingDword(a,b,c,d) +#define db_get(a,b,c,d) DBGetContactSetting(a,b,c,d) + +#define db_byte_set(a,b,c,d) DBWriteContactSettingByte(a,b,c,d) +#define db_word_set(a,b,c,d) DBWriteContactSettingWord(a,b,c,d) +#define db_dword_set(a,b,c,d) DBWriteContactSettingDword(a,b,c,d) +#define db_string_set(a,b,c,d) DBWriteContactSettingString(a,b,c,d) + +#define db_unset(a,b,c) DBDeleteContactSetting(a,b,c); + +#ifdef _DEBUG + #define DBGetContactSettingByte(a,b,c,d) DBGetContactSettingByte_Helper(a,b,c,d,__FILE__,__LINE__) + #define DBGetContactSettingWord(a,b,c,d) DBGetContactSettingWord_Helper(a,b,c,d,__FILE__,__LINE__) + #define DBGetContactSettingDword(a,b,c,d) DBGetContactSettingDword_Helper(a,b,c,d,__FILE__,__LINE__) + #define DBGetContactSetting(a,b,c,d) DBGetContactSetting_Helper(a,b,c,d,__FILE__,__LINE__) + #define DBGetContactSettingString(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,__FILE__,__LINE__,DBVT_ASCIIZ) + #define DBGetContactSettingWString(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,__FILE__,__LINE__,DBVT_WCHAR) + #define DBGetContactSettingUTF8String(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,__FILE__,__LINE__,DBVT_UTF8) +#else + #define DBGetContactSettingByte(a,b,c,d) DBGetContactSettingByte_Helper(a,b,c,d) + #define DBGetContactSettingWord(a,b,c,d) DBGetContactSettingWord_Helper(a,b,c,d) + #define DBGetContactSettingDword(a,b,c,d) DBGetContactSettingDword_Helper(a,b,c,d) + #define DBGetContactSetting(a,b,c,d) DBGetContactSetting_Helper(a,b,c,d) + #define DBGetContactSettingString(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,DBVT_ASCIIZ) + #define DBGetContactSettingWString(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,DBVT_WCHAR) + #define DBGetContactSettingUTF8String(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,DBVT_UTF8) +#endif + +#ifdef _UNICODE +#define DBGetContactSettingTString DBGetContactSettingWString +#else +#define DBGetContactSettingTString DBGetContactSettingString +#endif + +#define db_msg_dbg(s) MessageBoxA(0,(s),"",0); + +/* Deprecated & bizarre aliases */ +#define DBGetContactSettingStringUtf DBGetContactSettingUTF8String +#define DBWriteContactSettingStringUtf DBWriteContactSettingUTF8String +#ifdef _DEBUG + #define DBGetContactSettingW(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,__FILE__,__LINE__,0) +#else + #define DBGetContactSettingW(a,b,c,d) DBGetContactSettingString_Helper(a,b,c,d,0) +#endif + +#ifdef _DEBUG +#include +#endif + +__inline static int DBGetContactSettingByte_Helper(HANDLE hContact, const char *szModule, const char *szSetting, int errorValue +#ifdef _DEBUG + ,const char *szFile, const int nLine +#endif +) +{ + DBVARIANT dbv; + DBCONTACTGETSETTING cgs; + + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=&dbv; + if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs)) + return errorValue; +#ifdef _DEBUG + if(dbv.type!=DBVT_BYTE) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d for %s/%s not a byte, return: %d",szFile,nLine,szModule,szSetting,dbv.type); + buf[sizeof(buf)-1]=0; + db_msg_dbg(buf); + } +#endif + return dbv.bVal; +} + +__inline static int DBGetContactSettingWord_Helper(HANDLE hContact,const char *szModule,const char *szSetting,int errorValue +#ifdef _DEBUG + ,const char *szFile, const int nLine +#endif +) +{ + DBVARIANT dbv; + DBCONTACTGETSETTING cgs; + + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=&dbv; + if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs)) + return errorValue; +#ifdef _DEBUG + if(dbv.type!=DBVT_WORD) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d for %s/%s not a word, return: %d",szFile,nLine,szModule,szSetting,dbv.type); + buf[sizeof(buf)-1]=0; + db_msg_dbg(buf); + } +#endif + return dbv.wVal; +} + +__inline static DWORD DBGetContactSettingDword_Helper(HANDLE hContact,const char *szModule, const char *szSetting, DWORD errorValue +#ifdef _DEBUG + ,const char *szFile, const int nLine +#endif +) +{ + DBVARIANT dbv; + DBCONTACTGETSETTING cgs; + + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=&dbv; + if(CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs)) + return errorValue; +#ifdef _DEBUG + if(dbv.type!=DBVT_DWORD) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d for %s/%s not a dword, return: %d",szFile,nLine,szModule,szSetting,dbv.type); + buf[sizeof(buf)-1]=0; + db_msg_dbg(buf); + } +#endif + return dbv.dVal; +} + +__inline static INT_PTR DBGetContactSetting_Helper(HANDLE hContact,const char *szModule,const char *szSetting,DBVARIANT *dbv +#if defined(_DEBUG) + ,const char *szFile, const int nLine +#endif +) +{ + INT_PTR rc; + DBCONTACTGETSETTING cgs; + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=dbv; + + rc=CallService(MS_DB_CONTACT_GETSETTING,(WPARAM)hContact,(LPARAM)&cgs); +#if defined(_DEBUG) && defined(DBCHECKSETTINGS) + if (rc != 0) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d failed to fetch %s/%s",szFile,nLine,szModule,szSetting); + db_msg_dbg(buf); + } +#endif + return rc; +} + +__inline static INT_PTR DBGetContactSettingString_Helper(HANDLE hContact,const char *szModule,const char *szSetting,DBVARIANT *dbv, +#if defined(_DEBUG) + const char *szFile, const int nLine, +#endif + const int nType) +{ + INT_PTR rc; + DBCONTACTGETSETTING cgs; + cgs.szModule=szModule; + cgs.szSetting=szSetting; + cgs.pValue=dbv; + dbv->type=(BYTE)nType; + + rc=CallService(MS_DB_CONTACT_GETSETTING_STR,(WPARAM)hContact,(LPARAM)&cgs); +#if defined(_DEBUG) && defined(DBCHECKSETTINGS) + if (rc != 0) { + char buf[128]; + _snprintf(buf,sizeof(buf),"%s:%d failed to fetch %s/%s",szFile,nLine,szModule,szSetting); + db_msg_dbg(buf); + } +#endif + return rc; +} + +__inline static INT_PTR DBFreeVariant(DBVARIANT *dbv) +{ + return CallService(MS_DB_CONTACT_FREEVARIANT,0,(LPARAM)dbv); +} + +__inline static char *DBGetString(HANDLE hContact,const char *szModule,const char *szSetting) +{ + char *str=NULL; + DBVARIANT dbv={0}; + DBGetContactSettingString(hContact,szModule,szSetting,&dbv); + if(dbv.type==DBVT_ASCIIZ) + str=mir_strdup(dbv.pszVal); + DBFreeVariant(&dbv); + return str; +} + +#define DBGetStringA DBGetString + +__inline static wchar_t *DBGetStringW(HANDLE hContact,const char *szModule,const char *szSetting) +{ + wchar_t *str=NULL; + DBVARIANT dbv={0}; + DBGetContactSettingWString(hContact,szModule,szSetting,&dbv); + if(dbv.type==DBVT_WCHAR) + str=mir_wstrdup(dbv.pwszVal); + DBFreeVariant(&dbv); + return str; +} + +#ifdef _UNICODE +#define DBGetStringT DBGetStringW +#else +#define DBGetStringT DBGetString +#endif + +__inline static INT_PTR DBDeleteContactSetting(HANDLE hContact,const char *szModule,const char *szSetting) +{ + DBCONTACTGETSETTING cgs; + cgs.szModule=szModule; + cgs.szSetting=szSetting; + return CallService(MS_DB_CONTACT_DELETESETTING,(WPARAM)hContact,(LPARAM)&cgs); +} + +__inline static INT_PTR DBWriteContactSettingByte(HANDLE hContact,const char *szModule,const char *szSetting,BYTE val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_BYTE; + cws.value.bVal=val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingWord(HANDLE hContact,const char *szModule,const char *szSetting,WORD val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_WORD; + cws.value.wVal=val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingDword(HANDLE hContact,const char *szModule,const char *szSetting,DWORD val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_DWORD; + cws.value.dVal=val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingString(HANDLE hContact,const char *szModule,const char *szSetting,const char *val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_ASCIIZ; + cws.value.pszVal=(char*)val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingWString(HANDLE hContact,const char *szModule,const char *szSetting,const WCHAR *val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_WCHAR; + cws.value.pwszVal=(WCHAR*)val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +#ifdef _UNICODE +#define DBWriteContactSettingTString DBWriteContactSettingWString +#else +#define DBWriteContactSettingTString DBWriteContactSettingString +#endif + +__inline static INT_PTR DBWriteContactSettingUTF8String(HANDLE hContact,const char *szModule,const char *szSetting,const char *val) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_UTF8; + cws.value.pszVal=(char*)val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +__inline static INT_PTR DBWriteContactSettingBlob(HANDLE hContact,const char *szModule,const char *szSetting,void *val,unsigned len) +{ + DBCONTACTWRITESETTING cws; + + cws.szModule=szModule; + cws.szSetting=szSetting; + cws.value.type=DBVT_BLOB; + cws.value.cpbVal = (WORD)len; + cws.value.pbVal=(unsigned char*)val; + return CallService(MS_DB_CONTACT_WRITESETTING,(WPARAM)hContact,(LPARAM)&cws); +} + +/* inlined range tolerate versions */ + +__inline static BYTE DBGetContactSettingRangedByte(HANDLE hContact, const char *szModule, const char *szSetting, BYTE errorValue, BYTE minValue, BYTE maxValue) { + BYTE bVal = (BYTE)DBGetContactSettingByte(hContact, szModule, szSetting, errorValue); + + if (bVal < minValue || bVal > maxValue) { +#ifdef _DEBUG + char szBuf[MAX_PATH]; + _snprintf(szBuf,sizeof(szBuf),"(%s:%s) not in range of %d..%d",szModule,szSetting,minValue,maxValue); + szBuf[sizeof(szBuf)-1]=0; + MessageBoxA(0,szBuf,"DBGetContactSettingRangedByte failed",MB_ICONERROR); +#endif + return errorValue; + } + return bVal; +} + +__inline static WORD DBGetContactSettingRangedWord(HANDLE hContact, const char *szModule, const char *szSetting, WORD errorValue, WORD minValue, WORD maxValue) { + WORD wVal = (WORD)DBGetContactSettingWord(hContact, szModule, szSetting, errorValue); + + if (wVal < minValue || wVal > maxValue) { +#ifdef _DEBUG + char szBuf[MAX_PATH]; + _snprintf(szBuf,sizeof(szBuf),"(%s:%s) not in range of %d..%d",szModule,szSetting,minValue,maxValue); + szBuf[sizeof(szBuf)-1]=0; + MessageBoxA(0,szBuf,"DBGetContactSettingRangedWord failed",MB_ICONERROR); +#endif + return errorValue; + } + return wVal; +} + +__inline static DWORD DBGetContactSettingRangedDword(HANDLE hContact, const char *szModule, const char *szSetting, DWORD errorValue, DWORD minValue, DWORD maxValue) { + DWORD dVal = DBGetContactSettingDword(hContact, szModule, szSetting, errorValue); + + if (dVal < minValue || dVal > maxValue) { +#ifdef _DEBUG + char szBuf[MAX_PATH]; + _snprintf(szBuf,sizeof(szBuf),"(%s:%s) not in range of %d..%d",szModule,szSetting,minValue,maxValue); + szBuf[sizeof(szBuf)-1]=0; + MessageBoxA(0,szBuf,"DBGetContactSettingRangedDword failed",MB_ICONERROR); +#endif + return errorValue; + } + return dVal; +} + +#endif + +#endif // M_DATABASE_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_langpack.h b/plugins/!NotAdopted/WinPopup/sdk/m_langpack.h new file mode 100644 index 0000000000..a903313cb8 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_langpack.h @@ -0,0 +1,114 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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_LANGPACK_H__ +#define M_LANGPACK_H__ + +#define LANG_UNICODE 0x1000 + +//translates a single string into the user's local language v0.1.1.0+ +//wParam=0 +//lParam=(LPARAM)(const char*)szEnglish +//returns a pointer to the localised string. If there is no known translation +//it will return szEnglish. The return value does not need to be freed in any +//way +//Note that the Translate() macro as defined below will crash plugins that are +//loaded into Miranda 0.1.0.1 and earlier. If anyone's actually using one of +//these versions, I pity them. +#define MS_LANGPACK_TRANSLATESTRING "LangPack/TranslateString" +#define Translate(s) ((char*)CallService(MS_LANGPACK_TRANSLATESTRING,0,(LPARAM)(s))) +#define TranslateW(s) ((WCHAR*)CallService(MS_LANGPACK_TRANSLATESTRING,LANG_UNICODE,(LPARAM)(s))) +#ifdef _UNICODE + #define TranslateT(s) TranslateW(_T(s)) + #define TranslateTS(s) TranslateW(s) +#else + #define TranslateT(s) Translate(s) + #define TranslateTS(s) Translate(s) +#endif + +// If you're storing some string for calling later-on Translate or using it +// with an API call that does translation automatically marked with +// [TRANSLATED-BY-CORE] please wrap it with one of LPGEN macros in order to +// generate proper language pack. +#define LPGEN(s) s +#define LPGENW(s) L ## s +#ifdef _UNICODE + #define LPGENT(s) _T(s) +#else + #define LPGENT(s) s +#endif +//Those macros do NOTHING. They are just markers for lpgen.pl. + +//translates a dialog into the user's local language v0.1.1.0+ +//wParam=0 +//lParam=(LPARAM)(LANGPACKTRANSLATEDIALOG*)&lptd +//returns 0 on success, nonzero on failure +//This service only knows about the following controls: +//Window titles, STATIC, EDIT, Hyperlink, BUTTON +typedef struct { + int cbSize; + DWORD flags; + HWND hwndDlg; + const int *ignoreControls; //zero-terminated list of control IDs *not* to + //translate +} LANGPACKTRANSLATEDIALOG; +#define LPTDF_NOIGNOREEDIT 1 //translate all edit controls. By default + //non-read-only edit controls are not translated +#define LPTDF_NOTITLE 2 //do not translate the title of the dialog + +#define MS_LANGPACK_TRANSLATEDIALOG "LangPack/TranslateDialog" +__inline static INT_PTR TranslateDialogDefault(HWND hwndDlg) +{ + LANGPACKTRANSLATEDIALOG lptd; + lptd.cbSize=sizeof(lptd); + lptd.flags=0; + lptd.hwndDlg=hwndDlg; + lptd.ignoreControls=NULL; + return CallService(MS_LANGPACK_TRANSLATEDIALOG,0,(LPARAM)&lptd); +} + +//translates a menu into the user's local language v0.1.1.0+ +//wParam=(WPARAM)(HMENU)hMenu +//lParam=0 +//returns 0 on success, nonzero on failure +#define MS_LANGPACK_TRANSLATEMENU "LangPack/TranslateMenu" + +//returns the codepage used in the language pack v0.4.3.0+ +//wParam=0 +//lParam=0 +//returns the codepage stated in the langpack, or CP_ACP if no langpack is present +#define MS_LANGPACK_GETCODEPAGE "LangPack/GetCodePage" + +//returns the locale id associated with the language pack v0.4.3.0+ +//wParam=0 +//lParam=0 +//returns the Windows locale id stated in the langpack, or LOCALE_USER_DEFAULT if no langpack is present +#define MS_LANGPACK_GETLOCALE "LangPack/GetLocale" + +//returns the strdup/wcsdup of lparam according to the langpack v0.4.3.0+ +//wParam=0 +//lParam=(LPARAM)(char*)source string +//returns a string converted from char* to TCHAR* using the langpack codepage. +//This string should be freed using mir_free() then +#define MS_LANGPACK_PCHARTOTCHAR "LangPack/PcharToTchar" +#endif // M_LANGPACK_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_netlib.h b/plugins/!NotAdopted/WinPopup/sdk/m_netlib.h new file mode 100644 index 0000000000..086ca25d02 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_netlib.h @@ -0,0 +1,832 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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_NETLIB_H__ +#define M_NETLIB_H__ 1 + +#include "m_utils.h" + +//this module was created in 0.1.2.2 +//All error codes are returned via GetLastError() (or WSAGetLastError(): +//they're the same). +//This module is thread-safe where it is sensible for it to be so. This +//basically means that you can call anything from any thread, but don't try +//to predict what will happen if you try to recv() on the same connection from +//two different threads at the same time. +//Note that because the vast majority of the routines in this module return +//a pointer, I have decided to diverge from the rest of Miranda and go with +//the convention that functions return false on failure and nonzero on success. + +struct NETLIBHTTPREQUEST_tag; +typedef struct NETLIBHTTPREQUEST_tag NETLIBHTTPREQUEST; +struct NETLIBOPENCONNECTION_tag; +typedef struct NETLIBOPENCONNECTION_tag NETLIBOPENCONNECTION; + +//Initialises the netlib for a set of connections +//wParam=0 +//lParam=(LPARAM)(NETLIBUSER*)&nu +//Returns a HANDLE to be used for future netlib calls, NULL on failure +//NOTE: Netlib is loaded after any plugins, so you need to wait until +// ME_SYSTEM_MODULESLOADED before calling this function +//Netlib settings are stored under the module szSettingsModule +//All netlib settings being with "NL". +//The default settings for registered users that don't have any settings stored +//in the database are the same as those displayed by the page +//of the netlib options page. +//See notes below this function for the behaviour of HTTP gateways +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, ERROR_DUP_NAME +typedef int (*NETLIBHTTPGATEWAYINITPROC)(HANDLE hConn,NETLIBOPENCONNECTION *nloc,NETLIBHTTPREQUEST *nlhr); +typedef int (*NETLIBHTTPGATEWAYBEGINPROC)(HANDLE hConn,NETLIBOPENCONNECTION *nloc); +typedef int (*NETLIBHTTPGATEWAYWRAPSENDPROC)(HANDLE hConn,PBYTE buf,int len,int flags,MIRANDASERVICE pfnNetlibSend); +typedef PBYTE (*NETLIBHTTPGATEWAYUNWRAPRECVPROC)(NETLIBHTTPREQUEST *nlhr,PBYTE buf,int len,int *outBufLen,void *(*NetlibRealloc)(void*,size_t)); +typedef struct { + int cbSize; + char *szSettingsModule; //used for db settings and log + union { + char *szDescriptiveName; //used in options dialog, already translated + TCHAR *ptszDescriptiveName; + }; + DWORD flags; + char *szHttpGatewayHello; + char *szHttpGatewayUserAgent; //can be NULL to send no user-agent, also used by HTTPS proxies + NETLIBHTTPGATEWAYINITPROC pfnHttpGatewayInit; + NETLIBHTTPGATEWAYBEGINPROC pfnHttpGatewayBegin; //can be NULL if no beginning required + NETLIBHTTPGATEWAYWRAPSENDPROC pfnHttpGatewayWrapSend; //can be NULL if no wrapping required + NETLIBHTTPGATEWAYUNWRAPRECVPROC pfnHttpGatewayUnwrapRecv; //can be NULL if no wrapping required + int minIncomingPorts; //only if NUF_INCOMING. Will be used for validation of user input. +} NETLIBUSER; +#define NUF_INCOMING 0x01 //binds incoming ports +#define NUF_OUTGOING 0x02 //makes outgoing plain connections +#define NUF_HTTPGATEWAY 0x04 //can use HTTP gateway for plain sockets. ???HttpGateway* are valid. Enables the HTTP proxy option in options. +#define NUF_NOOPTIONS 0x08 //don't create an options page for this. szDescriptiveName is never used. +#define NUF_HTTPCONNS 0x10 //at least some connections are made for HTTP communication. Enables the HTTP proxy option in options. +#define NUF_NOHTTPSOPTION 0x20 //disable the HTTPS proxy option in options. Use this if all communication is HTTP. +#define NUF_UNICODE 0x40 //if set ptszDescriptiveName points to Unicode, otherwise it points to ANSI string +#define MS_NETLIB_REGISTERUSER "Netlib/RegisterUser" + +#if defined(_UNICODE) + #define NUF_TCHAR NUF_UNICODE +#else + #define NUF_TCHAR 0 +#endif + + + +//Assign a Netlib user handle a set of dynamic HTTP headers to be used with all +// +//HTTP connections that enable the HTTP-use-sticky headers flag. +//The headers persist until cleared with lParam=NULL. +// +//All memory should be allocated by the caller using malloc() from MS_SYSTEM_GET_MMI +//Once it has passed to Netlib, Netlib is the owner of it, the caller should not refer to the memory +//In any way after this point. +// +//wParam=(WPARAM)hNetLibUser +//lParam=(LPARAM)(char*)szHeaders +// +//NOTE: The szHeaders parameter should be a NULL terminated string following the HTTP header syntax. +//This string will be injected verbatim, thus the user should be aware of setting strings that are not +//headers. This service is NOT THREAD SAFE, only a single thread is expected to set the headers and a single +//thread reading the pointer internally, stopping race conditions and mutual exclusion don't happen. +// +//Version 0.3.2a+ (2003/10/27) +// +#define MS_NETLIB_SETSTICKYHEADERS "Netlib/SetStickyHeaders" + +/* Notes on HTTP gateway usage +When a connection is initiated through an HTTP proxy using +MS_NETLIB_OPENCONNECTION, netlib will GET nlu.szHttpGatewayHello and read +the replied headers. Once this succeeds nlu.pfnHttpGatewayInit will be called +with a valid handle to the connection, the NETLIBOPENCONNECTION structure that +MS_NETLIB_OPENCONNECTION was called with, and the replied HTTP headers as its +parameters. This function is responsible for recving and parsing the data then +calling MS_NETLIB_SETHTTPPROXYINFO with the appropriate information. +nlu.pfnHttpGatewayInit should return nonzero on success. If it returns zero +then the entire connection attempt will return signalling failure. If your +function needs to return an error code it can do so via SetLastError(). +If nlu.pfnHttpGatewayInit returns success without having called +MS_NETLIB_SETHTTPPROXYINFO then the connection attempt will fail anyway. +If you need more fine-tuned control over the GET/POST URLs than just appending +sequence numbers you can call MS_NETLIB_SETHTTPPROXYINFO from within your +wrap/unwrap functions (see below). + +Just prior to MS_NETLIB_OPENCONNECTION returning nlu.pfnHttpGatewayBegin is +called with the handle to the connection and the NETLIBOPENCONNECTION structure +as its parameters. This is for gateways that need special non-protocol +initialisation. If you do send any packets in this function, you probably want +to remember to use the MSG_NOHTTPGATEWAYWRAP flag. This function pointer can be +NULL if this functionality isn't needed. This function must return nonzero on +success. If it fails the connect attempt will return failure without changing +LastError. + +Whenever MS_NETLIB_SEND is called on a connection through an HTTP proxy and +the MSG_NOHTTPGATEWAYWRAP flags is not set and nlu.pfnHttpGatewayWrapSend is +not NULL, nlu.pfnHttpGatewayWrapSend will be called *instead* of sending the +data. It is this function's responsibility to wrap the sending data +appropriately for transmission and call pfnNetlibSend to send it again. +The flags parameter to nlu.pfnHttpGatewayWrapSend should be passed straight +through to the pfnNetlibSend call. It has already been ORed with +MSG_NOHTTPGATEWAYWRAP. nlu.pfnHttpGatewayWrapSend should return the a +number of the same type as MS_NETLIB_SEND, ie the number of bytes sent or +SOCKET_ERROR. The number of wrapping bytes should be subtracted so that the +return value appears as if the proxy wasn't there. +pfnNetlibSend() is identical to CallService(MS_NETLIB_SEND,...) but it's +quicker to call using this pointer than to do the CallService() lookup again. + +Whenever an HTTP reply is received inside MS_NETLIB_RECV the headers and data +are read into memory. If the headers indicate success then the data is passed +to nlu.pfnHttpGatewayUnwrapRecv (if it's non-NULL) for processing. This +function should remove (and do other processing if necessary) all HTTP proxy +specific headers and return a pointer to the buffer whose size is returned in +*outBufLen. If the buffer needs to be resized then NetlibRealloc() should be +used for that purpose, *not* your own CRT's realloc(). NetlibRealloc() behaves +identically to realloc() so it's possible to free the original buffer and +create a new one if that's the most sensible way to write your parser. +If errors are encountered you should SetLastError() and return NULL; +MS_NETLIB_RECV will return SOCKET_ERROR. If the passed buffer unwraps to +contain no actual data you should set *outBufLen to 0 but make sure you return +some non-NULL buffer that can be freed. + +When you call MS_NETLIB_SEND or MS_NETLIB_RECV from any of these functions, you +should use the MSG_DUMPPROXY flag so that the logging is neat. +*/ + +//Gets the user-configured settings for a netlib user +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBUSERSETTINGS*)&nlus +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//The pointers referred to in the returned struct will remain valid until +//the hUser handle is closed, or until the user changes the settings in the +//options page, so it's best not to rely on them for too long. +//Errors: ERROR_INVALID_PARAMETER +#define PROXYTYPE_SOCKS4 1 +#define PROXYTYPE_SOCKS5 2 +#define PROXYTYPE_HTTP 3 +#define PROXYTYPE_HTTPS 4 +#define PROXYTYPE_IE 5 +typedef struct { + int cbSize; // to be filled in before calling + int useProxy; // 1 or 0 + int proxyType; // a PROXYTYPE_ + char *szProxyServer; // can be NULL + int wProxyPort; // host byte order + int useProxyAuth; // 1 or 0. Always 0 for SOCKS4 + char *szProxyAuthUser; // can be NULL, always used by SOCKS4 + char *szProxyAuthPassword; // can be NULL + int useProxyAuthNtlm; // 1 or 0, only used by HTTP, HTTPS + int dnsThroughProxy; // 1 or 0 + int specifyIncomingPorts; // 1 or 0 + char *szIncomingPorts; // can be NULL. Of form "1024-1050,1060-1070,2000" + int specifyOutgoingPorts; // 0.3.3a+ + char *szOutgoingPorts; // 0.3.3a+ + int enableUPnP; // 0.6.1+ only for NUF_INCOMING + int validateSSL; +} NETLIBUSERSETTINGS; +#define MS_NETLIB_GETUSERSETTINGS "Netlib/GetUserSettings" + +//Changes the user-configurable settings for a netlib user +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBUSERSETTINGS*)&nlus +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This function is only really useful for people that specify NUF_NOOPTIONS +//and want to create their own options. +//Even if a setting is not active (eg szProxyAuthPassword when useProxyAuth is +//zero) that settings is still set for use in the options dialog. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_SETUSERSETTINGS "Netlib/SetUserSettings" + +//Closes a netlib handle +//wParam=(WPARAM)(HANDLE)hNetlibHandle +//lParam=0 +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This function should be called on all handles returned by netlib functions +//once you are done with them. If it's called on a socket-type handle, the +//socket will be closed. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_CLOSEHANDLE "Netlib/CloseHandle" +__inline static INT_PTR Netlib_CloseHandle(HANDLE h) {return CallService(MS_NETLIB_CLOSEHANDLE,(WPARAM)h,0);} + +//Open a port and wait for connections on it +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBBIND*)&nlb +//Returns a HANDLE on success, NULL on failure +//hUser should have been returned by MS_NETLIB_REGISTERUSER +//This function does the equivalent of socket(), bind(), getsockname(), +//listen(), accept() +//Internally this function creates a new thread which waits around in accept() +//for new connections. When one is received it calls nlb.pfnNewConnection *from +//this new thread* and then loops back to wait again. +//Close the returned handle to end the thread and close the open port. +//Errors: ERROR_INVALID_PARAMETER, any returned by socket() or bind() or +// listen() or getsockname() +// +// Notes: +// +// During development of 0.3.1a+ (2003/07/04) passing wPort != 0 +// will result in an attempt to bind on the port given in wPort +// if this port is taken then you will get an error, so be sure to check +// for such conditions. +// +// passing wPort != 0 is for people who need to open a set port for +// daemon activities, usually passing wPort==0 is what you want and +// will result in a free port given by the TCP/IP socket layer and/or +// seeded from the user selected port ranges. +// +// also note that wPort if != 0, will have be converted to network byte order +// +/* pExtra was added during 0.3.4+, prior its just two args, since we use the cdecl convention +it shouldnt matter */ + +#define NETLIBBIND_SIZEOF_V1 16 // sizeof(NETLIBBIND) prior to 0.3.4+ (2004/08/05) +#define NETLIBBIND_SIZEOF_V2 20 // sizeof(NETLIBBIND) prior to 0.6+ (2006/07/03) + +typedef void (*NETLIBNEWCONNECTIONPROC_V2)(HANDLE hNewConnection,DWORD dwRemoteIP, void * pExtra); +typedef void (*NETLIBNEWCONNECTIONPROC)(HANDLE hNewConnection,DWORD dwRemoteIP); +/* This is NETLIBBIND prior to 2004/08/05+, DONT use this anymore unless you want to work +with older cores, pExtra isnt available on older cores and never will be - for a period of time, the ABI +for this service was broken and older NETLIBBINDs were not supported, if NULL is returned and the +argument is good, then tell the user to upgrade to the latest CVS. + +The older structure was used til around 2004/08/05 */ +typedef struct { + int cbSize; + NETLIBNEWCONNECTIONPROC pfnNewConnection; + //function to call when there's a new connection. Params are: the + //new connection, IP of remote machine (host byte order) + DWORD dwInternalIP; //set on return, host byte order + WORD wPort; //set on return, host byte order +} NETLIBBINDOLD; + +typedef struct { + int cbSize; + union { // new code should use V2 + NETLIBNEWCONNECTIONPROC pfnNewConnection; + NETLIBNEWCONNECTIONPROC_V2 pfnNewConnectionV2; + }; + //function to call when there's a new connection. Params are: the + //new connection, IP of remote machine (host byte order) + DWORD dwInternalIP; //set on return, host byte order + WORD wPort; //set on return, host byte order + void * pExtra; //argument is sent to callback, added during 0.3.4+ + DWORD dwExternalIP; //set on return, host byte order + WORD wExPort; //set on return, host byte order +} NETLIBBIND; +#define MS_NETLIB_BINDPORT "Netlib/BindPort" + +//Open a connection +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBOPENCONNECTION*)&nloc +//Returns a HANDLE to the new connection on success, NULL on failure +//hUser must have been returned by MS_NETLIB_REGISTERUSER +//Internally this function is the equivalent of socket(), gethostbyname(), +//connect() +//If NLOCF_HTTP is set and hUser is configured for an HTTP or HTTPS proxy then +//this function will connect() to the proxy server only, without performing any +//initialisation conversation. +//If hUser is configured for an HTTP proxy and does not support HTTP gateways +//and you try to open a connection without specifying NLOCF_HTTP then this +//function will first attempt to open an HTTPS connection, if that fails it +//will try a direct connection, if that fails it will return failure with the +//error from the connect() during the direct connection attempt. +//Errors: ERROR_INVALID_PARAMETER, any returned by socket(), gethostbyname(), +// connect(), MS_NETLIB_SEND, MS_NETLIB_RECV, select() +// ERROR_TIMEOUT (during proxy communication) +// ERROR_BAD_FORMAT (very invalid proxy reply) +// ERROR_ACCESS_DENIED (by proxy) +// ERROR_CONNECTION_UNAVAIL (socks proxy can't connect to identd) +// ERROR_INVALID_ACCESS (proxy refused identd auth) +// ERROR_INVALID_DATA (proxy returned invalid code) +// ERROR_INVALID_ID_AUTHORITY (proxy requires use of auth method that's not supported) +// ERROR_GEN_FAILURE (socks5/https general failure) +// ERROR_CALL_NOT_IMPLEMENTED (socks5 command not supported) +// ERROR_INVALID_ADDRESS (socks5 address type not supported) +// HTTP: anything from nlu.pfnHttpGatewayInit, nlu.pfnHttpGatewayBegin, +// MS_NETLIB_SENDHTTPREQUEST or MS_NETLIB_RECVHTTPHEADERS +#define NLOCF_HTTP 0x0001 //this connection will be used for HTTP communications. If configured for an HTTP/HTTPS proxy the connection is opened as if there was no proxy. +#define NLOCF_STICKYHEADERS 0x0002 //this connection should send the sticky headers associated with NetLib user apart of any HTTP request +#define NLOCF_V2 0x0004 //this connection understands the newer structure, newer cbSize isnt enough +#define NLOCF_UDP 0x0008 // this connection is UDP +#define NLOCF_SSL 0x0010 // this connection is SSL +#define NLOCF_HTTPGATEWAY 0x0020 // this connection is HTTP Gateway + +/* Added during 0.4.0+ development!! (2004/11/29) prior to this, connect() blocks til a connection is made or +a hard timeout is reached, this can be anywhere between 30-60 seconds, and it stops Miranda from unloading whilst +this is attempted, clearing sucking - so now you can set a timeout of any value, there is still a hard limit which is +always reached by Windows, If a timeout occurs, or Miranda is exiting then you will get ERROR_TIMEOUT as soon as possible. +*/ +#define NETLIBOPENCONNECTION_V1_SIZE 16 /* old sizeof() is 14 bytes, but there is padding of 2 bytes */ +struct NETLIBOPENCONNECTION_tag { + int cbSize; + const char *szHost; //can contain the string representation of an IP + WORD wPort; //host byte order + DWORD flags; + unsigned int timeout; + /* optional, called in the context of the thread that issued the attempt, if it returns 0 the connection attempt is + stopped, the remaining timeout value can also be adjusted */ + int (*waitcallback) (unsigned int * timeout); +}; +//typedef struct NETLIBOPENCONNECTION_tag NETLIBOPENCONNECTION; //(above for reasons of forward referencing) +#define MS_NETLIB_OPENCONNECTION "Netlib/OpenConnection" + +//Sets the required information for an HTTP proxy connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBHTTPPROXYINFO*)&nlhpi +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This function is designed to be called from within pfnHttpGatewayInit +//See notes below MS_NETLIB_REGISTERUSER. +//Errors: ERROR_INVALID_PARAMETER +#define NLHPIF_USEGETSEQUENCE 0x0001 //append sequence numbers to GET requests +#define NLHPIF_USEPOSTSEQUENCE 0x0002 //append sequence numbers to POST requests +#define NLHPIF_GETPOSTSAMESEQUENCE 0x0004 //GET and POST use the same sequence +#define NLHPIF_HTTP11 0x0008 //HTTP 1.1 proxy +typedef struct { + int cbSize; + DWORD flags; + char *szHttpPostUrl; + char *szHttpGetUrl; + int firstGetSequence,firstPostSequence; +#if MIRANDA_VER >= 0x0900 + int combinePackets; +#endif +} NETLIBHTTPPROXYINFO; +#define MS_NETLIB_SETHTTPPROXYINFO "Netlib/SetHttpProxyInfo" + +//Gets the SOCKET associated with a netlib handle +//wParam=(WPARAM)(HANDLE)hNetlibHandle +//lParam=0 +//Returns the SOCKET on success, INVALID_SOCKET on failure +//hNetlibHandle should have been returned by MS_NETLIB_BINDPORT or +//MS_NETLIB_OPENCONNECTION only. +//Be careful how you use this socket because you might be connected via an +//HTTP proxy in which case calling send() or recv() will totally break things. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_GETSOCKET "Netlib/GetSocket" + +//URL-encode a string for x-www-form-urlencoded (and other) transmission +//wParam=0 +//lParam=(LPARAM)(const char *)pszString +//Returns a char* containing the new string. This must be freed with +//HeapFree(GetProcessHeap(),0,pszReturnString) when you're done with it. +//Returns NULL on error. +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY +#define MS_NETLIB_URLENCODE "Netlib/UrlEncode" + +//Base64 decode a string. See rfc1421. +//wParam=0 +//lParam=(LPARAM)(NETLIBBASE64*)&nlb64 +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//nlb64.pszEncoded and nlb64.cchEncoded contain the input string and its length +//(excluding terminating zero). +//nlb64.pbDecoded and nlb64.cbDecoded contain the buffer in which to put the +//output and the length of this buffer. The maximum output size for a given +//input is available from the macro Netlib_GetBase64DecodedBufferSize() below. +//On return nlb64.cbDecoded is set to the actual length of the decoded data. +//Errors: ERROR_INVALID_PARAMETER, ERROR_INVALID_DATA, ERROR_BUFFER_OVERFLOW +typedef struct { + char *pszEncoded; + int cchEncoded; + PBYTE pbDecoded; + int cbDecoded; +} NETLIBBASE64; +#define Netlib_GetBase64DecodedBufferSize(cchEncoded) (((cchEncoded)>>2)*3) +#define MS_NETLIB_BASE64DECODE "Netlib/Base64Decode" + +//Base64 encode a string. See rfc1421. +//wParam=0 +//lParam=(LPARAM)(NETLIBBASE64*)&nlb64 +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//nlb64.pbDecoded and nlb64.cbDecoded contain the input buffer and its length +//nlb64.pszEncoded and nlb64.cchEncoded contain the buffer in which to put the +//output and the length of this buffer. The maximum output size for a given +//input is available from the macro Netlib_GetBase64EncodedBufferSize() below. +//nlb64.pszEncoded is terminated with a 0. +//On return nlb64.cchEncoded is set to the actual length of the decoded data, +//excluding the terminating 0. +//Errors: ERROR_INVALID_PARAMETER, ERROR_BUFFER_OVERFLOW +#define Netlib_GetBase64EncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1) +#define MS_NETLIB_BASE64ENCODE "Netlib/Base64Encode" + +//Send an HTTP request over a connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBHTTPREQUEST*)&nlhr +//Returns number of bytes sent on success, SOCKET_ERROR on failure +//hConnection must have been returned by MS_NETLIB_OPENCONNECTION +//Note that if you use NLHRF_SMARTAUTHHEADER and NTLM authentication is in use +//then the full NTLM authentication transaction occurs, comprising sending the +//domain, receiving the challenge, then sending the response. +//nlhr.resultCode and nlhr.szResultDescr are ignored by this function. +//Errors: ERROR_INVALID_PARAMETER, anything returned by MS_NETLIB_SEND +typedef struct { + char *szName; + char *szValue; +} NETLIBHTTPHEADER; + +#define REQUEST_RESPONSE 0 //used by structure returned by MS_NETLIB_RECVHTTPHEADERS +#define REQUEST_GET 1 +#define REQUEST_POST 2 +#define REQUEST_CONNECT 3 +#define REQUEST_HEAD 4 // new in 0.5.1 +#define REQUEST_PUT 5 +#define REQUEST_DELETE 6 + +#define NLHRF_GENERATEHOST 0x00000001 //auto-generate a "Host" header from szUrl +#define NLHRF_REMOVEHOST 0x00000002 //remove any host and/or protocol portion of szUrl before sending it +#define NLHRF_SMARTREMOVEHOST 0x00000004 //removes host and/or protocol from szUrl unless the connection was opened through an HTTP or HTTPS proxy. +#define NLHRF_SMARTAUTHHEADER 0x00000008 //if the connection was opened through an HTTP or HTTPS proxy then send a Proxy-Authorization header if required. +#define NLHRF_HTTP11 0x00000010 //use HTTP 1.1 +#define NLHRF_PERSISTENT 0x00000020 //preserve connection on exit, open connection provided in the nlc field of the reply + //it should be supplied in nlc field of request for reuse or closed if not needed +#define NLHRF_SSL 0x00000040 //use SSL connection +#define NLHRF_NOPROXY 0x00000080 //do not use proxy server +#define NLHRF_REDIRECT 0x00000100 //handle HTTP redirect requests (response 30x), the resulting url provided in szUrl of the response +#define NLHRF_NODUMP 0x00010000 //never dump this to the log +#define NLHRF_NODUMPHEADERS 0x00020000 //don't dump http headers (only useful for POSTs and MS_NETLIB_HTTPTRANSACTION) +#define NLHRF_DUMPPROXY 0x00040000 //this transaction is a proxy communication. For dump filtering only. +#define NLHRF_DUMPASTEXT 0x00080000 //dump posted and reply data as text. Headers are always dumped as text. +#define NLHRF_NODUMPSEND 0x00100000 //do not dump sent message. +struct NETLIBHTTPREQUEST_tag { + int cbSize; + int requestType; //a REQUEST_ + DWORD flags; + char *szUrl; + NETLIBHTTPHEADER *headers; //If this is a POST request and headers + //doesn't contain a Content-Length it'll be added automatically + int headersCount; + char *pData; //data to be sent in POST request. + int dataLength; //must be 0 for REQUEST_GET/REQUEST_CONNECT + int resultCode; + char *szResultDescr; + HANDLE nlc; +}; +//typedef struct NETLIBHTTPREQUEST_tag NETLIBHTTPREQUEST; //(above for reasons of forward referencing) +#define MS_NETLIB_SENDHTTPREQUEST "Netlib/SendHttpRequest" + +//Receive HTTP headers +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=0 +//Returns a pointer to a NETLIBHTTPREQUEST structure on success, NULL on +//failure. +//Call MS_NETLIB_FREEHTTPREQUESTSTRUCT to free this. +//hConnection must have been returned by MS_NETLIB_OPENCONNECTION +//nlhr->pData=NULL and nlhr->dataLength=0 always. The requested data should +//be retrieved using MS_NETLIB_RECV once the header has been parsed. +//If the headers haven't finished within 60 seconds the function returns NULL +//and ERROR_TIMEOUT. +//Errors: ERROR_INVALID_PARAMETER, any from MS_NETLIB_RECV or select() +// ERROR_HANDLE_EOF (connection closed before headers complete) +// ERROR_TIMEOUT (headers still not complete after 60 seconds) +// ERROR_BAD_FORMAT (invalid character or line ending in headers, or first line is blank) +// ERROR_BUFFER_OVERFLOW (each header line must be less than 4096 chars long) +// ERROR_INVALID_DATA (first header line is malformed ("http/[01].[0-9] [0-9]+ .*", or no colon in subsequent line) +#define MS_NETLIB_RECVHTTPHEADERS "Netlib/RecvHttpHeaders" + +//Free the memory used by a NETLIBHTTPREQUEST structure +//wParam=0 +//lParam=(LPARAM)(NETLIBHTTPREQUEST*)pnlhr +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//This should only be called on structures returned by +//MS_NETLIB_RECVHTTPHEADERS or MS_NETLIB_HTTPTRANSACTION. Calling it on an +//arbitrary structure will have disastrous results. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_FREEHTTPREQUESTSTRUCT "Netlib/FreeHttpRequestStruct" + +//Do an entire HTTP transaction +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(NETLIBHTTPREQUEST*)&nlhr +//Returns a pointer to another NETLIBHTTPREQUEST structure on success, NULL on +//failure. +//Call MS_NETLIB_FREEHTTPREQUESTSTRUCT to free this. +//hUser must have been returned by MS_NETLIB_REGISTERUSER +//nlhr.szUrl should be a full HTTP URL. If it does not start with http://, that +//will be assumed (but it's best not to use this fact, for reasons of +//extensibility). +//This function is the equivalent of MS_NETLIB_OPENCONNECTION, +//MS_NETLIB_SENDHTTPREQ, MS_NETLIB_RECVHTTPHEADERS, MS_NETLIB_RECV, +//MS_NETLIB_CLOSEHANDLE +//nlhr.headers will be augmented with the following headers unless they have +//already been set by the caller: +// "Host" (regardless of whether it is requested in nlhr.flags) +// "User-Agent" (of the form "Miranda/0.1.2.2 (alpha)" or "Miranda/0.1.2.2") +// "Content-Length" (for POSTs only. Set to nlhr.dataLength) +//If you do not want to send one of these headers, create a nlhr.headers with +//szValue=NULL. +//In the return value headers, headerCount, pData, dataLength, resultCode and +//szResultDescr are all valid. +//In the return value pData[dataLength]==0 always, as an extra safeguard +//against programming slips. +//Note that the function can succeed (ie not return NULL) yet result in an HTTP +//error code. You should check that resultCode==2xx before proceeding. +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY, anything from the above +// list of functions +#define MS_NETLIB_HTTPTRANSACTION "Netlib/HttpTransaction" + +//Send data over a connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBBUFFER*)&nlb +//Returns the number of bytes sent on success, SOCKET_ERROR on failure +//Errors: ERROR_INVALID_PARAMETER +// anything from send(), nlu.pfnHttpGatewayWrapSend() +// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx) +// anything from socket(), connect(), +// MS_NETLIB_SENDHTTPREQUEST, MS_NETLIB_RECVHTTPHEADERS +//flags: +#define MSG_NOHTTPGATEWAYWRAP 0x010000 //don't wrap the outgoing packet using nlu.pfnHttpGatewayWrapSend +#define MSG_NODUMP 0x020000 //don't dump this packet to the log +#define MSG_DUMPPROXY 0x040000 //this is proxy communiciation. For dump filtering only. +#define MSG_DUMPASTEXT 0x080000 //this is textual data, don't dump as hex +#define MSG_RAW 0x100000 //send as raw data, bypass any HTTP proxy stuff +#define MSG_DUMPSSL 0x200000 //this is SSL traffic. For dump filtering only. +typedef struct { + char *buf; + int len; + int flags; +} NETLIBBUFFER; +#define MS_NETLIB_SEND "Netlib/Send" +static __inline INT_PTR Netlib_Send(HANDLE hConn,const char *buf,int len,int flags) { + NETLIBBUFFER nlb={(char*)buf,len,flags}; + return CallService(MS_NETLIB_SEND,(WPARAM)hConn,(LPARAM)&nlb); +} + +//Receive data over a connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(NETLIBBUFFER*)&nlb +//Returns the number of bytes read on success, SOCKET_ERROR on failure, +//0 if the connection has been closed +//Flags supported: MSG_PEEK, MSG_NODUMP, MSG_DUMPPROXY, MSG_NOHTTPGATEWAYWRAP, +// MSG_DUMPASTEXT, MSG_RAW +//On using MSG_NOHTTPGATEWAYWRAP: Because packets through an HTTP proxy are +// batched and cached and stuff, using this flag is not a guarantee that it +// will be obeyed, and if it is it may even be propogated to future calls +// even if you don't specify it then. Because of this, the flag should be +// considered an all-or-nothing thing: either use it for the entire duration +// of a connection, or not at all. +//Errors: ERROR_INVALID_PARAMETER, anything from recv() +// HTTP proxy: ERROR_GEN_FAILURE (http result code wasn't 2xx) +// ERROR_INVALID_DATA (no Content-Length header in reply) +// ERROR_NOT_ENOUGH_MEMORY (Content-Length very large) +// ERROR_HANDLE_EOF (connection closed before Content-Length bytes recved) +// anything from select(), MS_NETLIB_RECVHTTPHEADERS, +// nlu.pfnHttpGatewayUnwrapRecv, socket(), connect(), +// MS_NETLIB_SENDHTTPREQUEST +#define MS_NETLIB_RECV "Netlib/Recv" +static __inline INT_PTR Netlib_Recv(HANDLE hConn,char *buf,int len,int flags) { + NETLIBBUFFER nlb={buf,len,flags}; + return CallService(MS_NETLIB_RECV,(WPARAM)hConn,(LPARAM)&nlb); +} + +//Determine the status of one or more connections +//wParam=0 +//lParam=(LPARAM)(NETLIBSELECT*)&nls +//Returns the number of ready connections, SOCKET_ERROR on failure, +//0 if the timeout expired. +//All handles passed to this function must have been returned by either +//MS_NETLIB_OPENCONNECTION or MS_NETLIB_BINDPORT. +//The last handle in each list must be followed by either NULL or +//INVALID_HANDLE_VALUE. +//Errors: ERROR_INVALID_HANDLE, ERROR_INVALID_DATA, anything from select() +typedef struct { + int cbSize; + DWORD dwTimeout; //in milliseconds, INFINITE is acceptable + HANDLE hReadConns[FD_SETSIZE+1]; + HANDLE hWriteConns[FD_SETSIZE+1]; + HANDLE hExceptConns[FD_SETSIZE+1]; +} NETLIBSELECT; + +typedef struct { + int cbSize; + DWORD dwTimeout; //in milliseconds, INFINITE is acceptable + HANDLE hReadConns[FD_SETSIZE+1]; + HANDLE hWriteConns[FD_SETSIZE+1]; + HANDLE hExceptConns[FD_SETSIZE+1]; + /* Added in v0.3.3+ */ + BOOL hReadStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */ + BOOL hWriteStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */ + BOOL hExceptStatus[FD_SETSIZE+1]; /* out, [in, expected to be FALSE] */ +} NETLIBSELECTEX; + +#define MS_NETLIB_SELECT "Netlib/Select" +// added in v0.3.3 +#define MS_NETLIB_SELECTEX "Netlib/SelectEx" + +//Shutdown connection +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)0 +//Returns 0 +#define MS_NETLIB_SHUTDOWN "Netlib/Shutdown" +__inline static void Netlib_Shutdown(HANDLE h) {CallService(MS_NETLIB_SHUTDOWN,(WPARAM)h,0);} + +//Create a packet receiver +//wParam=(WPARAM)(HANDLE)hConnection +//lParam=(LPARAM)(int)maxPacketSize +//Returns a HANDLE on success, NULL on failure +//The packet receiver implements the common situation where you have variable +//length packets coming in over a connection and you want to split them up +//in order to handle them. +//The major limitation is that the buffer is created in memory, so you can't +//have arbitrarily large packets. +//Errors: ERROR_INVALID_PARAMETER, ERROR_OUTOFMEMORY +#define MS_NETLIB_CREATEPACKETRECVER "Netlib/CreatePacketRecver" + +//Get the next set of packets from a packet receiver +//wParam=(WPARAM)(HANDLE)hPacketRecver +//lParam=(LPARAM)(NETLIBPACKETRECVER*)&nlpr +//Returns the total number of bytes available in the buffer, 0 if the +//connection was closed, SOCKET_ERROR on error. +//hPacketRecver must have been returned by MS_NETLIB_CREATEPACKETRECVER +//If nlpr.bytesUsed is set to zero and the buffer is already full up to +//maxPacketSize, it is assumed that too large a packet has been received. All +//data in the buffer is discarded and receiving is begun anew. This will +//probably cause alignment problems so if you think this is likely to happen +//then you should deal with it yourself. +//Closing the packet receiver will not close the associated connection, but +//will discard any bytes still in the buffer, so if you intend to carry on +//reading from that connection, make sure you have processed the buffer first. +//This function is the equivalent of a memmove() to remove the first bytesUsed +//from the buffer, select() if dwTimeout is not INFINITE, then MS_NETLIB_RECV. +//Errors: ERROR_INVALID_PARAMETER, ERROR_TIMEOUT, +// anything from select(), MS_NETLIB_RECV +typedef struct { + int cbSize; + DWORD dwTimeout; //fill before calling. In milliseconds. INFINITE is valid + int bytesUsed; //fill before calling. This many bytes are removed from the start of the buffer. Set to 0 on return + int bytesAvailable; //equal to the return value, unless the return value is 0 + int bufferSize; //same as parameter to MS_NETLIB_CREATEPACKETRECVER + BYTE *buffer; //contains the recved data +} NETLIBPACKETRECVER; +#define MS_NETLIB_GETMOREPACKETS "Netlib/GetMorePackets" + +//Add a message to the log (if it's running) +//wParam=(WPARAM)(HANDLE)hUser +//lParam=(LPARAM)(const char *)szMessage +//Returns nonzero on success, 0 on failure (!! this is different to most of the rest of Miranda, but consistent with netlib) +//Do not include a final line ending in szMessage. +//Errors: ERROR_INVALID_PARAMETER +#define MS_NETLIB_LOG "Netlib/Log" + +//Sets a gateway polling timeout interval +//wParam=(WPARAM)(HANDLE)hConn +//lParam=(LPARAM)timeout +//Returns previous timeout value +//Errors: -1 +#define MS_NETLIB_SETPOLLINGTIMEOUT "Netlib/SetPollingTimeout" + +//Makes connection SSL +//wParam=(WPARAM)(HANDLE)hConn +//lParam=(LPARAM)(NETLIBSSL*)&nlssl or null if no certficate validation required +//Returns 0 on failure 1 on success +#define MS_NETLIB_STARTSSL "Netlib/StartSsl" + +typedef struct +{ + int cbSize; + const char *host; //Expected host name + int flags; //Reserved +} NETLIBSSL; + + +//here's a handy piece of code to let you log using printf-style specifiers: +//#include and before including this header in order to +//use it. +#if defined va_start && (defined _STDIO_DEFINED || defined _STDIO_H_) && (!defined NETLIB_NOLOGGING) +static INT_PTR Netlib_Logf(HANDLE hUser,const char *fmt,...) +{ + va_list va; + char szText[1024]; + + __try + { + va_start(va,fmt); + mir_vsnprintf(szText,sizeof(szText),fmt,va); + va_end(va); + return CallService(MS_NETLIB_LOG,(WPARAM)hUser,(LPARAM)szText); + } + __except(EXCEPTION_EXECUTE_HANDLER) {} + return 0; +} +#endif //defined va_start + +///////////////////////////////////////////////////////////////////////////////////////// +// Security providers (0.6+) + +#define NNR_UNICODE 1 + +#ifdef UNICODE +#define NNR_TCHAR 1 +#else +#define NNR_TCHAR 0 +#endif + +// Inits a required security provider. Right now only NTLM is supported +// Returns HANDLE = NULL on error or non-null value on success +#define MS_NETLIB_INITSECURITYPROVIDER "Netlib/InitSecurityProvider" + +static __inline HANDLE Netlib_InitSecurityProvider( char* szProviderName ) +{ + return (HANDLE)CallService( MS_NETLIB_INITSECURITYPROVIDER, 0, (LPARAM)szProviderName ); +} + +typedef struct { + size_t cbSize; + const TCHAR* szProviderName; + const TCHAR* szPrincipal; + unsigned flags; +} + NETLIBNTLMINIT2; + +#define MS_NETLIB_INITSECURITYPROVIDER2 "Netlib/InitSecurityProvider2" + +static __inline HANDLE Netlib_InitSecurityProvider2( const TCHAR* szProviderName, const TCHAR* szPrincipal ) +{ + NETLIBNTLMINIT2 temp = { sizeof(temp), szProviderName, szPrincipal, NNR_TCHAR }; + return (HANDLE)CallService( MS_NETLIB_INITSECURITYPROVIDER2, 0, (LPARAM)&temp ); +} + + +// Destroys a security provider's handle, provided by Netlib_InitSecurityProvider. +// Right now only NTLM is supported +#define MS_NETLIB_DESTROYSECURITYPROVIDER "Netlib/DestroySecurityProvider" + +static __inline void Netlib_DestroySecurityProvider( char* szProviderName, HANDLE hProvider ) +{ + CallService( MS_NETLIB_DESTROYSECURITYPROVIDER, (WPARAM)szProviderName, (LPARAM)hProvider ); +} + +// Returns the NTLM response string. The result value should be freed using mir_free + +typedef struct { + char* szChallenge; + char* userName; + char* password; +} + NETLIBNTLMREQUEST; + +#define MS_NETLIB_NTLMCREATERESPONSE "Netlib/NtlmCreateResponse" + +static __inline char* Netlib_NtlmCreateResponse( HANDLE hProvider, char* szChallenge, char* login, char* psw ) +{ + NETLIBNTLMREQUEST temp = { szChallenge, login, psw }; + return (char*)CallService( MS_NETLIB_NTLMCREATERESPONSE, (WPARAM)hProvider, (LPARAM)&temp ); +} + +typedef struct { + size_t cbSize; + const char* szChallenge; + const TCHAR* szUserName; + const TCHAR* szPassword; + unsigned complete; + unsigned flags; +} + NETLIBNTLMREQUEST2; + +#define MS_NETLIB_NTLMCREATERESPONSE2 "Netlib/NtlmCreateResponse2" + +static __inline char* Netlib_NtlmCreateResponse2( HANDLE hProvider, char* szChallenge, TCHAR* szLogin, TCHAR* szPass, unsigned *complete ) +{ + NETLIBNTLMREQUEST2 temp = { sizeof(temp), szChallenge, szLogin, szPass, 0, NNR_TCHAR }; + char* res = (char*)CallService( MS_NETLIB_NTLMCREATERESPONSE2, (WPARAM)hProvider, (LPARAM)&temp ); + *complete = temp.complete; + return res; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Netlib hooks (0.8+) + +// WARNING: these hooks are being called in the context of the calling thread, without switching +// to the first thread, like all another events do. The hook procedure should be ready for the +// multithreaded mode +// +// Parameters: +// wParam: NETLIBNOTIFY* - points to the data being sent/received +// lParam: NETLIBUSER* - points to the protocol definition + +typedef struct { + NETLIBBUFFER* nlb; // pointer to the request buffer + int result; // amount of bytes really sent/received +} + NETLIBNOTIFY; + +#define ME_NETLIB_FASTRECV "Netlib/OnRecv" // being called on every receive +#define ME_NETLIB_FASTSEND "Netlib/OnSend" // being called on every send +#define ME_NETLIB_FASTDUMP "Netlib/OnDump" // being called on every dump + +#endif // M_NETLIB_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_options.h b/plugins/!NotAdopted/WinPopup/sdk/m_options.h new file mode 100644 index 0000000000..0231efaedd --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_options.h @@ -0,0 +1,138 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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_OPTIONS_H__ +#define M_OPTIONS_H__ + +/* Opt/Initialise +The user opened the options dialog. Modules should do whatever initialisation +they need and call opt/addpage one or more times if they want pages displayed +in the options dialog +wParam=addInfo +lParam=0 +addInfo should be passed straight to the wParam of opt/addpage +*/ +#define ME_OPT_INITIALISE "Opt/Initialise" + +/* Opt/AddPage +Must only be called during an opt/initialise hook +Adds a page to the options dialog +wParam=addInfo +lParam=(LPARAM)(OPTIONSDIALOGPAGE*)odp +addInfo must have come straight from the wParam of opt/initialise +Pages in the options dialog operate just like pages in property sheets. See the +Microsoft documentation for details on how they operate. +Strings in the structure can be released as soon as the service returns, but +icons must be kept around. This is not a problem if you're loading them from a +resource. +Prior to v0.1.2.1 the options dialog would resize to fit the largest page, but +since then it is fixed in size. The largest page that fits neatly is 314x240 +DLUs. +*/ + +// WARNING: do not use Translate(TS) for pszTitle, pszGroup or pszTab as they +// are translated by the core, which may lead to double translation. +// Use LPGEN instead which are just dummy wrappers/markers for "lpgen.pl". +typedef struct { + int cbSize; + int position; //a position number, lower numbers are topmost + union { + char* pszTitle; // [TRANSLATED-BY-CORE] + TCHAR* ptszTitle; + }; + DLGPROC pfnDlgProc; + char *pszTemplate; + HINSTANCE hInstance; + HICON hIcon; //v0.1.0.1+ + union { + char* pszGroup; //v0.1.0.1+ [TRANSLATED-BY-CORE] + TCHAR* ptszGroup; //v0.1.0.1+ + }; + int groupPosition; //v0.1.0.1+ + HICON hGroupIcon; //v0.1.0.1+ + DWORD flags; //v0.1.2.1+ + int nIDBottomSimpleControl; //v0.1.2.1+ if in simple mode the dlg will be cut off after this control, 0 to disable + int nIDRightSimpleControl; //v0.1.2.1+ if in simple mode the dlg will be cut off after this control, 0 to disable + UINT *expertOnlyControls; + int nExpertOnlyControls; //v0.1.2.1+ these controls will be hidden in simple mode. Array must remain valid for duration of dlg. + + #if MIRANDA_VER >= 0x0600 + union { + char* pszTab; //v0.6.0.0+ [TRANSLATED-BY-CORE] + TCHAR* ptszTab; //v0.6.0.0+ + }; + #endif + + #if MIRANDA_VER >= 0x0800 + LPARAM dwInitParam; //v0.8.0.0+ a value to pass to lParam of WM_INITDIALOG message + #endif +} + OPTIONSDIALOGPAGE; + +#define OPTIONPAGE_OLD_SIZE (offsetof(OPTIONSDIALOGPAGE, flags)) +#if MIRANDA_VER >= 0x0600 + #define OPTIONPAGE_OLD_SIZE2 (offsetof(OPTIONSDIALOGPAGE, pszTab)) +#endif +#if MIRANDA_VER >= 0x0800 + #define OPTIONPAGE_OLD_SIZE3 (offsetof(OPTIONSDIALOGPAGE, dwInitParam)) +#endif + +#define ODPF_SIMPLEONLY 1 // page is only shown when in simple mode +#define ODPF_EXPERTONLY 2 // " expert mode +#define ODPF_BOLDGROUPS 4 // give group box titles a bold font +#define ODPF_UNICODE 8 // string fields in OPTIONSDIALOGPAGE are WCHAR* +#define ODPF_USERINFOTAB 16 // options page is tabbed + +#if defined( _UNICODE ) + #define ODPF_TCHAR ODPF_UNICODE +#else + #define ODPF_TCHAR 0 +#endif + +#define PSN_EXPERTCHANGED 2 //sent to pages via WM_NOTIFY when the expert checkbox is clicked. lParam=new state +#define PSM_ISEXPERT (WM_USER+101) //returns true/false +#define PSM_GETBOLDFONT (WM_USER+102) //returns HFONT used for group box titles +#define MS_OPT_ADDPAGE "Opt/AddPage" + +//Opens the options dialog, optionally at the specified page v0.1.2.1+ +//wParam=0 +//lParam=(LPARAM)(OPENOPTIONSDIALOG*)&ood; +//Returns 0 on success, nonzero on failure +//The behaviour if the options dialog is already open is that it will just be +//activated, the page won't be changed. This may change in the future. +typedef struct { + int cbSize; + const char *pszGroup; //set to NULL if it's a root item + const char *pszPage; //set to NULL to just open the options at no + //specific page + const char *pszTab; //set to NULL to just open the options at no + //specific tab +} OPENOPTIONSDIALOG; +#define MS_OPT_OPENOPTIONS "Opt/OpenOptions" + +//Opens the options dialog, with only specified page v0.8.0.x+ +#define MS_OPT_OPENOPTIONSPAGE "Opt/OpenOptionsPage" + +#define SETTING_SHOWEXPERT_DEFAULT 1 + +#endif //M_OPTIONS_H__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_plugins.h b/plugins/!NotAdopted/WinPopup/sdk/m_plugins.h new file mode 100644 index 0000000000..8cbd5a4ba1 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_plugins.h @@ -0,0 +1,85 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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_PLUGINS_H__ +#define M_PLUGINS_H__ + +/* + Undocumented: Do NOT use. + Version: 0.3.4.1+ (2004/10/04) +*/ +#define DBPE_DONE 1 +#define DBPE_CONT 0 +#define DBPE_HALT (-1) +typedef struct PLUGIN_DB_ENUM { + int cbSize; + // 0 = continue, 1 = found, -1 = stop now + int (*pfnEnumCallback) ( char * pluginname, /*DATABASELINK*/ void * link, LPARAM lParam); + LPARAM lParam; +} PLUGIN_DB_ENUM; +#define MS_PLUGINS_ENUMDBPLUGINS "Plugins/DbEnumerate" + + +//#define DEFMOD_PROTOCOLICQ 1 //removed from v0.3 alpha +//#define DEFMOD_PROTOCOLMSN 2 //removed from v0.1.2.0+ +#define DEFMOD_UIFINDADD 3 +#define DEFMOD_UIUSERINFO 4 +#define DEFMOD_SRMESSAGE 5 +#define DEFMOD_SRURL 6 +#define DEFMOD_SREMAIL 7 +#define DEFMOD_SRAUTH 8 +#define DEFMOD_SRFILE 9 +#define DEFMOD_UIHELP 10 +#define DEFMOD_UIHISTORY 11 +//#define DEFMOD_RNDCHECKUPD 12 //removed from v0.3.1 alpha +//#define DEFMOD_RNDICQIMPORT 13 //removed from v0.3 alpha +#define DEFMOD_RNDAUTOAWAY 14 +#define DEFMOD_RNDUSERONLINE 15 +//#define DEFMOD_RNDCRYPT 16 // v0.1.0.1-v0.1.2.0 +#define DEFMOD_SRAWAY 17 // v0.1.0.1+ +#define DEFMOD_RNDIGNORE 18 // v0.1.0.1+ +#define DEFMOD_UIVISIBILITY 19 // v0.1.1.0+, options page only +#define DEFMOD_UICLUI 20 // v0.1.1.0+ +//#define DEFMOD_UIPLUGINOPTS 21 // removed from 0.4.0.1 +//#define DEFMOD_PROTOCOLNETLIB 22 // removed from 0.8.0.5 +#define DEFMOD_RNDIDLE 23 // v0.3.4a+ +#define DEFMOD_CLISTALL 24 // v0.3.4a+ (2004/09/28) +#define DEFMOD_DB 25 // v0.3.4.3+ (2004/10/11) +#define DEFMOD_FONTSERVICE 26 // v0.7.0+ (2006/11/17) +#define DEFMOD_UPDATENOTIFY 27 +#define DEFMOD_SSL 28 // v0.8.0+ +#define DEFMOD_HIGHEST 28 + +//plugins/getdisabledefaultarray +//gets an array of the modules that the plugins report they want to replace +//wParam=lParam=0 +//returns a pointer to an array of INT_PTR, with elements 1 or 0 indexed by the +//DEFMOD_ constants. 1 to signify that the default module shouldn't be loaded. +//this is primarily for use by the core's module initialiser, but could also +//be used by modules that are doing naughty things that are very +//feature-dependent +#define MS_PLUGINS_GETDISABLEDEFAULTARRAY "Plugins/GetDisableDefaultArray" + +#endif // M_PLUGINS_H__ + + diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_popup.h b/plugins/!NotAdopted/WinPopup/sdk/m_popup.h new file mode 100644 index 0000000000..419f2bd396 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_popup.h @@ -0,0 +1,424 @@ +/* +=============================================================================== + PopUp plugin +Plugin Name: PopUp +Plugin authors: Luca Santarelli aka hrk (hrk@users.sourceforge.net) + Victor Pavlychko aka zazoo (nullbie@gmail.com) +=============================================================================== +The purpose of this plugin is to give developers a common "platform/interface" +to show PopUps. It is born from the source code of NewStatusNotify, another +plugin I've made. + +Remember that users *must* have this plugin enabled, or they won't get any +popup. Write this in the requirements, do whatever you wish ;-)... but tell +them! +=============================================================================== +*/ + +#ifndef M_POPUP_H +#define M_POPUP_H + +/* +NOTE! Since Popup 1.0.1.2 there is a main meun group called "PopUps" where I +have put a "Enable/Disable" item. You can add your own "enable/disable" items +by adding these lines before you call MS_CLIST_ADDMAINMENUITEM: +mi.pszPopUpName = Translate("PopUps"); +mi.position = 0; //You don't need it and it's better if you put it to zero. +*/ + +#define MAX_CONTACTNAME 2048 +#define MAX_SECONDLINE 2048 + +// This is the basic data you'll need to fill and pass to the service function. +typedef struct +{ + HANDLE lchContact; // Handle to the contact, can be NULL (main contact). + HICON lchIcon; // Handle to a icon to be shown. Cannot be NULL. + union + { + char lptzContactName[MAX_CONTACTNAME]; // This is the contact name or the first line in the plugin. Cannot be NULL. + char lpzContactName[MAX_CONTACTNAME]; + }; + union + { + char lptzText[MAX_SECONDLINE]; // This is the second line text. Users can choose to hide it. Cannot be NULL. + char lpzText[MAX_SECONDLINE]; + }; + COLORREF colorBack; // COLORREF to be used for the background. Can be NULL, default will be used. + COLORREF colorText; // COLORREF to be used for the text. Can be NULL, default will be used. + WNDPROC PluginWindowProc; // Read below. Can be NULL; default will be used. + void * PluginData; // Read below. Can be NULL. +} POPUPDATA, * LPPOPUPDATA; + +// Extended popup data +typedef struct +{ + HANDLE lchContact; + HICON lchIcon; + union + { + char lptzContactName[MAX_CONTACTNAME]; + char lpzContactName[MAX_CONTACTNAME]; + }; + union + { + char lptzText[MAX_SECONDLINE]; + char lpzText[MAX_SECONDLINE]; + }; + COLORREF colorBack; + COLORREF colorText; + WNDPROC PluginWindowProc; + void * PluginData; + int iSeconds; // Custom delay time in seconds. -1 means "forever", 0 means "default time". + char cZero[16]; // Some unused bytes which may come useful in the future. +} POPUPDATAEX, *LPPOPUPDATAEX; + +// Unicode version of POPUPDATAEX +typedef struct +{ + HANDLE lchContact; + HICON lchIcon; + union + { + WCHAR lptzContactName[MAX_CONTACTNAME]; + WCHAR lpwzContactName[MAX_CONTACTNAME]; + }; + union + { + WCHAR lptzText[MAX_SECONDLINE]; + WCHAR lpwzText[MAX_SECONDLINE]; + }; + COLORREF colorBack; + COLORREF colorText; + WNDPROC PluginWindowProc; + void * PluginData; + int iSeconds; + char cZero[16]; +} POPUPDATAW, *LPPOPUPDATAW; + +#if defined(_UNICODE) || defined(UNICODE) + typedef POPUPDATAW POPUPDATAT; + typedef LPPOPUPDATAW LPPOPUPDATAT; +#else + typedef POPUPDATAEX POPUPDATAT; + typedef LPPOPUPDATAEX LPPOPUPDATAT; +#endif + +/* PopUp/AddPopup +Creates, adds and shows a popup, given a (valid) POPUPDATA structure pointer. + +wParam = (WPARAM)(*POPUPDATA)PopUpDataAddress +lParam = 0 + +Returns: > 0 on success, 0 if creation went bad, -1 if the PopUpData contained unacceptable values. +NOTE: it returns -1 if the PopUpData was not valid, if there were already too many popups, if the module was disabled. +Otherwise, it can return anything else... + +Popup Plus 2.0.4.0+ +You may pass additional creation flags via lParam: + APF_RETURN_HWND ....... function returns handle to newly created popup window (however this calls are a bit slower) + APF_CUSTOM_POPUP ...... new popup is created in hidden state and doesn't obey to popup queue rules. + you may control it via UM_* messages and custom window procedure +*/ +#define APF_RETURN_HWND 0x1 +#define APF_CUSTOM_POPUP 0x2 + +#define MS_POPUP_ADDPOPUP "PopUp/AddPopUp" +static INT_PTR __inline PUAddPopUp(POPUPDATA* ppdp) { + return CallService(MS_POPUP_ADDPOPUP, (WPARAM)ppdp,0); +} + +#define MS_POPUP_ADDPOPUPEX "PopUp/AddPopUpEx" +static INT_PTR __inline PUAddPopUpEx(POPUPDATAEX* ppdp) { + return CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)ppdp,0); +} + +#define MS_POPUP_ADDPOPUPW "PopUp/AddPopUpW" +static INT_PTR __inline PUAddPopUpW(POPUPDATAW* ppdp) { + return CallService(MS_POPUP_ADDPOPUPW, (WPARAM)ppdp,0); +} + +#if defined(_UNICODE) || defined(UNICODE) + #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPW + #define PUAddPopUpT PUAddPopUpW +#else + #define MS_POPUP_ADDPOPUPT MS_POPUP_ADDPOPUPEX + #define PUAddPopUpT PUAddPopUpEx +#endif + + +/* PopUp/GetContact +Returns the handle to the contact associated to the specified PopUpWindow. + +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = 0; + +Returns: the HANDLE of the contact. Can return NULL, meaning it's the main contact. -1 means failure. +*/ +#define MS_POPUP_GETCONTACT "PopUp/GetContact" +static HANDLE __inline PUGetContact(HWND hPopUpWindow) { + return (HANDLE)CallService(MS_POPUP_GETCONTACT, (WPARAM)hPopUpWindow,0); +} + +/* PopUp/GetPluginData +Returns custom plugin date associated with popup + +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = (LPARAM)(PLUGINDATA*)PluginDataAddress; + +Returns: the address of the PLUGINDATA structure. Can return NULL, meaning nothing was given. -1 means failure. + +IMPORTANT NOTE: it doesn't seem to work if you do: +CallService(..., (LPARAM)aPointerToAStruct); +and then use that struct. +Do this, instead: +aPointerToStruct = CallService(..., (LPARAM)aPointerToAStruct); +and it will work. Just look at the example I've written above (PopUpDlgProc). + +*/ +#define MS_POPUP_GETPLUGINDATA "PopUp/GetPluginData" +static void __inline * PUGetPluginData(HWND hPopUpWindow) { + long * uselessPointer = NULL; + return (void*)CallService(MS_POPUP_GETPLUGINDATA,(WPARAM)hPopUpWindow,(LPARAM)uselessPointer); +} + +/* PopUp/IsSecondLineShown +Checks if second line is enable + +wParam = 0 +lParam = 0 + +Returns: 0 if the user has chosen not to have the second line, 1 if he choose to have the second line. +*/ +#define MS_POPUP_ISSECONDLINESHOWN "PopUp/IsSecondLineShown" +static BOOL __inline PUIsSecondLineShown() { + return (BOOL)CallService(MS_POPUP_ISSECONDLINESHOWN,0,0); +} + +/* PopUp/Query + +Requests an action or an answer from PopUp module. + +wParam = (WPARAM)wpQuery + +returns 0 on success, -1 on error, 1 on stupid calls ;-) +*/ + +#define PUQS_ENABLEPOPUPS 1 // returns 0 if state was changed, 1 if state wasn't changed +#define PUQS_DISABLEPOPUPS 2 // " " +#define PUQS_GETSTATUS 3 //Returns 1 (TRUE) if popups are enabled, 0 (FALSE) if popups are disabled. + +#define MS_POPUP_QUERY "PopUp/Query" + +/* UM_FREEPLUGINDATA +Process this message if you have allocated your own memory. (i.e.: POPUPDATA.PluginData != NULL) + +wParam = 0 +lParam = 0 +*/ +#define UM_FREEPLUGINDATA (WM_USER + 0x0200) + +/* UM_DESTROYPOPUP +Send this message when you want to destroy the popup, or use the function below. + +wParam = 0 +lParam = 0 +*/ +#define UM_DESTROYPOPUP (WM_USER + 0x0201) +static int __inline PUDeletePopUp(HWND hWndPopUp) { + return (int)SendMessage(hWndPopUp, UM_DESTROYPOPUP,0,0); +} + +/* UM_INITPOPUP +This message is sent to the PopUp when its creation has been finished, so POPUPDATA (and thus your PluginData) is reachable. +Catch it if you needed to catch WM_CREATE or WM_INITDIALOG, which you'll never ever get in your entire popup-life. +Return value: if you process this message, return 0. If you don't process it, return 0. Do whatever you like ;-) + +wParam = (WPARAM)(HWND)hPopUpWindow (this is useless, you get message inside your popup window) +lParam = 0 +*/ +#define UM_INITPOPUP (WM_USER + 0x0202) + +/* PopUp/Changetext +Changes the text displayed in the second line of the popup. + +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = (LPARAM)(char*)lpzNewText + +returns: > 0 for success, -1 for failure, 0 if the failure is due to second line not being shown. (but you could call +PUIsSecondLineShown() before changing the text...) +*/ +#define MS_POPUP_CHANGETEXT "PopUp/Changetext" +static int __inline PUChangeText(HWND hWndPopUp, LPCTSTR lpzNewText) { + return (int)CallService(MS_POPUP_CHANGETEXT, (WPARAM)hWndPopUp, (LPARAM)lpzNewText); +} + +#define MS_POPUP_CHANGETEXTW "PopUp/ChangetextW" +static int __inline PUChangeTextW(HWND hWndPopUp, LPCWSTR lpwzNewText) { + return (int)CallService(MS_POPUP_CHANGETEXTW, (WPARAM)hWndPopUp, (LPARAM)lpwzNewText); +} + +#if defined(_UNICODE) || defined(UNICODE) + #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXTW + #define PUChangeTextT PUChangeTextW +#else + #define MS_POPUP_CHANGETEXTT MS_POPUP_CHANGETEXT + #define PUChangeTextT PUChangeText +#endif + +/* PopUp/Change +Changes the entire popup + +wParam = (WPARAM)(HWND)hPopUpWindow +lParam = (LPARAM)(POPUPDATAEX*)newData +*/ +#define MS_POPUP_CHANGE "PopUp/Change" +static int __inline PUChange(HWND hWndPopUp, POPUPDATAEX *newData) { + return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData); +} + +#define MS_POPUP_CHANGEW "PopUp/ChangeW" +static int __inline PUChangeW(HWND hWndPopUp, POPUPDATAW *newData) { + return (int)CallService(MS_POPUP_CHANGE, (WPARAM)hWndPopUp, (LPARAM)newData); +} + +#if defined(_UNICODE) || defined(UNICODE) + #define MS_POPUP_CHANGET MS_POPUP_CHANGEW + #define PUChangeT PUChangeW +#else + #define MS_POPUP_CHANGET MS_POPUP_CHANGE + #define PUChangeT PUChange +#endif + +/* UM_CHANGEPOPUP +This message is triggered by Change/ChangeText services. You also may post it directly :) + +wParam = Modification type +lParam = value of type defined by wParam +*/ + +#define CPT_TEXT 1 // lParam = (char *)text +#define CPT_TEXTW 2 // lParam = (WCHAR *)text +#define CPT_TITLE 3 // lParam = (char *)title +#define CPT_TITLEW 4 // lParam = (WCHAR *)title +#define CPT_DATA 5 // lParam = (POPUPDATA *)data +#define CPT_DATAEX 6 // lParam = (POPUPDATAEX *)data +#define CPT_DATAW 7 // lParam = (POPUPDATAW *)data + +#define UM_CHANGEPOPUP (WM_USER + 0x0203) + +#if defined(_UNICODE) || defined(UNICODE) + #define CPT_TEXTT CPT_TEXTW + #define CPT_TITLET CPT_TITLEW + #define CPT_DATAT CPT_DATAW +#else + #define CPT_TEXTT CPT_TEXT + #define CPT_TITLET CPT_TITLE + #define CPT_DATAT CPT_DATA +#endif + +/* PopUp/ShowMessage +This is mainly for developers. +Shows a warning message in a PopUp. It's useful if you need a "MessageBox" like function, but you don't want a modal +window (which will interfere with a DialogProcedure. MessageBox steals focus and control, this one not. + +wParam = (char *)lpzMessage +lParam = 0; + +Returns: 0 if the popup was shown, -1 in case of failure. +*/ +#define SM_WARNING 0x01 //Triangle icon. +#define SM_NOTIFY 0x02 //Exclamation mark icon. +#define MS_POPUP_SHOWMESSAGE "PopUp/ShowMessage" +#define MS_POPUP_SHOWMESSAGEW "PopUp/ShowMessageW" + +static int __inline PUShowMessage(char *lpzText, BYTE kind) { + return (int)CallService(MS_POPUP_SHOWMESSAGE, (WPARAM)lpzText,(LPARAM)kind); +} + +static int __inline PUShowMessageW(wchar_t *lpwzText, BYTE kind) { + return (int)CallService(MS_POPUP_SHOWMESSAGEW, (WPARAM)lpwzText,(LPARAM)kind); +} + +#ifdef _UNICODE +#define PUShowMessageT PUShowMessageW +#else +#define PUShowMessageT PUShowMessage +#endif + +//------------- Class API ----------------// + +typedef struct { + int cbSize; + int flags; + char *pszName; + union { + char *pszDescription; + wchar_t *pwszDescription; + TCHAR *ptszDescription; + }; + + HICON hIcon; + + COLORREF colorBack; + COLORREF colorText; + + WNDPROC PluginWindowProc; + + int iSeconds; +} POPUPCLASS; + +#define PCF_UNICODE 0x0001 + +#ifdef _UNICODE +#define PCF_TCHAR PCF_UNICODE +#else +#define PCF_TCHAR 0 +#endif + +// wParam = 0 +// lParam = (POPUPCLASS *)&pc +#define MS_POPUP_REGISTERCLASS "PopUp/RegisterClass" + +typedef struct { + int cbSize; + char *pszClassName; + union { + const char *pszTitle; + const wchar_t *pwszTitle; + const TCHAR *ptszTitle; + }; + union { + const char *pszText; + const wchar_t *pwszText; + const TCHAR *ptszText; + }; + void *PluginData; + HANDLE hContact; +} POPUPDATACLASS; + +// wParam = 0 +// lParam = (POPUPDATACLASS *)&pdc +#define MS_POPUP_ADDPOPUPCLASS "PopUp/AddPopupClass" + +static INT_PTR __inline ShowClassPopup(char *name, char *title, char *text) { + POPUPDATACLASS d = {sizeof(d), name}; + d.pszTitle = title; + d.pszText = text; + return CallService(MS_POPUP_ADDPOPUPCLASS, 0, (LPARAM)&d); +} + +static INT_PTR __inline ShowClassPopupW(char *name, wchar_t *title, wchar_t *text) { + POPUPDATACLASS d = {sizeof(d), name}; + d.pwszTitle = title; + d.pwszText = text; + return CallService(MS_POPUP_ADDPOPUPCLASS, 0, (LPARAM)&d); +} + +#ifdef _UNICODE +#define ShowClassPopupT ShowClassPopupW +#else +#define ShowClassPopupT ShowClassPopup +#endif + +#endif // __m_popup_h__ diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_protocols.h b/plugins/!NotAdopted/WinPopup/sdk/m_protocols.h new file mode 100644 index 0000000000..d2032db977 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_protocols.h @@ -0,0 +1,487 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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. +*/ + +//this module was created in v0.1.1.0 + +#ifndef M_PROTOCOLS_H__ +#define M_PROTOCOLS_H__ 1 + +#include "statusmodes.h" + +//call a specific protocol service. See the PS_ constants in m_protosvc.h +#if MIRANDA_VER < 0x800 +__inline static INT_PTR CallProtoService(const char *szModule,const char *szService,WPARAM wParam,LPARAM lParam) +{ + char str[MAXMODULELABELLENGTH]; + _snprintf(str, sizeof(str), "%s%s", szModule, szService); + str[MAXMODULELABELLENGTH-1] = 0; + return CallService(str,wParam,lParam); +} +#endif + +//send a general request through the protocol chain for a contact +//wParam=0 +//lParam=(LPARAM)(CCSDATA*)&ccs +//returns the value as documented in the PS_ definition (m_protosvc.h) + +typedef struct { + HANDLE hContact; + const char *szProtoService; //a PS_ constant + WPARAM wParam; + LPARAM lParam; +} CCSDATA; + +#define MS_PROTO_CALLCONTACTSERVICE "Proto/CallContactService" + +#if MIRANDA_VER < 0x800 +__inline static INT_PTR CallContactService(HANDLE hContact,const char *szProtoService,WPARAM wParam,LPARAM lParam) +{ + CCSDATA ccs; + ccs.hContact=hContact; + ccs.szProtoService=szProtoService; + ccs.wParam=wParam; + ccs.lParam=lParam; + return CallService(MS_PROTO_CALLCONTACTSERVICE,0,(LPARAM)&ccs); +} +#endif + +//a general network 'ack' +//wParam=0 +//lParam=(LPARAM)(ACKDATA*)&ack +//Note that just because definitions are here doesn't mean they will be sent. +//Read the documentation for the function you are calling to see what replies +//you will receive. +typedef struct { + int cbSize; + const char *szModule; //the name of the protocol module which initiated this ack + HANDLE hContact; + int type; //an ACKTYPE_ constant + int result; //an ACKRESULT_ constant + HANDLE hProcess; //a caller-defined process code + LPARAM lParam; //caller-defined extra info +} ACKDATA; +#define ACKTYPE_MESSAGE 0 +#define ACKTYPE_URL 1 +#define ACKTYPE_FILE 2 +#define ACKTYPE_CHAT 3 +#define ACKTYPE_AWAYMSG 4 +#define ACKTYPE_AUTHREQ 5 +#define ACKTYPE_ADDED 6 +#define ACKTYPE_GETINFO 7 +#define ACKTYPE_SETINFO 8 +#define ACKTYPE_LOGIN 9 +#define ACKTYPE_SEARCH 10 +#define ACKTYPE_NEWUSER 11 +#define ACKTYPE_STATUS 12 +#define ACKTYPE_CONTACTS 13 //send/recv of contacts +#define ACKTYPE_AVATAR 14 //send/recv of avatars from a protocol +#define ACKTYPE_EMAIL 15 //notify if the unread emails changed + +#define ACKRESULT_SUCCESS 0 +#define ACKRESULT_FAILED 1 + +//'in progress' result codes: +#define ACKRESULT_CONNECTING 100 +#define ACKRESULT_CONNECTED 101 +#define ACKRESULT_INITIALISING 102 +#define ACKRESULT_SENTREQUEST 103 //waiting for reply... +#define ACKRESULT_DATA 104 //blob of file data sent/recved, or search result +#define ACKRESULT_NEXTFILE 105 //file transfer went to next file +#define ACKRESULT_FILERESUME 106 //a file is about to be received, see PS_FILERESUME +#define ACKRESULT_DENIED 107 //a file send has been denied +#define ACKRESULT_STATUS 108 //an ack or a series of acks to do with a task have a status change +#define ACKRESULT_LISTENING 109 //waiting for connection +#define ACKRESULT_CONNECTPROXY 110 //connecting to file proxy +#define ACKRESULT_SEARCHRESULT 111 //result of extended search + +#define ME_PROTO_ACK "Proto/Ack" + +// v0.3.2+: When result is ACKRESULT_FAILED or ACKRESULT_DENIED, lParam can point to +// a human readable string with an explanation. For example: "The message was too +// long to be delivered". If no error message is specified, lParam must be NULL. +// Right now only explanations from ACKTYPE_MESSAGE is shown. + +//when type==ACKTYPE_FILE && (result==ACKRESULT_DATA || result==ACKRESULT_FILERESUME), +//lParam points to this + +#if MIRANDA_VER >= 0x0900 + #define FNAMECHAR TCHAR +#else + #define FNAMECHAR char +#endif + +#define PFTS_RECEIVING 0 +#define PFTS_SENDING 1 +#define PFTS_UNICODE 2 +#define PFTS_UTF 4 + +#if defined( _UNICODE ) + #define PFTS_TCHAR PFTS_UNICODE +#else + #define PFTS_TCHAR 0 +#endif + +typedef struct tagPROTOFILETRANSFERSTATUS_V1 +{ + size_t cbSize; + HANDLE hContact; + int sending; + char **files; + int totalFiles; + int currentFileNumber; + unsigned long totalBytes; + unsigned long totalProgress; + char *workingDir; + char *currentFile; + unsigned long currentFileSize; + unsigned long currentFileProgress; + unsigned long currentFileTime; //as seconds since 1970 +} +PROTOFILETRANSFERSTATUS_V1; + +#if MIRANDA_VER < 0x0900 + +typedef PROTOFILETRANSFERSTATUS_V1 PROTOFILETRANSFERSTATUS; + +#else + +typedef struct tagPROTOFILETRANSFERSTATUS +{ + size_t cbSize; + HANDLE hContact; + DWORD flags; // one of PFTS_* constants + + union { + char **pszFiles; + TCHAR **ptszFiles; + WCHAR **pwszFiles; + }; + + int totalFiles; + int currentFileNumber; + unsigned __int64 totalBytes; + unsigned __int64 totalProgress; + + union { + char *szWorkingDir; + TCHAR *tszWorkingDir; + WCHAR *wszWorkingDir; + }; + + union { + char *szCurrentFile; + TCHAR *tszCurrentFile; + WCHAR *wszCurrentFile; + }; + + unsigned __int64 currentFileSize; + unsigned __int64 currentFileProgress; + unsigned __int64 currentFileTime; //as seconds since 1970 +} +PROTOFILETRANSFERSTATUS; + +#endif + +//Enumerate the currently running protocols +//wParam=(WPARAM)(int*)&numberOfProtocols +//lParam=(LPARAM)(PROTOCOLDESCRIPTOR***)&ppProtocolDescriptors +//Returns 0 on success, nonzero on failure +//Neither wParam nor lParam may be NULL +//The list returned by this service is the protocol modules currently installed +//and running. It is not the complete list of all protocols that have ever been +//installed. +//IMPORTANT NOTE #1: the list returned is not static, it may be changed in the +//program's lifetime. Do not use this list in the global context, copy protocols +//names otherwise. +//IMPORTANT NOTE #2: in version 0.8 this service is mapped to the MS_PROTO_ENUMACCOUNTS +//service to provide the compatibility with old plugins (first three members of +//PROTOACCOUNT are equal to the old PROTOCOLDESCRIPTOR format). If you declare the +//MIRANDA_VER macro with value greater or equal to 0x800, use MS_PROTO_ENUMPROTOS +//service instead to obtain the list of running protocols instead of accounts. +//Note that a protocol module need not be an interface to an Internet server, +//they can be encryption and loads of other things, too. +//And yes, before you ask, that is triple indirection. Deal with it. +//Access members using ppProtocolDescriptors[index]->element + +#define PROTOCOLDESCRIPTOR_V3_SIZE (sizeof(size_t)+sizeof(INT_PTR)+sizeof(char*)) + + // initializes an empty account +typedef struct tagPROTO_INTERFACE* ( *pfnInitProto )( const char* szModuleName, const TCHAR* szUserName ); + +// deallocates an account instance +typedef int ( *pfnUninitProto )( struct tagPROTO_INTERFACE* ); + +// removes an account from the database +typedef int ( *pfnDestroyProto )( struct tagPROTO_INTERFACE* ); + +typedef struct { + size_t cbSize; + char *szName; // unique name of the module + int type; // module type, see PROTOTYPE_ constants + + // 0.8.0+ additions + #if MIRANDA_VER >= 0x800 + pfnInitProto fnInit; // initializes an empty account + pfnUninitProto fnUninit; // deallocates an account instance + pfnDestroyProto fnDestroy; // removes an account + #endif +} + PROTOCOLDESCRIPTOR; + +// v0.3.3+: +// +// For recv, it will go from lower to higher, so in this case: +// check ignore, decrypt (encryption), translate +// +// For send, it will go translate, encrypt, ignore(??), send +// +// The DB will store higher numbers here, LOWER in the protocol chain, and lower numbers +// here HIGHER in the protocol chain +// +#define PROTOTYPE_IGNORE 50 // added during v0.3.3 +#define PROTOTYPE_PROTOCOL 1000 +#define PROTOTYPE_ENCRYPTION 2000 +#define PROTOTYPE_FILTER 3000 +#define PROTOTYPE_TRANSLATION 4000 +#define PROTOTYPE_OTHER 10000 //avoid using this if at all possible +#define PROTOTYPE_DISPROTO 20000 + +#if MIRANDA_VER >= 0x800 + #define MS_PROTO_ENUMPROTOS "Proto/EnumProtos" + #define MS_PROTO_ENUMPROTOCOLS "Proto/EnumAccounts" +#else + #define MS_PROTO_ENUMPROTOCOLS "Proto/EnumProtocols" +#endif + +//determines if a protocol module is loaded or not +//wParam=0 +//lParam=(LPARAM)(const char*)szName +//Returns a pointer to the PROTOCOLDESCRIPTOR if the protocol is loaded, or +//NULL if it isn't. +#define MS_PROTO_ISPROTOCOLLOADED "Proto/IsProtocolLoaded" + +//gets the network-level protocol associated with a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//Returns a char* pointing to the asciiz name of the protocol or NULL if the +//contact has no protocol. There is no need to free() it or anything. +//This is the name of the module that actually accesses the network for that +//contact. +#define MS_PROTO_GETCONTACTBASEPROTO "Proto/GetContactBaseProto" + +//determines whether the specified contact has the given protocol in its chain +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(const char*)szName +//Returns -1 if it is base protocol, positive number if it is filter and 0 if it doesn't +#define MS_PROTO_ISPROTOONCONTACT "Proto/IsProtoOnContact" + +#define PROTOTYPE_SELFTYPING_OFF 0 +#define PROTOTYPE_SELFTYPING_ON 1 +//This service is for notifying protocols that the user is typing a message v0.3.3+ +//in a message dialog. +//This is typically sent by a message dialog when a user in the clist is typing. +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(int)typing state +//NOTE: Only protocols should generally call this service +#define MS_PROTO_SELFISTYPING "Proto/SelfIsTyping" + +#define PROTOTYPE_CONTACTTYPING_OFF 0 +#define PROTOTYPE_CONTACTTYPING_INFINITE 2147483647 +//This service is for notifying message dialogs/other plugins of a user typing. v0.3.3+ +//This is typically sent by a protocol when a user in the clist is typing. +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(int)time (secs) +//NOTE: The time in seconds is used to tell a message dialog (or other plugin) +//how long to display its notification. If time is 0, then notification +//of typing ends. +//NOTE: Only protocols should generally call this service +#define MS_PROTO_CONTACTISTYPING "Proto/ContactIsTyping" + +//This hook notifies when a user is typing. If a message dialog supports sending v0.3.3+ +//typing notifications it should hook this event and fire the +//ProtoService PSS_USERISTYPING to the contacts protocol *after* verifying +//that the hContact is not NULL and the the user wishes to send notifications +//to this user (checked visibility, individual typing blocking, etc). +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(int)typing state +#define ME_PROTO_CONTACTISTYPING "Proto/ContactIsTypingEvent" + +// -------------- accounts support --------------------- 0.8.0+ + +typedef struct tagACCOUNT +{ + int cbSize; // sizeof this structure + char* szModuleName; // unique physical account name (matches database module name) + int type; // always equal to PROTOTYPE_PROTOCOL + TCHAR* tszAccountName; // user-defined account name + char* szProtoName; // physical protocol name + int bIsEnabled; // is account enabled? + int bIsVisible; // is account visible? + int iOrder; // account order in various menus & lists + BOOL bOldProto; // old-styled account (one instance per dll) + struct tagPROTO_INTERFACE* ppro; // pointer to the underlying object + + HWND hwndAccMgrUI; + BOOL bAccMgrUIChanged; + BOOL bDynDisabled; // dynamic disable flag, is never written to db +} + PROTOACCOUNT; + +//account enumeration service +//wParam=(WPARAM)(int*)piNumAccounts +//lParam=(LPARAM)(PROTOACCOUNT**)paAccounts +#define MS_PROTO_ENUMACCOUNTS "Proto/EnumAccounts" + +__inline static INT_PTR ProtoEnumAccounts( int* accNumber, PROTOACCOUNT*** accArray ) +{ return CallService( MS_PROTO_ENUMACCOUNTS, ( WPARAM )accNumber, (LPARAM)accArray ); +} + +//retrieves an account's interface by its physical name (database module) +//wParam=0 +//lParam=(LPARAM)(char*)szAccountName +//return value = PROTOACCOUNT* or NULL +#define MS_PROTO_GETACCOUNT "Proto/GetAccount" + +__inline static PROTOACCOUNT* ProtoGetAccount( const char* accName ) +{ return (PROTOACCOUNT*)CallService( MS_PROTO_GETACCOUNT, 0, (LPARAM)accName ); +} + +//this event is fired when the accounts list gets changed +//wParam = event type (1 - added, 2 - changed, 3 - deleted, 4 - upgraded, 5 - enabled/disabled) +//lParam = (LPARAM)(PROTOACCOUNT*) - account being changed + +#define PRAC_ADDED 1 +#define PRAC_CHANGED 2 +#define PRAC_REMOVED 3 +#define PRAC_UPGRADED 4 +#define PRAC_CHECKED 5 + + +#define ME_PROTO_ACCLISTCHANGED "Proto/AccListChanged" + +//displays the Account Manager +//wParam=0 +//lParam=0 +#define MS_PROTO_SHOWACCMGR "Protos/ShowAccountManager" + +//determines if an account is enabled or not +//wParam = 0 +//lParam = (LPARAM)(PROTOACCOUNT*) +//Returns 1 if an account is valid and enabled, 0 otherwise +#define MS_PROTO_ISACCOUNTENABLED "Proto/IsAccountEnabled" + +__inline static int IsAccountEnabled( const PROTOACCOUNT* pa ) +{ +#if MIRANDA_VER < 0x0900 + return pa && (( pa->bIsEnabled && !pa->bDynDisabled ) || pa->bOldProto ); +#else + return (int)CallService( MS_PROTO_ISACCOUNTENABLED, 0, (LPARAM)pa ); +#endif +} + +//determines if an account is locked or not +//wParam = 0 +//lParam = (LPARAM)(char*)szAccountName +//Returns 1 if an account is locked and not supposed to change status, 0 otherwise +#define MS_PROTO_ISACCOUNTLOCKED "Proto/IsAccountLocked" + + +//gets the account associated with a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=0 +//Returns a char* pointing to the asciiz name of the protocol or NULL if the +//contact has no protocol. There is no need to mir_free() it or anything. +//This is the name of the module that actually accesses the network for that +//contact. +#define MS_PROTO_GETCONTACTBASEACCOUNT "Proto/GetContactBaseAccount" + +/* -------------- avatar support --------------------- + +First a protocol must report it supports PF4_AVATARS via PS_GETCAPS, secondly +it will return the following acks for certain events, the protocol must use +ProtoBroadcastAck(), listeners must hook ME_PROTO_ACK, note that lParam = ACKDATA* + +*/ + +/* + + The following ACKs MUST be sent in order of .result via ProtoBroadcastAck() + + .szModule = protocol module + .hContact = contact the avatar is for, or 0 if its for the user + .type = ACKTYPE_AVATAR + .result = ACKRESULT_CONNECTING, ACKRESULT_CONNECTED, ACKRESULT_SENTREQUEST, ACKRESULT_DATA + .hProcess = protocol specific + .lParam = 0 + + Once the transfer is complete the following ACKs MUST be sent by the protocol + + .result = ACKRESULT_SUCCESS or ACKRESULT_FAILED + .hProcess = (HANDLE) &PROTO_AVATAR_INFORMATION + .lParam = 0; + + Anytime before or during the ack or series of acks ACKRESULT_STATUS maybe sent, this might + be sent a long while before anything else happens (or after anything happening) For avatars + it allows callers to identify status information to do with the avatar, including the time + before background transport has been created, so that you know an avatar will be exchanged + sometime in the future. + + When ACKRESULT_STATUS, hProcess is the result code - the value of this is protocol dependent, + See protocol documentation to do with avatars for what codes are defined and what they mean. + +*/ + +#define PA_FORMAT_UNKNOWN 0 // the protocol can not determine much about the "bitmap" +#define PA_FORMAT_PNG 1 // the image is PNG +#define PA_FORMAT_JPEG 2 +#define PA_FORMAT_ICON 3 +#define PA_FORMAT_BMP 4 +#define PA_FORMAT_GIF 5 +#define PA_FORMAT_SWF 6 +#define PA_FORMAT_XML 7 + +typedef struct { + int cbSize; // sizeof() + HANDLE hContact; // this might have to be set by the caller too + int format; // PA_FORMAT_* + char filename[MAX_PATH]; // full path to filename which contains the avatar +} PROTO_AVATAR_INFORMATION; + +#define GAIF_FORCE 1 // force an update of the avatar if there is none + +#define GAIR_SUCCESS 0 // information about the avatar has been returned +#define GAIR_WAITFOR 1 // you must hook ME_PROTO_ACK and wait for replies about avatar status +#define GAIR_NOAVATAR 2 // sorry, this contact has no avatars + +/* + wParam : GAIF_* + lParam : (LPARAM) &PROTO_AVATAR_INFORMATION + Affect : Make a request to the protocol to return information about a hContact's avatar (or main user) + it can return information, tell you there is none, or if forced start requesting an avatar. + Note: + Version: 0.3.4+ (2004/09/13) +*/ +#define PS_GETAVATARINFO "/GetAvatarInformation" + + +#endif // M_PROTOCOLS_H diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_protomod.h b/plugins/!NotAdopted/WinPopup/sdk/m_protomod.h new file mode 100644 index 0000000000..bae8146373 --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_protomod.h @@ -0,0 +1,136 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2008 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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. +*/ +//this module was created in v0.1.1.0 + +//this header file is for the use of protocol modules only. Other users should +//use the functions exposed in m_protocols.h and m_protosvc.h + +#ifndef M_PROTOMOD_H__ +#define M_PROTOMOD_H__ 1 + +#include + +#include "m_protocols.h" + +//notify the protocol manager that you're around +//wParam=0 +//lParam=(PROTOCOLDESCRIPTOR*)&descriptor +//returns 0 on success, nonzero on failure +//This service must be called in your module's Load() routine. +//descriptor.type can be a value other than the PROTOTYPE_ constants specified +//above to provide more precise positioning information for the contact +//protocol lists. It is strongly recommended that you give values relative to +//the constants, however, by adding or subtracting small integers (<=100). +//PROTOTYPE_PROTOCOL modules must not do this. The value must be exact. +//See MS_PROTO_ENUMPROTOCOLS for more notes. +#define MS_PROTO_REGISTERMODULE "Proto/RegisterModule" + +//adds the specified protocol module to the chain for a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(const char*)szName +//returns 0 on success, nonzero on failure +//The module is added in the correct position according to the type given when +//it was registered. +#define MS_PROTO_ADDTOCONTACT "Proto/AddToContact" + +//removes the specified protocol module from the chain for a contact +//wParam=(WPARAM)(HANDLE)hContact +//lParam=(LPARAM)(const char*)szName +//returns 0 on success, nonzero on failure +#define MS_PROTO_REMOVEFROMCONTACT "Proto/RemoveFromContact" + +//Create a protocol service +//Protocol services are called with wParam and lParam as standard if they are +//to be called with CallProtoService() (as PS_ services are) +//If they are called with CallContactService() (PSS_ and PSR_ services) then +//they are called with lParam=(CCSDATA*)&ccs and wParam an opaque internal +//reference that should be passed unchanged to MS_PROTO_CHAIN*. +__inline static HANDLE CreateProtoServiceFunction(const char *szModule,const char *szService,MIRANDASERVICE serviceProc) +{ + char str[MAXMODULELABELLENGTH]; + _snprintf(str, sizeof(str), "%s%s", szModule, szService); + str[MAXMODULELABELLENGTH-1] = 0; + return CreateServiceFunction(str,serviceProc); +} + +//Call the next service in the chain for this send operation +//wParam=wParam +//lParam=lParam +//The return value should be returned immediately +//wParam and lParam should be passed as the parameters that your service was +//called with. wParam must remain untouched but lParam is a CCSDATA structure +//that can be copied and modified if needed. +//Typically, the last line of any chaining protocol function is +//return CallService(MS_PROTO_CHAINSEND,wParam,lParam); +#define MS_PROTO_CHAINSEND "Proto/ChainSend" + +//Call the next service in the chain for this receive operation +//wParam=wParam +//lParam=lParam +//The return value should be returned immediately +//wParam and lParam should be passed as the parameters that your service was +//called with. wParam must remain untouched but lParam is a CCSDATA structure +//that can be copied and modified if needed. +//When being initiated by the network-access protocol module, wParam should be +//zero. +//Thread safety: ms_proto_chainrecv is completely thread safe since 0.1.2.0 +//Calls to it are translated to the main thread and passed on from there. The +//function will not return until all callees have returned, irrepective of +//differences between threads the functions are in. +#define MS_PROTO_CHAINRECV "Proto/ChainRecv" + +//Broadcast a ME_PROTO_ACK event +//wParam=0 +//lParam=(LPARAM)(ACKDATA*)&ack +//returns the return value of the notifyeventhooks() call +//Thread safety: me_proto_ack is completely thread safe since 0.1.2.0 +//See the notes in core/modules.h under NotifyEventHooks() +#define MS_PROTO_BROADCASTACK "Proto/BroadcastAck" +__inline static INT_PTR ProtoBroadcastAck(const char *szModule,HANDLE hContact,int type,int result,HANDLE hProcess,LPARAM lParam) +{ + ACKDATA ack={0}; + ack.cbSize=sizeof(ACKDATA); + ack.szModule=szModule; ack.hContact=hContact; + ack.type=type; ack.result=result; + ack.hProcess=hProcess; ack.lParam=lParam; + return CallService(MS_PROTO_BROADCASTACK,0,(LPARAM)&ack); +} + +/* -- Added during 0.3.4 (2004/09/27) development! ----- +*/ + +/* + wParam: (HANDLE)hContact + lParam: 0 + Affect: Given a hContact, return the protocol that is registered for it, or NULL if no such protocol exists, + the returned string does not have to be freed and is valid even for multiple threads. + Note: Prior to 2004/09/28 this service WAS NOT THREAD SAFE and was slower + Note: Prior to 2004/09/28 this service would return NULL for a hContact if the protocol module + associated with the hContact was not currently loaded, no such check is performed now. + Version: 0.3.4 (2004/09/28) +*/ +#define MS_PROTODIR_PROTOFROMCONTACT MS_PROTO_GETCONTACTBASEPROTO + +#endif // M_PROTOMOD_H__ + + diff --git a/plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h b/plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h new file mode 100644 index 0000000000..c314bda3aa --- /dev/null +++ b/plugins/!NotAdopted/WinPopup/sdk/m_protosvc.h @@ -0,0 +1,775 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2009 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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. +*/ + +//this module was created in v0.1.1.0 + +//none of these services should be used on their own (ie using CallService, +//CreateServiceFunction(), etc), hence the PS_ prefix. Instead use the services +//exposed in m_protocols.h + +#ifndef M_PROTOSVC_H__ +#define M_PROTOSVC_H__ 1 + +#include "m_protocols.h" + +/*************************** NON-CONTACT SERVICES ************************/ +//these should be called with CallProtoService() + +//Get the capability flags of the module. +//wParam=flagNum +//lParam=0 +//Returns a bitfield corresponding to wParam. See the #defines below +//Should return 0 for unknown values of flagNum +//Non-network-access modules should return flags to represent the things they +//actually actively use, not the values that it is known to pass through +//correctly +#define PFLAGNUM_1 1 +#define PF1_IMSEND 0x00000001 //supports IM sending +#define PF1_IMRECV 0x00000002 //supports IM receiving +#define PF1_IM (PF1_IMSEND|PF1_IMRECV) +#define PF1_URLSEND 0x00000004 //supports separate URL sending +#define PF1_URLRECV 0x00000008 //supports separate URL receiving +#define PF1_URL (PF1_URLSEND|PF1_URLRECV) +#define PF1_FILESEND 0x00000010 //supports file sending +#define PF1_FILERECV 0x00000020 //supports file receiving +#define PF1_FILE (PF1_FILESEND|PF1_FILERECV) +#define PF1_MODEMSGSEND 0x00000040 //supports broadcasting away messages +#define PF1_MODEMSGRECV 0x00000080 //supports reading others' away messages +#define PF1_MODEMSG (PF1_MODEMSGSEND|PF1_MODEMSGRECV) +#define PF1_SERVERCLIST 0x00000100 //contact lists are stored on the server, not locally. See notes below +#define PF1_AUTHREQ 0x00000200 //will get authorisation requests for some or all contacts +#define PF1_ADDED 0x00000400 //will get 'you were added' notifications +#define PF1_VISLIST 0x00000800 //has an invisible list +#define PF1_INVISLIST 0x00001000 //has a visible list for when in invisible mode +#define PF1_INDIVSTATUS 0x00002000 //supports setting different status modes to each contact +#define PF1_EXTENSIBLE 0x00004000 //the protocol is extensible and supports plugin-defined messages +#define PF1_PEER2PEER 0x00008000 //supports direct (not server mediated) communication between clients +#define PF1_NEWUSER 0x00010000 //supports creation of new user IDs +#define PF1_CHAT 0x00020000 //has a realtime chat capability +#define PF1_INDIVMODEMSG 0x00040000 //supports replying to a mode message request with different text depending on the contact requesting +#define PF1_BASICSEARCH 0x00080000 //supports a basic user searching facility +#define PF1_EXTSEARCH 0x00100000 //supports one or more protocol-specific extended search schemes +#define PF1_CANRENAMEFILE 0x00200000 //supports renaming of incoming files as they are transferred +#define PF1_FILERESUME 0x00400000 //can resume broken file transfers, see PS_FILERESUME below +#define PF1_ADDSEARCHRES 0x00800000 //can add search results to the contact list +#define PF1_CONTACTSEND 0x01000000 //can send contacts to other users +#define PF1_CONTACTRECV 0x02000000 //can receive contacts from other users +#define PF1_CONTACT (PF1_CONTACTSEND|PF1_CONTACTRECV) +#define PF1_CHANGEINFO 0x04000000 //can change our user information stored on server +#define PF1_SEARCHBYEMAIL 0x08000000 //supports a search by e-mail feature +#define PF1_USERIDISEMAIL 0x10000000 //set if the uniquely identifying field of the network is the e-mail address +#define PF1_SEARCHBYNAME 0x20000000 //supports searching by nick/first/last names +#define PF1_EXTSEARCHUI 0x40000000 //has a dialog box to allow searching all the possible fields +#define PF1_NUMERICUSERID 0x80000000 //the unique user IDs for this protocol are numeric + +#define PFLAGNUM_2 2 //the status modes that the protocol supports +#define PF2_ONLINE 0x00000001 //an unadorned online mode +#define PF2_INVISIBLE 0x00000002 +#define PF2_SHORTAWAY 0x00000004 //Away on ICQ, BRB on MSN +#define PF2_LONGAWAY 0x00000008 //NA on ICQ, Away on MSN +#define PF2_LIGHTDND 0x00000010 //Occupied on ICQ, Busy on MSN +#define PF2_HEAVYDND 0x00000020 //DND on ICQ +#define PF2_FREECHAT 0x00000040 +#define PF2_OUTTOLUNCH 0x00000080 +#define PF2_ONTHEPHONE 0x00000100 +#define PF2_IDLE 0x00000200 //added during 0.3.4 (2004/09/13) + +//the status modes that the protocol supports +//away-style messages for. Uses the PF2_ flags. +// PFLAGNUM_3 is implemented by protocol services that support away messages +// there may be no support and 0 will be returned, if there is +// support it will consist of a set of PF2_* bits +#define PFLAGNUM_3 3 + +// given a status will return what bit flags to test for +static __inline unsigned long Proto_Status2Flag(int status) +{ + switch(status) { + case ID_STATUS_ONLINE: return PF2_ONLINE; + case ID_STATUS_OFFLINE: return 0; + case ID_STATUS_INVISIBLE: return PF2_INVISIBLE; + case ID_STATUS_OUTTOLUNCH: return PF2_OUTTOLUNCH; + case ID_STATUS_ONTHEPHONE: return PF2_ONTHEPHONE; + case ID_STATUS_AWAY: return PF2_SHORTAWAY; + case ID_STATUS_NA: return PF2_LONGAWAY; + case ID_STATUS_OCCUPIED: return PF2_LIGHTDND; + case ID_STATUS_DND: return PF2_HEAVYDND; + case ID_STATUS_FREECHAT: return PF2_FREECHAT; + case ID_STATUS_IDLE: return PF2_IDLE; + } + return 0; +} + +#define PFLAGNUM_4 4 //misc options +#define PF4_FORCEAUTH 0x00000001 // forces auth requests to be sent when adding users +#define PF4_FORCEADDED 0x00000002 // forces "you were added" requests to be sent +#define PF4_NOCUSTOMAUTH 0x00000004 // protocol doesn't support custom auth text (doesn't show auth text box) +#define PF4_SUPPORTTYPING 0x00000008 // protocol supports user is typing messages v0.3.3+ +#define PF4_SUPPORTIDLE 0x00000010 // protocol understands idle, added during v0.3.4+ (2004/09/13) +#define PF4_AVATARS 0x00000020 // protocol has avatar support, added during v0.3.4 (2004/09/13) +#define PF4_OFFLINEFILES 0x00000040 // protocols supports sending files to offline users (v0.5.2) +#define PF4_IMSENDUTF 0x00000080 // protocol is able to process messages in utf-8 (v.0.7.0+) +#define PF4_IMSENDOFFLINE 0x00000100 // protocol supports sending offline messages (v0.8.0+) +#define PF4_INFOSETTINGSVC 0x00000200 // protocol supports user info translation services (v0.8.0+) +#define PF4_NOAUTHDENYREASON 0x00000400 // protocol doesn't support authorization deny reason (v0.9.0+) + +#define PFLAG_UNIQUEIDTEXT 100 //returns a static buffer of text describing the unique field by which this protocol identifies users (already translated), or NULL + +#define PFLAG_MAXCONTACTSPERPACKET 200 //v0.1.2.2+: returns the maximum number of contacts which can be sent in a single PSS_CONTACTS, lParam=(LPARAM)hContact. + +#define PFLAG_UNIQUEIDSETTING 300 // returns the setting name of where the unique id is stored + +#define PFLAG_MAXLENOFMESSAGE 400 // v0.3.2+: return the maximum length of an instant message, lParam=(LPARAM)hContact + +/* + + A protocol might not support this cap, it allows a protocol to say that PFLAGNUM_2 is for + statuses contacts supports, and that PFLAGNUM_5 is for statuses a protocol can SET TO ITSELF, + if this is not replied to, then PFLAGNUM_2 is alone in telling you which statuses a protocol + can set to and what statuses a contact can set to as well. + + E.g. A protocol might report 'wireless' users but a login of the protocol from Miranda can + not set itself to 'wireless' so PFLAGNUM_2 would return PF2_ONTHEPHONE and PFLAGNUM_5 would + return PF2_ONTHEPHONE as well, this means "I will get contacts who are on the phone but you can + not set on the phone" and so on. + + Do note that the reply here is a NEGATION of bitflags reported for PFLAGNUM_2, e.g. returning + PF2_ONTHEPHONE for PFLAGNUM_2 and returning the same for PFLAGNUM_5 says that you DO NOT SUPPORT + PF2_ONTHEPHONE for the user to PS_SETSTATUS to, but you will expect other contacts to have + that status, e.g. you can get onthephone for users but can't go online with onthephone. + + The same PF2_* status flags are used in the reply. + +Added during 0.3.4 (2004/09/14) +*/ +#define PFLAGNUM_5 5 + +/* Deleting contacts from protocols that store the contact list on the server: +If a contact is deleted while the protocol is online, it is expected that the +protocol will have hooked me_db_contact_deleted and take the appropriate +action by itself. +If a contact is deleted while the protocol is offline, the contact list will +display a message to the user about the problem, and set the byte setting +"CList"/"Delete" to 1. Each time such a protocol changes status from offline +or connecting to online the contact list will check for contacts with this +flag set and delete them at that time. Your hook for me_db_contact_deleted +will pick this up and everything will be good. +*/ +#define PS_GETCAPS "/GetCaps" + +//Get a human-readable name for the protocol +//wParam=cchName +//lParam=(LPARAM)(char*)szName +//Returns 0 on success, nonzero on failure +//cchName is the number of characters in the buffer szName +//This should be translated before being returned +//Some example strings are: +//"ICQ", "AIM", "RSA-1024 Encryption" +#define PS_GETNAME "/GetName" + +//Loads one of the protocol-specific icons +//wParam=whichIcon +//lParam=0 +//Returns the HICON, or NULL on failure +//The returned HICON must be DestroyIcon()ed. +//The UI should overlay the online icon with a further UI-specified icon to +//represent the exact status mode. +#define PLI_PROTOCOL 1 //An icon representing the protocol (eg the multicoloured flower for ICQ) +#define PLI_ONLINE 2 //Online state icon for that protocol (eg green flower for ICQ) +#define PLI_OFFLINE 3 //Offline state icon for that protocol (eg red flower for ICQ) +#define PLIF_LARGE 0 //OR with one of the above to get the large (32x32 by default) icon +#define PLIF_SMALL 0x10000 //OR with one of the above to get the small (16x16 by default) icon +#define PLIF_ICOLIB 0x20000 //the returned HICON is managed by IcoLib, DO NOT DestroyIcon() it +#define PLIF_ICOLIBHANDLE 0x40000 //the function will return IcoLib handle not HICON +#define PS_LOADICON "/LoadIcon" + +//Change the protocol's status mode +//wParam=newMode, from ui/contactlist/statusmodes.h +//lParam=0 +//returns 0 on success, nonzero on failure +//Will send an ack with: +//type=ACKTYPE_STATUS, result=ACKRESULT_SUCCESS, hProcess=(HANDLE)previousMode, lParam=newMode +//when the change completes. This ack is sent for all changes, not just ones +//caused by calling this function. +//Note that newMode can be ID_STATUS_CONNECTING<=newMode